diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..9c18a2a3 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,39 @@ +# Contributing to kdb VS Code Extension + +Your input is very welcome, some examples of this include: + +- Reporting a bug +- Submitting a fix +- Proposing new features + +## Reporting a bug + +Bugs can be reported via [Issues](https://github.com/KxSystems/kx-vscode/issues) + +Where possible include: + +- Quick summary and/or background +- Steps to reproduce + - Be specific + - Provide sample code if you can +- What you expected would happen +- What actually happens +- Other relevant notes + +## Submitting a fix + +Fixes can be submitted via a pull request: + +1. Fork the repo and create your branch from `dev` +2. If you've added code that should be tested, add tests +3. Ensure the test suite passes, using `npm run test` +4. Apply the prettier formatting, using a plugin or manually using `npm run format` +5. Create a pull request for your branch + +### License + +When you submit code changes your submissions are understood to be under the same [Apache 2.0](https://github.com/KxSystems/kx-vscode/blob/main/LICENSE) that covers the project. Please feel free to contact the maintainers if that's a concern. + +## Proposing a new feature + +Please use vscode-questions@kx.com to raise any questions, feature requests or feedback. diff --git a/.github/ISSUE_TEMPLATE/BUG.YML b/.github/ISSUE_TEMPLATE/BUG.YML new file mode 100644 index 00000000..24e3d844 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG.YML @@ -0,0 +1,40 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug", "triage"] +projects: ["KxSystems/kx-vscode"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to complete this bug report + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you if we need more info? + placeholder: ex. email@example.com + validations: + required: false + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "A bug happened!" + validations: + required: true + - type: input + id: version + attributes: + label: Version + description: What version of the extension are you running? + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output (e.g. contents of the 'kdb' Output pane) + render: shell diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..3ba13e0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 00000000..50ab2fcf --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,3 @@ +### Changes introduced by this PR + +- diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92f330f8..7563315f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: name: lcov - name: Install dependencies - run: yarn install + run: npm install - name: SonarCloud Scan uses: sonarsource/sonarqube-scan-action@master diff --git a/.github/workflows/prod_release.yml b/.github/workflows/prod_release.yml new file mode 100644 index 00000000..6cabf097 --- /dev/null +++ b/.github/workflows/prod_release.yml @@ -0,0 +1,137 @@ +name: KX VS Code Production Release Workflow + +on: + push: + tags: + - "v[129].[0-9]+.[0-9]+" + +env: + NODE_ENV: production + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout source code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 16.x + - name: Install dependencies + run: npm ci --include=dev + - name: Build VSIX file + run: npm run build + - name: Run Tests + run: xvfb-run -a npm run test + - name: Packaging + run: npm run package + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: KDB-VSCode-Extension + path: ./kdb-*vsix + + app-sec: + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout source code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 16.x + + - name: Install dependencies + run: npm install + + - name: SonarCloud Scan + uses: sonarsource/sonarqube-scan-action@master + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + + - name: Snyk scan for all vulnerabilities + uses: snyk/actions/node@master + continue-on-error: true + env: + SNYK_TOKEN: ${{ secrets.pink_snyk_api_key }} + + - name: Snyk scan for high or critical vulnerabilities + uses: snyk/actions/node@master + env: + SNYK_TOKEN: ${{ secrets.pink_snyk_api_key }} + with: + args: --severity-threshold=high + + release: + needs: app-sec + runs-on: ubuntu-latest + steps: + - name: Set Tag Var + id: vars + run: | + VERSION=${{ github.ref_name }} + echo "run_tag=$(echo ${VERSION:1})" >> $GITHUB_OUTPUT + - name: Checkout code + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Download VSIX file from build job + uses: actions/download-artifact@v3 + with: + name: KDB-VSCode-Extension + - name: Get Body + run: | + sed -n "/# ${{ github.ref_name }}/,/# v/{s/^# .*//;p;}" CHANGELOG.md > temp.md + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref_name }} + body_path: ./temp.md + - name: Upload Release Asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: kdb-${{ steps.vars.outputs.run_tag }}.vsix + asset_name: kdb-${{ steps.vars.outputs.run_tag }}.vsix + asset_content_type: application/octet-stream + + # manual-approve: + # needs: release + # environment: + # name: approvers + # runs-on: ubuntu-latest + # steps: + # - name: Manual Approve + # run: echo "Manually approved" + + # publish: + # needs: manual-approve + # - name: Checkout source code + # uses: actions/checkout@v2 + # with: + # fetch-depth: 0 + # - name: Install Node.js + # uses: actions/setup-node@v3 + # with: + # node-version: 16.x + # - name: Install dependencies + # run: npm ci --include=dev + # - name: Publish to VSCode Marketplace + # run: npm run publish + # env: + # VSCE_PAT: ${{ secrets.VSCE_PAT }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index daa4d1ee..35bd89b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -24,11 +24,11 @@ jobs: - name: Install dependencies run: npm ci --include=dev - name: Build VSIX file - run: yarn run build + run: npm run build - name: Run Tests - run: xvfb-run -a yarn run coverage + run: xvfb-run -a npm run coverage - name: Packaging - run: yarn run package + run: npm run package - name: Upload artifact uses: actions/upload-artifact@v3 with: @@ -56,7 +56,11 @@ jobs: node-version: 16.x - name: Install dependencies - run: yarn install + run: npm install + + - name: get-npm-version + id: package-version + uses: martinbeentjes/npm-get-version-action@v1.3.1 - name: Download lcov result from test job uses: actions/download-artifact@v3 @@ -65,9 +69,13 @@ jobs: - name: SonarCloud Scan uses: sonarsource/sonarqube-scan-action@master + continue-on-error: true env: SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }} + with: + args: > + -Dsonar.projectVersion=${{ steps.package-version.outputs.current-version}} - name: Snyk scan for all vulnerabilities uses: snyk/actions/node@master @@ -77,6 +85,7 @@ jobs: - name: Snyk scan for high or critical vulnerabilities uses: snyk/actions/node@master + continue-on-error: true env: SNYK_TOKEN: ${{ secrets.pink_snyk_api_key }} with: @@ -84,6 +93,7 @@ jobs: - name: Snyk Monitor uses: snyk/actions/node@master + continue-on-error: true env: SNYK_TOKEN: ${{ secrets.pink_snyk_api_key }} with: diff --git a/CHANGELOG.md b/CHANGELOG.md index dce43348..e8396cfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,14 @@ All notable changes to the kdb extension will be documented in this file. -# 1.0.1 + +# v1.0.1 ### Internal Improvements - Documentation improvements -# 1.0.0 +# v1.0.0 ### Enhancements @@ -25,13 +26,13 @@ All notable changes to the kdb extension will be documented in this file. - kdb connections tree is now sorted - Autocomplete fixes for embedded namespaces -# 0.1.17 +# v0.1.17 ### Internal Improvements - KX Language Server improvements -# 0.1.16 +# v0.1.16 ### Internal Improvements @@ -39,7 +40,7 @@ All notable changes to the kdb extension will be documented in this file. - Preview KX Language Server implementation -# 0.1.15 +# v0.1.15 ### Enhancements @@ -47,7 +48,7 @@ All notable changes to the kdb extension will be documented in this file. - Refresh functionality moved from context menu to icon in view title bar -# 0.1.14 +# v0.1.14 ### Fixes @@ -59,7 +60,7 @@ All notable changes to the kdb extension will be documented in this file. - Fix to filter "," namespace from views retrieval -# 0.1.13 +# v0.1.13 ### Enhancements @@ -81,7 +82,7 @@ All notable changes to the kdb extension will be documented in this file. - Logo improved to work with both light and dark themes -# 0.1.12 +# v0.1.12 ### Enhancements @@ -97,7 +98,7 @@ All notable changes to the kdb extension will be documented in this file. - Added language server to support code completion and navigation -# 0.1.11 +# v0.1.11 ### Enhancements @@ -117,7 +118,7 @@ All notable changes to the kdb extension will be documented in this file. - Branding updates -# 0.1.10 +# v0.1.10 ### Enhancements @@ -133,7 +134,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.9 +# v0.1.9 ### Enhancements @@ -147,7 +148,7 @@ All notable changes to the kdb extension will be documented in this file. - Removed q terminal from the extension with the decision to use the editor and output window in favor of the confusion with the terminal. -# 0.1.8 +# v0.1.8 ### Enhancements @@ -157,7 +158,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.7 +# v0.1.7 ### Enhancements @@ -167,7 +168,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.6 +# v0.1.6 ### Enhancements @@ -177,7 +178,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.5 +# v0.1.5 ### Enhancements @@ -191,7 +192,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.4 +# v0.1.4 ### Enhancements @@ -201,7 +202,7 @@ All notable changes to the kdb extension will be documented in this file. ### Internal Improvements -# 0.1.3 +# v0.1.3 ### Enhancements @@ -217,7 +218,7 @@ All notable changes to the kdb extension will be documented in this file. - Initial infrastructure code for SQL queries from editor, more to come in next release. -# 0.1.2 +# v0.1.2 ### Enhancements @@ -235,7 +236,7 @@ All notable changes to the kdb extension will be documented in this file. - Updated the internal connection manager caching for better response and less connections required when using multiple inputs such as q terminal and the editor pane. -# 0.1.1 +# v0.1.1 ### Enhancements diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 8b137891..00000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/LICENSE b/LICENSE index 8d641b91..c61b6639 100644 --- a/LICENSE +++ b/LICENSE @@ -1,39 +1,201 @@ -© KX Systems, Inc 2023 - -Version Number: 1.0 Date Last Revised: September 2023 - -Software License Agreement for use of kdb VS Code extension (“Agreement”) - -CAREFULLY READ THE FOLLOWING TERMS AND CONDITIONS. BY DOWNLOADING OR USING THE SOFTWARE, YOU ACKNOWLEDGE AND AGREE TO BE BOUND BY THESE TERMS AND CONDITIONS, WHICH MAY BE UPDATED FROM TIME TO TIME. “END USER” OR “YOU” MEANS YOU, THE USER OF THE SOFTWARE. YOU WARRANT THAT THE IDENTIFICATION DETAILS AND INFORMATION THAT YOU PROVIDE TO US, INCLUDING BUT NOT LIMITED TO, YOUR NAME, EMAIL ADDRESS, LOCATION, TELEPHONE NUMBER AND INTENDED USE ARE TRUE AND CORRECT. YOU ACKNOWLEDGE AND AGREE THAT THIS AGREEMENT IS ENFORCEABLE AND LEGALLY BINDING. - -NO ACCESS OR USE OF THE SOFTWARE IS PERMITTED FROM THOSE COUNTRIES WHERE SUCH USE IS PROHIBITED BY TRADE CONTROL LAWS. - -This Agreement is made between KX Systems, Inc. (“KX” or “we”) and the End User for access and use of KX’s kdb VS Code extension software, any updates, new versions and/or any documentation provided to you by KX (jointly, the “Software”). You agree to use the Software subject to the terms and conditions set forth below which shall be subject to change from time to time. - -1. LICENSE GRANTS - -1.1 Grant of License. KX hereby grants End User a non-transferable, non-exclusive license, without right of sublicense, to install and use the Software solely in connection with KX’s kdb+ or kdb Insights Enterprise software, which is made available by KX under separate licensing terms. End User will not attempt to circumvent any restrictions imposed on the Software or use the Software for any purpose other than stated above. - -1.2 Software Use Restrictions. End User may not: (a) modify any part of the Software or create derivative works thereof, (b) sell, lease, license or distribute the Software to any third party, (c) attempt to decompile, disassemble or reverse engineer the Software, (d) copy the Software, except for purposes of installing and executing it within the limitations set out at clause 1.1, (e) use or attempt to use the Software in any way that is unlawful or fraudulent or has any unlawful or fraudulent purpose or effect, (f) use or attempt to use the Software in any way that would breach the license granted herein. - -1.3 Software Performance. End User shall not distribute or otherwise make available to any third party any report regarding the performance of the Software, Software benchmarks or any information from such a report. - -1.4 Intellectual Property Ownership Rights. End User acknowledges and agrees that KX owns all rights, title and interest in and to the Software and in and to all of KX’s patents, trademarks, trade names, inventions, copyrights, know-how and trade secrets relating to its design, manufacture and operation, including all inventions, customizations, enhancements, improvements, updates, derivative works and other modifications and all related rights shall automatically vest in KX immediately upon creation. End User will not register any trademark, patent or copyright which uses or references the Software. The use by End User of such proprietary rights is authorized only for the purposes set forth herein, and upon termination of this Agreement for any reason, such authorization will cease. End User acknowledges that the Software is proprietary and contains confidential and valuable trade secrets of KX. - -2. SUPPORT. KX may at its discretion provide support to End User in relation to the Software. - -3. FEES. The Software is licensed to End User without charge. - -4. NO WARRANTY. THE SOFTWARE IS PROVIDED “AS IS.” KX EXPRESSLY DISCLAIMS AND NEGATES ALL WARRANTIES, WHETHER EXPRESSED, IMPLIED, STATUTORY OR OTHERWISE, AND SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT OF - -INTELLECTUAL PROPERTY OR OTHER VIOLATION OF RIGHTS. KX DOES NOT WARRANT THAT THE SOFTWARE WILL MEET END USER REQUIREMENTS OR THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR FREE. - -5. LIMITATION OF LIABILITY. WE DO NOT EXCLUDE OR LIMIT IN ANY WAY OUR LIABILITY TO YOU WHERE IT WOULD BE UNLAWFUL TO DO SO. SUBJECT TO THE FOREGOING SENTENCE, (I) KX’S LIABILITY UNDER OR IN CONNECTION WITH THIS AGREEMENT UNDER ANY LEGAL OR EQUITABLE THEORY, INCLUDING BREACH OF CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY SHALL BE LIMITED TO US$100, AND (II) IN NO EVENT SHALL KX BE LIABLE FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER SIMILAR DAMAGES, INCLUDING BUT NOT LIMITED TO DAMAGE TO REPUTATION, LOSS OF EARNINGS, LOSS OF PROFIT, LOSS OF BUSINESS OR BUSINESS OPPORTUNITY OR BUSINESS INTERRUPTION IN CONNECTION WITH OR ARISING OUT OF THIS AGREEMENT AND/OR THE USE OF OR INABILITY TO USE THE SOFTWARE, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -6. TERM AND TERMINATION OF AGREEMENT. This Agreement shall terminate immediately upon KX’s written notice to End User and KX may at its discretion suspend or terminate End User’s use of the Software at any time. Upon termination of this Agreement or at any time upon KX’s written request, End User shall permanently delete or destroy all copies of the Software in its possession. - -7. GOVERNING LAW AND JURISDICTION. This Agreement and all related documents and all matters arising out of or relating to this Agreement whether in contract, tort, or statute shall be governed by and construed in accordance with the laws of the State of New York, United States of America, except as to copyright matters covered by U.S. Federal Law. Each party irrevocably and unconditionally agrees to the exclusive jurisdiction of the State of New York, and it will not commence any action, litigation, or proceeding of any kind whatsoever against any other party in any way arising from or relating to this Agreement and all contemplated transactions, including, but not limited to, contract, equity, tort, fraud, and statutory claims, in any forum other than the State of New York (except as permitted by KX as detailed below). End User hereby waives any objections to venue in those courts. Each party agrees that a final judgment in any such action, litigation, or proceeding is conclusive and may be enforced in other jurisdictions by suit on the judgment or in any other manner provided by law. Should any provision of this Agreement be declared unenforceable in any jurisdiction, then such provision shall be deemed to be severed from this Agreement and shall not affect the remainder hereof. Furthermore, with respect to a violation by End User of Section 1 (License Grant), KX will have the right at its discretion to seek remedies in courts of competent jurisdiction within any applicable territory. The United Nations Convention on Contracts for the International Sale of Goods and the Uniform Computer information Transactions Act, as currently enacted by any jurisdiction or as may be codified or amended from time to time by any jurisdiction, do not apply to this Agreement. - -8. TRADE CONTROL. You acknowledge that Software (including its related technical data and services) may be deemed dual use and is subject to, without limitation, the export control laws and regulations of the United Kingdom, European Union, and United States of America (“Trade Control Laws”). You agree to fully comply with those Trade Control Laws in connection with Software including where applicable assisting in obtaining any necessary governmental approvals, licenses and undertakings. You will not, and will not allow any third party, to use, export, re-export or transfer, directly or indirectly, of any part of the Software in violation of any Trade Control Laws or to a destination subject to US, UN, EU, UK or Organisation for Security and Cooperation in Europe (OSCE) embargo, or to any individual or entity listed on the denied parties’ lists. A statement on the Export Controls applicable to the Software, is available at the following website: Export Statement – KX. Any dispute in relation to this clause 8 shall be governed in accordance with clause 7 unless Trade Control Laws determine otherwise. You acknowledge that we may not be permitted (and, in such an event, shall be excused from any requirement) to deliver or grant access to the Software, or perform support or services, due to an embargo, trade sanction or other comparable restrictive measure. - -9. GENERAL. This is the only Agreement between End User and KX relating to the Software. The provisions of section 1.4 (“Intellectual Property Ownership Rights”), section 4 (“No Warranty”), section 5 (“Limitation of Liability”), section 6 (“Term and Termination”), section 9 (“General”) shall survive the termination of this Agreement for any reason. All other rights and obligations of the parties shall cease upon termination of this Agreement. This Agreement constitutes the sole and entire agreement of the parties with respect to the subject matter of this Agreement and supersedes all prior and contemporaneous understandings, agreements, and representations and warranties, both written and oral, with respect to such subject matter. You agree that you shall have no remedies in respect of any statement, representation, assurance or warranty (whether made innocently or negligently) that is not set out in this Agreement. Except for the limited rights and licenses expressly granted under this Agreement, nothing in this Agreement grants, by implication, waiver, estoppel, or otherwise, to you or any third party. If we fail to insist that you perform any of your obligations under this Agreement, or if we do not enforce our rights against you, or if we delay in doing so, that will not mean that we have waived our rights against you and will not mean that you do not have to comply with those obligations. If we do waive a default by you, we will only do so in writing and that will not mean that we will automatically waive any later default by you. \ No newline at end of file + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +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. diff --git a/README.md b/README.md index 34674639..7d7ae5d1 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,12 @@ # kdb Visual Studio Code extension -This is a companion extension for kdb developers to edit q files, connect to kdb processes, and run queries. This VS Code extension can be used alongside [kdb Insights Enterprise](https://code.kx.com/insights/enterprise/index.html) when using a shared kdb process. +This is a companion extension for kdb developers to edit q files, connect to kdb processes, and run queries. This VS Code extension can be used alongside [kdb Insights Enterprise](https://code.kx.com/insights/enterprise/index.html) when using a shared kdb process. -Please use vscode-questions@kx.com to raise any questions, issues or feedback. +Please use vscode-questions@kx.com to raise any questions, issues or feedback. - ## Contents @@ -21,34 +19,31 @@ Please use vscode-questions@kx.com to raise any questions, issues or feedback. - [Settings](#settings) - [Shortcuts](#shortcuts) - ## Why q for VS Code? With the kdb VS Code extension you can: - Install q. - Write q syntax with support for predict and autocomplete. -- Execute q from a single line of code, code block or q file. +- Execute q from a single line of code, code block or q file. - Write and execute q code against kdb Insights Enterprise. - View results from your queries. - ## Get started If you have an existing q installation, you will see the message `q runtime installed` and can go directly to adding [connections](#connections). If you are new to q, you can install q with the kdb VS Code extension; see [install q](#install-q). - ### Install q -**Step 1**: Download the latest version of kdb+. Different versions of kdb+ are available, and the version you download will determine the supported features in VS Code: +**Step 1**: Download the latest version of kdb+. Different versions of kdb+ are available, and the version you download will determine the supported features in VS Code: -item | write q | run q queries | explore results | shared kdb process with kdb Insights ----- | ------- | ------------- | --------------- | ---------------------------------- -[kdb+ Personal Edition](https://kx.com/kdb-personal-edition-download/) | yes | yes | yes | no -[kdb Insights Personal Edition](https://kx.com/kdb-insights-personal-edition-license-download/) | yes | yes | yes | no -[kdb Insights Enterprise Personal Edition](https://trykdb.kx.com/) | yes | yes | yes | yes +| item | write q | run q queries | explore results | shared kdb process with kdb Insights | +| ----------------------------------------------------------------------------------------------- | ------- | ------------- | --------------- | ------------------------------------ | +| [kdb+ Personal Edition](https://kx.com/kdb-personal-edition-download/) | yes | yes | yes | no | +| [kdb Insights Personal Edition](https://kx.com/kdb-insights-personal-edition-license-download/) | yes | yes | yes | no | +| kdb Insights Enterprise | yes | yes | yes | yes | Contact licadmin@kx.com for commercial kdb licensing. @@ -56,43 +51,43 @@ Contact licadmin@kx.com for commercial kdb licensing. Extract the file to a directory; instructions are available for [Linux, macOS and Windows](https://code.kx.com/q/learn/install/#step-2-unzip-your-download). -* I want to learn more about [kdb+ installation](https://code.kx.com/q/learn/install/) +- I want to learn more about [kdb+ installation](https://code.kx.com/q/learn/install/) -**Step 3**: The welcome email will also have your kdb, `k4.lic` or `kc.lic` license as an attachment. We recommend you add your kdb license to your q installation directory, or `QHOME`, and define this location in your environment variables. It is essential you define an environment variable for VS Code to recognize a valid license. +**Step 3**: The welcome email will also have your kdb, `k4.lic` or `kc.lic` license as an attachment. We recommend you add your kdb license to your q installation directory, or `QHOME`, and define this location in your environment variables. It is essential you define an environment variable for VS Code to recognize a valid license. -*Note*: If your kdb license is stored outside of your q (`QHOME`) directory, create a `QLIC` environment variable instead. +_Note_: If your kdb license is stored outside of your q (`QHOME`) directory, create a `QLIC` environment variable instead. -* I want to learn [how to define a QHOME environment variable](https://code.kx.com/q/learn/install/#step-5-edit-your-profile). +- I want to learn [how to define a QHOME environment variable](https://code.kx.com/q/learn/install/#step-5-edit-your-profile). ### Install q with VS Code. You can install q from the VS Code extension. You still need to register for [kdb Insights Personal Edition](https://kx.com/kdb-insights-personal-edition-license-download/) to obtain a license and VS Code will guide you through steps to install. The license will be incorporated as part of the kdb VS Code extension, although a `QHOME` environment variable is still required if you wish to utilise the q installation outside of VS Code. -**Step 1**: Click `Install new instance` from the prompt if no q installation is flagged. If this prompt is cancelled, then use the aforementioned [install q](#install-q). +**Step 1**: Click `Install new instance` from the prompt if no q installation is flagged. If this prompt is cancelled, then use the aforementioned [install q](#install-q). -![installnewinstance](https://code.kx.com/img/vscode/installnewinstance.jpg) +![installnewinstance](https://github.com/KxSystems/kx-vscode/blob/main/img/installnewinstance.jpg?raw=true) -**Step 2**: If you have already registered for kdb+ or kdb Insights, then choose `Select/Enter a license`. If you haven't registered, choose `Acquire license`, this will open a dialog with a redirect link to register for [kdb Insights Personal Edition](https://kx.com/kdb-insights-personal-edition-license-download/). +**Step 2**: If you have already registered for kdb+ or kdb Insights, then choose `Select/Enter a license`. If you haven't registered, choose `Acquire license`, this will open a dialog with a redirect link to register for [kdb Insights Personal Edition](https://kx.com/kdb-insights-personal-edition-license-download/). -![findlicense](https://code.kx.com/img/vscode/findlicense.jpg) +![findlicense](https://github.com/KxSystems/kx-vscode/blob/main/img/findlicense.jpg?raw=true) -**Step 3**: With the license secured, you can then link this to VS Code by either `pasting license string` or `selecting license file` from your PC; the latter method is recommended for new users. +**Step 3**: With the license secured, you can then link this to VS Code by either `pasting license string` or `selecting license file` from your PC; the latter method is recommended for new users. -![findlicense](https://code.kx.com/img/vscode/pastelicense.jpg) +![findlicense](https://github.com/KxSystems/kx-vscode/blob/main/img/pastelicense.jpg?raw=true) -The base64 encoded license string can be found in the welcome email received after registration, under the download link for the license file. +The base64 encoded license string can be found in the welcome email received after registration, under the download link for the license file. -![welcomeemaillicense](https://code.kx.com/img/vscode/weclomeemail.jpg) +![welcomeemaillicense](https://github.com/KxSystems/kx-vscode/blob/main/img/weclomeemail.jpg?raw=true) -The `k4.lic` or `kc.lic` license file can be downloaded to your PC. +The `k4.lic` or `kc.lic` license file can be downloaded to your PC. **Step 4**: Set a [`QHOME` environment variable](https://code.kx.com/q/learn/install/#step-5-edit-your-profile) to the location used by the kdb VS Code install. A notification dialog displays the location of q, as do the extension [settings](#settings). This will allows you to use q outside of VSCode. -![qfound](https://code.kx.com/img/vscode/installationofqfound.jpg) +![qfound](https://github.com/KxSystems/kx-vscode/blob/main/img/installationofqfound.jpg?raw=true) If q is installed at `C:\q`, then `QHOME` is `C:\q`. -To finish, a prompt is offered with an opt-in to receive a newsletter. +To finish, a prompt is offered with an opt-in to receive a newsletter. ## Connections @@ -102,99 +97,95 @@ The kdb VS Code extension allows you to connect VS Code to a q process; this can **Step 1**: Identify the remote location of a running process. The hostname and port will be required along with any authentication information. -**Step 2**: Within the kdb VS Code extension, click *connect to kdb server*, or *Add new connection** from the *CONNECTIONS* context menu. +**Step 2**: Within the kdb VS Code extension, click _connect to kdb server_, or *Add new connection\*\* from the *CONNECTIONS\* context menu. -![connecttoakdbserver](https://code.kx.com/img/vscode/connecttoakdbserver.png) +![connecttoakdbserver](https://github.com/KxSystems/kx-vscode/blob/main/img/connecttoakdbserver.png?raw=true) **Step 3**: When prompted to select the kdb type, choose **Enter a kdb endpoint**. -![setendpoint](https://code.kx.com/img/vscode/step1connecttoakdbserver.jpg) +![setendpoint](https://github.com/KxSystems/kx-vscode/blob/main/img/step1connecttoakdbserver.jpg?raw=true) -**Step 4**: Assign a *server name / alias*. The server name selected **cannot be `local` or `insights`**, as these are reserved for use by [managed q sessions](#managed-q-session) and [kdb Insights Enterprise connections](#kdb-insights-enterprise); e.g. *dev* +**Step 4**: Assign a _server name / alias_. The server name selected **cannot be `local` or `insights`**, as these are reserved for use by [managed q sessions](#managed-q-session) and [kdb Insights Enterprise connections](#kdb-insights-enterprise); e.g. _dev_ -**Step 5**: Set the *hostname* or ip address of the kdb server; e.g. *localhost*. +**Step 5**: Set the _hostname_ or ip address of the kdb server; e.g. _localhost_. -**Step 6**: Set the *port* used by the kdb server; e.g. *5001*. +**Step 6**: Set the _port_ used by the kdb server; e.g. _5001_. -* I want to learn more about [setting a q port](https://code.kx.com/q/basics/ipc/) +- I want to learn more about [setting a q port](https://code.kx.com/q/basics/ipc/) -**Step 7**: If authentication is required, define the *username*, then the *password*; clicking Enter with these inputs blank skips these steps. +Upon completion, the localhost connection appears under _KX:CONNECTIONS_ in the left hand panel. -**Step 8**: An option to enable TLS encryption is offered; the default is *false*. +![localkdbconnection](https://github.com/KxSystems/kx-vscode/blob/main/img/localkdbconnection.jpg?raw=true) -* I want to learn more [about TLS encryption](https://code.kx.com/q/kb/ssl/). +**Step 7**: Right-click the connection to _connect kdb server_. Ensure the q process is running. -Upon completion, the localhost connection appears under *KX:CONNECTIONS* in the left hand panel. +![localkdbconnection](https://github.com/KxSystems/kx-vscode/blob/main/img/connectserver.jpg?raw=true) -![localkdbconnection](https://code.kx.com/img/vscode/localkdbconnection.jpg) +If authentication is required to access the connection, from the connection dropdown menu, add the required _username_ and the _password_, clicking Enter to move between the two. -**Step 9**: Right-click the connection to *connect kdb server*. Ensure the q process is running. - -![localkdbconnection](https://code.kx.com/img/vscode/connectserver.jpg) +From the connection dropdown menu there is also an option to enable TLS encryption; the default is _false_. +- I want to learn more [about TLS encryption](https://code.kx.com/q/kb/ssl/). ### Managed q session This runs a q session using the existing kdb installed as part of the kdb VS Code extension. -**Step 1**: Click *connect to kdb server* or *Add new connection* from the *CONNECTIONS* context menu. +**Step 1**: Click _connect to kdb server_ or _Add new connection_ from the _CONNECTIONS_ context menu. -![connecttoakdbserver](https://code.kx.com/img/vscode/connecttoakdbserver.png) +![connecttoakdbserver](https://github.com/KxSystems/kx-vscode/blob/main/img/connecttoakdbserver.png?raw=true) **Step 2**: When prompted to select the kdb type, choose **Enter a kdb endpoint**. -![setendpoint](https://code.kx.com/img/vscode/step1connecttoakdbserver.jpg) - -**Step 3**: Set the *server name / alias* to `local`. +![setendpoint](https://github.com/KxSystems/kx-vscode/blob/main/img/step1connecttoakdbserver.jpg?raw=true) -**Step 4**: Set the *hostname*; e.g. *localhost* +**Step 3**: Set the _server name / alias_ to `local`. -**Step 5**: Set the *port* for the kdb server. Ensure the port used doesn't conflict with any other running q process; e.g. *5002* +**Step 4**: Set the _hostname_; e.g. _localhost_ -* I want to learn more about [setting a q port](https://code.kx.com/q/basics/ipc/) +**Step 5**: Set the _port_ for the kdb server. Ensure the port used doesn't conflict with any other running q process; e.g. _5002_ -**Step 6**: Right-click the managed q process listed under *KX:CONNECTIONS*, and click *Start q process*. +- I want to learn more about [setting a q port](https://code.kx.com/q/basics/ipc/) -![setendpoint](https://code.kx.com/img/vscode/managedqprocess.jpg) +**Step 6**: Right-click the managed q process listed under _KX:CONNECTIONS_, and click _Start q process_. -**Step 7**: From the same right-click menu, click *Connect kdb server*. This connects to the child q process running inside the kdb VS Code extension. +![setendpoint](https://github.com/KxSystems/kx-vscode/blob/main/img/managedqprocess.jpg?raw=true) -If you close the extension, the connection to the child q process also closes. +**Step 7**: From the same right-click menu, click _Connect kdb server_. This connects to the child q process running inside the kdb VS Code extension. +If you close the extension, the connection to the child q process also closes. ### kdb Insights Enterprise -For kdb Insights Enterprise, the kdb VS Code extension is using a shared kdb process. Unlike for a **managed q session**, you must have [kdb Insights Enterprise Personal Edition](https://trykdb.kx.com/) running before using these connections. +For kdb Insights Enterprise, the kdb VS Code extension is using a shared kdb process. Unlike for a **managed q session**, you must have [kdb Insights Enterprise Personal Edition](https://trykdb.kx.com/kx/signup) running before using these connections. -**Step 1**: Click *connect to kdb server*. +**Step 1**: Click _connect to kdb server_. -![connecttoakdbserver](https://code.kx.com/img/vscode/connecttoakdbserver.png) +![connecttoakdbserver](https://github.com/KxSystems/kx-vscode/blob/main/img/connecttoakdbserver.png?raw=true) -**Step 2**: When prompted to select a kdb type, choose *Connect to kdb insights* +**Step 2**: When prompted to select a kdb type, choose _Connect to kdb insights_ -![connecttoinsights](https://code.kx.com/img/vscode/connecttoinsights.jpg) +![connecttoinsights](https://github.com/KxSystems/kx-vscode/blob/main/img/connecttoinsights.jpg?raw=true) -**Step 3**: Create a *server name / alias*; this can be any name, aside from `local`, which is used by the [managed q session](#managed-q-session). +**Step 3**: Create a _server name / alias_; this can be any name, aside from `local`, which is used by the [managed q session](#managed-q-session). -**Step 4**: Set the *hostname*. This is the remote address of your kdb Insights Enterprise deployment: e.g `https://mykdbinsights.cloudapp.azure.com` +**Step 4**: Set the _hostname_. This is the remote address of your kdb Insights Enterprise deployment: e.g `https://mykdbinsights.cloudapp.azure.com` -**Step 5**: The kdb Insights Enterprise connection is listed under *KX:Connections*, with its own icon. Right-click the connection and *Connect to Insights* +**Step 5**: The kdb Insights Enterprise connection is listed under _KX:Connections_, with its own icon. Right-click the connection and _Connect to Insights_ -![connecttoinsights](https://code.kx.com/img/vscode/kdbinsightsconnection.jpg) +![connecttoinsights](https://github.com/KxSystems/kx-vscode/blob/main/img/kdbinsightsconnection.jpg?raw=true) -**Step 6**: The kdb VS Code extension runs an authentication step with the remote kdb Insights Enterprise process; sign-in to kdb Insights Enterprise. +**Step 6**: The kdb VS Code extension runs an authentication step with the remote kdb Insights Enterprise process; sign-in to kdb Insights Enterprise. -![authenticateinsights](https://code.kx.com/img/vscode/insightsauthenticate.jpg) +![authenticateinsights](https://github.com/KxSystems/kx-vscode/blob/main/img/insightsauthenticate.jpg?raw=true) -After a successful connection to a kdb Insights Enterprise process, a new *DATA SOURCES* panel will become available in the kdb VS Code extension. - -![insightsdatasources](https://code.kx.com/img/vscode/datasources.jpg) +After a successful connection to a kdb Insights Enterprise process, a new _DATA SOURCES_ panel will become available in the kdb VS Code extension. +![insightsdatasources](https://github.com/KxSystems/kx-vscode/blob/main/img/datasources.jpg?raw=true) Once connected to a q process, go to [execute code](#execute-code). -[//]: # (In what context is the reserved alias name `insights` used? - BMA - the context is used on build the connection tree; different icon; different connection process. - DF - Is this connection process currently supported in kdb VS Code extension; if so, do we need to document it here?) - +[//]: # "In what context is the reserved alias name `insights` used? - BMA - the context is used on build the connection tree; different icon; different connection process. - DF - Is this connection process currently supported in kdb VS Code extension; if so, do we need to document it here?" ## kdb language server @@ -204,15 +195,13 @@ A kdb language server is bundled with the kdb VS Code extension. It offers vario - [Code navigation](#code-navigation) - [Code completion](#code-completion) - ### Syntax highlighting The extension provides keyword syntax highlighting, comments and linting help. -![Syntax Highlighting](https://code.kx.com/img/vscode/syntax-highlighting.png) - -![Linting](https://code.kx.com/img/vscode/linting.png) +![Syntax Highlighting](https://github.com/KxSystems/kx-vscode/blob/main/img/syntax-highlighting.png?raw=true) +![Linting](https://github.com/KxSystems/kx-vscode/blob/main/img/linting.png?raw=true) ### Code navigation @@ -223,22 +212,21 @@ While developing q scripts, the kdb VS Code extension supports: Navigate to the definition of a function - Find/go to all references - + View references of a function both on the side view and inline with the editor - ![Find all references](https://code.kx.com/img/vscode/find-all-references.png) + ![Find all references](https://github.com/KxSystems/kx-vscode/blob/main/img/find-all-references.png?raw=true) - ![Go to References](https://code.kx.com/img/vscode/go-to-references.png) + ![Go to References](https://github.com/KxSystems/kx-vscode/blob/main/img/go-to-references.png?raw=true) ### Code Completion -- Keyword auto complete for the q language +- Keyword auto complete for the q language - ![Autocomplete](https://code.kx.com/img/vscode/autocomplete.png) + ![Autocomplete](https://github.com/KxSystems/kx-vscode/blob/main/img/autocomplete.png?raw=true) - Autocomplete for local and remotely connected q processes - ## Execute code Leaning on VS Code's extensive integrations with SCMs, all code is typically stored and loaded into a VS Code workspace. From there, the kdb VS Code extension allows you execute code against both kdb processes, and kdb Insights Enterprise endpoints. @@ -249,16 +237,15 @@ There are three options available from the right-click menu for executing code: - Execute current selection - Takes the current selection (or current line if nothing is selected) and executes it against the connected q process. Results are displayed in the [output window and/or the kdb results window](#view-results). + Takes the current selection (or current line if nothing is selected) and executes it against the connected q process. Results are displayed in the [output window and/or the kdb results window](#view-results). - Execute entire file - Takes the current file and executes it against the connected q process. Results are displayed in the [output window](#view-results). Returned data are displayed in the [kdb results window](#view-results). + Takes the current file and executes it against the connected q process. Results are displayed in the [output window](#view-results). Returned data are displayed in the [kdb results window](#view-results). - Run q file in new q instance - If q is installed and executable from the terminal, you can execute an entire script on a newly launched q instance. Executing a file on a new instance is done in the terminal, and allows interrogation of the active q process from the terminal window. - + If q is installed and executable from the terminal, you can execute an entire script on a newly launched q instance. Executing a file on a new instance is done in the terminal, and allows interrogation of the active q process from the terminal window. ### Insights query execution @@ -273,12 +260,10 @@ kdb Insights Enterprise supports the use of data sources, where you can build a To create a data source: 1. In the Data Sources view, click the Options button and select 'Add Data Source'. - 1. Click on the created data source where the name, API and parameterization can be applied. - 1. Click Save to persist the data source to the VS Code workspace. -![data Source](https://code.kx.com/img/vscode/data-source.png) +![data Source](https://github.com/KxSystems/kx-vscode/blob/main/img/data-source.png?raw=true) To run a data source, click 'Run' and the results populate the output and kdb results windows. @@ -286,19 +271,17 @@ In addition to [API queries](https://code.kx.com/insights/api/database/query/get #### Populate scratchpad -You can use a data source to populate a scratchpad with a dataset, allowing you to build complex APIs and pipelines within VS Code and kdb Insights Enterprise. +You can use a data source to populate a scratchpad with a dataset, allowing you to build complex APIs and pipelines within VS Code and kdb Insights Enterprise. To do this: 1. Create a data source and execute it using the 'Populate Scratchpad' button. - The scratchpad is populated. - + The scratchpad is populated. 1. At the prompt, provide a variable to populate your own scratchpad instance with the data. 1. Return to VS Code and execute q code against the data in your scratchpad. -![Populate Scratchpad](https://code.kx.com/img/vscode/populate-scratchpad.png) - +![Populate Scratchpad](https://github.com/KxSystems/kx-vscode/blob/main/img/populate-scratchpad.png?raw=true) ## View results @@ -306,32 +289,35 @@ All query executions happen remotely from the kdb VS Code extension either again - An output view - The output view displays results as they are received by the kdb VS Code extension. It includes the query executed, a timestamp and the results. + The output view displays results as they are received by the kdb VS Code extension. It includes the query executed, a timestamp and the results. - ![Output view](https://code.kx.com/img/vscode/output-results.png) + ![Output view](https://github.com/KxSystems/kx-vscode/blob/main/img/output-results.png?raw=true) - **Note:** You can enable/disable auto-scrolling in the VS Code settings. This setting determines whether the output view scrolls to the latest results. + **Note:** You can enable/disable auto-scrolling in the VS Code settings. This setting determines whether the output view scrolls to the latest results. - ![Output autoscrolling](https://code.kx.com/img/vscode/auto-scrolling.png) + ![Output autoscrolling](https://github.com/KxSystems/kx-vscode/blob/main/img/auto-scrolling.png?raw=true) -- A kdb results view + **Note** You can hide or show the full details in the console output. Go to settings of the vscode, search for kdb, check the option "Hide Detailed Console Query Output" (this option is checked by default) - Results are displayed under the kdb results view, which shows the returned data in a table. + ![Hide Detailed Console Query Output](https://github.com/KxSystems/kx-vscode/blob/main/img/hide-detailed-console-query.png?raw=true) - ![kdb results view](https://code.kx.com/img/vscode/kdbview-results.png) +- A kdb results view + Results are displayed under the kdb results view, which shows the returned data in a table. + + ![kdb results view](https://github.com/KxSystems/kx-vscode/blob/main/img/kdbview-results.png?raw=true) ## Settings -To update kdb VS Code settings, search for `kdb` from _Preferences_ > _Settings_, or right-click the settings icon in kdb VS Code marketplace panel and choose _Extension Settings_. +To update kdb VS Code settings, search for `kdb` from _Preferences_ > _Settings_, or right-click the settings icon in kdb VS Code marketplace panel and choose _Extension Settings_. -Item | Action ----------------------------------------------------------- | ------- -Hide notification of installation path after first install | yes/no; default `no` -Hide subscription to newsletter after first install | yes/no; default `no` -Insights Enterprise Connections for Explorer | [edit JSON settings](#insights-enterprise-connections-for-explorer) -QHOME directory for q runtime | Display location path of q installation -Servers | [edit JSON settings](#servers) +| Item | Action | +| ---------------------------------------------------------- | ------------------------------------------------------------------- | +| Hide notification of installation path after first install | yes/no; default `no` | +| Hide subscription to newsletter after first install | yes/no; default `no` | +| Insights Enterprise Connections for Explorer | [edit JSON settings](#insights-enterprise-connections-for-explorer) | +| QHOME directory for q runtime | Display location path of q installation | +| Servers | [edit JSON settings](#servers) | ### Insights Enterprise Connections for Explorer @@ -373,7 +359,7 @@ Servers | [edit JSON settings "kdb.qHomeDirectory": "C:\\qhomedirectory", "kdb.hideInstallationNotification": true, "kdb.servers": { - + "23XdJyFk7hXb35Z3yw2vP87HOHFIfy0PDoo5+/G1o7A=": { "auth": true, "serverName": "127.0.0.1", @@ -393,15 +379,13 @@ Servers | [edit JSON settings } ``` - ## Shortcuts -| Key | Action | -| - | - | -| F12 | Go to definition | -| Shift + F12 | Go to references | -| Cmd/Ctrl + Shift + F12 | Find all references | -| Ctrl + Q | Execute current selection | -| Ctrl + Shift + Q | Execute entire file | -| Ctrl + Shift + R | Run q file in new q instance | - +| Key | Action | +| ---------------------- | ---------------------------- | +| F12 | Go to definition | +| Shift + F12 | Go to references | +| Cmd/Ctrl + Shift + F12 | Find all references | +| Ctrl + Q | Execute current selection | +| Ctrl + Shift + Q | Execute entire file | +| Ctrl + Shift + R | Run q file in new q instance | diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index e69de29b..00000000 diff --git a/SUPPORT.md b/SUPPORT.md deleted file mode 100644 index 8b137891..00000000 --- a/SUPPORT.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/img/hide-detailed-console-query.png b/img/hide-detailed-console-query.png new file mode 100644 index 00000000..92f1ae68 Binary files /dev/null and b/img/hide-detailed-console-query.png differ diff --git a/language-configuration.json b/language-configuration.json index 77fac739..f3018c7e 100644 --- a/language-configuration.json +++ b/language-configuration.json @@ -16,7 +16,22 @@ ["(", ")"], ["\"", "\""] ], + "onEnterRules": [ + { + "beforeText": "^[{[(]", + "action": { + "indent": "indent" + } + }, + { + "beforeText": "^s*[)}]]", + "action": { + "indent": "outdent" + } + } + ], "comments": { + "blockComment": ["/", "\\"], "lineComment": "/" }, "wordPattern": "(`:[a-zA-Z0-9._/]*)|(`[a-zA-Z0-9._]*)|(-?\\d*\\.\\d\\w*)|([^\\`\\~\\$\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\<\\>\\/\\?\\s]+)" diff --git a/package-lock.json b/package-lock.json index 7fc18543..deee4dbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,23 +9,17 @@ "version": "1.0.1", "license": "MIT", "dependencies": { - "@azure/arm-resources": "4.2.2", - "@azure/arm-subscriptions": "3.1.2", - "@azure/core-auth": "^1.4.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-nodeauth": "^3.1.1", - "@microsoft/vscode-azext-utils": "0.3.7", "@types/antlr4": "^4.11.2", "@types/graceful-fs": "^4.1.6", "@types/klaw": "^3.0.3", "@types/picomatch": "^2.3.0", "@vscode/webview-ui-toolkit": "^1.2.2", "@windozer/node-q": "^2.6.0", - "ag-grid-community": "^30.1.0", + "ag-grid-community": "^30.2.0", "antlr4-runtime": "^4.13.0", "antlr4ts": "^0.5.0-alpha.4", - "axios": "^1.4.0", - "azure-arm-resource": "^7.4.0", + "axios": "^1.6.0", + "chevrotain": "^10.5.0", "csv-parser": "^3.0.0", "esbuild-plugin-copy": "^2.1.1", "extract-zip": "^2.0.1", @@ -65,6 +59,7 @@ "@types/semver": "^7.5.0", "@types/sinon": "^10.0.13", "@types/vscode": "^1.66.0", + "@types/vscode-webview": "^1.57.2", "@typescript-eslint/eslint-plugin": "^5.36.2", "@typescript-eslint/parser": "^5.36.2", "@vscode/test-electron": "^2.2.3", @@ -80,9 +75,11 @@ "istanbul-lib-report": "^2.0.8", "istanbul-lib-source-maps": "^3.0.6", "istanbul-reports": "^3.1.6", + "lit": "^2.8.0", "mocha": "^10.2.0", "mocha-junit-reporter": "^2.2.0", "mocha-multi-reporters": "^1.5.1", + "mock-fs": "^5.2.0", "prettier": "^2.7.1", "rimraf": "^3.0.2", "sinon": "^15.0.1", @@ -106,121 +103,6 @@ "node": ">=0.10.0" } }, - "node_modules/@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", - "dependencies": { - "tslib": "^2.2.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@azure/abort-controller/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/@azure/arm-resources": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.2.2.tgz", - "integrity": "sha512-Oic1OcEwgex3X1KkhP9UM/E/taIaS9oID7PL/CZ8knD7qtVNSRvTxP3uvD3ZpH9NYBYXngJsX5xyRu66iFN+rA==", - "deprecated": "Please note, versions of this package with version numbers 4.2.2 and below have been deprecated as of 31-March-2022. We strongly encourage you to upgrade to version 5.0.0 or above to continue receiving updates. Refer to our deprecation policy: https://azure.github.io/azure-sdk/policies_support.html for more details.", - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-azure-js": "^2.1.0", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "node_modules/@azure/arm-subscriptions": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-3.1.2.tgz", - "integrity": "sha512-fO1Sxjn27At53Zkgs0tKW9l6iYavfbVgkK4rCFYa2d3M5yofGctHafYDTHQLnp7dYwUzGzTHrBMlyrKo92QpAQ==", - "deprecated": "Please note, versions of this package with version numbers 3.1.2 and below have been deprecated as of 31-March-2022. We strongly encourage you to upgrade to version 4.0.0 or above to continue receiving updates. Refer to our deprecation policy: https://azure.github.io/azure-sdk/policies_support.html for more details.", - "dependencies": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-azure-js": "^2.1.0", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.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.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "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.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - }, - "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==", - "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==", - "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-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==", - "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.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -235,12 +117,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.22.15", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -250,22 +132,22 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" @@ -305,21 +187,21 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz", - "integrity": "sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -328,9 +210,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -354,19 +236,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.19.tgz", - "integrity": "sha512-ZCcpVPK64krfdScRbpxF6xA5fz7IOsfMwx1tcACvCzt6JY+0aHkBk7eIU8FRDSZRU5Zei6Z4JfgAxN1bqXGECg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.16", - "@babel/types": "^7.22.19", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -384,19 +266,48 @@ } }, "node_modules/@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", + "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", + "dependencies": { + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", + "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", + "dependencies": { + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "node_modules/@chevrotain/types": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" + }, + "node_modules/@chevrotain/utils": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -413,18 +324,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", - "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -445,21 +356,21 @@ } }, "node_modules/@eslint/js": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", - "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" }, @@ -481,9 +392,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "node_modules/@jridgewell/gen-mapping": { @@ -525,66 +436,39 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@microsoft/1ds-core-js": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.12.tgz", - "integrity": "sha512-cHpxZZ+pbtOyqFMFB/c1COpaOE3VPFU6phYVHVvOA9DvoeMZfI/Xrxaj7B/vfq4MmkiE7nOAPhv5ZRn+i6OogA==", - "dependencies": { - "@microsoft/applicationinsights-core-js": "2.8.14", - "@microsoft/applicationinsights-shims": "^2.0.2", - "@microsoft/dynamicproto-js": "^1.1.7" - } - }, - "node_modules/@microsoft/1ds-post-js": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.12.tgz", - "integrity": "sha512-vhIVYg4FzBfwtM8tBqDUq3xU+cFu6SQ7biuJHtQpd5PVjDgvAovVOMRF1khsZE/k2rttRRBpmBgNEqG3Ptoysw==", - "dependencies": { - "@microsoft/1ds-core-js": "3.2.12", - "@microsoft/applicationinsights-shims": "^2.0.2", - "@microsoft/dynamicproto-js": "^1.1.7" - } + "node_modules/@lit-labs/ssr-dom-shim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz", + "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==", + "dev": true }, - "node_modules/@microsoft/applicationinsights-core-js": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.14.tgz", - "integrity": "sha512-XacWUHdjSHMUwdngMZBp0oiCBifD56CQK2Egu2PiBiF4xu2AO2yNCtWSXsQX2g5OkEhVwaEjfa/aH3WbpYxB1g==", + "node_modules/@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "dev": true, "dependencies": { - "@microsoft/applicationinsights-shims": "2.0.2", - "@microsoft/dynamicproto-js": "^1.1.9" - }, - "peerDependencies": { - "tslib": "*" + "@lit-labs/ssr-dom-shim": "^1.0.0" } }, - "node_modules/@microsoft/applicationinsights-shims": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz", - "integrity": "sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg==" - }, - "node_modules/@microsoft/dynamicproto-js": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz", - "integrity": "sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ==" - }, "node_modules/@microsoft/fast-element": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.12.0.tgz", "integrity": "sha512-gQutuDHPKNxUEcQ4pypZT4Wmrbapus+P9s3bR/SEOLsMbNqNoXigGImITygI5zhb+aA5rzflM6O8YWkmRbGkPA==" }, "node_modules/@microsoft/fast-foundation": { - "version": "2.49.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.0.tgz", - "integrity": "sha512-Wk4e4QXFVtT5hPwhMfHyGY30kixM0td8aDs7bAD6NM2z2SCBNvpTTWp+FCjx0I0lpUMlMenb6wsw7pMWQreRkQ==", + "version": "2.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.2.tgz", + "integrity": "sha512-xA7WP/Td33SW0zkpHRH5LUDxyLOPnPQQXieRxc080uLWxoGXhVxo6Rz7b6qwiL+e2IadNCm7X7KcrgsUhJwvBg==", "dependencies": { "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-web-utilities": "^5.4.1", @@ -612,48 +496,6 @@ "exenv-es6": "^1.1.1" } }, - "node_modules/@microsoft/vscode-azext-utils": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.3.7.tgz", - "integrity": "sha512-TCIo1rVPYso5r9UrDfZK2j9FvvruW4BOTjtgK9g8F6gRB3FvpBd8AlQhXcffe8NmKNPJhbmdRSwhk51EujK2FA==", - "dependencies": { - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "open": "^8.0.4", - "semver": "^7.3.7", - "vscode-nls": "^5.0.1", - "vscode-tas-client": "^0.1.47" - } - }, - "node_modules/@microsoft/vscode-azext-utils/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/@microsoft/vscode-azext-utils/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/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -686,18 +528,6 @@ "node": ">= 8" } }, - "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/@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -752,20 +582,20 @@ } }, "node_modules/@types/antlr4": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@types/antlr4/-/antlr4-4.11.2.tgz", - "integrity": "sha512-WVDiUppozGAKAL76KbXX63A4U4a0HfHM/5X7+GWzen7OaS/7eJEMdd61B+Hhl52Kedcmr80/jNeeWrM3Z/icig==" + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@types/antlr4/-/antlr4-4.11.5.tgz", + "integrity": "sha512-fMe+kM+6ccLkUbCYQ7tNHlWNX4dVmTdRykib5S8sdWGHBxFFKN9/srtpXpILBY08RJYld5bOe3+tB2Qz6WmHZw==" }, "node_modules/@types/bluebird": { - "version": "3.5.38", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.38.tgz", - "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.41.tgz", + "integrity": "sha512-/OT2UoYPu2fqGNS85UYUx0Ke8Zd/vM0/Au0JqLInTprkRO0NexYe7qAUkDsjhsO3BKHI14wX/UhN5SUaoFVDUQ==", "dev": true }, "node_modules/@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.4.tgz", + "integrity": "sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==", "dev": true }, "node_modules/@types/extract-zip": { @@ -798,42 +628,42 @@ } }, "node_modules/@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" } }, "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", "dev": true, "dependencies": { "@types/istanbul-lib-report": "*" } }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "node_modules/@types/jwt-decode": { @@ -847,9 +677,9 @@ } }, "node_modules/@types/klaw": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/klaw/-/klaw-3.0.3.tgz", - "integrity": "sha512-mXlRDFbTLpVysvxahXUQav0hFctgu3Fqr2xmSrpf/ptO/FwOp7SFEGsJkEihwshMbof3/BIiVJ/o42cuOOuv6g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/klaw/-/klaw-3.0.5.tgz", + "integrity": "sha512-sX8M64GwQbEhPA4GrOUYEl/0Cc9oz5Effoaj43B4o3bsVwskxEipparp8tI1E6lhs2s1R1u/0KeNvf/9OR1cAA==", "dev": true, "dependencies": { "@types/node": "*" @@ -862,31 +692,34 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.3.tgz", + "integrity": "sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==", "dev": true }, "node_modules/@types/node": { - "version": "18.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.4.tgz", - "integrity": "sha512-ATL4WLgr7/W40+Sp1WnNTSKbgVn6Pvhc/2RHAdt8fl6NsQyp4oPCi2eKcGOvA494bwf1K/W6nGgZ9TwDqvpjdw==", - "devOptional": true + "version": "18.18.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.7.tgz", + "integrity": "sha512-bw+lEsxis6eqJYW8Ql6+yTqkE6RuFtsQPSe5JxXbqYRFQEER5aJA9a5UH9igqDWm3X4iLHIKOHlnAXLM4mi7uQ==", + "devOptional": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==", "dev": true, "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.0" } }, "node_modules/@types/node-fetch/node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "dependencies": { "asynckit": "^0.4.0", @@ -898,15 +731,15 @@ } }, "node_modules/@types/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-I+BytjxOlNYA285zP/3dVCRcE+OAvgHQZQt26MP7T7JbZ9DM/3W2WfViU1XuLypCzAx8PTC+MlYO3WLqjTyZ3g==", "dev": true }, "node_modules/@types/request": { - "version": "2.48.8", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz", - "integrity": "sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ==", + "version": "2.48.11", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.11.tgz", + "integrity": "sha512-HuihY1+Vss5RS9ZHzRyTGIzwPTdrJBkCm/mAeLRYrOQu/MGqyezKXWOK1VhCnR+SDbp9G2mRUP+OVEqCrzpcfA==", "dev": true, "dependencies": { "@types/caseless": "*", @@ -916,9 +749,9 @@ } }, "node_modules/@types/request-promise": { - "version": "4.1.48", - "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.48.tgz", - "integrity": "sha512-sLsfxfwP5G3E3U64QXxKwA6ctsxZ7uKyl4I28pMj3JvV+ztWECRns73GL71KMOOJME5u1A5Vs5dkBqyiR1Zcnw==", + "version": "4.1.50", + "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.50.tgz", + "integrity": "sha512-pW52uoS7pTwKz+vHCnG9R0QbwVR9HkqyppEabcQxeBM6QjdCvTcW9ABJWznLetPyYOmbrtRPCzf/5itf/a2Rug==", "dev": true, "dependencies": { "@types/bluebird": "*", @@ -926,42 +759,54 @@ } }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.16", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", - "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", + "version": "10.0.20", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", + "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" } }, "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.4.tgz", + "integrity": "sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==", "dev": true }, "node_modules/@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.4.tgz", + "integrity": "sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==", + "dev": true + }, + "node_modules/@types/trusted-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.5.tgz", + "integrity": "sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==", "dev": true }, "node_modules/@types/vscode": { - "version": "1.81.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.81.0.tgz", - "integrity": "sha512-YIaCwpT+O2E7WOMq0eCgBEABE++SX3Yl/O02GoMIF2DO3qAtvw7m6BXFYsxnc6XyzwZgh6/s/UG78LSSombl2w==", + "version": "1.83.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", + "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", + "dev": true + }, + "node_modules/@types/vscode-webview": { + "version": "1.57.3", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.3.tgz", + "integrity": "sha512-8at2UVGjA/6gcLOay+J8wOars6VsDqAqPxRHYihH0XFUaXt+2AZ+Hd9hSoUbnhjicb6V1xe7rfjb7j4Ri2n1fg==", "dev": true }, "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.2.tgz", + "integrity": "sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==", "optional": true, "dependencies": { "@types/node": "*" @@ -1155,22 +1000,16 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "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/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true }, "node_modules/@vscode/test-electron": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.4.tgz", - "integrity": "sha512-eWzIqXMhvlcoXfEFNWrVu/yYT5w6De+WZXR/bafUQhAp8+8GkQo95Oe14phwiRUPv8L+geAKl/QM2+PoT3YW3g==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.6.tgz", + "integrity": "sha512-M31xGH0RgqNU6CZ4/9g39oUMJ99nLzfjA+4UbtIQ6TcXQ6+2qkjOOxedmPBDDCg26/3Al5ubjY80hIoaMwKYSw==", "dev": true, "dependencies": { "http-proxy-agent": "^4.0.1", @@ -1208,29 +1047,10 @@ "node": ">=0.10" } }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", - "engines": { - "node": ">=10.0.0" - } - }, - "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==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -1248,45 +1068,10 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/adal-node": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.4.tgz", - "integrity": "sha512-zIcvbwQFKMUtKxxj8YMHeTT1o/TPXfVNsTXVgXD8sxwV6h4AFQgK77dRciGhuEF9/Sdm3UQPJVPc/6XxrccSeA==", - "dependencies": { - "@xmldom/xmldom": "^0.8.3", - "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/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/adal-node/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.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/ag-grid-community": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-30.1.0.tgz", - "integrity": "sha512-D69e63CUALxfgLZSu1rXC8Xiyhu6+17zxzTV8cWsyvt5GeSDv2frQ3BKOqGZbUfVoOCLv2SQoHVTTqw8OjxavA==" + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-30.2.0.tgz", + "integrity": "sha512-Gd6GXmtzEQSCDloBdRxxCDqnjTBRAOf/zzlaxxyyVBJgc+cePuNgGdplRUhT/rwIiDwvyuoynvxelVE/iYdXsA==" }, "node_modules/agent-base": { "version": "6.0.2", @@ -1346,9 +1131,9 @@ } }, "node_modules/antlr4": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.0.tgz", - "integrity": "sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", "dev": true, "engines": { "node": ">=16" @@ -1424,6 +1209,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "peer": true, "dependencies": { "safer-buffer": "~2.1.0" } @@ -1432,18 +1218,11 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "peer": true, "engines": { "node": ">=0.8" } }, - "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dependencies": { - "lodash": "^4.17.14" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -1453,6 +1232,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "peer": true, "engines": { "node": "*" } @@ -1460,12 +1240,13 @@ "node_modules/aws4": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "peer": true }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -1485,16 +1266,6 @@ "node": ">= 6" } }, - "node_modules/azure-arm-resource": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/azure-arm-resource/-/azure-arm-resource-7.4.0.tgz", - "integrity": "sha512-GT332g4i90W/PjsKxCMHYnexP6qwWOeWT0iucqLFQYV4C4PnNL8P5SFBuwo2qgbexcqtTSbyZg/YJJ5QLfYxDA==", - "deprecated": "This package is deprecated in favor of @azure/arm-resources which works both on node.js and browsers", - "dependencies": { - "ms-rest": "^2.3.3", - "ms-rest-azure": "^2.5.5" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1505,6 +1276,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "peer": true, "dependencies": { "tweetnacl": "^0.14.3" } @@ -1605,11 +1377,6 @@ "node": "*" } }, - "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": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "node_modules/buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -1657,7 +1424,8 @@ "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "peer": true }, "node_modules/chainsaw": { "version": "0.1.0", @@ -1712,6 +1480,19 @@ "node": ">=0.4.0" } }, + "node_modules/chevrotain": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", + "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", + "dependencies": { + "@chevrotain/cst-dts-gen": "10.5.0", + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "@chevrotain/utils": "10.5.0", + "lodash": "4.17.21", + "regexp-to-ast": "0.5.0" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -1784,7 +1565,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==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "node_modules/concat-map": { "version": "0.0.1", @@ -1839,6 +1621,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "peer": true, "dependencies": { "assert-plus": "^1.0.0" }, @@ -1846,19 +1629,6 @@ "node": ">=0.10" } }, - "node_modules/date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha512-wJMBjqlwXR0Iv0wUo/lFbhSQ7MmG1hl36iuxuE91kW+5b5sWbase73manEqNH9sOLFAMG83B4ffNKq9/Iq0FVA==", - "engines": { - "node": ">0.4.0" - } - }, - "node_modules/dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1893,22 +1663,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "engines": { - "node": ">=0.10.0" - } - }, - "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/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1943,11 +1697,6 @@ "integrity": "sha512-+CEod3IzwjvhQOMXFSU6nrqdTwrhzOiacNzzXlwBVFm7C4y2rbuEWs5WaRsI/3IZeSWORA5F1q8FBh3gm4HSsw==", "dev": true }, - "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", @@ -1960,62 +1709,6 @@ "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/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, "node_modules/duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -2029,19 +1722,12 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "peer": true, "dependencies": { "jsbn": "~0.1.0", "safer-buffer": "^2.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==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/ejs": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", @@ -2066,14 +1752,6 @@ "once": "^1.4.0" } }, - "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/esbuild": { "version": "0.15.18", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", @@ -2212,27 +1890,20 @@ "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": "8.46.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", - "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.1", - "@eslint/js": "^8.46.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -2240,7 +1911,7 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.2", + "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", @@ -2306,9 +1977,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2513,14 +2184,6 @@ "node": ">=0.10.0" } }, - "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==", - "engines": { - "node": ">=6" - } - }, "node_modules/exenv-es6": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", @@ -2529,7 +2192,8 @@ "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "peer": true }, "node_modules/extract-zip": { "version": "2.0.1", @@ -2556,7 +2220,8 @@ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" - ] + ], + "peer": true }, "node_modules/fast-deep-equal": { "version": "3.1.3", @@ -2660,28 +2325,29 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==", "funding": [ { "type": "individual", @@ -2701,6 +2367,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "peer": true, "engines": { "node": "*" } @@ -2709,6 +2376,7 @@ "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", @@ -2744,9 +2412,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "hasInstallScript": true, "optional": true, "os": [ @@ -2850,6 +2518,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "peer": true, "dependencies": { "assert-plus": "^1.0.0" } @@ -2906,9 +2575,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2954,6 +2623,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "peer": true, "engines": { "node": ">=4" } @@ -2963,6 +2633,7 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "deprecated": "this library is no longer supported", + "peer": true, "dependencies": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -2984,6 +2655,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, "bin": { "he": "bin/he" } @@ -2994,43 +2666,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/html-to-text": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", - "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", - "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", @@ -3045,19 +2680,6 @@ "node": ">= 6" } }, - "node_modules/http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -3140,21 +2762,8 @@ "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==" - }, - "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" - } + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "node_modules/is-extglob": { "version": "2.1.1", @@ -3210,18 +2819,11 @@ "node": ">=8" } }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "peer": true }, "node_modules/is-unicode-supported": { "version": "0.1.0", @@ -3258,7 +2860,8 @@ "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "peer": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", @@ -3480,7 +3083,8 @@ "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "peer": true }, "node_modules/jsesc": { "version": "2.5.2", @@ -3494,10 +3098,17 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "peer": true }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3513,7 +3124,8 @@ "node_modules/json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "peer": true }, "node_modules/jsonfile": { "version": "6.1.0", @@ -3526,20 +3138,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -3558,30 +3156,20 @@ "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "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==", - "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==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/klaw": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", @@ -3627,6 +3215,37 @@ "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", "dev": true }, + "node_modules/lit": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", + "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==", + "dev": true, + "dependencies": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.3.0", + "lit-html": "^2.8.0" + } + }, + "node_modules/lit-element": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz", + "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==", + "dev": true, + "dependencies": { + "@lit-labs/ssr-dom-shim": "^1.1.0", + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.8.0" + } + }, + "node_modules/lit-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", + "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", + "dev": true, + "dependencies": { + "@types/trusted-types": "^2.0.2" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4059,6 +3678,15 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mock-fs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.2.0.tgz", + "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -4083,86 +3711,11 @@ "node": "*" } }, - "node_modules/moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" - }, "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/ms-rest": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/ms-rest/-/ms-rest-2.5.6.tgz", - "integrity": "sha512-3Scy/pF43wqPEPeJxhOsLs16m6Rt+9zqf+jKdg+guuonytKmFSxerQM2exlQIDTqFVTsLXrPEGFWTGSwivRRkA==", - "dependencies": { - "ajv": "6.12.3", - "duplexer": "^0.1.1", - "http-signature": "1.3.6", - "is-buffer": "^1.1.6", - "is-stream": "^1.1.0", - "moment": "^2.21.0", - "request": "^2.88.2", - "through": "^2.3.8", - "tunnel": "0.0.5", - "uuid": "^3.2.1" - } - }, - "node_modules/ms-rest-azure": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/ms-rest-azure/-/ms-rest-azure-2.6.2.tgz", - "integrity": "sha512-h74ezkiMQ1y8tD0kf0MK2kdCONAP70i032Dt8kBrFsvj3ZqGRj+DHHNRCGLDfkBkSXhILGMeiF8Ji/iSCUJLJg==", - "dependencies": { - "adal-node": "^0.2.2", - "async": "^2.6.4", - "ms-rest": "^2.3.2", - "request": "^2.88.0", - "uuid": "^3.2.1" - } - }, - "node_modules/ms-rest-azure/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.", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/ms-rest/node_modules/ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", - "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/ms-rest/node_modules/tunnel": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz", - "integrity": "sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/ms-rest/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.", - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -4187,31 +3740,10 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "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/nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", + "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", "dev": true, "dependencies": { "@sinonjs/commons": "^2.0.0", @@ -4243,9 +3775,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -4262,9 +3794,9 @@ } }, "node_modules/node-q": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-q/-/node-q-2.6.1.tgz", - "integrity": "sha512-OH8mx8R9jSjkMNkMUWrwUFiR/QEmfnqSYp61VxfTmSicvfz5UqufuY3Sh0l6o6hN10xeLKViWWngUs9QNYfstA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-q/-/node-q-2.7.0.tgz", + "integrity": "sha512-rLvqnarAtNHdeyS7RRQmg4yjd6qxtfZcTL9jsQQZ2UBCMPz3/k/WtJPXieb4Xe4EjgjBO8txuJz+Rot9iUwOzg==", "dependencies": { "buffer-indexof-polyfill": "1.0.1", "long": "3.0.3", @@ -4295,6 +3827,7 @@ "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "peer": true, "engines": { "node": "*" } @@ -4383,18 +3916,6 @@ "node": ">=6" } }, - "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/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4453,7 +3974,8 @@ "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "peer": true }, "node_modules/picomatch": { "version": "2.3.1", @@ -4549,6 +4071,7 @@ "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "peer": true, "engines": { "node": ">=0.6" } @@ -4572,23 +4095,6 @@ } ] }, - "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", @@ -4642,11 +4148,17 @@ "node": ">=8.10.0" } }, + "node_modules/regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "peer": true, "dependencies": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -4709,6 +4221,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -4722,6 +4235,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -4736,6 +4250,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "peer": true, "dependencies": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -4751,6 +4266,7 @@ "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.", + "peer": true, "bin": { "uuid": "bin/uuid" } @@ -4782,14 +4298,6 @@ "node": ">=4" } }, - "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", @@ -4878,23 +4386,8 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "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" - } + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "peer": true }, "node_modules/semver": { "version": "7.5.4", @@ -4950,6 +4443,7 @@ "version": "15.2.0", "resolved": "https://registry.npmjs.org/sinon/-/sinon-15.2.0.tgz", "integrity": "sha512-nPS85arNqwBXaIsFCkolHjGIkFo+Oxu9vbgmBJizLAhqe6P2o3Qmj3KCUoRkfhHtvgDhZdWD3risLHAUJ8npjw==", + "deprecated": "16.1.1", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0", @@ -5018,9 +4512,10 @@ } }, "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "peer": true, "dependencies": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -5180,33 +4675,12 @@ "tar-fs": "^1.8.1" } }, - "node_modules/tas-client": { - "version": "0.1.58", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.58.tgz", - "integrity": "sha512-fOWii4wQXuo9Zl0oXgvjBzZWzKc5MmUR6XQWX93WU2c1SaP1plPo/zvXP8kpbZ9fvegFOHdapszYqMTRq/SRtg==", - "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/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, "node_modules/to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -5279,18 +4753,11 @@ "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==", - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, "node_modules/tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "peer": true, "dependencies": { "safe-buffer": "^5.0.1" }, @@ -5301,7 +4768,8 @@ "node_modules/tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "peer": true }, "node_modules/type-check": { "version": "0.4.0", @@ -5349,10 +4817,11 @@ "node": ">=4.2.0" } }, - "node_modules/underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true }, "node_modules/universalify": { "version": "2.0.0", @@ -5400,14 +4869,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "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/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -5415,6 +4876,7 @@ "engines": [ "node >=0.6.0" ], + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -5424,7 +4886,8 @@ "node_modules/verror/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": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "peer": true }, "node_modules/vscode-dts": { "version": "0.3.3", @@ -5517,9 +4980,9 @@ } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", - "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", "dev": true }, "node_modules/vscode-languageserver-types": { @@ -5528,22 +4991,6 @@ "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==", "dev": true }, - "node_modules/vscode-nls": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==" - }, - "node_modules/vscode-tas-client": { - "version": "0.1.63", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.63.tgz", - "integrity": "sha512-TY5TPyibzi6rNmuUB7eRVqpzLzNfQYrrIl/0/F8ukrrbzOrKVvS31hM3urE+tbaVrnT+TMYXL16GhX57vEowhA==", - "dependencies": { - "tas-client": "0.1.58" - }, - "engines": { - "vscode": "^1.19.1" - } - }, "node_modules/vscode-test": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", @@ -5561,9 +5008,9 @@ } }, "node_modules/vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" }, "node_modules/webidl-conversions": { "version": "3.0.1", @@ -5661,34 +5108,6 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "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==", - "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==", - "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==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -5783,116 +5202,6 @@ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, - "@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", - "requires": { - "tslib": "^2.2.0" - }, - "dependencies": { - "tslib": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "@azure/arm-resources": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@azure/arm-resources/-/arm-resources-4.2.2.tgz", - "integrity": "sha512-Oic1OcEwgex3X1KkhP9UM/E/taIaS9oID7PL/CZ8knD7qtVNSRvTxP3uvD3ZpH9NYBYXngJsX5xyRu66iFN+rA==", - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-azure-js": "^2.1.0", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@azure/arm-subscriptions": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@azure/arm-subscriptions/-/arm-subscriptions-3.1.2.tgz", - "integrity": "sha512-fO1Sxjn27At53Zkgs0tKW9l6iYavfbVgkK4rCFYa2d3M5yofGctHafYDTHQLnp7dYwUzGzTHrBMlyrKo92QpAQ==", - "requires": { - "@azure/core-auth": "^1.1.4", - "@azure/ms-rest-azure-js": "^2.1.0", - "@azure/ms-rest-js": "^2.2.0", - "tslib": "^1.10.0" - } - }, - "@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.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "@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.6.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.1.tgz", - "integrity": "sha512-t0hLfiEKfMUoqhG+U1oid7Pva4bbDPHYfJNiB7BiIjRkj1pyC++4N3huJfqY6aRH6VTB0rvtzQwjM4K6qpfOig==" - } - } - }, - "@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==", - "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==", - "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" - } - }, - "@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==", - "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.22.13", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", @@ -5904,31 +5213,31 @@ } }, "@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "requires": { - "@babel/types": "^7.22.15", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, "@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { @@ -5956,26 +5265,26 @@ "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz", - "integrity": "sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true }, "@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" } }, "@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/template": { @@ -5990,19 +5299,19 @@ } }, "@babel/traverse": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.19.tgz", - "integrity": "sha512-ZCcpVPK64krfdScRbpxF6xA5fz7IOsfMwx1tcACvCzt6JY+0aHkBk7eIU8FRDSZRU5Zei6Z4JfgAxN1bqXGECg==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, "requires": { "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.22.16", - "@babel/types": "^7.22.19", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -6016,16 +5325,45 @@ } }, "@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, + "@chevrotain/cst-dts-gen": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", + "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", + "requires": { + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "@chevrotain/gast": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", + "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", + "requires": { + "@chevrotain/types": "10.5.0", + "lodash": "4.17.21" + } + }, + "@chevrotain/types": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" + }, + "@chevrotain/utils": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" + }, "@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -6036,15 +5374,15 @@ } }, "@eslint-community/regexpp": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", - "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true }, "@eslint/eslintrc": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.1.tgz", - "integrity": "sha512-9t7ZA7NGGK8ckelF0PQCfcxIUzs1Md5rrO6U/c+FIQNanea5UZC0wqKXH4vHBccmu4ZJgZ2idtPeW7+Q2npOEA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -6059,18 +5397,18 @@ } }, "@eslint/js": { - "version": "8.46.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.46.0.tgz", - "integrity": "sha512-a8TLtmPi8xzPkCbp/OGFUo5yhRkHM2Ko9kOWP4znJr0WAhWyThaw3PnwX4vOTWOAMsV2uRt32PPDcEz63esSaA==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", "dev": true }, "@humanwhocodes/config-array": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", - "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^1.2.1", + "@humanwhocodes/object-schema": "^2.0.1", "debug": "^4.1.1", "minimatch": "^3.0.5" } @@ -6082,9 +5420,9 @@ "dev": true }, "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", "dev": true }, "@jridgewell/gen-mapping": { @@ -6117,63 +5455,39 @@ "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", + "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "@microsoft/1ds-core-js": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.12.tgz", - "integrity": "sha512-cHpxZZ+pbtOyqFMFB/c1COpaOE3VPFU6phYVHVvOA9DvoeMZfI/Xrxaj7B/vfq4MmkiE7nOAPhv5ZRn+i6OogA==", - "requires": { - "@microsoft/applicationinsights-core-js": "2.8.14", - "@microsoft/applicationinsights-shims": "^2.0.2", - "@microsoft/dynamicproto-js": "^1.1.7" - } - }, - "@microsoft/1ds-post-js": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.12.tgz", - "integrity": "sha512-vhIVYg4FzBfwtM8tBqDUq3xU+cFu6SQ7biuJHtQpd5PVjDgvAovVOMRF1khsZE/k2rttRRBpmBgNEqG3Ptoysw==", - "requires": { - "@microsoft/1ds-core-js": "3.2.12", - "@microsoft/applicationinsights-shims": "^2.0.2", - "@microsoft/dynamicproto-js": "^1.1.7" - } + "@lit-labs/ssr-dom-shim": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.1.2.tgz", + "integrity": "sha512-jnOD+/+dSrfTWYfSXBXlo5l5f0q1UuJo3tkbMDCYA2lKUYq79jaxqtGEvnRoh049nt1vdo1+45RinipU6FGY2g==", + "dev": true }, - "@microsoft/applicationinsights-core-js": { - "version": "2.8.14", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.14.tgz", - "integrity": "sha512-XacWUHdjSHMUwdngMZBp0oiCBifD56CQK2Egu2PiBiF4xu2AO2yNCtWSXsQX2g5OkEhVwaEjfa/aH3WbpYxB1g==", + "@lit/reactive-element": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz", + "integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==", + "dev": true, "requires": { - "@microsoft/applicationinsights-shims": "2.0.2", - "@microsoft/dynamicproto-js": "^1.1.9" + "@lit-labs/ssr-dom-shim": "^1.0.0" } }, - "@microsoft/applicationinsights-shims": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz", - "integrity": "sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg==" - }, - "@microsoft/dynamicproto-js": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.9.tgz", - "integrity": "sha512-n1VPsljTSkthsAFYdiWfC+DKzK2WwcRp83Y1YAqdX552BstvsDjft9YXppjUzp11BPsapDoO1LDgrDB0XVsfNQ==" - }, "@microsoft/fast-element": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/@microsoft/fast-element/-/fast-element-1.12.0.tgz", "integrity": "sha512-gQutuDHPKNxUEcQ4pypZT4Wmrbapus+P9s3bR/SEOLsMbNqNoXigGImITygI5zhb+aA5rzflM6O8YWkmRbGkPA==" }, "@microsoft/fast-foundation": { - "version": "2.49.0", - "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.0.tgz", - "integrity": "sha512-Wk4e4QXFVtT5hPwhMfHyGY30kixM0td8aDs7bAD6NM2z2SCBNvpTTWp+FCjx0I0lpUMlMenb6wsw7pMWQreRkQ==", + "version": "2.49.2", + "resolved": "https://registry.npmjs.org/@microsoft/fast-foundation/-/fast-foundation-2.49.2.tgz", + "integrity": "sha512-xA7WP/Td33SW0zkpHRH5LUDxyLOPnPQQXieRxc080uLWxoGXhVxo6Rz7b6qwiL+e2IadNCm7X7KcrgsUhJwvBg==", "requires": { "@microsoft/fast-element": "^1.12.0", "@microsoft/fast-web-utilities": "^5.4.1", @@ -6198,41 +5512,6 @@ "exenv-es6": "^1.1.1" } }, - "@microsoft/vscode-azext-utils": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/@microsoft/vscode-azext-utils/-/vscode-azext-utils-0.3.7.tgz", - "integrity": "sha512-TCIo1rVPYso5r9UrDfZK2j9FvvruW4BOTjtgK9g8F6gRB3FvpBd8AlQhXcffe8NmKNPJhbmdRSwhk51EujK2FA==", - "requires": { - "@vscode/extension-telemetry": "^0.6.2", - "dayjs": "^1.11.2", - "escape-string-regexp": "^2.0.0", - "html-to-text": "^8.2.0", - "open": "^8.0.4", - "semver": "^7.3.7", - "vscode-nls": "^5.0.1", - "vscode-tas-client": "^0.1.47" - }, - "dependencies": { - "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" - } - }, - "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" - } - } - } - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -6256,15 +5535,6 @@ "fastq": "^1.6.0" } }, - "@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" - } - }, "@sinonjs/commons": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", @@ -6318,20 +5588,20 @@ "dev": true }, "@types/antlr4": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@types/antlr4/-/antlr4-4.11.2.tgz", - "integrity": "sha512-WVDiUppozGAKAL76KbXX63A4U4a0HfHM/5X7+GWzen7OaS/7eJEMdd61B+Hhl52Kedcmr80/jNeeWrM3Z/icig==" + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/@types/antlr4/-/antlr4-4.11.5.tgz", + "integrity": "sha512-fMe+kM+6ccLkUbCYQ7tNHlWNX4dVmTdRykib5S8sdWGHBxFFKN9/srtpXpILBY08RJYld5bOe3+tB2Qz6WmHZw==" }, "@types/bluebird": { - "version": "3.5.38", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.38.tgz", - "integrity": "sha512-yR/Kxc0dd4FfwtEoLZMoqJbM/VE/W7hXn/MIjb+axcwag0iFmSPK7OBUZq1YWLynJUoWQkfUrI7T0HDqGApNSg==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.41.tgz", + "integrity": "sha512-/OT2UoYPu2fqGNS85UYUx0Ke8Zd/vM0/Au0JqLInTprkRO0NexYe7qAUkDsjhsO3BKHI14wX/UhN5SUaoFVDUQ==", "dev": true }, "@types/caseless": { - "version": "0.12.2", - "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", - "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==", + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.4.tgz", + "integrity": "sha512-2in/lrHRNmDvHPgyormtEralhPcN3An1gLjJzj2Bw145VBxkQ75JEXW6CTdMAwShiHQcYsl2d10IjQSdJSJz4g==", "dev": true }, "@types/extract-zip": { @@ -6363,42 +5633,42 @@ } }, "@types/graceful-fs": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", - "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.8.tgz", + "integrity": "sha512-NhRH7YzWq8WiNKVavKPBmtLYZHxNY19Hh+az28O/phfp68CF45pMFud+ZzJ8ewnxnC5smIdF3dqFeiSUQ5I+pw==", "dev": true, "requires": { "@types/node": "*" } }, "@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-zONci81DZYCZjiLe0r6equvZut0b+dBRPBN5kBDjsONnutYNtJMoWQ9uR2RkL1gLG9NMTzvf+29e5RFfPbeKhQ==", "dev": true }, "@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.2.tgz", + "integrity": "sha512-8toY6FgdltSdONav1XtUHl4LN1yTmLza+EuDazb/fEmRNCwjyqNVIQWs2IfC74IqjHkREs/nQ2FWq5kZU9IC0w==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*" } }, "@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.3.tgz", + "integrity": "sha512-1nESsePMBlf0RPRffLZi5ujYh7IH1BWL4y9pr+Bn3cJBdxz+RTP8bUFljLz9HvzhhOSWKdyBZ4DIivdL6rvgZg==", "dev": true, "requires": { "@types/istanbul-lib-report": "*" } }, "@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", "dev": true }, "@types/jwt-decode": { @@ -6411,9 +5681,9 @@ } }, "@types/klaw": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/klaw/-/klaw-3.0.3.tgz", - "integrity": "sha512-mXlRDFbTLpVysvxahXUQav0hFctgu3Fqr2xmSrpf/ptO/FwOp7SFEGsJkEihwshMbof3/BIiVJ/o42cuOOuv6g==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/klaw/-/klaw-3.0.5.tgz", + "integrity": "sha512-sX8M64GwQbEhPA4GrOUYEl/0Cc9oz5Effoaj43B4o3bsVwskxEipparp8tI1E6lhs2s1R1u/0KeNvf/9OR1cAA==", "dev": true, "requires": { "@types/node": "*" @@ -6426,31 +5696,34 @@ "dev": true }, "@types/mocha": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.1.tgz", - "integrity": "sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q==", + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.3.tgz", + "integrity": "sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==", "dev": true }, "@types/node": { - "version": "18.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.4.tgz", - "integrity": "sha512-ATL4WLgr7/W40+Sp1WnNTSKbgVn6Pvhc/2RHAdt8fl6NsQyp4oPCi2eKcGOvA494bwf1K/W6nGgZ9TwDqvpjdw==", - "devOptional": true + "version": "18.18.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.18.7.tgz", + "integrity": "sha512-bw+lEsxis6eqJYW8Ql6+yTqkE6RuFtsQPSe5JxXbqYRFQEER5aJA9a5UH9igqDWm3X4iLHIKOHlnAXLM4mi7uQ==", + "devOptional": true, + "requires": { + "undici-types": "~5.26.4" + } }, "@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-lX17GZVpJ/fuCjguZ5b3TjEbSENxmEk1B2z02yoXSK9WMEWRivhdSY73wWMn6bpcCDAOh6qAdktpKHIlkDk2lg==", "dev": true, "requires": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.0" }, "dependencies": { "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, "requires": { "asynckit": "^0.4.0", @@ -6461,15 +5734,15 @@ } }, "@types/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-I+BytjxOlNYA285zP/3dVCRcE+OAvgHQZQt26MP7T7JbZ9DM/3W2WfViU1XuLypCzAx8PTC+MlYO3WLqjTyZ3g==", "dev": true }, "@types/request": { - "version": "2.48.8", - "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.8.tgz", - "integrity": "sha512-whjk1EDJPcAR2kYHRbFl/lKeeKYTi05A15K9bnLInCVroNDCtXce57xKdI0/rQaA3K+6q0eFyUBPmqfSndUZdQ==", + "version": "2.48.11", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.11.tgz", + "integrity": "sha512-HuihY1+Vss5RS9ZHzRyTGIzwPTdrJBkCm/mAeLRYrOQu/MGqyezKXWOK1VhCnR+SDbp9G2mRUP+OVEqCrzpcfA==", "dev": true, "requires": { "@types/caseless": "*", @@ -6479,9 +5752,9 @@ } }, "@types/request-promise": { - "version": "4.1.48", - "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.48.tgz", - "integrity": "sha512-sLsfxfwP5G3E3U64QXxKwA6ctsxZ7uKyl4I28pMj3JvV+ztWECRns73GL71KMOOJME5u1A5Vs5dkBqyiR1Zcnw==", + "version": "4.1.50", + "resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.50.tgz", + "integrity": "sha512-pW52uoS7pTwKz+vHCnG9R0QbwVR9HkqyppEabcQxeBM6QjdCvTcW9ABJWznLetPyYOmbrtRPCzf/5itf/a2Rug==", "dev": true, "requires": { "@types/bluebird": "*", @@ -6489,42 +5762,54 @@ } }, "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", "dev": true }, "@types/sinon": { - "version": "10.0.16", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", - "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", + "version": "10.0.20", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.20.tgz", + "integrity": "sha512-2APKKruFNCAZgx3daAyACGzWuJ028VVCUDk6o2rw/Z4PXT0ogwdV4KUegW0MwVs0Zu59auPXbbuBJHF12Sx1Eg==", "dev": true, "requires": { "@types/sinonjs__fake-timers": "*" } }, "@types/sinonjs__fake-timers": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz", - "integrity": "sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA==", + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.4.tgz", + "integrity": "sha512-GDV68H0mBSN449sa5HEj51E0wfpVQb8xNSMzxf/PrypMFcLTMwJMOM/cgXiv71Mq5drkOQmUGvL1okOZcu6RrQ==", "dev": true }, "@types/tough-cookie": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.2.tgz", - "integrity": "sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.4.tgz", + "integrity": "sha512-95Sfz4nvMAb0Nl9DTxN3j64adfwfbBPEYq14VN7zT5J5O2M9V6iZMIIQU1U+pJyl9agHYHNCqhCXgyEtIRRa5A==", + "dev": true + }, + "@types/trusted-types": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.5.tgz", + "integrity": "sha512-I3pkr8j/6tmQtKV/ZzHtuaqYSQvyjGRKH4go60Rr0IDLlFxuRT5V32uvB1mecM5G1EVAUyF/4r4QZ1GHgz+mxA==", "dev": true }, "@types/vscode": { - "version": "1.81.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.81.0.tgz", - "integrity": "sha512-YIaCwpT+O2E7WOMq0eCgBEABE++SX3Yl/O02GoMIF2DO3qAtvw7m6BXFYsxnc6XyzwZgh6/s/UG78LSSombl2w==", + "version": "1.83.1", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.83.1.tgz", + "integrity": "sha512-BHu51NaNKOtDf3BOonY3sKFFmZKEpRkzqkZVpSYxowLbs5JqjOQemYFob7Gs5rpxE5tiGhfpnMpcdF/oKrLg4w==", + "dev": true + }, + "@types/vscode-webview": { + "version": "1.57.3", + "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.3.tgz", + "integrity": "sha512-8at2UVGjA/6gcLOay+J8wOars6VsDqAqPxRHYihH0XFUaXt+2AZ+Hd9hSoUbnhjicb6V1xe7rfjb7j4Ri2n1fg==", "dev": true }, "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.2.tgz", + "integrity": "sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==", "optional": true, "requires": { "@types/node": "*" @@ -6629,19 +5914,16 @@ "eslint-visitor-keys": "^3.3.0" } }, - "@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" - } + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true }, "@vscode/test-electron": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.4.tgz", - "integrity": "sha512-eWzIqXMhvlcoXfEFNWrVu/yYT5w6De+WZXR/bafUQhAp8+8GkQo95Oe14phwiRUPv8L+geAKl/QM2+PoT3YW3g==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@vscode/test-electron/-/test-electron-2.3.6.tgz", + "integrity": "sha512-M31xGH0RgqNU6CZ4/9g39oUMJ99nLzfjA+4UbtIQ6TcXQ6+2qkjOOxedmPBDDCg26/3Al5ubjY80hIoaMwKYSw==", "dev": true, "requires": { "http-proxy-agent": "^4.0.1", @@ -6670,23 +5952,10 @@ "node-uuid": "1.4.7" } }, - "@xmldom/xmldom": { - "version": "0.8.10", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", - "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" - }, - "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==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.11.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", + "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true }, "acorn-jsx": { @@ -6696,40 +5965,10 @@ "dev": true, "requires": {} }, - "adal-node": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/adal-node/-/adal-node-0.2.4.tgz", - "integrity": "sha512-zIcvbwQFKMUtKxxj8YMHeTT1o/TPXfVNsTXVgXD8sxwV6h4AFQgK77dRciGhuEF9/Sdm3UQPJVPc/6XxrccSeA==", - "requires": { - "@xmldom/xmldom": "^0.8.3", - "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": { - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, "ag-grid-community": { - "version": "30.1.0", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-30.1.0.tgz", - "integrity": "sha512-D69e63CUALxfgLZSu1rXC8Xiyhu6+17zxzTV8cWsyvt5GeSDv2frQ3BKOqGZbUfVoOCLv2SQoHVTTqw8OjxavA==" + "version": "30.2.0", + "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-30.2.0.tgz", + "integrity": "sha512-Gd6GXmtzEQSCDloBdRxxCDqnjTBRAOf/zzlaxxyyVBJgc+cePuNgGdplRUhT/rwIiDwvyuoynvxelVE/iYdXsA==" }, "agent-base": { "version": "6.0.2", @@ -6773,9 +6012,9 @@ } }, "antlr4": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.0.tgz", - "integrity": "sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.1.tgz", + "integrity": "sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==", "dev": true }, "antlr4-runtime": { @@ -6832,6 +6071,7 @@ "version": "0.2.6", "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "peer": true, "requires": { "safer-buffer": "~2.1.0" } @@ -6839,15 +6079,8 @@ "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, - "async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "requires": { - "lodash": "^4.17.14" - } + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "peer": true }, "asynckit": { "version": "0.4.0", @@ -6857,17 +6090,19 @@ "aws-sign2": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==" + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "peer": true }, "aws4": { "version": "1.12.0", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" + "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", + "peer": true }, "axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -6886,15 +6121,6 @@ } } }, - "azure-arm-resource": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/azure-arm-resource/-/azure-arm-resource-7.4.0.tgz", - "integrity": "sha512-GT332g4i90W/PjsKxCMHYnexP6qwWOeWT0iucqLFQYV4C4PnNL8P5SFBuwo2qgbexcqtTSbyZg/YJJ5QLfYxDA==", - "requires": { - "ms-rest": "^2.3.3", - "ms-rest-azure": "^2.5.5" - } - }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6905,6 +6131,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "peer": true, "requires": { "tweetnacl": "^0.14.3" } @@ -6990,11 +6217,6 @@ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" }, - "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": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "buffer-fill": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", @@ -7027,7 +6249,8 @@ "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" + "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", + "peer": true }, "chainsaw": { "version": "0.1.0", @@ -7069,6 +6292,19 @@ "integrity": "sha512-4uF+X0GMPac82R3P1bZJCxDbEaJZvveosJELubRPC7mW8uku/PJLEl+Gv1TIR2YKOyDaoEmAcfw5/s2g8cJbhQ==", "dev": true }, + "chevrotain": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", + "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", + "requires": { + "@chevrotain/cst-dts-gen": "10.5.0", + "@chevrotain/gast": "10.5.0", + "@chevrotain/types": "10.5.0", + "@chevrotain/utils": "10.5.0", + "lodash": "4.17.21", + "regexp-to-ast": "0.5.0" + } + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -7127,7 +6363,8 @@ "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==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -7170,20 +6407,11 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "peer": true, "requires": { "assert-plus": "^1.0.0" } }, - "date-utils": { - "version": "1.2.21", - "resolved": "https://registry.npmjs.org/date-utils/-/date-utils-1.2.21.tgz", - "integrity": "sha512-wJMBjqlwXR0Iv0wUo/lFbhSQ7MmG1hl36iuxuE91kW+5b5sWbase73manEqNH9sOLFAMG83B4ffNKq9/Iq0FVA==" - }, - "dayjs": { - "version": "1.11.9", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz", - "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==" - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -7204,16 +6432,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" - }, - "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==" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7239,11 +6457,6 @@ "integrity": "sha512-+CEod3IzwjvhQOMXFSU6nrqdTwrhzOiacNzzXlwBVFm7C4y2rbuEWs5WaRsI/3IZeSWORA5F1q8FBh3gm4HSsw==", "dev": true }, - "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", @@ -7253,44 +6466,6 @@ "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" - } - }, - "duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" - }, "duplexer2": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", @@ -7304,19 +6479,12 @@ "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "peer": true, "requires": { "jsbn": "~0.1.0", "safer-buffer": "^2.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==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, "ejs": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz", @@ -7337,11 +6505,6 @@ "once": "^1.4.0" } }, - "entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" - }, "esbuild": { "version": "0.15.18", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", @@ -7439,24 +6602,20 @@ "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": "8.46.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.46.0.tgz", - "integrity": "sha512-cIO74PvbW0qU8e0mIvk5IV3ToWdCq5FYG6gWPHHkx6gNdjlbAYvtfHmlCMXxjcoVaIdwy/IAt3+mDkZkfvb2Dg==", + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.1", - "@eslint/js": "^8.46.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -7464,7 +6623,7 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.2", + "eslint-visitor-keys": "^3.4.3", "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", @@ -7598,9 +6757,9 @@ } }, "eslint-visitor-keys": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.2.tgz", - "integrity": "sha512-8drBzUEyZ2llkpCA67iYrgEssKDUu68V8ChqqOfFupIaG/LCVPUT+CoGJpT77zJprs4T/W7p07LP7zAIMuweVw==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { @@ -7660,11 +6819,6 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "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==" - }, "exenv-es6": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/exenv-es6/-/exenv-es6-1.1.1.tgz", @@ -7673,7 +6827,8 @@ "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "peer": true }, "extract-zip": { "version": "2.0.1", @@ -7689,7 +6844,8 @@ "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "peer": true }, "fast-deep-equal": { "version": "3.1.3", @@ -7775,35 +6931,38 @@ "dev": true }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "requires": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz", + "integrity": "sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==" }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "peer": true }, "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", @@ -7833,9 +6992,9 @@ "dev": true }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "optional": true }, "fstream": { @@ -7907,6 +7066,7 @@ "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "peer": true, "requires": { "assert-plus": "^1.0.0" } @@ -7953,9 +7113,9 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -7988,12 +7148,14 @@ "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "peer": true }, "har-validator": { "version": "5.1.5", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "peer": true, "requires": { "ajv": "^6.12.3", "har-schema": "^2.0.0" @@ -8008,7 +7170,8 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true }, "html-escaper": { "version": "2.0.2", @@ -8016,30 +7179,6 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "html-to-text": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.2.1.tgz", - "integrity": "sha512-aN/3JvAk8qFsWVeE9InWAWueLXrbkoVZy0TkzaGhoRBC2gCFEeRLDDJN3/ijIGHohy6H+SZzUQWN/hcYtaPK8w==", - "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", @@ -8051,16 +7190,6 @@ "debug": "4" } }, - "http-signature": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz", - "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.14.1" - } - }, "https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -8125,12 +7254,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" - }, - "is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-extglob": { "version": "2.1.1", @@ -8168,15 +7293,11 @@ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "peer": true }, "is-unicode-supported": { "version": "0.1.0", @@ -8204,7 +7325,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "peer": true }, "istanbul-lib-coverage": { "version": "3.2.0", @@ -8377,7 +7499,8 @@ "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "peer": true }, "jsesc": { "version": "2.5.2", @@ -8385,10 +7508,17 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "peer": true }, "json-schema-traverse": { "version": "0.4.1", @@ -8404,7 +7534,8 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "peer": true }, "jsonfile": { "version": "6.1.0", @@ -8415,17 +7546,6 @@ "universalify": "^2.0.0" } }, - "jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -8444,30 +7564,20 @@ "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", "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==", - "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==", - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "klaw": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-4.1.0.tgz", @@ -8504,6 +7614,37 @@ "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", "dev": true }, + "lit": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz", + "integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==", + "dev": true, + "requires": { + "@lit/reactive-element": "^1.6.0", + "lit-element": "^3.3.0", + "lit-html": "^2.8.0" + } + }, + "lit-element": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz", + "integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==", + "dev": true, + "requires": { + "@lit-labs/ssr-dom-shim": "^1.1.0", + "@lit/reactive-element": "^1.3.0", + "lit-html": "^2.8.0" + } + }, + "lit-html": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz", + "integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==", + "dev": true, + "requires": { + "@types/trusted-types": "^2.0.2" + } + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -8821,6 +7962,12 @@ "lodash": "^4.17.15" } }, + "mock-fs": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-5.2.0.tgz", + "integrity": "sha512-2dF2R6YMSZbpip1V1WHKGLNjr/k48uQClqMVb5H3MOvwc9qhYis3/IWbj02qIg/Y8MDXKFF4c5v0rxx2o6xTZw==", + "dev": true + }, "moment": { "version": "2.29.4", "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", @@ -8839,75 +7986,11 @@ "moment": "^2.29.4" } }, - "moo": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", - "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==" - }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, - "ms-rest": { - "version": "2.5.6", - "resolved": "https://registry.npmjs.org/ms-rest/-/ms-rest-2.5.6.tgz", - "integrity": "sha512-3Scy/pF43wqPEPeJxhOsLs16m6Rt+9zqf+jKdg+guuonytKmFSxerQM2exlQIDTqFVTsLXrPEGFWTGSwivRRkA==", - "requires": { - "ajv": "6.12.3", - "duplexer": "^0.1.1", - "http-signature": "1.3.6", - "is-buffer": "^1.1.6", - "is-stream": "^1.1.0", - "moment": "^2.21.0", - "request": "^2.88.2", - "through": "^2.3.8", - "tunnel": "0.0.5", - "uuid": "^3.2.1" - }, - "dependencies": { - "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", - "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" - } - }, - "tunnel": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.5.tgz", - "integrity": "sha512-gj5sdqherx4VZKMcBA4vewER7zdK25Td+z1npBqpbDys4eJrLx+SlYjJvq1bDXs2irkuJM5pf8ktaEQVipkrbA==" - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "ms-rest-azure": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/ms-rest-azure/-/ms-rest-azure-2.6.2.tgz", - "integrity": "sha512-h74ezkiMQ1y8tD0kf0MK2kdCONAP70i032Dt8kBrFsvj3ZqGRj+DHHNRCGLDfkBkSXhILGMeiF8Ji/iSCUJLJg==", - "requires": { - "adal-node": "^0.2.2", - "async": "^2.6.4", - "ms-rest": "^2.3.2", - "request": "^2.88.0", - "uuid": "^3.2.1" - }, - "dependencies": { - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, "nanoid": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", @@ -8926,21 +8009,10 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "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" - } - }, "nise": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.4.tgz", - "integrity": "sha512-8+Ib8rRJ4L0o3kfmyVCL7gzrohyDe0cMFTBa2d364yIrEGMEoetznKJx899YxjybU6bL9SQkYPSBBs1gyYs8Xg==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-5.1.5.tgz", + "integrity": "sha512-VJuPIfUFaXNRzETTQEEItTOP8Y171ijr+JLq42wHes3DiryR8vT+1TXQW/Rx8JNUhyYYWyIvjXTU6dOhJcs9Nw==", "dev": true, "requires": { "@sinonjs/commons": "^2.0.0", @@ -8971,17 +8043,17 @@ } }, "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "requires": { "whatwg-url": "^5.0.0" } }, "node-q": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-q/-/node-q-2.6.1.tgz", - "integrity": "sha512-OH8mx8R9jSjkMNkMUWrwUFiR/QEmfnqSYp61VxfTmSicvfz5UqufuY3Sh0l6o6hN10xeLKViWWngUs9QNYfstA==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-q/-/node-q-2.7.0.tgz", + "integrity": "sha512-rLvqnarAtNHdeyS7RRQmg4yjd6qxtfZcTL9jsQQZ2UBCMPz3/k/WtJPXieb4Xe4EjgjBO8txuJz+Rot9iUwOzg==", "requires": { "buffer-indexof-polyfill": "1.0.1", "long": "3.0.3", @@ -9001,7 +8073,8 @@ "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "peer": true }, "once": { "version": "1.4.0", @@ -9066,15 +8139,6 @@ "callsites": "^3.0.0" } }, - "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" - } - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -9123,7 +8187,8 @@ "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "peer": true }, "picomatch": { "version": "2.3.1", @@ -9191,27 +8256,14 @@ "qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "peer": true }, "queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" }, - "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", @@ -9261,10 +8313,16 @@ "picomatch": "^2.2.1" } }, + "regexp-to-ast": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" + }, "request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "peer": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -9292,6 +8350,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "peer": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -9302,6 +8361,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "peer": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -9312,6 +8372,7 @@ "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "peer": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -9322,7 +8383,8 @@ "uuid": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "peer": true } } }, @@ -9363,11 +8425,6 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "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", @@ -9414,20 +8471,8 @@ "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "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" - } + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "peer": true }, "semver": { "version": "7.5.4", @@ -9522,9 +8567,10 @@ "dev": true }, "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "peer": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -9656,35 +8702,12 @@ "tar-fs": "^1.8.1" } }, - "tas-client": { - "version": "0.1.58", - "resolved": "https://registry.npmjs.org/tas-client/-/tas-client-0.1.58.tgz", - "integrity": "sha512-fOWii4wQXuo9Zl0oXgvjBzZWzKc5MmUR6XQWX93WU2c1SaP1plPo/zvXP8kpbZ9fvegFOHdapszYqMTRq/SRtg==", - "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" - } - } - } - }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" - }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -9739,15 +8762,11 @@ "tslib": "^1.8.1" } }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "peer": true, "requires": { "safe-buffer": "^5.0.1" } @@ -9755,7 +8774,8 @@ "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "peer": true }, "type-check": { "version": "0.4.0", @@ -9784,10 +8804,11 @@ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true }, - "underscore": { - "version": "1.13.6", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", - "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "devOptional": true }, "universalify": { "version": "2.0.0", @@ -9834,15 +8855,11 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "peer": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -9852,7 +8869,8 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "peer": true } } }, @@ -9929,9 +8947,9 @@ } }, "vscode-languageserver-textdocument": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", - "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==", "dev": true }, "vscode-languageserver-types": { @@ -9940,19 +8958,6 @@ "integrity": "sha512-SYU4z1dL0PyIMd4Vj8YOqFvHu7Hz/enbWtpfnVbJHU4Nd1YNYx8u0ennumc6h48GQNeOLxmwySmnADouT/AuZA==", "dev": true }, - "vscode-nls": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==" - }, - "vscode-tas-client": { - "version": "0.1.63", - "resolved": "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.63.tgz", - "integrity": "sha512-TY5TPyibzi6rNmuUB7eRVqpzLzNfQYrrIl/0/F8ukrrbzOrKVvS31hM3urE+tbaVrnT+TMYXL16GhX57vEowhA==", - "requires": { - "tas-client": "0.1.58" - } - }, "vscode-test": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.6.1.tgz", @@ -9966,9 +8971,9 @@ } }, "vscode-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.7.tgz", - "integrity": "sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==" + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", + "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==" }, "webidl-conversions": { "version": "3.0.1", @@ -10047,25 +9052,6 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "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==", - "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==" - }, - "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==" - }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index cfcb438c..f80fe180 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,10 @@ "vscode": "^1.66.0" }, "icon": "resources/images/kx-logo-vs.png", + "repository": { + "type": "git", + "url": "https://github.com/KxSystems/kx-vscode.git" + }, "aiKey": "93119af7-5d98-45d0-abf8-5074976a1472", "capabilities": { "untrustedWorkspaces": { @@ -32,6 +36,8 @@ "onCommand:kdb.removeConnection", "onCommand:kdb.connect", "onCommand:kdb.disconnect", + "onCommand:kdb.addAuthentication", + "onCommand:kdb.enableTLS", "onCommand:kdb.dataSource.addDataSource", "onCommand:kdb.dataSource.saveDataSource", "onCommand:kdb.dataSource.runDataSource", @@ -42,6 +48,7 @@ "onCommand:kdb.resultsPanel.clear", "onCommand:kdb.resultsPanel.export.csv", "onView:kdb-servers", + "onView:kdb-query-history", "onView:kdb-datasources-explorer", "onView:kdb-results", "onTerminalProfile:kdb.q-terminal" @@ -159,6 +166,11 @@ "type": "boolean", "description": "Hide notification for installation path, after first install" }, + "kdb.hideDetailedConsoleQueryOutput": { + "type": "boolean", + "description": "Hide detailed console query output", + "default": true + }, "kdb.qHomeDirectory": { "type": "string", "description": "QHOME directory for q runtime" @@ -199,6 +211,15 @@ "command": "kdb.connect", "title": "Connect server" }, + { + "command": "kdb.addAuthentication", + "title": "Add Authentication", + "position": "end" + }, + { + "command": "kdb.enableTLS", + "title": "Enable TLS" + }, { "command": "kdb.insightsConnect", "title": "Connect to Insights" @@ -211,6 +232,14 @@ "command": "kdb.disconnect", "title": "Disconnect" }, + { + "command": "kdb.queryHistory.rerun", + "title": "Rerun query" + }, + { + "command": "kdb.queryHistory.clear", + "title": "Clear query history" + }, { "command": "kdb.dataSource.addDataSource", "title": "Add new DataSource" @@ -253,15 +282,18 @@ }, { "command": "kdb.terminal.run", - "title": "Run q file in a new q instance" + "title": "Run q file in a new q instance", + "when": "kdb.QHOME || config.kdb.qHomeDirectory" }, { "command": "kdb.execute.selectedQuery", - "title": "Execute Current Selection" + "title": "Execute Current Selection", + "when": "kdb.connected" }, { "command": "kdb.execute.fileQuery", - "title": "Execute Entire File" + "title": "Execute Entire File", + "when": "kdb.connected" } ], "keybindings": [ @@ -269,19 +301,19 @@ "command": "kdb.execute.selectedQuery", "key": "ctrl+d", "mac": "cmd+d", - "when": "editorLangId == q" + "when": "editorLangId == q && kdb.connected" }, { "command": "kdb.execute.fileQuery", "key": "ctrl+shift+d", "mac": "cmd+shift+d", - "when": "editorLangId == q" + "when": "editorLangId == q && kdb.connected" }, { "command": "kdb.terminal.run", "key": "ctrl+shift+r", "mac": "cmd+shift+r", - "when": "editorLangId == q" + "when": "editorLangId == q && (kdb.QHOME || config.kdb.qHomeDirectory)" } ], "snippets": [ @@ -339,6 +371,12 @@ "name": "Connections", "icon": "resources/server.svg" }, + { + "id": "kdb-query-history", + "name": "Query History", + "contextualTitle": "Query History", + "icon": "resources/history.svg" + }, { "id": "kdb-datasources-explorer", "name": "Data Sources", @@ -358,6 +396,10 @@ { "view": "kdb-servers", "contents": "No connections registered.\n[Add Connection](command:kdb.addConnection)" + }, + { + "view": "kdb-datasources-explorer", + "contents": "No data sources registered.\n[Add Data Source](command:kdb.dataSource.addDataSource)" } ], "menus": { @@ -393,6 +435,14 @@ { "command": "kdb.disconnect", "when": "false" + }, + { + "command": "kdb.addAuthentication", + "when": "false" + }, + { + "command": "kdb.enableTLS", + "when": "false" } ], "webview/context": [ @@ -427,6 +477,11 @@ "when": "view == kdb-results", "group": "resultsPanel" }, + { + "command": "kdb.queryHistory.clear", + "when": "view == kdb-query-history", + "group": "queryHistory" + }, { "command": "kdb.resultsPanel.export.csv", "when": "view == kdb-results", @@ -437,7 +492,17 @@ { "command": "kdb.connect", "when": "view == kdb-servers && viewItem not in kdb.connected && viewItem in kdb.rootNodes", - "group": "connection" + "group": "connection@1" + }, + { + "command": "kdb.addAuthentication", + "when": "view == kdb-servers && viewItem not in kdb.insightsNodes && viewItem in kdb.kdbNodesWithoutAuth", + "group": "connection@3" + }, + { + "command": "kdb.enableTLS", + "when": "view == kdb-servers && viewItem not in kdb.insightsNodes && viewItem in kdb.kdbNodesWithoutTls", + "group": "connection@4" }, { "command": "kdb.insightsConnect", @@ -457,7 +522,7 @@ { "command": "kdb.removeConnection", "when": "view == kdb-servers && viewItem in kdb.rootNodes", - "group": "connection" + "group": "connection@2" }, { "command": "kdb.startLocalProcess", @@ -469,6 +534,11 @@ "when": "view == kdb-servers && viewItem in kdb.local && viewItem in kdb.running && viewItem in kdb.rootNodes", "group": "connection" }, + { + "command": "kdb.queryHistory.rerun", + "when": "view == kdb-query-history", + "group": "queryHistory" + }, { "command": "kdb.dataSource.openDataSource", "when": "view == kdb-datasources-explorer && viewItem in kdb.dataSourceTreeNodes", @@ -488,35 +558,38 @@ "editor/title": [ { "command": "kdb.terminal.run", - "when": "resourceLangId == q", + "when": "resourceLangId == q && (kdb.QHOME || config.kdb.qHomeDirectory)", "group": "navigation" }, { "command": "kdb.execute.fileQuery", - "when": "resourceLangId == q", + "when": "resourceLangId == q && kdb.connected", "group": "navigation" } ], "editor/context": [ { "command": "kdb.terminal.run", - "when": "resourceLangId == q", + "when": "resourceLangId == q && (kdb.QHOME || config.kdb.qHomeDirectory)", "group": "q" }, { "command": "kdb.execute.selectedQuery", "group": "q", - "when": "editorLangId == q" + "when": "editorLangId == q && kdb.connected" }, { "command": "kdb.execute.fileQuery", "group": "q", - "when": "editorLangId == q" + "when": "editorLangId == q && kdb.connected" } ] } }, "license": "MIT", + "bugs": { + "url": "https://github.com/KxSystems/kx-vscode/issues" + }, "homepage": "https://kx.com", "scripts": { "vscode:prepublish": "npm run -S esbuild-base -- --minify --keep-names", @@ -551,6 +624,7 @@ "@types/semver": "^7.5.0", "@types/sinon": "^10.0.13", "@types/vscode": "^1.66.0", + "@types/vscode-webview": "^1.57.2", "@typescript-eslint/eslint-plugin": "^5.36.2", "@typescript-eslint/parser": "^5.36.2", "@vscode/test-electron": "^2.2.3", @@ -566,9 +640,11 @@ "istanbul-lib-report": "^2.0.8", "istanbul-lib-source-maps": "^3.0.6", "istanbul-reports": "^3.1.6", + "lit": "^2.8.0", "mocha": "^10.2.0", "mocha-junit-reporter": "^2.2.0", "mocha-multi-reporters": "^1.5.1", + "mock-fs": "^5.2.0", "prettier": "^2.7.1", "rimraf": "^3.0.2", "sinon": "^15.0.1", @@ -580,23 +656,17 @@ "vscode-test": "^1.6.1" }, "dependencies": { - "@azure/arm-resources": "4.2.2", - "@azure/arm-subscriptions": "3.1.2", - "@azure/core-auth": "^1.4.0", - "@azure/ms-rest-azure-env": "^2.0.0", - "@azure/ms-rest-nodeauth": "^3.1.1", - "@microsoft/vscode-azext-utils": "0.3.7", "@types/antlr4": "^4.11.2", "@types/graceful-fs": "^4.1.6", "@types/klaw": "^3.0.3", "@types/picomatch": "^2.3.0", "@vscode/webview-ui-toolkit": "^1.2.2", "@windozer/node-q": "^2.6.0", - "ag-grid-community": "^30.1.0", + "ag-grid-community": "^30.2.0", "antlr4-runtime": "^4.13.0", "antlr4ts": "^0.5.0-alpha.4", - "axios": "^1.4.0", - "azure-arm-resource": "^7.4.0", + "axios": "^1.6.0", + "chevrotain": "^10.5.0", "csv-parser": "^3.0.0", "esbuild-plugin-copy": "^2.1.1", "extract-zip": "^2.0.1", @@ -618,8 +688,5 @@ "vscode-languageserver": "^8.1.0", "vscode-languageserver-textdocument": "^1.0.7", "vscode-uri": "^3.0.7" - }, - "extensionDependencies": [ - "ms-vscode.azure-account" - ] + } } diff --git a/release_process.md b/release_process.md index c0af8574..0df8852f 100644 --- a/release_process.md +++ b/release_process.md @@ -1,40 +1,17 @@ -# Release process for KX VSCode extension +# Release process for kdb VS Code extension -The release process for the extension requires multiple steps. Some of these are automated with scripts and can be called from future CI/CD platforms, such as Azure DevOps or GitHub workflows. Currently this process is quite manual as the extension is not published to the marketplace yet. +On each push to the `main` or `dev` branches` a VSIX file is built and uploaded to [Downloads Portal](https://portal.dl.kx.com/assets/raw/kdb-vscode/) ## Steps for creating a new release -1. Build the extension and run all tests. +1. Update the [package.json](package.json) to bump the version for the extension. This is important because when installing the package (VSIX), it's important to have the updated version to ensure VSCode does not install another version. This uses semantic version of build.release.patch (e.g., 0.1.8) -``` -yarn install -yarn run build -yarn run test -``` +2. Update the [CHANGELOG.md](CHANGELOG.md) to include the release version the the appropriate comments on updates. This uses semantic version of build.release.patch (e.g., v0.1.8) -2. Run the extension in developer mode to test that the functionality of the change is valid. +3. Merge the changes -``` -Press , wait for extension host to launch, tests functionality -``` - -3. Update the [package.json](package.json) to bump the version for the extension. This is important because when installing the package (VSIX), it's important to have the updated version to ensure VSCode does not install another version. This applies after the extension is published to the marketplace. This uses semantic version of build.release.patch (e.g., 0.1.8) - -4. Update the [CHANGELOG.md](CHANGELOG.md) to include the release version the the appropriate comments on updates. - -5. Package the extension. This will create the bundled extension (essentially compressing and minifing all code to a single js file) and then creating the manifest and assets for what will be published to the marketplace. This will output a VSIX file, which is a compressed file of these assets. - -``` -yarn run package -``` - -6. Start a new VS Code instance and install the extension by sideloading. This is done by navigating to the extensions tab and from the ellipse menu click on 'Install from VSIX'. Again, run the same tests as in step above. This is used to validate that the bundling/miniflying and compression didn't result in any breakage. - -7. Share the VSIX with team members, get feedback. - -8. After this is completed, a release can be created in GitHub. This _can_ be automated but currently is manual. - - - First, create a new draft release in the GitHub repo - - Name the release v0.1.x to ensure the version matches the new version. - - Copy the section for the version from the [CHANGELOG.md](CHANGELOG.md) to the notes. - - Add the VSIX as a binary for the release. +4. Create a tag on main locally, then push it to remote. + ```bash + git tag v1.0.0 + git push origin v1.0.0 + ``` diff --git a/resources/evaluate.q b/resources/evaluate.q index 224defa2..26fa7311 100644 --- a/resources/evaluate.q +++ b/resources/evaluate.q @@ -1,4 +1,4 @@ -{[ctx; code] +{[ctx; code; stringify] if [-10h ~ type ctx; ctx: enlist ctx]; toString: {[data] @@ -110,14 +110,14 @@ if [err ~ enlist " "; err: "syntax error"]; userCode: (-1 + last where (.Q.trp ~ first first @) each backtrace) # backtrace; - callstack: {`name`text`index!(x[1;0]; x[1;3]; x 2)} each userCode; - callstack[-1 + count callstack; `text]: (neg count suffix) _ (count prefix) _ (last callstack) `text; - callstack[-1 + count callstack; `index]-: count prefix; + userCode[;3]: reverse 1 + til count userCode; + userCode[-1 + count userCode; 1; 3]: (neg count suffix) _ (count prefix) _ userCode[-1 + count userCode; 1; 3]; + userCode[-1 + count userCode; 2]-: count prefix; (!) . flip ( (`result; ::); (`errored; 1b); (`error; err); - (`backtrace; callstack)) + (`backtrace; .Q.sbt userCode)) }[suffix; prefix]]; if [isLastLine or result`errored; system "d ", cachedCtx; @@ -125,7 +125,7 @@ index +: 1]; }; result: evalInContext[ctx; splitExpression stripTrailingSemi wrapLines removeMultilineComments code]; - if [not result `errored; + if [(not result `errored) and stringify; result[`result]: toString result `result]; result } diff --git a/server/src/parser/lexer.ts b/server/src/parser/lexer.ts new file mode 100644 index 00000000..039bb2ff --- /dev/null +++ b/server/src/parser/lexer.ts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { Lexer } from "chevrotain"; +import { + BinaryLiteral, + ByteLiteral, + CharLiteral, + DateLiteral, + DateTimeLiteral, + FloatLiteral, + IntegerLiteral, + MiliTimeLiteral, + MinuteLiteral, + MonthLiteral, + NanoTimeLiteral, + SecondLiteral, + TimeStampLiteral, +} from "./literals"; +import { + BinaryColon, + BlockComment, + Colon, + Dot, + EndOfLine, + Identifier, + Infix, + Keyword, + LBracket, + LCurly, + LParen, + LineComment, + Quote, + RBracket, + RCurly, + RParen, + SemiColon, + Underscore, + WhiteSpace, +} from "./tokens"; + +export const QTokens = [ + BlockComment, + LineComment, + CharLiteral, + WhiteSpace, + EndOfLine, + Quote, + SemiColon, + LParen, + RParen, + LBracket, + RBracket, + LCurly, + RCurly, + Dot, + Underscore, + TimeStampLiteral, + DateTimeLiteral, + MiliTimeLiteral, + NanoTimeLiteral, + DateLiteral, + MonthLiteral, + SecondLiteral, + MinuteLiteral, + FloatLiteral, + BinaryLiteral, + ByteLiteral, + IntegerLiteral, + Infix, + BinaryColon, + Colon, + Keyword, + Identifier, +]; + +export const QLexer = new Lexer(QTokens); diff --git a/server/src/parser/literals.ts b/server/src/parser/literals.ts new file mode 100644 index 00000000..280dbc7c --- /dev/null +++ b/server/src/parser/literals.ts @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { createToken } from "chevrotain"; + +export const CharLiteral = createToken({ + name: "CharLiteral", + pattern: /"(?:\\.|(?:(?!\r?\n\S)[^"]))*"/, +}); + +export const FloatLiteral = createToken({ + name: "FloatLiteral", + pattern: /-?(?:\d+\.\d+|\.\d+|\d+\.)(?:e[+-]?\d?\d)?e?/, +}); + +export const IntegerLiteral = createToken({ + name: "IntegerLiteral", + pattern: /-?\d+[jhi]?/, +}); + +export const BinaryLiteral = createToken({ + name: "BinaryLiteral", + pattern: /[01]+b/, +}); + +export const ByteLiteral = createToken({ + name: "ByteLiteral", + pattern: /0x(?:[0-9a-fA-F]{2})+/, +}); + +export const DateLiteral = createToken({ + name: "DateLiteral", + pattern: /\d{4}\.\d{2}\.\d{2}/, +}); + +export const MiliTimeLiteral = createToken({ + name: "MiliTimeLiteral", + pattern: /\d{2}:\d{2}:\d{2}\.\d{3}/, +}); + +export const NanoTimeLiteral = createToken({ + name: "NanoTimeLiteral", + pattern: /(?:0D)?\d{2}:\d{2}:\d{2}\.\d{9}/, +}); + +export const DateTimeLiteral = createToken({ + name: "DateTimeLiteral", + pattern: /\d{4}\.\d{2}\.\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}/, +}); + +export const TimeStampLiteral = createToken({ + name: "TimeStampLiteral", + pattern: /\d{4}\.\d{2}\.\d{2}D\d{2}:\d{2}:\d{2}\.\d{9}/, +}); + +export const MonthLiteral = createToken({ + name: "MonthLiteral", + pattern: /\d{4}\.\d{2}m/, + longer_alt: DateLiteral, +}); + +export const SecondLiteral = createToken({ + name: "SecondLiteral", + pattern: /\d{2}:\d{2}:\d{2}/, +}); + +export const MinuteLiteral = createToken({ + name: "MinuteLiteral", + pattern: /\d{2}:\d{2}/, + longer_alt: SecondLiteral, +}); diff --git a/server/src/parser/parser.ts b/server/src/parser/parser.ts new file mode 100644 index 00000000..f2526705 --- /dev/null +++ b/server/src/parser/parser.ts @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { CstParser } from "chevrotain"; +import { QLexer, QTokens } from "./lexer"; +import { + BinaryLiteral, + ByteLiteral, + CharLiteral, + DateLiteral, + DateTimeLiteral, + FloatLiteral, + IntegerLiteral, + MiliTimeLiteral, + MinuteLiteral, + MonthLiteral, + NanoTimeLiteral, + SecondLiteral, + TimeStampLiteral, +} from "./literals"; +import { + BinaryColon, + Colon, + Dot, + EndOfLine, + Identifier, + Infix, + Keyword, + LBracket, + LCurly, + LParen, + RBracket, + RCurly, + RParen, + SemiColon, + Underscore, +} from "./tokens"; + +class Parser extends CstParser { + constructor() { + super(QTokens, { recoveryEnabled: true }); + this.performSelfAnalysis(); + } + + public script = this.RULE("script", () => { + this.MANY(() => this.SUBRULE(this.statement)); + }); + + private statement = this.RULE("statement", () => { + this.MANY(() => this.SUBRULE(this.expression)); + this.SUBRULE(this.terminate); + }); + + private terminate = this.RULE("terminate", () => { + this.OR([ + { ALT: () => this.CONSUME(EndOfLine) }, + { ALT: () => this.CONSUME(SemiColon) }, + ]); + }); + + private expression = this.RULE("expression", () => { + this.OR([ + { ALT: () => this.SUBRULE(this.literal) }, + { ALT: () => this.SUBRULE(this.keyword) }, + { ALT: () => this.SUBRULE(this.list) }, + { ALT: () => this.SUBRULE(this.lambda) }, + { ALT: () => this.SUBRULE(this.bracket) }, + { ALT: () => this.SUBRULE(this.assignment) }, + { ALT: () => this.SUBRULE(this.infix) }, + { ALT: () => this.SUBRULE(this.identifier) }, + ]); + }); + + private list = this.RULE("list", () => { + this.CONSUME(LParen); + this.MANY_SEP({ + SEP: SemiColon, + DEF: () => this.MANY(() => this.SUBRULE(this.expression)), + }); + this.CONSUME(RParen); + }); + + private lambda = this.RULE("lambda", () => { + this.CONSUME(LCurly); + this.OPTION(() => this.SUBRULE(this.bracket)); + this.MANY_SEP({ + SEP: SemiColon, + DEF: () => this.MANY(() => this.SUBRULE(this.expression)), + }); + this.CONSUME(RCurly); + }); + + private bracket = this.RULE("bracket", () => { + this.CONSUME(LBracket); + this.MANY_SEP({ + SEP: SemiColon, + DEF: () => this.MANY(() => this.SUBRULE(this.expression)), + }); + this.CONSUME(RBracket); + }); + + private assignment = this.RULE("assignment", () => { + this.OPTION(() => this.SUBRULE(this.infix)); + this.CONSUME(Colon); + this.SUBRULE(this.expression); + }); + + private infix = this.RULE("infix", () => { + this.CONSUME(Infix); + }); + + private literal = this.RULE("literal", () => { + this.OR([ + { ALT: () => this.CONSUME(CharLiteral) }, + { ALT: () => this.CONSUME(TimeStampLiteral) }, + { ALT: () => this.CONSUME(DateTimeLiteral) }, + { ALT: () => this.CONSUME(MiliTimeLiteral) }, + { ALT: () => this.CONSUME(NanoTimeLiteral) }, + { ALT: () => this.CONSUME(DateLiteral) }, + { ALT: () => this.CONSUME(MonthLiteral) }, + { ALT: () => this.CONSUME(SecondLiteral) }, + { ALT: () => this.CONSUME(MinuteLiteral) }, + { ALT: () => this.CONSUME(FloatLiteral) }, + { ALT: () => this.CONSUME(BinaryLiteral) }, + { ALT: () => this.CONSUME(ByteLiteral) }, + { ALT: () => this.CONSUME(IntegerLiteral) }, + ]); + }); + + private keyword = this.RULE("keyword", () => { + this.OR([ + { ALT: () => this.CONSUME(Keyword) }, + { ALT: () => this.CONSUME(Underscore) }, + { ALT: () => this.CONSUME(Dot) }, + { ALT: () => this.CONSUME(BinaryColon) }, + ]); + }); + + private identifier = this.RULE("identifier", () => { + this.CONSUME(Identifier); + }); + + public parse(script: string) { + const lexed = QLexer.tokenize(script); + this.input = lexed.tokens; + return this.script(); + } +} + +export const QParser = new Parser(); diff --git a/server/src/parser/tokens.ts b/server/src/parser/tokens.ts new file mode 100644 index 00000000..7774cef2 --- /dev/null +++ b/server/src/parser/tokens.ts @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { Lexer, createToken } from "chevrotain"; +import { + DateTimeLiteral, + MiliTimeLiteral, + MinuteLiteral, + NanoTimeLiteral, + SecondLiteral, + TimeStampLiteral, +} from "./literals"; + +export const BlockComment = createToken({ + name: "BlockComment", + pattern: /(?<=(\r?\n|[ \t]*))\/(?:[ \t]*\r?\n)[^\\]*\\?/, + group: Lexer.SKIPPED, +}); + +export const LineComment = createToken({ + name: "LineComment", + pattern: /(?:(?<=\r?\n|[ \t])|(? { - await this.validateTextDocument(change.document); + // await this.validateTextDocument(change.document); }); this.connection.onNotification("analyzeSourceCode", (config) => this.analyzer.analyzeWorkspace(config) @@ -399,44 +400,28 @@ export default class QLangServer { private async validateTextDocument( textDocument: TextDocument ): Promise { - const settings = await this.getDocumentSettings(textDocument.uri); const text = textDocument.getText(); - const pattern = /\b[A-Z]{2,}\b/g; - let m: RegExpExecArray | null; - - let problems = 0; + QParser.parse(text); const diagnostics: Diagnostic[] = []; - while ((m = pattern.exec(text)) && problems < 1000) { - problems++; + let problems = QParser.errors.length; + if (problems > 1000) { + problems = 1000; + } + for (let i = 0; i < problems; i++) { + const error = QParser.errors[i]; const diagnostic: Diagnostic = { - severity: DiagnosticSeverity.Warning, + severity: DiagnosticSeverity.Error, range: { - start: textDocument.positionAt(m.index), - end: textDocument.positionAt(m.index + m[0].length), + start: textDocument.positionAt(error.token.startOffset), + end: textDocument.positionAt( + error.token.endOffset || error.token.startOffset + ), }, - message: `${m[0]} is all uppercase.`, - source: "ex", + message: error.message, + source: "kdb", }; - diagnostic.relatedInformation = [ - { - location: { - uri: textDocument.uri, - range: Object.assign({}, diagnostic.range), - }, - message: "Spelling matters", - }, - { - location: { - uri: textDocument.uri, - range: Object.assign({}, diagnostic.range), - }, - message: "Particularly for names", - }, - ]; - diagnostics.push(diagnostic); } - this.connection.sendDiagnostics({ uri: textDocument.uri, diagnostics }); } diff --git a/sonar-project.properties b/sonar-project.properties index 909ef1ef..fa50dec0 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,5 +1,6 @@ sonar.projectKey=kxvscode +sonar.qualitygate.wait=true sonar.sources=src,server sonar.tests=test sonar.javascript.lcov.reportPaths=lcov.info -sonar.coverage.exclusions=server/src/utils/antlrGrammars/**,server/src/utils/parserUtils.ts,src/ipc/** \ No newline at end of file +sonar.coverage.exclusions=server/src/utils/antlrGrammars/**,server/src/utils/parserUtils.ts,src/ipc/**,src/models/**,src/webview/** diff --git a/src/commands/dataSourceCommand.ts b/src/commands/dataSourceCommand.ts index 9b8457d8..349dba45 100644 --- a/src/commands/dataSourceCommand.ts +++ b/src/commands/dataSourceCommand.ts @@ -16,13 +16,16 @@ import path from "path"; import { InputBoxOptions, Uri, window } from "vscode"; import { ext } from "../extensionVariables"; import { getDataBodyPayload } from "../models/data"; -import { DataSourceFiles, defaultDataSourceFile } from "../models/dataSource"; +import { + DataSourceFiles, + DataSourceTypes, + createDefaultDataSourceFile, +} from "../models/dataSource"; import { scratchpadVariableInput } from "../models/items/server"; import { DataSourcesPanel } from "../panels/datasource"; import { KdbDataSourceTreeItem } from "../services/dataSourceTreeProvider"; import { checkIfTimeParamIsCorrect, - convertDataSourceFormToDataSourceFile, convertTimeToTimestamp, createKdbDataSourcesFolder, getConnectedInsightsNode, @@ -33,7 +36,8 @@ import { getDataInsights, getMeta, importScratchpad, - writeQueryResult, + writeQueryResultsToConsole, + writeQueryResultsToView, } from "./serverCommand"; export async function addDataSource(): Promise { @@ -49,7 +53,7 @@ export async function addDataSource(): Promise { filePath = path.join(kdbDataSourcesFolderPath, fileName); } const dataSourceName = fileName.replace(ext.kdbDataSourceFileExtension, ""); - const defaultDataSourceContent = defaultDataSourceFile; + const defaultDataSourceContent = createDefaultDataSourceFile(); const insightsNode = getConnectedInsightsNode(); defaultDataSourceContent.name = dataSourceName; defaultDataSourceContent.insightsNode = insightsNode; @@ -145,21 +149,25 @@ export async function openDataSource( ); } -export async function saveDataSource(dataSourceForm: any): Promise { +export async function saveDataSource( + dataSourceForm: DataSourceFiles +): Promise { const kdbDataSourcesFolderPath = createKdbDataSourcesFolder(); if (!kdbDataSourcesFolderPath) { return; } - if (dataSourceForm.name === "") { + if (!dataSourceForm.originalName || dataSourceForm.name === "") { window.showErrorMessage("Name is required"); return; } + if (dataSourceForm.name !== dataSourceForm.originalName) { await renameDataSource(dataSourceForm.originalName, dataSourceForm.name); } - const fileContent = convertDataSourceFormToDataSourceFile(dataSourceForm); + dataSourceForm.insightsNode = getConnectedInsightsNode(); + const fileContent = dataSourceForm; const dataSourceFilePath = path.join( kdbDataSourcesFolderPath, @@ -168,11 +176,13 @@ export async function saveDataSource(dataSourceForm: any): Promise { if (fs.existsSync(dataSourceFilePath)) { fs.writeFileSync(dataSourceFilePath, JSON.stringify(fileContent)); + window.showInformationMessage(`DataSource ${dataSourceForm.name} saved.`); } - window.showInformationMessage(`DataSource ${dataSourceForm.name} saved.`); } -export async function populateScratchpad(dataSourceForm: any): Promise { +export async function populateScratchpad( + dataSourceForm: DataSourceFiles +): Promise { const scratchpadVariable: InputBoxOptions = { prompt: scratchpadVariableInput.prompt, placeHolder: scratchpadVariableInput.placeholder, @@ -191,7 +201,9 @@ export async function populateScratchpad(dataSourceForm: any): Promise { }); } -export async function runDataSource(dataSourceForm: any): Promise { +export async function runDataSource( + dataSourceForm: DataSourceFiles +): Promise { Object.assign(ext.insightsMeta, await getMeta()); if (!ext.insightsMeta.assembly) { ext.outputChannel.appendLine( @@ -202,151 +214,207 @@ export async function runDataSource(dataSourceForm: any): Promise { ); return; } - const fileContent = convertDataSourceFormToDataSourceFile(dataSourceForm); + + dataSourceForm.insightsNode = getConnectedInsightsNode(); + const fileContent = dataSourceForm; let res: any; - const selectedType = - fileContent.dataSource.selectedType.toString() === "API" - ? "API" - : fileContent.dataSource.selectedType.toString() === "QSQL" - ? "QSQL" - : "SQL"; + const selectedType = getSelectedType(fileContent); switch (selectedType) { case "API": - const isTimeCorrect = checkIfTimeParamIsCorrect( - fileContent.dataSource.api.startTS, - fileContent.dataSource.api.endTS - ); - if (!isTimeCorrect) { - window.showErrorMessage( - "The time parameters(startTS and endTS) are not correct, please check the format or if the startTS is before the endTS" - ); - break; - } - const startTS = - fileContent.dataSource.api.startTS !== "" - ? convertTimeToTimestamp(fileContent.dataSource.api.startTS) - : undefined; - const endTS = - fileContent.dataSource.api.endTS !== "" - ? convertTimeToTimestamp(fileContent.dataSource.api.endTS) - : undefined; - const fill = - fileContent.dataSource.api.fill !== "" - ? fileContent.dataSource.api.fill - : undefined; - const temporary = - fileContent.dataSource.api.temporary !== "" - ? fileContent.dataSource.api.temporary - : undefined; - const filter = - fileContent.dataSource.api.filter.length > 0 - ? fileContent.dataSource.api.filter - : undefined; - const groupBy = - fileContent.dataSource.api.groupBy.length > 0 - ? fileContent.dataSource.api.groupBy - : undefined; - const agg = - fileContent.dataSource.api.agg.length > 0 - ? fileContent.dataSource.api.agg - : undefined; - const sortCols = - fileContent.dataSource.api.sortCols.length > 0 - ? fileContent.dataSource.api.sortCols - : undefined; - const slice = - fileContent.dataSource.api.slice.length > 0 - ? fileContent.dataSource.api.slice - : undefined; - const labels = - fileContent.dataSource.api.labels.length > 0 - ? fileContent.dataSource.api.labels - : undefined; - const apiBody: getDataBodyPayload = { - table: fileContent.dataSource.api.table, - }; - if (startTS !== undefined) { - apiBody.startTS = startTS; - } + res = await runApiDataSource(fileContent); + break; + case "QSQL": + res = await runQsqlDataSource(fileContent); + break; + case "SQL": + default: + res = await runSqlDataSource(fileContent); + break; + } - if (endTS !== undefined) { - apiBody.endTS = endTS; - } + if (ext.resultsViewProvider.isVisible()) { + writeQueryResultsToView(res, selectedType); + } else { + writeQueryResultsToConsole( + res, + getQuery(fileContent, selectedType), + selectedType + ); + } +} - if (fill !== undefined) { - apiBody.fill = fill; - } +export function getSelectedType(fileContent: DataSourceFiles): string { + const selectedType = fileContent.dataSource.selectedType; + switch (selectedType) { + case DataSourceTypes.API: + return "API"; + case DataSourceTypes.QSQL: + return "QSQL"; + case DataSourceTypes.SQL: + return "SQL"; + default: + throw new Error(`Invalid selectedType: ${selectedType}`); + } +} - if (temporary !== undefined) { - apiBody.temporary = temporary; - } +export async function runApiDataSource( + fileContent: DataSourceFiles +): Promise { + const isTimeCorrect = checkIfTimeParamIsCorrect( + fileContent.dataSource.api.startTS, + fileContent.dataSource.api.endTS + ); + if (!isTimeCorrect) { + window.showErrorMessage( + "The time parameters(startTS and endTS) are not correct, please check the format or if the startTS is before the endTS" + ); + return; + } + const apiBody = getApiBody(fileContent); + const apiCall = await getDataInsights( + ext.insightsAuthUrls.dataURL, + JSON.stringify(apiBody) + ); + if (apiCall?.arrayBuffer) { + return handleWSResults(apiCall.arrayBuffer); + } +} - if (filter !== undefined) { - apiBody.filter = filter.map((filterEl: string) => { - return filterEl.split(";"); - }); - } +export function getApiBody( + fileContent: DataSourceFiles +): Partial { + const api = fileContent.dataSource.api; - if (groupBy !== undefined) { - apiBody.groupBy = groupBy; - } + const apiBody: getDataBodyPayload = { + table: fileContent.dataSource.api.table, + startTS: convertTimeToTimestamp(api.startTS), + endTS: convertTimeToTimestamp(api.endTS), + }; - if (agg !== undefined) { - apiBody.agg = agg; - } + const optional = api.optional; - if (sortCols !== undefined) { - apiBody.sortCols = sortCols; + if (optional) { + if (optional.filled) { + apiBody.fill = api.fill; + } + if (optional.temporal) { + apiBody.temporality = api.temporality; + if (api.temporality === "slice") { + const start = api.startTS.split("T"); + if (start.length === 2) { + start[1] = optional.startTS; + const end = api.endTS.split("T"); + if (end.length === 2) { + end[1] = optional.endTS; + apiBody.startTS = convertTimeToTimestamp(start.join("T")); + apiBody.endTS = convertTimeToTimestamp(end.join("T")); + } + } } + } - if (slice !== undefined) { - apiBody.slice = slice; - } + const labels = optional.labels.filter((label) => label.active); - if (labels !== undefined) { - apiBody.labels = labels; - } - const apiCall = await getDataInsights( - ext.insightsAuthUrls.dataURL, - JSON.stringify(apiBody) + if (labels.length > 0) { + apiBody.labels = Object.assign( + {}, + ...labels.map((label) => ({ [label.key]: label.value })) ); - if (apiCall?.arrayBuffer) { - res = handleWSResults(apiCall.arrayBuffer); - } - writeQueryResult(res, "GetData - table: " + apiBody.table, selectedType); - break; + } + + const filters = optional.filters + .filter((filter) => filter.active) + .map((filter) => [ + filter.operator, + filter.column, + ((values: string) => { + const tokens = values.split(/[;\s]+/).map((token) => { + const number = parseFloat(token); + return isNaN(number) ? token : number; + }); + return tokens.length === 1 ? tokens[0] : tokens; + })(filter.values), + ]); + + if (filters.length > 0) { + apiBody.filter = filters; + } + + const sorts = optional.sorts + .filter((sort) => sort.active) + .map((sort) => sort.column); + + if (sorts.length > 0) { + apiBody.sortCols = sorts; + } + + const aggs = optional.aggs + .filter((agg) => agg.active) + .map((agg) => [agg.key, agg.operator, agg.column]); + + if (aggs.length > 0) { + apiBody.agg = aggs; + } + + const groups = optional.groups + .filter((group) => group.active) + .map((group) => group.column); + + if (groups.length > 0) { + apiBody.groupBy = groups; + } + } + + return apiBody; +} + +export async function runQsqlDataSource( + fileContent: DataSourceFiles +): Promise { + const assembly = fileContent.dataSource.qsql.selectedTarget.slice(0, -4); + const target = fileContent.dataSource.qsql.selectedTarget.slice(-3); + const qsqlBody = { + assembly: assembly, + target: target, + query: fileContent.dataSource.qsql.query, + }; + const qsqlCall = await getDataInsights( + ext.insightsAuthUrls.qsqlURL, + JSON.stringify(qsqlBody) + ); + if (qsqlCall?.arrayBuffer) { + return handleWSResults(qsqlCall.arrayBuffer); + } +} + +export async function runSqlDataSource( + fileContent: DataSourceFiles +): Promise { + const sqlBody = { + query: fileContent.dataSource.sql.query, + }; + const sqlCall = await getDataInsights( + ext.insightsAuthUrls.sqlURL, + JSON.stringify(sqlBody) + ); + if (sqlCall?.arrayBuffer) { + return handleWSResults(sqlCall.arrayBuffer); + } +} + +export function getQuery( + fileContent: DataSourceFiles, + selectedType: string +): string { + switch (selectedType) { + case "API": + return `GetData - table: ${fileContent.dataSource.api.table}`; case "QSQL": - const assembly = fileContent.dataSource.qsql.selectedTarget.slice(0, -4); - const target = fileContent.dataSource.qsql.selectedTarget.slice(-3); - const qsqlBody = { - assembly: assembly, - target: target, - query: fileContent.dataSource.qsql.query, - }; - const qsqlCall = await getDataInsights( - ext.insightsAuthUrls.qsqlURL, - JSON.stringify(qsqlBody) - ); - if (qsqlCall?.arrayBuffer) { - res = handleWSResults(qsqlCall.arrayBuffer); - } - writeQueryResult(res, fileContent.dataSource.qsql.query, selectedType); - break; + return fileContent.dataSource.qsql.query; case "SQL": default: - const sqlBody = { - query: fileContent.dataSource.sql.query, - }; - const sqlCall = await getDataInsights( - ext.insightsAuthUrls.sqlURL, - JSON.stringify(sqlBody) - ); - if (sqlCall?.arrayBuffer) { - res = handleWSResults(sqlCall.arrayBuffer); - } - writeQueryResult(res, fileContent.dataSource.sql.query, selectedType); - break; + return fileContent.dataSource.sql.query; } } diff --git a/src/commands/serverCommand.ts b/src/commands/serverCommand.ts index 401e6bd7..35a025d0 100644 --- a/src/commands/serverCommand.ts +++ b/src/commands/serverCommand.ts @@ -18,19 +18,21 @@ import { join } from "path"; import requestPromise from "request-promise"; import * as url from "url"; import { - commands, InputBoxOptions, Position, ProgressLocation, QuickPickItem, QuickPickOptions, Range, + commands, + env, window, } from "vscode"; import { ext } from "../extensionVariables"; import { isCompressed, uncompress } from "../ipc/c"; import { Connection } from "../models/connection"; import { GetDataObjectPayload } from "../models/data"; +import { DataSourceFiles, DataSourceTypes } from "../models/dataSource"; import { ExecutionTypes } from "../models/execution"; import { Insights } from "../models/insights"; import { @@ -70,7 +72,7 @@ import { import { refreshDataSourcesPanel } from "../utils/dataSource"; import { ExecutionConsole } from "../utils/executionConsole"; import { openUrl } from "../utils/openUrl"; -import { sanitizeQuery } from "../utils/queryUtils"; +import { handleWSResults, sanitizeQuery } from "../utils/queryUtils"; import { validateServerAlias, validateServerName, @@ -146,6 +148,81 @@ export async function addInsightsConnection() { }); } +// Not possible to test secrets +/* istanbul ignore next */ +export function addAuthConnection(serverKey: string): void { + const connectionUsername: InputBoxOptions = { + prompt: connectionUsernameInput.prompt, + placeHolder: connectionUsernameInput.placeholder, + validateInput: (value: string | undefined) => validateServerUsername(value), + }; + const connectionPassword: InputBoxOptions = { + prompt: connectionPasswordInput.prompt, + placeHolder: connectionPasswordInput.placeholder, + password: true, + }; + window.showInputBox(connectionUsername).then(async (username) => { + if (username?.trim()?.length) { + window.showInputBox(connectionPassword).then(async (password) => { + if (password?.trim()?.length) { + const servers: Server | undefined = getServers(); + // store secrets + if ( + (username != undefined || username != "") && + (password != undefined || password != "") && + servers && + servers[serverKey] + ) { + servers[serverKey].auth = true; + ext.secretSettings.storeAuthData( + serverKey, + `${username}:${password}` + ); + await updateServers(servers); + const newServers = getServers(); + if (newServers != undefined) { + ext.serverProvider.refresh(newServers); + } + } + } + }); + } + }); +} + +export async function enableTLS(serverKey: string): Promise { + const servers: Server | undefined = getServers(); + + // validate if TLS is possible + if (ext.openSslVersion === null) { + window + .showErrorMessage( + "OpenSSL not found, please ensure this is installed", + "More Info", + "Cancel" + ) + .then(async (result) => { + if (result === "More Info") { + await openUrl("https://code.kx.com/q/kb/ssl/"); + } + }); + return; + } + if (servers && servers[serverKey]) { + servers[serverKey].tls = true; + await updateServers(servers); + const newServers = getServers(); + if (newServers != undefined) { + ext.serverProvider.refresh(newServers); + } + return; + } + window.showErrorMessage( + "Server not found, please ensure this is a correct server", + "Cancel" + ); +} + export function addKdbConnection(): void { const connectionAlias: InputBoxOptions = { prompt: connectionAliasInput.prompt, @@ -162,16 +239,6 @@ export function addKdbConnection(): void { placeHolder: connectionPortInput.placeholder, validateInput: (value: string | undefined) => validateServerPort(value), }; - const connectionUsername: InputBoxOptions = { - prompt: connectionUsernameInput.prompt, - placeHolder: connectionUsernameInput.placeholder, - validateInput: (value: string | undefined) => validateServerUsername(value), - }; - const connectionPassword: InputBoxOptions = { - prompt: connectionPasswordInput.prompt, - placeHolder: connectionPasswordInput.placeholder, - password: true, - }; const connectionTls: InputBoxOptions = { prompt: connnectionTls.prompt, @@ -184,102 +251,54 @@ export function addKdbConnection(): void { if (hostname) { window.showInputBox(connectionPort).then(async (port) => { if (port) { - window.showInputBox(connectionUsername).then(async (username) => { - window.showInputBox(connectionPassword).then(async (password) => { - window.showInputBox(connectionTls).then(async (tls) => { - let tlsEnabled; - if (tls !== undefined && tls === "true") { - tlsEnabled = true; - } else { - tlsEnabled = false; - } - - // validate if TLS is possible - if (tlsEnabled && ext.openSslVersion === null) { - window - .showErrorMessage( - "OpenSSL not found, please ensure this is installed", - "More Info", - "Cancel" - ) - .then(async (result) => { - if (result === "More Info") { - await openUrl("https://code.kx.com/q/kb/ssl/"); - } - }); - return; - } - - // store secrets - let authUsed = false; - if ( - (username != undefined || username != "") && - (password != undefined || password != "") - ) { - authUsed = true; - ext.secretSettings.storeAuthData( - alias !== undefined - ? getHash(`${hostname}${port}${alias}`) - : getHash(`${hostname}${port}`), - `${username}:${password}` - ); - } - - let servers: Server | undefined = getServers(); - - if ( - servers != undefined && - servers[getHash(`${hostname}:${port}`)] - ) { - await window.showErrorMessage( - `Server ${hostname}:${port} already exists.` - ); - } else { - const key = - alias != undefined - ? getHash(`${hostname}${port}${alias}`) - : getHash(`${hostname}${port}`); - if (servers === undefined) { - servers = { - key: { - auth: authUsed, - serverName: hostname, - serverPort: port, - serverAlias: alias, - managed: alias === "local" ? true : false, - tls: tlsEnabled, - }, - }; - if (servers[0].managed) { - await addLocalConnectionContexts( - getServerName(servers[0]) - ); - } - } else { - servers[key] = { - auth: authUsed, - serverName: hostname, - serverPort: port, - serverAlias: alias, - managed: alias === "local" ? true : false, - tls: tlsEnabled, - }; - if (servers[key].managed) { - await addLocalConnectionContexts( - getServerName(servers[key]) - ); - } - } - - await updateServers(servers); - const newServers = getServers(); - if (newServers != undefined) { - ext.serverProvider.refresh(newServers); - } - } - }); - }); - }); + let servers: Server | undefined = getServers(); + + if ( + servers != undefined && + servers[getHash(`${hostname}:${port}`)] + ) { + await window.showErrorMessage( + `Server ${hostname}:${port} already exists.` + ); + } else { + const key = + alias != undefined + ? getHash(`${hostname}${port}${alias}`) + : getHash(`${hostname}${port}`); + if (servers === undefined) { + servers = { + key: { + auth: false, + serverName: hostname, + serverPort: port, + serverAlias: alias, + managed: alias === "local" ? true : false, + tls: false, + }, + }; + if (servers[0].managed) { + await addLocalConnectionContexts(getServerName(servers[0])); + } + } else { + servers[key] = { + auth: false, + serverName: hostname, + serverPort: port, + serverAlias: alias, + managed: alias === "local" ? true : false, + tls: false, + }; + if (servers[key].managed) { + await addLocalConnectionContexts(getServerName(servers[key])); + } + } + + await updateServers(servers); + const newServers = getServers(); + if (newServers != undefined) { + ext.serverProvider.refresh(newServers); + } + } } }); } @@ -288,6 +307,10 @@ export function addKdbConnection(): void { } export async function removeConnection(viewItem: KdbNode): Promise { + if (viewItem.label.indexOf("connected") !== -1) { + await disconnect(); + } + const servers: Server | undefined = getServers(); const key = @@ -314,6 +337,14 @@ export async function removeConnection(viewItem: KdbNode): Promise { } export async function connectInsights(viewItem: InsightsNode): Promise { + if (env.remoteName === "ssh-remote") { + window.showErrorMessage( + "Connecting to a kdb Insights Enterprise server with a remote connection is not supported.", + "" + ); + return; + } + commands.executeCommand("kdb-results.focus"); await getCurrentToken(viewItem.details.server, viewItem.details.alias); @@ -450,29 +481,29 @@ export async function getDataInsights( export async function importScratchpad( variableName: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any - params: any + params: DataSourceFiles ): Promise { if (ext.connectionNode instanceof InsightsNode) { let queryParams, coreUrl: string; - switch (params.selectedType) { - case "API": + switch (params.dataSource.selectedType) { + case DataSourceTypes.API: queryParams = { - table: params.selectedTable, - startTS: params.startTS, - endTS: params.endTS, + table: params.dataSource.api.table, + startTS: params.dataSource.api.startTS, + endTS: params.dataSource.api.endTS, }; coreUrl = ext.insightsScratchpadUrls.import; break; - case "SQL": - queryParams = { query: params.sql }; + case DataSourceTypes.SQL: + queryParams = { query: params.dataSource.sql.query }; coreUrl = ext.insightsScratchpadUrls.importSql; break; - case "QSQL": - const assemblyParts = params.selectedTarget.split(" "); + case DataSourceTypes.QSQL: + const assemblyParts = params.dataSource.qsql.selectedTarget.split(" "); queryParams = { assembly: assemblyParts[0], target: assemblyParts[1], - query: params.qsql, + query: params.dataSource.qsql.query, }; coreUrl = ext.insightsScratchpadUrls.importQsql; break; @@ -552,6 +583,7 @@ export async function getScratchpadQuery( context?: string ): Promise { if (ext.connectionNode instanceof InsightsNode) { + const isTableView = ext.resultsViewProvider.isVisible(); const scratchpadURL = new url.URL( ext.insightsAuthUrls.scratchpadURL, ext.connectionNode.details.server @@ -582,7 +614,14 @@ export async function getScratchpadQuery( Authorization: `Bearer ${token.accessToken}`, Username: username.preferred_username, }, - body: { expression: query, language: "q", context: context || "." }, + body: { + expression: query, + isTableView, + language: "q", + context: context || ".", + sampleFn: "first", + sampleSize: 10000, + }, json: true, }; @@ -602,7 +641,17 @@ export async function getScratchpadQuery( scratchpadURL.toString(), options ); - + if ( + isTableView && + spRes?.data && + Array.isArray(spRes.data) && + !spRes.error + ) { + const buffer = new Uint8Array( + spRes.data.map((x: string) => parseInt(x, 16)) + ).buffer; + return handleWSResults(buffer); + } return spRes; } ); @@ -614,6 +663,10 @@ export async function getScratchpadQuery( export async function removeInsightsConnection( viewItem: InsightsNode ): Promise { + if (viewItem.label.indexOf("connected") !== -1) { + await disconnect(); + } + const insights: Insights | undefined = getInsights(); const key = getHash(viewItem.details.server); @@ -635,6 +688,7 @@ export async function removeInsightsConnection( export async function connect(viewItem: KdbNode): Promise { commands.executeCommand("kdb-results.focus"); await commands.executeCommand("setContext", "kdb.insightsConnected", false); + const queryConsole = ExecutionConsole.start(); // handle cleaning up existing connection if ( ext.connectionNode !== undefined && @@ -759,8 +813,14 @@ export async function executeQuery( writeScratchpadResult(queryRes, query); } else if (ext.connection !== undefined && ext.connection.connected) { query = sanitizeQuery(query); - const queryRes = await ext.connection.executeQuery(query, context); - writeQueryResult(queryRes, query); + + if (ext.resultsViewProvider.isVisible()) { + const queryRes = await ext.connection.executeQuery(query, context, false); + writeQueryResultsToView(queryRes, query); + } else { + const queryRes = await ext.connection.executeQuery(query, context, true); + writeQueryResultsToConsole(queryRes, query); + } } else { const isConnected = ext.connection ? ext.connection.connected @@ -810,7 +870,7 @@ export function getQueryContext(lineNum?: number): string { return context; } -export function runQuery(type: ExecutionTypes) { +export function runQuery(type: ExecutionTypes, rerunQuery?: string) { const editor = window.activeTextEditor; if (editor) { let context; @@ -830,8 +890,9 @@ export function runQuery(type: ExecutionTypes) { } break; case ExecutionTypes.QueryFile: + case ExecutionTypes.ReRunQuery: default: - query = editor.document.getText(); + query = rerunQuery ? rerunQuery : editor.document.getText(); context = getQueryContext(); } executeQuery(query, context); @@ -863,7 +924,7 @@ export async function loadServerObjects(): Promise { } } -export function writeQueryResult( +export function writeQueryResultsToConsole( result: string | string[], query: string, dataSourceType?: string @@ -890,7 +951,17 @@ export function writeQueryResult( } } -function writeScratchpadResult(result: ScratchpadResult, query: string): void { +export function writeQueryResultsToView( + result: any, + dataSourceType?: string +): void { + commands.executeCommand("kdb.resultsPanel.update", result, dataSourceType); +} + +export function writeScratchpadResult( + result: ScratchpadResult, + query: string +): void { const queryConsole = ExecutionConsole.start(); if (result.error) { @@ -901,10 +972,10 @@ function writeScratchpadResult(result: ScratchpadResult, query: string): void { ext.connectionNode?.label ? ext.connectionNode.label : "" ); } else { - queryConsole.append( - result.data, - query, - ext.connectionNode?.label ? ext.connectionNode.label : "" - ); + if (ext.resultsViewProvider.isVisible()) { + writeQueryResultsToView(result, "SCRATCHPAD"); + } else { + writeQueryResultsToConsole(result.data, query); + } } } diff --git a/src/extension.ts b/src/extension.ts index eeabeaf8..7f8b437b 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -11,6 +11,7 @@ * specific language governing permissions and limitations under the License. */ +import { env } from "node:process"; import path from "path"; import { CancellationToken, @@ -49,10 +50,12 @@ import { stopLocalProcessByServerName, } from "./commands/installTools"; import { + addAuthConnection, addNewConnection, connect, connectInsights, disconnect, + enableTLS, removeConnection, removeInsightsConnection, runQuery, @@ -72,6 +75,10 @@ import { KdbNode, KdbTreeProvider, } from "./services/kdbTreeProvider"; +import { + QueryHistoryProvider, + QueryHistoryTreeItem, +} from "./services/queryHistoryProvider"; import { KdbResultsViewProvider } from "./services/resultsPanelProvider"; import { checkLocalInstall, @@ -96,15 +103,22 @@ export async function activate(context: ExtensionContext) { ext.serverProvider = new KdbTreeProvider(servers!, insights!); ext.dataSourceProvider = new KdbDataSourceProvider(); + ext.queryHistoryProvider = new QueryHistoryProvider(); ext.resultsViewProvider = new KdbResultsViewProvider( ext.context.extensionUri ); + commands.executeCommand("setContext", "kdb.QHOME", env.QHOME); + window.registerTreeDataProvider("kdb-servers", ext.serverProvider); window.registerTreeDataProvider( "kdb-datasources-explorer", ext.dataSourceProvider ); + window.registerTreeDataProvider( + "kdb-query-history", + ext.queryHistoryProvider + ); // initialize local servers if (servers !== undefined) { @@ -142,6 +156,18 @@ export async function activate(context: ExtensionContext) { commands.registerCommand("kdb.connect", async (viewItem: KdbNode) => { await connect(viewItem); }), + + commands.registerCommand( + "kdb.addAuthentication", + async (viewItem: KdbNode) => { + addAuthConnection(viewItem.children[0]); + } + ), + + commands.registerCommand("kdb.enableTLS", async (viewItem: KdbNode) => { + await enableTLS(viewItem.children[0]); + }), + commands.registerCommand( "kdb.insightsConnect", async (viewItem: InsightsNode) => { @@ -170,6 +196,17 @@ export async function activate(context: ExtensionContext) { ext.serverProvider.reload(); ext.connection?.update(); }), + commands.registerCommand( + "kdb.queryHistory.rerun", + (viewItem: QueryHistoryTreeItem) => { + runQuery(ExecutionTypes.ReRunQuery, viewItem.details.query); + } + ), + commands.registerCommand("kdb.queryHistory.clear", () => { + ext.kdbQueryHistoryList.length = 0; + ext.kdbQueryHistoryNodes.length = 0; + ext.queryHistoryProvider.refresh(); + }), commands.registerCommand("kdb.dataSource.addDataSource", async () => { await addDataSource(); }), diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index 0329247e..d8f6bde8 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -16,6 +16,7 @@ import { LanguageClient } from "vscode-languageclient/node"; import { Connection } from "./models/connection"; import { LocalProcess } from "./models/localProcess"; import { MetaObjectPayload } from "./models/meta"; +import { QueryHistory } from "./models/queryHistory"; import { ServerObject } from "./models/serverObject"; import { KdbDataSourceProvider } from "./services/dataSourceTreeProvider"; import { @@ -23,6 +24,7 @@ import { KdbNode, KdbTreeProvider, } from "./services/kdbTreeProvider"; +import { QueryHistoryProvider } from "./services/queryHistoryProvider"; import { KdbResultsViewProvider } from "./services/resultsPanelProvider"; import AuthSettings from "./utils/secretStorage"; @@ -33,6 +35,7 @@ export namespace ext { export let consolePanel: OutputChannel; export let serverProvider: KdbTreeProvider; export let dataSourceProvider: KdbDataSourceProvider; + export let queryHistoryProvider: QueryHistoryProvider; export let resultsViewProvider: KdbResultsViewProvider; export let serverObjects: ServerObject; export let openSslVersion: string | null; @@ -40,13 +43,18 @@ export namespace ext { export const rowLimit = 150000000; export let connection: Connection | undefined; + export let hideDetailedConsoleQueryOutput: boolean; export let connectionNode: KdbNode | InsightsNode | undefined; export const kdbDataSourceFolder = ".kdb-datasources"; export const kdbDataSourceFileExtension = ".ds"; export const kdbDataSourceFileGlob = "*.ds"; export const kdbDataSourceRootNodes: string[] = []; + export const kdbQueryHistoryNodes: string[] = []; + export const kdbQueryHistoryList: QueryHistory[] = []; export const kdbrootNodes: string[] = []; export const kdbinsightsNodes: string[] = []; + export const kdbNodesWithoutAuth: string[] = []; + export const kdbNodesWithoutTls: string[] = []; export const maxRetryCount = 5; export let secretSettings: AuthSettings; diff --git a/src/models/connection.ts b/src/models/connection.ts index f8aa7410..6766cb60 100644 --- a/src/models/connection.ts +++ b/src/models/connection.ts @@ -15,7 +15,10 @@ import * as nodeq from "node-q"; import { commands, window } from "vscode"; import { ext } from "../extensionVariables"; import { delay } from "../utils/core"; -import { handleQueryResults } from "../utils/execution"; +import { + convertArrayOfArraysToObjects, + handleQueryResults, +} from "../utils/execution"; import { queryWrapper } from "../utils/queryUtils"; import { QueryResult, QueryResultType } from "./queryResult"; @@ -92,8 +95,9 @@ export class Connection { public async executeQuery( command: string, - context?: string - ): Promise { + context?: string, + stringify?: boolean + ): Promise { let result; let retryCount = 0; while (this.connection === undefined) { @@ -109,12 +113,16 @@ export class Connection { wrapper, context ?? ".", command, + !!stringify, (err: Error, res: QueryResult) => { if (err) { result = handleQueryResults(err.toString(), QueryResultType.Error); } else if (res) { if (res.errored) { - result = handleQueryResults(res.error, QueryResultType.Error); + result = handleQueryResults( + res.error + (res.backtrace ? "\n" + res.backtrace : ""), + QueryResultType.Error + ); } else { result = res.result; } @@ -126,6 +134,10 @@ export class Connection { await delay(500); } + if (!stringify) { + result = convertArrayOfArraysToObjects(result); + } + return result; } diff --git a/src/models/data.ts b/src/models/data.ts index f2017d38..22acfc2c 100644 --- a/src/models/data.ts +++ b/src/models/data.ts @@ -25,14 +25,14 @@ export type GetDataObjectPayload = { export type getDataBodyPayload = { table: string; - startTS?: string; - endTS?: string; - fill?: string; - temporary?: string; - filter?: string[][]; + startTS: string; + endTS: string; + labels?: { [id: string]: string }; + filter?: (string | number | (string | number)[])[][]; groupBy?: string[]; - agg?: string[]; - sortCols?: string[]; + agg?: string[][]; + fill?: string; + temporality?: string; slice?: string[]; - labels?: string[]; + sortCols?: string[]; }; diff --git a/src/models/dataSource.ts b/src/models/dataSource.ts index bfe7906d..c0a41b63 100644 --- a/src/models/dataSource.ts +++ b/src/models/dataSource.ts @@ -12,13 +12,14 @@ */ export enum DataSourceTypes { - API, - QSQL, - SQL, + API = "API", + QSQL = "QSQL", + SQL = "SQL", } export interface DataSourceFiles { name: string; + originalName?: string; insightsNode?: string; dataSource: { selectedType: DataSourceTypes; @@ -28,13 +29,24 @@ export interface DataSourceFiles { startTS: string; endTS: string; fill: string; - temporary: string; + temporality: string; filter: string[]; groupBy: string[]; agg: string[]; sortCols: string[]; slice: string[]; labels: string[]; + optional?: { + filled: boolean; + temporal: boolean; + startTS: string; + endTS: string; + filters: Filter[]; + labels: Label[]; + sorts: Sort[]; + aggs: Agg[]; + groups: Group[]; + }; }; qsql: { query: string; @@ -46,30 +58,130 @@ export interface DataSourceFiles { }; } -export const defaultDataSourceFile: DataSourceFiles = { - name: "DataSource", - dataSource: { - selectedType: DataSourceTypes.API, - api: { - selectedApi: "", - table: "", - startTS: "", - endTS: "", - fill: "", - temporary: "", - filter: [], - groupBy: [], - agg: [], - sortCols: [], - slice: [], - labels: [], +export function createDefaultDataSourceFile(): DataSourceFiles { + return { + name: "DataSource", + dataSource: { + selectedType: DataSourceTypes.API, + api: { + selectedApi: "", + table: "", + startTS: "", + endTS: "", + fill: "", + temporality: "", + filter: [], + groupBy: [], + agg: [], + sortCols: [], + slice: [], + labels: [], + }, + qsql: { + query: "", + selectedTarget: "", + }, + sql: { + query: "", + }, }, - qsql: { - query: "", - selectedTarget: "", - }, - sql: { - query: "", - }, - }, + }; +} + +export const filterOperators = [ + "in", + "within", + "<", + ">", + "<=", + ">=", + "=", + "<>", + "like", +]; + +export const aggOperators = [ + "all", + "any", + "avg", + "count", + "dev", + "distinct", + "first", + "last", + "max", + "min", + "prd", + "sdev", + "scov", + "sum", + "svar", + "var", +]; + +export type Filter = { + active: boolean; + column: string; + operator: string; + values: string; +}; + +export function createFilter(): Filter { + return { + active: false, + column: "", + operator: "", + values: "", + }; +} + +export type Label = { + active: boolean; + key: string; + value: string; }; + +export function createLabel(): Label { + return { + active: false, + key: "", + value: "", + }; +} + +export type Sort = { + active: boolean; + column: string; +}; + +export function createSort(): Sort { + return { + active: false, + column: "", + }; +} + +export type Agg = { + active: boolean; + key: string; + operator: string; + column: string; +}; + +export function createAgg(): Agg { + return { + active: false, + key: "", + operator: "", + column: "", + }; +} + +export type Group = { + active: boolean; + column: string; +}; + +export function createGroup(): Group { + return createSort(); +} diff --git a/src/models/execution.ts b/src/models/execution.ts index 196ca0a8..87af5cdd 100644 --- a/src/models/execution.ts +++ b/src/models/execution.ts @@ -14,4 +14,5 @@ export enum ExecutionTypes { QuerySelection, QueryFile, + ReRunQuery, } diff --git a/src/models/messages.ts b/src/models/messages.ts new file mode 100644 index 00000000..69f8fc93 --- /dev/null +++ b/src/models/messages.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { DataSourceFiles } from "./dataSource"; +import { MetaObjectPayload } from "./meta"; + +export type DataSourceMessage = { + isInsights: boolean; + insightsMeta: MetaObjectPayload; + dataSourceName: string; + dataSourceFile: DataSourceFiles; +}; diff --git a/src/models/queryHistory.ts b/src/models/queryHistory.ts new file mode 100644 index 00000000..602ea0ba --- /dev/null +++ b/src/models/queryHistory.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { ServerType } from "./server"; + +export interface QueryHistory { + connectionName: string; + connectionType: ServerType; + query: string; + time: string; + success: boolean; +} diff --git a/src/models/queryResult.ts b/src/models/queryResult.ts index 6428f093..450b3c95 100644 --- a/src/models/queryResult.ts +++ b/src/models/queryResult.ts @@ -36,5 +36,5 @@ export enum QueryResultType { } export const queryConstants = { - error: "!@#ERROR^&*%-", + error: "Error:", }; diff --git a/src/models/server.ts b/src/models/server.ts index 0030b5a0..8e51210f 100644 --- a/src/models/server.ts +++ b/src/models/server.ts @@ -11,6 +11,12 @@ * specific language governing permissions and limitations under the License. */ +export enum ServerType { + INSIGHTS, + KDB, + undefined, +} + export interface ServerDetails { serverName: string; serverPort: string; diff --git a/src/panels/datasource.ts b/src/panels/datasource.ts index 5cc79e4a..ede71ece 100644 --- a/src/panels/datasource.ts +++ b/src/panels/datasource.ts @@ -14,6 +14,7 @@ import * as vscode from "vscode"; import { ext } from "../extensionVariables"; import { DataSourceFiles } from "../models/dataSource"; +import { DataSourceMessage } from "../models/messages"; import { InsightsNode } from "../services/kdbTreeProvider"; import { getNonce } from "../utils/getNonce"; import { getUri } from "../utils/getUri"; @@ -23,20 +24,20 @@ export class DataSourcesPanel { private uri; public readonly _panel: vscode.WebviewPanel; private _disposables: vscode.Disposable[] = []; - public static dataSourceFile: DataSourceFiles; + private dataSourceFile: DataSourceFiles; private constructor( panel: vscode.WebviewPanel, extensionUri: vscode.Uri, - datasourceFile: DataSourceFiles + dataSourceFile: DataSourceFiles ) { this.uri = extensionUri; + this.dataSourceFile = dataSourceFile; this._panel = panel; this._panel.onDidDispose(() => this.dispose(), null, this._disposables); this._panel.webview.html = this._getWebviewContent( this._panel.webview, - extensionUri, - datasourceFile + extensionUri ); this._panel.webview.onDidReceiveMessage((message) => { if (message.command === "kdb.dataSource.saveDataSource") { @@ -61,19 +62,20 @@ export class DataSourcesPanel { public static render( extensionUri: vscode.Uri, - datasourceFile: DataSourceFiles + dataSourceFile: DataSourceFiles ) { - this.dataSourceFile = datasourceFile; if (DataSourcesPanel.currentPanel) { DataSourcesPanel.currentPanel.dispose(); } const panel = vscode.window.createWebviewPanel( "dataSource", - datasourceFile.name, + dataSourceFile.name, vscode.ViewColumn.One, { // Enable javascript in the webview enableScripts: true, + // Keep content even when the webview no longer in the foreground + retainContextWhenHidden: true, // Restrict the webview to only load resources from the `out` directory localResourceRoots: [vscode.Uri.joinPath(extensionUri, "out")], } @@ -82,8 +84,10 @@ export class DataSourcesPanel { DataSourcesPanel.currentPanel = new DataSourcesPanel( panel, extensionUri, - datasourceFile + dataSourceFile ); + + DataSourcesPanel.currentPanel.update(); } public static close() { @@ -93,7 +97,7 @@ export class DataSourcesPanel { } public refresh() { - DataSourcesPanel.render(this.uri, DataSourcesPanel.dataSourceFile); + DataSourcesPanel.render(this.uri, this.dataSourceFile); } public dispose() { @@ -109,570 +113,42 @@ export class DataSourcesPanel { } } - private generateTarget( - isInsights: boolean, - isMetaLoaded: boolean, - targetApi: string - ) { - if (isInsights && isMetaLoaded) { - const auxOptions = ext.insightsMeta.dap - .map((dap) => { - const generatedValue = `${dap.assembly}-qe ${dap.instance}`; - const option = `${generatedValue}`; - return option; - }) - .join(""); - return /* html*/ ` - ${auxOptions} - `; - } - return /* html*/ ` - Not connected to Insights - `; - } + private update() { + const dataSourceFile = this.dataSourceFile; + const dataSourceName = dataSourceFile.name; + const insightsMeta = ext.insightsMeta; + const isInsights = ext.connectionNode instanceof InsightsNode; - private generateTables( - isInsights: boolean, - isMetaLoaded: boolean, - targetTable: string - ) { - if (isInsights && isMetaLoaded) { - const auxOptions = ext.insightsMeta.assembly - .flatMap((assembly) => { - return assembly.tbls.map((tbl) => { - const generatedValue = tbl; - const option = `${generatedValue}`; - return option; - }); - }) - .join(""); - return /* html*/ ` - ${auxOptions} - `; - } - return /* html*/ ` - Not connected to Insights - `; - } + const message: DataSourceMessage = { + isInsights, + insightsMeta, + dataSourceName, + dataSourceFile, + }; - private generateApiTarget( - isInsights: boolean, - isMetaLoaded: boolean, - target: string - ) { - return isInsights && isMetaLoaded - ? /* html*/ ` - ${ext.insightsMeta.api - .filter( - (api) => - api.api === ".kxi.getData" || !api.api.startsWith(".kxi.") - ) - .map((api) => { - const generatedValue = - api.api === ".kxi.getData" - ? api.api.replace(".kxi.", "") - : api.api; - return `${generatedValue}`; - }) - .join("")} - ` - : /* html*/ ` - Not connected to Insights - `; - } - - private generateAPIListParams( - listParamType: string, - actualParamArray: string[] - ): string { - let params = ""; - if (actualParamArray.length > 0) { - params = actualParamArray - .map((param, i) => { - return /* html */ `
- -
`; - }) - .join(""); - } else { - params = /* html */ `
- -
`; - } - return params; + this._panel.webview.postMessage(message); } private _getWebviewContent( webview: vscode.Webview, - extensionUri: vscode.Uri, - datasourceFile: DataSourceFiles + extensionUri: vscode.Uri ) { - const isMetaLoaded = ext.insightsMeta.dap ? true : false; - const isInsights = ext.connectionNode instanceof InsightsNode; const webviewUri = getUri(webview, extensionUri, ["out", "webview.js"]); const nonce = getNonce(); - const styleUri = getUri(webview, extensionUri, [ - "out", - "dataSourcesPanel.css", - ]); - const resetStyleUri = getUri(webview, extensionUri, ["out", "reset.css"]); - const vscodeStyleUri = getUri(webview, extensionUri, ["out", "vscode.css"]); - - const tabSelected = - datasourceFile.dataSource.selectedType.toString() === "API" - ? "tab-1" - : datasourceFile.dataSource.selectedType.toString() === "QSQL" - ? "tab-2" - : "tab-3"; - const loadedSelectedType = - datasourceFile.dataSource.selectedType.toString() === "API" - ? "API" - : datasourceFile.dataSource.selectedType.toString() === "QSQL" - ? "QSQL" - : "SQL"; - const filterParams = this.generateAPIListParams( - "filter", - datasourceFile.dataSource.api.filter - ); - const groupByParams = this.generateAPIListParams( - "groupBy", - datasourceFile.dataSource.api.groupBy - ); - const aggParams = this.generateAPIListParams( - "agg", - datasourceFile.dataSource.api.agg - ); - const sortColsParams = this.generateAPIListParams( - "sortCols", - datasourceFile.dataSource.api.sortCols - ); - const sliceParams = this.generateAPIListParams( - "slice", - datasourceFile.dataSource.api.slice - ); - const labelsParams = this.generateAPIListParams( - "labels", - datasourceFile.dataSource.api.labels - ); - - const apiSelected = datasourceFile.dataSource.api.selectedApi; - const tableSelected = datasourceFile.dataSource.api.table; - const startTS = datasourceFile.dataSource.api.startTS; - const endTS = datasourceFile.dataSource.api.endTS; - const fill = datasourceFile.dataSource.api.fill; - const temporary = datasourceFile.dataSource.api.temporary; - const qsql = datasourceFile.dataSource.qsql.query; - const qsqlTarget = datasourceFile.dataSource.qsql.selectedTarget; - const sql = datasourceFile.dataSource.sql.query; - const name = datasourceFile.name; - const targetHtml = this.generateTarget( - isInsights, - isMetaLoaded, - qsqlTarget - ); - - const apiHtml = this.generateApiTarget( - isInsights, - isMetaLoaded, - apiSelected - ); - - const tableHtml = this.generateTables( - isInsights, - isMetaLoaded, - tableSelected - ); - - return /*html*/ ` - - + return /* html */ ` + + - - - - + DataSource -
-
-
-
- - - -
-
- - API - QSQL - SQL - - -
-
- -
-
- -
-
- startTS -
-
- endTS -
-
- fill -
-
- temporary -
-
- - ${filterParams} -
-
- ADD FILTER - REMOVE FILTER -
-
- - ${groupByParams} -
-
- ADD GROUP BY - REMOVE GROUP BY -
-
- - ${aggParams} -
-
- ADD AGG - REMOVE AGG -
-
- - ${sortColsParams} -
-
- ADD SORT COLS - REMOVE SORT COLS -
-
- - ${sliceParams} -
-
- ADD SLICE - REMOVE SLICE -
-
- - ${labelsParams} -
-
- ADD LABEL - REMOVE LABEL -
-
-
- -
-
- -
-
- Query -
- -
-
- -
-
- Query -
-
-
-
-
-
-
-
- SAVE -
-
- RUN -
-
- POPULATE SCRATCHPAD -
-
-
-
-
-
+ - - + `; } } diff --git a/src/services/kdbTreeProvider.ts b/src/services/kdbTreeProvider.ts index 74ddd63b..194099a8 100644 --- a/src/services/kdbTreeProvider.ts +++ b/src/services/kdbTreeProvider.ts @@ -316,6 +316,50 @@ export class KdbNode extends TreeItem { commands.executeCommand("setContext", "kdb.rootNodes", ext.kdbrootNodes); } + // set context for nodes without auth + if (details.auth === false) { + if (ext.kdbNodesWithoutAuth.indexOf(label) === -1) { + ext.kdbNodesWithoutAuth.push(label); + commands.executeCommand( + "setContext", + "kdb.kdbNodesWithoutAuth", + ext.kdbNodesWithoutAuth + ); + } + } else { + const index = ext.kdbNodesWithoutAuth.indexOf(label); + if (index !== -1) { + ext.kdbNodesWithoutAuth.splice(index, 1); + commands.executeCommand( + "setContext", + "kdb.kdbNodesWithoutAuth", + ext.kdbNodesWithoutAuth + ); + } + } + + // set context for nodes without tls + if (details.tls === false) { + if (ext.kdbNodesWithoutTls.indexOf(label) === -1) { + ext.kdbNodesWithoutTls.push(label); + commands.executeCommand( + "setContext", + "kdb.kdbNodesWithoutTls", + ext.kdbNodesWithoutTls + ); + } + } else { + const index = ext.kdbNodesWithoutTls.indexOf(label); + if (index !== -1) { + ext.kdbNodesWithoutTls.splice(index, 1); + commands.executeCommand( + "setContext", + "kdb.kdbNodesWithoutTls", + ext.kdbNodesWithoutTls + ); + } + } + super(label, collapsibleState); this.description = this.getDescription(); } diff --git a/src/services/queryHistoryProvider.ts b/src/services/queryHistoryProvider.ts new file mode 100644 index 00000000..42b0e788 --- /dev/null +++ b/src/services/queryHistoryProvider.ts @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { + Event, + EventEmitter, + MarkdownString, + ProviderResult, + ThemeIcon, + TreeDataProvider, + TreeItem, + TreeItemCollapsibleState, + commands, +} from "vscode"; +import { ext } from "../extensionVariables"; +import { QueryHistory } from "../models/queryHistory"; +import { getConnectionType } from "../utils/queryUtils"; + +type QueryHistoryType = QueryHistoryTreeItem | undefined | void; + +export class QueryHistoryProvider implements TreeDataProvider { + private _onDidChangeTreeData: EventEmitter = + new EventEmitter(); + private queryList = ext.kdbQueryHistoryList; + readonly onDidChangeTreeData: Event = + this._onDidChangeTreeData.event; + + reload(): void { + this._onDidChangeTreeData.fire(); + } + + refresh(): void { + this._onDidChangeTreeData.fire(); + } + + getTreeItem(element: QueryHistoryTreeItem): QueryHistoryTreeItem { + return element; + } + + getChildren( + element?: QueryHistoryTreeItem + ): ProviderResult { + if (!element) { + return this.getQueryHistoryList(); + } else { + return Promise.resolve([]); + } + } + + private getQueryHistoryList(): Promise { + return Promise.resolve( + this.queryList.map((query) => { + const label = query.connectionName + " - " + query.time; + return new QueryHistoryTreeItem( + label, + query, + TreeItemCollapsibleState.None + ); + }) + ); + } +} + +export class QueryHistoryTreeItem extends TreeItem { + constructor( + public label: string, + public readonly details: QueryHistory, + public readonly collapsibleState: TreeItemCollapsibleState + ) { + super(label, collapsibleState); + if (ext.kdbQueryHistoryNodes.indexOf(label) === -1) { + ext.kdbQueryHistoryNodes.push(label); + commands.executeCommand( + "setContext", + "kdb.kdbQueryHistoryList", + ext.kdbQueryHistoryList + ); + } + this.iconPath = new ThemeIcon(this.defineQueryIcon(details.success)); + this.tooltip = this.getTooltip(); + } + + defineQueryIcon(success: boolean): string { + return success ? "testing-passed-icon" : "testing-error-icon"; + } + + getTooltip(): MarkdownString { + const connType = getConnectionType(this.details.connectionType); + const tooltipMd = new MarkdownString(); + tooltipMd.appendMarkdown("### Query History Details\n"); + tooltipMd.appendMarkdown( + "- Connection Name: **" + this.details.connectionName + "** \n" + ); + tooltipMd.appendMarkdown("- Connection Type: **" + connType + "** \n"); + tooltipMd.appendMarkdown("- Time: **" + this.details.time + "** \n"); + tooltipMd.appendMarkdown("- Query:"); + tooltipMd.appendCodeblock(this.details.query, "q"); + return tooltipMd; + } +} + +// export class QueryHistoryNode extends TreeItem { +// constructor(public readonly details: QueryHistory) { +// super(path.basename(resourceUri.fsPath)); +// this.iconPath = new ThemeIcon("circuit-board"); +// this.command = { +// command: "kdb.queryHistory.rerun", +// title: "Rerun Query", +// arguments: [resourceUri], +// }; +// } +// } diff --git a/src/services/resultsPanelProvider.ts b/src/services/resultsPanelProvider.ts index b9df2cca..0c2dcd37 100644 --- a/src/services/resultsPanelProvider.ts +++ b/src/services/resultsPanelProvider.ts @@ -11,7 +11,6 @@ * specific language governing permissions and limitations under the License. */ -import { GridOptions } from "ag-grid-community"; import { ColorThemeKind, Uri, @@ -55,10 +54,7 @@ export class KdbResultsViewProvider implements WebviewViewProvider { }); } - public updateResults( - queryResults: string | string[], - dataSourceType?: string - ) { + public updateResults(queryResults: any, dataSourceType?: string) { if (this._view) { this._view.show?.(true); this._view.webview.postMessage(queryResults); @@ -69,6 +65,28 @@ export class KdbResultsViewProvider implements WebviewViewProvider { } } + public removeEndCommaFromStrings(data: string[]): string[] { + return data.map((element) => { + if (element.endsWith(",")) { + return element.slice(0, -1); + } + return element; + }); + } + + convertToCsv(data: any[]): string[] { + const keys = Object.keys(data[0]); + const header = keys.join(","); + const rows = data.map((obj) => { + return keys + .map((key) => { + return obj[key]; + }) + .join(","); + }); + return [header, ...rows]; + } + exportToCsv() { if (ext.resultPanelCSV === "") { window.showErrorMessage("No results to export"); @@ -83,32 +101,24 @@ export class KdbResultsViewProvider implements WebviewViewProvider { utils.exportToCsv(workspaceUri); } - convertToGrid(queryResult: any): string | GridOptions { - if (queryResult === "") { - return `

No results to show

`; - } - - const vectorRes = - typeof queryResult === "string" - ? utils.convertResultStringToVector(queryResult) - : utils.convertResultToVector(queryResult); - if (vectorRes.length === 1) { - return `

${vectorRes[0]}

`; - } - ext.resultPanelCSV = vectorRes.map((row) => row.join(",")).join("\n"); - const keys = vectorRes[0]; - const value = vectorRes.slice(1); - const rowData = value.map((row) => - keys.reduce((obj: any, key: string, index: number) => { - key = this.sanitizeString(key); - obj[key] = this.sanitizeString(row[index]); - return obj; - }, {}) - ); - const columnDefs = keys.map((str: string) => ({ - field: this.sanitizeString(str), - })); - return { + convertToGrid(queryResult: any[]): string { + const columnDefs = Object.keys(queryResult[0]).map((key: string) => { + const sanitizedKey = this.sanitizeString(key); + return { field: sanitizedKey, headerName: sanitizedKey }; + }); + const rowData = queryResult.map((row: any) => { + for (const key in row) { + if (Object.prototype.hasOwnProperty.call(row, key)) { + row[key] = + row[key] !== undefined && row[key] !== null + ? this.sanitizeString(row[key]) + : ""; + } + } + return row; + }); + ext.resultPanelCSV = this.convertToCsv(rowData).join("\n"); + return JSON.stringify({ defaultColDef: { sortable: true, resizable: true, @@ -122,10 +132,21 @@ export class KdbResultsViewProvider implements WebviewViewProvider { pagination: true, paginationPageSize: 100, cacheBlockSize: 100, - }; + enableCellTextSelection: true, + ensureDomOrder: true, + suppressContextMenu: true, + }); + } + + isVisible(): boolean { + return !!this._view?.visible; } - sanitizeString(str: string): string { + sanitizeString(str: string | string[]): string { + if (str instanceof Array) { + str = str.join(" "); + } + str = str.toString(); str = str.trim(); str = str.replace(/['"`]/g, ""); str = str.replace(/\$\{/g, ""); @@ -139,12 +160,14 @@ export class KdbResultsViewProvider implements WebviewViewProvider { return "ag-theme-alpine"; } - private _getWebviewContent( - queryResult: string | string[], - _dataSourceType?: string - ) { + private _getLibUri(path: string) { + return this._view + ? getUri(this._view.webview, this._extensionUri, ["out", path]) + : ""; + } + + private _getWebviewContent(queryResult: any, _dataSourceType?: string) { ext.resultPanelCSV = ""; - let rowsCount = 0; this._results = queryResult; const agGridTheme = this.defineAgGridTheme(); if (this._view) { @@ -153,71 +176,24 @@ export class KdbResultsViewProvider implements WebviewViewProvider { "webview.js", ]); const nonce = getNonce(); - const styleUri = getUri(this._view.webview, this._extensionUri, [ - "out", - "resultsPanel.css", - ]); - const resetStyleUri = getUri(this._view.webview, this._extensionUri, [ - "out", - "reset.css", - ]); - const vscodeStyleUri = getUri(this._view.webview, this._extensionUri, [ - "out", - "vscode.css", - ]); - const agGridJS = getUri(this._view.webview, this._extensionUri, [ - "out", - "ag-grid-community.min.js", - ]); - const agGridStyle = getUri(this._view.webview, this._extensionUri, [ - "out", - "ag-grid.min.css", - ]); - const agGridThemeStyle = getUri(this._view.webview, this._extensionUri, [ - "out", - "ag-theme-alpine.min.css", - ]); let result = ""; let gridOptionsString = ""; - let rowsLimited = ""; - if (typeof queryResult === "string" && queryResult.endsWith("\n..\n")) { - queryResult = queryResult.slice(0, -4); - rowsLimited = - "

Showing results returned from q instance, that is limited by your q settings"; + + let isGrid = false; + if (typeof queryResult === "string" || typeof queryResult === "number") { + result = + queryResult !== "" + ? `

${queryResult}

` + : "

No results to show

"; } else if ( - queryResult instanceof Array && - queryResult.length > 0 && - queryResult[queryResult.length - 1].endsWith("\n..\n") + typeof queryResult === "object" && + queryResult !== null && + queryResult instanceof Array ) { - queryResult[0] = queryResult[0].slice(0, -4); - rowsLimited = - "

Showing results returned from q instance, that is limited by your q settings"; + isGrid = true; + gridOptionsString = this.convertToGrid(queryResult); } - if (queryResult !== "") { - const convertedGrid = this.convertToGrid(queryResult); - if (typeof convertedGrid === "string") { - result = convertedGrid; - } else { - gridOptionsString = JSON.stringify(convertedGrid); - } - } - const isGrid = - gridOptionsString !== "" && - gridOptionsString !== "

No results to show

"; - const gridOptionsObj = isGrid ? JSON.parse(gridOptionsString) : ""; - const gridRows = isGrid ? [...gridOptionsObj.rowData] : ""; - if (isGrid) { - const totalRowsLenght = JSON.stringify(gridRows).length; - if (totalRowsLenght > ext.rowLimit) { - const sampleRowLength = JSON.stringify(gridRows[0]).length; - rowsCount = Math.round(ext.rowLimit / sampleRowLength); - rowsLimited = `

Showing ${rowsCount} of ${gridRows.length} rows due high amount of data, to retrieve the entire data, export to CSV

`; - const expectedRows = gridRows.slice(0, rowsCount); - gridOptionsObj.rowData = expectedRows; - gridOptionsString = JSON.stringify(gridOptionsObj); - } - } result = gridOptionsString === "" ? result !== "" @@ -230,19 +206,22 @@ export class KdbResultsViewProvider implements WebviewViewProvider { - - - - - + + + + + Q Results - + -
+
${result} - ${rowsLimited}
@@ -253,8 +232,12 @@ export class KdbResultsViewProvider implements WebviewViewProvider { const gridDiv = document.getElementById('grid'); const obj = JSON.parse('${gridOptionsString}'); const gridApi = new agGrid.Grid(gridDiv, obj); + document.getElementById("results").scrollIntoView(); } }); + document.addEventListener('contextmenu', (e) => { + e.stopImmediatePropagation() + }, true); diff --git a/src/services/terminalProvider.ts b/src/services/terminalProvider.ts deleted file mode 100644 index de969630..00000000 --- a/src/services/terminalProvider.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 1998-2023 Kx Systems Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software 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. - */ - -import { EventEmitter, Pseudoterminal, window } from "vscode"; -import { ext } from "../extensionVariables"; - -export function getPty(): Pseudoterminal { - let line = ""; - const emt: EventEmitter = new EventEmitter(); - - const pty = { - onDidWrite: emt.event, - open: () => emt.fire("q)"), - close: () => { - /* noop */ - }, - handleInput: async (data: string) => { - if (data === "\r") { - if (!ext.connection?.connected) { - window.showErrorMessage( - "No active connection, please register/connect to a kdb server" - ); - close(); - } - - const result = await ext.connection?.execute(line); - emt.fire(`\r\n${result}\r\n\r\nq)`); - line = ""; - return; - } - - if (data === "\x7f") { - if (line.length === 0) { - return; - } - line = line.substr(0, line.length - 1); - emt.fire("\x1b[D"); - emt.fire("\x1b[P"); - return; - } - - line += data; - emt.fire(data); - }, - }; - return pty; -} diff --git a/src/utils/core.ts b/src/utils/core.ts index bdd2d8dc..31e35f3e 100644 --- a/src/utils/core.ts +++ b/src/utils/core.ts @@ -171,13 +171,51 @@ export function getServers(): Server | undefined { return workspace.getConfiguration().get("kdb.servers"); } +export function getHideDetailedConsoleQueryOutput(): void { + const setting = workspace + .getConfiguration() + .get("kdb.hideDetailedConsoleQueryOutput"); + if (setting === undefined) { + workspace + .getConfiguration() + .update( + "kdb.hideDetailedConsoleQueryOutput", + true, + ConfigurationTarget.Global + ); + ext.hideDetailedConsoleQueryOutput = true; + } else { + ext.hideDetailedConsoleQueryOutput = setting; + } +} +export function setOutputWordWrapper(): void { + let existWrap = false; + const logConfig = workspace.getConfiguration("[Log]"); + if (logConfig) { + const wordWrap = logConfig["editor.wordWrap"]; + if (wordWrap) { + existWrap = true; + } + } + if (!existWrap) { + workspace + .getConfiguration() + .update( + "[Log]", + { "editor.wordWrap": "off" }, + ConfigurationTarget.Global + ); + } +} + export function getInsights(): Insights | undefined { const configuration = workspace.getConfiguration(); - const insights = - configuration.get("kdb.insightsEnterpriseConnections"); + const insights = configuration.get( + "kdb.insightsEnterpriseConnections" + ); - return insights && Object.keys(insights).length > 0 - ? insights + return insights && Object.keys(insights).length > 0 + ? insights : configuration.get("kdb.insights"); } diff --git a/src/utils/dataSource.ts b/src/utils/dataSource.ts index 57fe4cd0..afcdea63 100644 --- a/src/utils/dataSource.ts +++ b/src/utils/dataSource.ts @@ -14,11 +14,7 @@ import * as fs from "fs"; import path from "path"; import { ext } from "../extensionVariables"; -import { - DataSourceFiles, - DataSourceTypes, - defaultDataSourceFile, -} from "../models/dataSource"; +import { DataSourceFiles } from "../models/dataSource"; import { DataSourcesPanel } from "../panels/datasource"; export function createKdbDataSourcesFolder(): string { @@ -39,72 +35,6 @@ export function createKdbDataSourcesFolder(): string { return kdbDataSourcesFolderPath; } -export function convertDataSourceFormToDataSourceFile( - form: any -): DataSourceFiles { - const insightsNode = getConnectedInsightsNode(); - const fileContent = defaultDataSourceFile; - const filter: string[] = []; - const groupBy: string[] = []; - const agg: string[] = []; - const sortCols: string[] = []; - const slice: string[] = []; - const labels: string[] = []; - fileContent.name = form.name; - fileContent.insightsNode = insightsNode; - fileContent.dataSource.selectedType = form.selectedType as DataSourceTypes; - fileContent.dataSource.api.selectedApi = form.selectedApi; - fileContent.dataSource.api.table = form.selectedTable; - fileContent.dataSource.api.startTS = form.startTS; - fileContent.dataSource.api.endTS = form.endTS; - fileContent.dataSource.api.fill = form.fill; - fileContent.dataSource.api.temporary = form.temporary; - fileContent.dataSource.qsql.query = form.qsql; - fileContent.dataSource.qsql.selectedTarget = form.selectedTarget; - fileContent.dataSource.sql.query = form.sql; - - for (const [key, value] of Object.entries(form)) { - if (key.includes("filter")) { - if (value) { - filter.push(value.toString()); - } - } - if (key.includes("groupBy")) { - if (value) { - groupBy.push(value.toString()); - } - } - if (key.includes("agg")) { - if (value) { - agg.push(value.toString()); - } - } - if (key.includes("sortCols")) { - if (value) { - sortCols.push(value.toString()); - } - } - if (key.includes("slice")) { - if (value) { - slice.push(value.toString()); - } - } - if (key.includes("labels")) { - if (value) { - labels.push(value.toString()); - } - } - } - fileContent.dataSource.api.filter = filter; - fileContent.dataSource.api.groupBy = groupBy; - fileContent.dataSource.api.agg = agg; - fileContent.dataSource.api.sortCols = sortCols; - fileContent.dataSource.api.slice = slice; - fileContent.dataSource.api.labels = labels; - - return fileContent; -} - export function convertTimeToTimestamp(time: string): string { try { const date = new Date(time); @@ -167,3 +97,9 @@ export function refreshDataSourcesPanel(): void { DataSourcesPanel.currentPanel.refresh(); } } + +export function convertDataSourceFormToDataSourceFile( + form: any +): DataSourceFiles { + return form as DataSourceFiles; +} diff --git a/src/utils/execution.ts b/src/utils/execution.ts index cd85e655..64ac6912 100644 --- a/src/utils/execution.ts +++ b/src/utils/execution.ts @@ -15,7 +15,7 @@ import { env } from "node:process"; import path from "path"; import { Uri, window, workspace } from "vscode"; import { ext } from "../extensionVariables"; -import { QueryResultType, queryConstants } from "../models/queryResult"; +import { QueryResultType } from "../models/queryResult"; interface tblHeader { label: string; @@ -57,7 +57,7 @@ export function handleQueryResults( // break; case QueryResultType.Error: default: - handledResult = queryConstants.error + results; + handledResult = results; break; } return handledResult; @@ -124,3 +124,31 @@ export async function exportToCsv(workspaceUri: Uri): Promise { await workspace.fs.writeFile(filePath, Buffer.from(ext.resultPanelCSV)); window.showTextDocument(filePath, { preview: false }); } + +export function convertArrayOfArraysToObjects(arr: any): any[] { + if (!Array.isArray(arr) || arr.length === 0) { + return arr; + } + + const firstRow = arr[0]; + if (!Array.isArray(firstRow) || firstRow.length === 0) { + return arr; + } + + const numColumns = firstRow.length; + const result: any[] = []; + + for (let i = 0; i < numColumns; i++) { + const obj: any = {}; + for (const row of arr) { + if (!Array.isArray(row) || row.length !== numColumns) { + return []; + } + const key = Object.keys(row[i])[0]; + obj[key] = row[i][key]; + } + result.push(obj); + } + + return result; +} diff --git a/src/utils/executionConsole.ts b/src/utils/executionConsole.ts index 211faa91..21628eea 100644 --- a/src/utils/executionConsole.ts +++ b/src/utils/executionConsole.ts @@ -12,6 +12,14 @@ */ import { OutputChannel, commands, window } from "vscode"; +import { ext } from "../extensionVariables"; +import { QueryHistory } from "../models/queryHistory"; +import { ServerType } from "../models/server"; +import { KdbNode } from "../services/kdbTreeProvider"; +import { + getHideDetailedConsoleQueryOutput, + setOutputWordWrapper, +} from "./core"; import { convertRowsToConsole } from "./queryUtils"; export class ExecutionConsole { @@ -23,6 +31,7 @@ export class ExecutionConsole { } public static start(): ExecutionConsole { + setOutputWordWrapper(); if (!ExecutionConsole.current) { const _console = window.createOutputChannel("q Console Output"); ExecutionConsole.current = new ExecutionConsole(_console); @@ -68,6 +77,8 @@ export class ExecutionConsole { serverName: string, dataSourceType?: string ): void { + getHideDetailedConsoleQueryOutput(); + const hideDetails = ext.hideDetailedConsoleQueryOutput; output = this.checkOutput(output, query); let dataSourceRes: string[] = []; if (dataSourceType === undefined) { @@ -77,24 +88,32 @@ export class ExecutionConsole { dataSourceRes = convertRowsToConsole(output); } } + const connectionType: ServerType = + ext.connectionNode instanceof KdbNode + ? ServerType.KDB + : ServerType.INSIGHTS; + addQueryHistory(query, serverName, connectionType, true); + //TODO: this._console.clear(); Add an option in the future to clear or not the console const date = new Date(); - this._console.appendLine( - `>>> ${serverName} @ ${date.toLocaleTimeString()} <<<` - ); - this.appendQuery(query); + if (!hideDetails) { + this._console.appendLine( + `>>> ${serverName} @ ${date.toLocaleTimeString()} <<<` + ); + this.appendQuery(query); + } if (Array.isArray(output) && dataSourceType === undefined) { this._console.appendLine(output[0]); output.forEach((o) => this._console.appendLine(o)); } else if (dataSourceRes.length > 0) { dataSourceRes.forEach((o) => this._console.appendLine(o)); - this.rendResults(output, dataSourceType); } else { output = Array.isArray(output) ? output.join("\n") : output; this._console.appendLine(output); - this.rendResults(output, dataSourceType); } - this._console.appendLine(`<<<\n`); + if (!hideDetails) { + this._console.appendLine(`<<<\n`); + } } public appendQueryError( @@ -103,36 +122,60 @@ export class ExecutionConsole { isConnected: boolean, serverName: string ): void { + getHideDetailedConsoleQueryOutput(); + const hideDetails = ext.hideDetailedConsoleQueryOutput; this._console.show(true); //TODO: this._console.clear(); Add an option in the future to clear or not the console const date = new Date(); - this._console.appendLine( - `<<< ERROR - ${serverName} @ ${date.toLocaleTimeString()} >>>` - ); + if (!hideDetails) { + this._console.appendLine( + `<<< ERROR - ${serverName} @ ${date.toLocaleTimeString()} >>>` + ); + } if (isConnected) { - this._console.appendLine(`ERROR Query executed: ${query}`); - this._console.appendLine(result); + const connectionType: ServerType = + ext.connectionNode instanceof KdbNode + ? ServerType.KDB + : ServerType.INSIGHTS; + if (!hideDetails) { + this._console.appendLine(`ERROR Query executed: ${query}\n`); + this._console.appendLine(result); + } else { + this._console.appendLine(`Error: ${result}`); + } + addQueryHistory(query, serverName, connectionType, false); } else { window.showErrorMessage(`Please connect to a kdb+ server`); this._console.appendLine(`Please connect to a kdb+ server`); commands.executeCommand("kdb.disconnect"); + addQueryHistory(query, "No connection", ServerType.undefined, false); + } + if (!hideDetails) { + this._console.appendLine(`<<< >>>`); } - this._console.appendLine(`<<< >>>`); } // this to debug in case debug of extension doesn't work public appendQueryDebug(msg: string) { this._console.appendLine(msg); } - - public rendResults(query: string | string[], dataSourceType?: string) { - if (dataSourceType !== undefined) { - commands.executeCommand("kdb-results.focus"); - } - commands.executeCommand("kdb.resultsPanel.update", query, dataSourceType); - } } -export function appendQuery(query: string) { - throw new Error("Function not implemented."); +export function addQueryHistory( + query: string, + connectionName: string, + connectionType: ServerType, + success: boolean +) { + const newQueryHistory: QueryHistory = { + query: query, + time: new Date().toLocaleString(), + success, + connectionName, + connectionType, + }; + + ext.kdbQueryHistoryList.unshift(newQueryHistory); + + ext.queryHistoryProvider.refresh(); } diff --git a/src/utils/queryUtils.ts b/src/utils/queryUtils.ts index c4d39775..8bedff78 100644 --- a/src/utils/queryUtils.ts +++ b/src/utils/queryUtils.ts @@ -16,6 +16,7 @@ import { join } from "path"; import { ext } from "../extensionVariables"; import { deserialize, isCompressed, uncompress } from "../ipc/c"; import { Parse } from "../ipc/parse.qlist"; +import { ServerType } from "../models/server"; export function sanitizeQuery(query: string): string { if (query[0] === "`") { @@ -46,6 +47,9 @@ export function handleWSResults(ab: ArrayBuffer): any { if (res.rows.length === 0) { return "No results found."; } + if (ext.resultsViewProvider.isVisible()) { + return getValueFromArray(res.rows); + } return convertRows(res.rows); } catch (error) { console.log(error); @@ -53,15 +57,31 @@ export function handleWSResults(ab: ArrayBuffer): any { } } +export function getValueFromArray(arr: any[]): string | any[] { + if (arr.length === 1 && typeof arr[0] === "object" && arr[0] !== null) { + const obj = arr[0]; + const keys = Object.keys(obj); + if (keys.length === 1 && keys[0] === "Value") { + return String(obj.Value); + } + } + return arr; +} + export function convertRows(rows: any[]): any[] { if (rows.length === 0) { return []; } const keys = Object.keys(rows[0]); - const result = [keys.join(",")]; + const result = [keys.join("#$#;#$#")]; for (const row of rows) { - const values = keys.map((key) => row[key]); - result.push(values.join(",")); + const values = keys.map((key) => { + if (Array.isArray(row[key])) { + return row[key].join(" "); + } + return row[key]; + }); + result.push(values.join("#$#;#$#")); } return result; } @@ -71,36 +91,28 @@ export function convertRowsToConsole(rows: string[]): string[] { return []; } - const vector = []; - for (let i = 0; i < rows.length; i++) { - vector.push(rows[i].split(",")); - } + const vector = rows.map((row) => row.split("#$#;#$#")); - const columnCounters = []; - for (let j = 0; j < vector[0].length; j++) { - let maxLength = 0; - for (let i = 0; i < vector.length; i++) { - maxLength = Math.max(maxLength, vector[i][j].length); - } - columnCounters.push(maxLength + 2); - } + const columnCounters = vector[0].reduce((counters: number[], _, j) => { + const maxLength = vector.reduce( + (max, row) => Math.max(max, row[j].length), + 0 + ); + counters.push(maxLength + 2); + return counters; + }, []); - for (let i = 0; i < vector.length; i++) { - const row = vector[i]; - for (let j = 0; j < row.length; j++) { - const value = row[j]; + vector.forEach((row) => { + row.forEach((value, j) => { const counter = columnCounters[j]; const diff = counter - value.length; if (diff > 0) { row[j] = value + " ".repeat(diff); } - } - } + }); + }); - const result = []; - for (let i = 0; i < vector.length; i++) { - result.push(vector[i].join("")); - } + const result = vector.map((row) => row.join("")); const totalCount = columnCounters.reduce((sum, count) => sum + count, 0); const totalCounter = "-".repeat(totalCount); @@ -108,3 +120,14 @@ export function convertRowsToConsole(rows: string[]): string[] { return result; } + +export function getConnectionType(type: ServerType): string { + switch (type) { + case ServerType.KDB: + return "kdb"; + case ServerType.INSIGHTS: + return "insights"; + default: + return "undefined"; + } +} diff --git a/src/validators/azureValidator.ts b/src/validators/azureValidator.ts deleted file mode 100644 index 80a34dfb..00000000 --- a/src/validators/azureValidator.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 1998-2023 Kx Systems Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software 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. - */ - -import { ResourceGroups } from "@azure/arm-resources"; -import { Debounce } from "./debounceValidation"; -import { Validator } from "./validator"; - -const debounce = new Debounce(); - -export async function validateResourceGroupName( - name: string, - resourceGroups: ResourceGroups -): Promise { - const errors = new Validator(name) - .isNotEmpty() - .hasNoForbiddenChar( - new RegExp("/^(?=.*[.]$).*$/g"), - "Input value must not have '.' at the end." - ) - .hasNoForbiddenChar( - new RegExp("/[#`*\"'%;,!@$^&+=?/<>|[]{}:\\~]/g"), - "'#', '`', '*', '\"', ''', '%', ';', ',', '!', '@', '$', '^', '&', '+', '=', '?', '/', '<', '>', '|', '[', ']', '{', '}', ':', '\\', '~'" - ) - .inLengthRange(1, 90) - .getErrors(); - - if (errors) { - return "Invalid resource group name"; - } - - const timeOverFunction = buildTimeOverFunction( - name, - resourceGroups.checkExistence.bind(resourceGroups), - "A resource group with the same name already exists." - ); - - return await debounce.debounced(timeOverFunction); -} - -function buildTimeOverFunction( - name: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - checkExistence: (name: string) => Promise, - errorMessage: string -): () => Promise { - return async () => { - const validator = new Validator(name); - - await validator.isAvailable(checkExistence, errorMessage); - - return validator.getErrors(); - }; -} diff --git a/src/validators/debounceValidation/index.ts b/src/validators/debounceValidation/index.ts deleted file mode 100644 index c42fac86..00000000 --- a/src/validators/debounceValidation/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1998-2023 Kx Systems Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software 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. - */ - -export class Debounce { - private debounceEvent: { - timeout?: NodeJS.Timeout; - resolve?: (value: string | null) => void; - } = {}; - - private readonly timeout: number; - - constructor(options: { timeout: number } = { timeout: 300 }) { - this.timeout = options.timeout; - } - - public debounced( - timeOverFunction: () => Promise - ): Promise { - if (this.debounceEvent.timeout) { - this.debounceEvent.resolve!(null); - clearTimeout(this.debounceEvent.timeout); - } - - return new Promise((resolve, reject) => { - this.debounceEvent.resolve = resolve; - - this.debounceEvent.timeout = setTimeout(async () => { - try { - resolve(await timeOverFunction()); - } catch (e) { - reject(e); - } finally { - this.debounceEvent.timeout = undefined; - this.debounceEvent.resolve = undefined; - } - }, this.timeout); - }); - } -} diff --git a/src/validators/validationFunctions/hasLowerCase.ts b/src/validators/validationFunctions/hasLowerCase.ts index 1e2130f7..c7a5e687 100644 --- a/src/validators/validationFunctions/hasLowerCase.ts +++ b/src/validators/validationFunctions/hasLowerCase.ts @@ -15,7 +15,7 @@ import { IRule } from "../rule"; export class HasLowerCase implements IRule { public validate(value: string): string | null { - const hasLowerCase = value.search("/(?=.*[a-z]).*/g") !== -1; + const hasLowerCase = value.search("[a-z]+") !== -1; return hasLowerCase ? null : "Password should have at least one lowercase letter from a to z."; diff --git a/src/validators/validationFunctions/isAvailable.ts b/src/validators/validationFunctions/isAvailable.ts deleted file mode 100644 index 11153742..00000000 --- a/src/validators/validationFunctions/isAvailable.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 1998-2023 Kx Systems Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software 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. - */ - -import { IRule } from "../rule"; - -export class IsAvailable implements IRule { - constructor( - private readonly checkAvailable: (name: string) => Promise< - | { - message: string | null; - nameAvailable: boolean; - reason: string; - } - | boolean - >, - private readonly errorMessage?: string - ) {} - - public async validate(name: string): Promise { - if (!!name) { - const response = (await this.checkAvailable(name)) as { - message: string; - nameAvailable: boolean; - reason: string; - }; - if ( - response && - !response.nameAvailable && - response.reason === "AlreadyExists" - ) { - return this.errorMessage || response.message; - } - } - return null; - } -} diff --git a/src/validators/validator.ts b/src/validators/validator.ts index 3c2285f6..dedb30a5 100644 --- a/src/validators/validator.ts +++ b/src/validators/validator.ts @@ -15,7 +15,6 @@ import { IRule } from "./rule"; import { HasLowerCase } from "./validationFunctions/hasLowerCase"; import { HasNoForbiddenChar } from "./validationFunctions/hasNoForbiddenChar"; import { HasSpecialChar } from "./validationFunctions/hasSpecialChar"; -import { IsAvailable } from "./validationFunctions/isAvailable"; import { IsNotEmpty } from "./validationFunctions/isNotEmpty"; import { LengthRange } from "./validationFunctions/lengthRange"; @@ -56,30 +55,10 @@ export class Validator { return this; } - public async isAvailable( - checkAvailable: ( - name: string - ) => Promise< - | { message: string | null; nameAvailable: boolean; reason: string } - | boolean - >, - errorMessage: string - ): Promise { - await this.validate(new IsAvailable(checkAvailable, errorMessage)); - return this; - } - private validateSync(fn: IRule): void { const error = fn.validate(this.value) as string | null; if (error) { this.errors.add(error); } } - - private async validate(fn: IRule): Promise { - const error = await fn.validate(this.value); - if (error) { - this.errors.add(error); - } - } } diff --git a/src/webview/components/kdbDataSourceView.ts b/src/webview/components/kdbDataSourceView.ts new file mode 100644 index 00000000..704c3e61 --- /dev/null +++ b/src/webview/components/kdbDataSourceView.ts @@ -0,0 +1,947 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { LitElement, html } from "lit"; +import { customElement, state } from "lit/decorators.js"; +import { + Agg, + DataSourceFiles, + DataSourceTypes, + Filter, + Group, + Label, + Sort, + aggOperators, + createAgg, + createFilter, + createGroup, + createLabel, + createSort, + filterOperators, +} from "../../models/dataSource"; +import { DataSourceMessage } from "../../models/messages"; +import { MetaObjectPayload } from "../../models/meta"; +import { kdbStyles, vscodeStyles } from "./styles"; + +const MAX_RULES = 32; + +@customElement("kdb-data-source-view") +export class KdbDataSourceView extends LitElement { + static styles = [vscodeStyles, kdbStyles]; + + @state() declare isInsights: boolean; + @state() declare isMetaLoaded: boolean; + @state() declare insightsMeta: MetaObjectPayload; + @state() declare originalName: string; + @state() declare name: string; + @state() declare selectedType: DataSourceTypes; + @state() declare selectedApi: string; + @state() declare selectedTable: string; + @state() declare startTS: string; + @state() declare endTS: string; + @state() declare fill: string; + @state() declare filled: boolean; + @state() declare temporality: string; + @state() declare temporal: boolean; + @state() declare sliceStartTS: string; + @state() declare sliceEndTS: string; + @state() declare filters: Filter[]; + @state() declare labels: Label[]; + @state() declare sorts: Sort[]; + @state() declare aggs: Agg[]; + @state() declare groups: Group[]; + @state() declare qsqlTarget: string; + @state() declare qsql: string; + @state() declare sql: string; + + constructor() { + super(); + this.isInsights = false; + this.isMetaLoaded = false; + this.insightsMeta = {} as MetaObjectPayload; + this.originalName = ""; + this.name = ""; + this.selectedType = DataSourceTypes.API; + this.selectedApi = ""; + this.selectedTable = ""; + this.startTS = ""; + this.endTS = ""; + this.fill = ""; + this.filled = false; + this.temporality = ""; + this.temporal = false; + this.sliceStartTS = ""; + this.sliceEndTS = ""; + this.filters = [createFilter()]; + this.labels = [createLabel()]; + this.sorts = [createSort()]; + this.aggs = [createAgg()]; + this.groups = [createGroup()]; + this.qsqlTarget = ""; + this.qsql = ""; + this.sql = ""; + } + + connectedCallback() { + super.connectedCallback(); + window.addEventListener("message", this.message); + } + + disconnectedCallback() { + window.removeEventListener("message", this.message); + super.disconnectedCallback(); + } + + private message = (event: MessageEvent) => { + const params = event.data; + const ds = params.dataSourceFile; + this.isInsights = params.isInsights; + this.isMetaLoaded = !!params.insightsMeta.dap; + this.insightsMeta = params.insightsMeta; + this.originalName = params.dataSourceName; + this.name = params.dataSourceName; + this.selectedType = ds.dataSource.selectedType; + this.selectedApi = ds.dataSource.api.selectedApi; + this.selectedTable = ds.dataSource.api.table; + this.startTS = ds.dataSource.api.startTS; + this.endTS = ds.dataSource.api.endTS; + this.fill = ds.dataSource.api.fill; + this.temporality = ds.dataSource.api.temporality; + this.qsqlTarget = ds.dataSource.qsql.selectedTarget; + this.qsql = ds.dataSource.qsql.query; + this.sql = ds.dataSource.sql.query; + const optional = ds.dataSource.api.optional; + if (optional) { + this.filled = optional.filled; + this.temporal = optional.temporal; + this.sliceStartTS = optional.startTS; + this.sliceEndTS = optional.endTS; + this.filters = optional.filters; + this.labels = optional.labels; + this.sorts = optional.sorts; + this.aggs = optional.aggs; + this.groups = optional.groups; + } + }; + + private get data(): DataSourceFiles { + return { + name: this.name, + originalName: this.originalName, + dataSource: { + selectedType: this.selectedType, + api: { + selectedApi: this.selectedApi, + table: this.selectedTable, + startTS: this.startTS, + endTS: this.endTS, + fill: this.fill, + temporality: this.temporality, + filter: [], + groupBy: [], + agg: [], + sortCols: [], + slice: [], + labels: [], + optional: { + filled: this.filled, + temporal: this.temporal, + startTS: this.sliceStartTS, + endTS: this.sliceEndTS, + filters: this.filters, + labels: this.labels, + sorts: this.sorts, + aggs: this.aggs, + groups: this.groups, + }, + }, + qsql: { + query: this.qsql, + selectedTarget: this.qsqlTarget, + }, + sql: { + query: this.sql, + }, + }, + }; + } + + private readonly vscode = acquireVsCodeApi(); + + private get selectedTab() { + switch (this.selectedType) { + case DataSourceTypes.API: + return "tab-1"; + case DataSourceTypes.QSQL: + return "tab-2"; + case DataSourceTypes.SQL: + return "tab-3"; + default: + return "tab-1"; + } + } + + private save() { + this.vscode.postMessage({ + command: "kdb.dataSource.saveDataSource", + data: this.data, + }); + } + + private run() { + this.vscode.postMessage({ + command: "kdb.dataSource.runDataSource", + data: this.data, + }); + } + + private populateScratchpad() { + this.vscode.postMessage({ + command: "kdb.dataSource.populateScratchpad", + data: this.data, + }); + } + + private renderApiOptions(selected: string) { + if (this.isInsights && this.isMetaLoaded) { + return html` + ${this.insightsMeta.api + .filter( + (api) => api.api === ".kxi.getData" || !api.api.startsWith(".kxi.") + ) + .map((api) => { + const value = + api.api === ".kxi.getData" + ? api.api.replace(".kxi.", "") + : api.api; + + return html` + ${value} + `; + })} + `; + } + return []; + } + + private renderTableOptions(selected: string) { + if (this.isInsights && this.isMetaLoaded) { + return this.insightsMeta.assembly.flatMap((assembly) => { + return assembly.tbls.map((value) => { + if (!this.selectedTable) { + this.selectedTable = value; + } + return html` + ${value} + `; + }); + }); + } + return []; + } + + private renderColumnOptions(selected: string) { + if (this.isInsights && this.isMetaLoaded) { + const schema = this.insightsMeta.schema; + if (schema) { + const found = schema.find((item) => item.table === this.selectedTable); + if (found) { + return found.columns.map( + ({ column }) => + html` + ${column} + ` + ); + } + } + } + return []; + } + + private renderTargetOptions(selected: string) { + if (this.isInsights && this.isMetaLoaded) { + return this.insightsMeta.dap.map((dap) => { + const value = `${dap.assembly}-qe ${dap.instance}`; + return html` + ${value} + `; + }); + } + return []; + } + + private renderFilter(filter: Filter) { + return html` +
+ + + + ${this.filters.indexOf(filter) === 0 ? "Set Parameter" : ""} + +
+ + + - +
+
+ `; + } + + private renderLabel(label: Label) { + return html` +
+ + ${this.labels.indexOf(label) === 0 + ? "Filter By Label" + : ""} + ${this.labels.indexOf(label) === 0 ? "Value" : ""} +
+ + + - +
+
+ `; + } + + private renderSort(sort: Sort) { + return html` +
+ + +
+ + + - +
+
+ `; + } + + private renderAgg(agg: Agg) { + return html` +
+ + ${this.aggs.indexOf(agg) === 0 + ? "Define Output Aggregate" + : ""} + + +
+ + + - +
+
+ `; + } + + private renderGroup(group: Group) { + return html` +
+ + +
+ + + - +
+
+ `; + } + + render() { + return html` +
+
+
+ Data Source Name +
+ +
+ + API + QSQL + SQL + +
+
+ +
+ +
+ +
+ +
+ Start Time +
+ +
+ End Time +
+ +
+ + +
+ +
+ + + Start Time + End Time +
+ +
+ ${this.filters.map((filter) => this.renderFilter(filter))} +
+
+ ${this.labels.map((label) => this.renderLabel(label))} +
+
+ ${this.sorts.map((sort) => this.renderSort(sort))} +
+
+ ${this.aggs.map((agg) => this.renderAgg(agg))} +
+
+ ${this.groups.map((group) => this.renderGroup(group))} +
+
+
+ + +
+
+ +
+
+ Query +
+
+
+ + +
+
+ Query +
+
+
+
+
+
+
+
+ Save + Run +
+ Populate Scratchpad +
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "kdb-data-source-view": KdbDataSourceView; + } +} diff --git a/src/webview/components/styles.ts b/src/webview/components/styles.ts new file mode 100644 index 00000000..62a30dbc --- /dev/null +++ b/src/webview/components/styles.ts @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import { css } from "lit"; + +export const vscodeStyles = css` + .dropdown-container { + box-sizing: border-box; + display: flex; + flex-flow: column nowrap; + align-items: flex-start; + justify-content: flex-start; + } + + .dropdown-container label { + display: block; + color: var(--vscode-foreground); + cursor: pointer; + font-size: var(--vscode-font-size); + line-height: normal; + margin-bottom: 2px; + } +`; + +export const kdbStyles = css` + .w-full { + min-width: 50em; + } + + .col { + display: flex; + flex-direction: column; + gap: 1em; + } + + .row { + display: flex; + flex-direction: row; + gap: 1em; + } + + .align-start { + justify-content: flex-start; + } + + .align-end { + justify-content: flex-end; + } + + .align-top { + align-items: flex-start; + } + + .align-bottom { + align-items: flex-end; + } + + .gap-1 { + gap: 4px; + } + + .grow { + flex-grow: 1; + } + + .mt-1 { + margin-top: 1em; + } + + .mb-1 { + margin-bottom: 1em; + } + + .mt-6 { + margin-top: 6em; + } + + .dropdown, + .text-field { + width: 12em; + } + + .dropdown.larger, + .text-field.larger { + width: 14.5em; + } +`; diff --git a/src/webview/main.ts b/src/webview/main.ts index 9adab0a5..0e9f8b37 100644 --- a/src/webview/main.ts +++ b/src/webview/main.ts @@ -15,5 +15,6 @@ import { allComponents, provideVSCodeDesignSystem, } from "@vscode/webview-ui-toolkit"; +import "./components/kdbDataSourceView"; provideVSCodeDesignSystem().register(allComponents); diff --git a/src/webview/styles/resultsPanel.css b/src/webview/styles/resultsPanel.css index b9cba75f..1ac18633 100644 --- a/src/webview/styles/resultsPanel.css +++ b/src/webview/styles/resultsPanel.css @@ -1,6 +1,6 @@ html, body { - height: 100vh; + height: 86vh; width: 100%; box-sizing: border-box; -webkit-overflow-scrolling: touch; diff --git a/syntaxes/q.tmLanguage.json b/syntaxes/q.tmLanguage.json index 3c506cc3..95783a3a 100644 --- a/syntaxes/q.tmLanguage.json +++ b/syntaxes/q.tmLanguage.json @@ -9,332 +9,272 @@ "include": "#strings" }, { - "include": "#constants" + "include": "#qcumber" }, { - "include": "#keywords" + "include": "#operators" + }, + { + "include": "#commands" }, { - "include": "#function" + "include": "#literals" }, { - "include": "#invalids" + "include": "#keywords" + }, + { + "include": "#identifiers" } ], "repository": { "comments": { "patterns": [ { - "name": "comment.inline.q", - "match": "\\s/.*" + "name": "comment.block.q", + "begin": "^\\/\\s*$", + "end": "^\\\\\\s*$" }, { - "begin": "^(//?)(?:\\s*)(!.*)", - "end": "(?=^)", - "beginCaptures": { - "1": { - "name": "comment.line.slash.q" - }, - "2": { - "name": "comment.line.attention.q" + "name": "comment.line.q", + "match": "(?:(?<=\\r?\\n|[ \\t])|(?~|&]" + }, + { + "name": "keyword.other.control.q", + "match": "[\\/\\\\':]:" + }, + { + "name": "keyword.other.control.q", + "match": "[$!?#@'^]" + }, + { + "name": "punctuation.assignment.q", + "match": ":" + }, + { + "name": "punctuation.terminator.statement.q", + "match": ";" } ] }, - "invalids": { + "commands": { "patterns": [ { - "name": "invalid.illegal.bracket.q", - "match": "^[}\\]\\)].*" + "name": "constant.character.q", + "match": "\\\\(ts|cd|[arsbBSctCTdueEvfwgWlxzo12p_P\\\\])" } ] }, - "constants": { + "literals": { "patterns": [ { - "name": "support.function.utility.q", - "match": "\\.Q\\.(a|A|addmonths|addr|b6|bt|btoa|bv|Cf|chk|cn|D|dd|def|dpft|dpfts|dsftg|en|ens|f|fc|ff|fk|fmt|fps|fs|fsn|ft|fu|gc|gz|hdpf|hg|host|hp|id|ind|j10|j12|k|l|M|MAP|nA|opt|P|par|pd|PD|pf|pn|pt|pv|PV|qp|qt|res|S|s|s1|sbt|sha1|trp|ts|ty|u|v|V|view|vp|w|x|x10|x12|Xf)\\b" + "name": "support.type.symbol.q", + "match": "`:?[.\\w]*" }, { - "name": "support.function.json.q", - "match": "\\.j\\.(j|k|jd)\\b" + "name": "constant.numeric.timestamp.q", + "match": "\\d{4}\\.\\d{2}\\.\\d{2}D\\d{2}:\\d{2}:\\d{2}\\.\\d{9}" }, { - "name": "support.function.callback.q", - "match": "\\.z\\.(ac|bm|exit|p[cdghiopqsw]|ts|vs|w[cos])\\b" + "name": "constant.numeric.datetime.q", + "match": "\\d{4}\\.\\d{2}\\.\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}" }, { - "name": "support.constant.system.info.q", - "match": "\\.z\\.([a-fhiklno-qstuwxzDKNPTWXZ]|ex|ey|pm|zd)\\b" + "name": "constant.numeric.date.q", + "match": "\\d{4}\\.\\d{2}\\.\\d{2}" }, { - "name": "support.function.http.q", - "match": "\\.h\\.(br|c0|c1|cd|code|d|ed|edsn|fram|ha|hb|hc|he|hn|HOME|hp|hr|ht|hta|htac|htc|html|http|hu|hug|hy|iso8601|jx|logo|nbr|pre|sa|sb|sc|td|text|tx|ty|uh|val|xd|xmp|xs|xt)\\b" + "name": "constant.numeric.month.q", + "match": "\\d{4}\\.\\d{2}m" }, { - "name": "constant.language.null.q", - "match": "\\b0(N[ghijepmdznuvt]?|n)\\b" + "name": "constant.numeric.nanotime.q", + "match": "(?:0D)?\\d{2}:\\d{2}:\\d{2}\\.\\d{9}" }, - { - "name": "support.function.internal.q", - "match": "\\-([1-9]|1[0-689]|2[0-79]|3[01368]|120)!" + "name": "constant.numeric.militime.q", + "match": "\\d{2}:\\d{2}:\\d{2}\\.\\d{3}" }, { - "name": "constant.language.boolean.q", - "match": "\\b[01]+b\\b" + "name": "constant.numeric.second.q", + "match": "\\d{2}:\\d{2}:\\d{2}" }, { - "name": "support.function.file.q", - "match": "\\b(0:|1:|2:)" + "name": "constant.numeric.minute.q", + "match": "\\d{2}:\\d{2}" }, { - "name": "constant.language.infinity.q", - "match": "-?0(W[hijepdnutv]?|wz?)\\b" + "name": "constant.numeric.binary.q", + "match": "[01]+b" }, { - "name": "constant.other.date", - "match": "\\b([12]\\d{3}\\.(0[1-9]|1[0-2])\\.(0[1-9]|[12]\\d|3[01]))\\b" + "name": "constant.numeric.byte.q", + "match": "0x(?:[0-9a-fA-F]{2})+" }, { - "name": "constant.other.date.month", - "match": "\\b([12]\\d{3}\\.(0[1-9]|1[0-2])m)\\b" + "name": "constant.language.null.q", + "match": "\\b0N[hjenpmdznuvtg]\\b" }, { - "name": "constant.other.date.time.q", - "match": "\\b([01]\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d{0,3})?))?)\\b" + "name": "constant.numeric.infinity.q", + "match": "\\b0[wnWN]\\b" }, { - "name": "constant.other.date.timespan.q", - "match": "\\b\\d+D(([01]\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d{0,9})?))?)?)?n?\\b" + "name": "constant.numeric.float.q", + "match": "-?(?:\\d+\\.\\d+|\\.\\d+|\\d+\\.)(?:e[-+]?\\d?\\d)?e?" }, { - "name": "constant.other.timestamp.q", - "match": "\\b([12]\\d{3}\\.(0[1-9]|1[0-2])\\.(0[1-9]|[12]\\d|3[01]))(p|D|Dp|D(([01]\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d{0,9})?))?)?p?))\\b" - }, + "name": "constant.numeric.integer.q", + "match": "-?\\d+[jhife]?" + } + ] + }, + "keywords": { + "patterns": [ { - "name": "constant.numeric.byte", - "match": "\\b0x[0-9a-fA-F]+\\b" + "name": "keyword.other.namespace.h.q", + "match": "\\.h\\.(br|code|fram|ha|hb|ht|hta|htac|htc|html|http|nbr|pre|he|hn|hp|hy|hu|hug|sc|uh|sa|text|xmp|cd|d|ed|edsn|hc|hr|iso8601|jx|td|tx|xd|xs|xt|c0|c1|HOME|logo|sb|ty|val)\\b" }, { - "name": "constant.numeric.guid.q", - "match": "\\b([\\da-f]{8}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{4}-[\\da-f]{12})\\b" + "name": "keyword.other.namespace.j.q", + "match": "\\.j\\.(j|k|jd)\\b" }, { - "name": "constant.other.timestamp.datetime.q", - "match": "\\b([12]\\d{3}\\.(0[1-9]|1[0-2])\\.(0[1-9]|[12]\\d|3[01]))(z|T|Tz|T(([01]\\d|2[0-3])(:([0-5]\\d)(:([0-5]\\d(\\.\\d{0,3})?))?)?z?))\\b" + "name": "keyword.other.namespace.Q.q", + "match": "\\.[Qq]\\.(addmonths|Cf|Xf|btoa|j10|j12|M|ty|x10|x12|chk|dpft|dpfts|dsftg|en|ens|fk|hdpf|qt|qp|bv|ind|cn|MAP|D|par|PD|pd|pf|pn|qp|pt|PV|pv|vp|D|P|u|bt|dd|def|f|ff|fmt|ft|fu|gc|gz|id|qt|res|s|s1|sbt|trp|ts|u|V|v|view|A|a|b6|nA|k|opt|w|x|addr|fps|fpn|fs|fsn|hg|host|hp|l|sha1)\\b" }, { - "name": "constant.numeric.decimal.q", - "match": "(?x)((?<=[^a-zA-Z0-9]|\\s|^)-)?(?:\n (?:\\b[0-9]+(\\.)[0-9]*e[+-]?[0-9]+[ef]?)| # 1.1e+3\n (?:\\b[0-9]+(\\.)e[+-]?[0-9]+[ef]?)| # 1.e+3\n (?:\\B(\\.)[0-9]+e[+-]?[0-9]+[ef]?)| # .1e+3\n (?:\\b[0-9]+e[+-]?[0-9]+[ef]?)| # 1e+3\n (?:\\b[0-9]+(\\.)[0-9]*[ef]?)| # 1.1\n (?:\\b[0-9]+(\\.)[ef]?)| # 1.\n (?:\\B(\\.)[0-9]+[ef]?)| # .1\n (?:\\b[0-9]+[efhij]?(?!\\.)) # 1efhij\n)" + "name": "keyword.other.namespace.z.q", + "match": "\\.z\\.(a|b|c|D/d|e|ex|ey|f|h|i|K|k|l|N|n|o|P|p|pm|q|s|T|t|u|W|w|X|x|Z|z|zd|ac|bm|exit|pc|pd|pg|ph|pi|po|pp|pq|ps|pw|ts|vs|wc|wo|ws|d|D)\\b" }, { - "name": "support.type.q", - "match": "`(boolean|byte|short|int|long|real|float|char|symbol|timestamp|month|date|datetime|timespan|minute|second|time|year|mm|dd|hh|uu|ss)(?=\\$)" + "name": "keyword.other.namespace.m.q", + "match": "\\.m\\.\\w+\\b" }, { - "name": "support.attribute.q", - "match": "`[supg](?=#)" + "name": "keyword.other.namespace.q", + "match": "\\.[hjqQzm]\\b" }, { - "name": "constant.other.symbol.q", - "match": "`(:[a-zA-Z\\d_\\.:/]*|[a-zA-Z\\d_\\.:]*)" + "name": "keyword.other.control.q", + "match": "\\b(do|exit|if|while)\\b" }, { - "name": "constant.other.cmd.q", - "match": "^\\\\.+" + "name": "keyword.other.env.q", + "match": "\\b(getenv|gtime|ltime|setenv)\\b" }, { - "name": "constant.other.namespace.q", - "match": "^[a-zA-Z]\\)" - } - ] - }, - "keywords": { - "patterns": [ + "name": "keyword.other.interpret.q", + "match": "\\b(eval|parse|reval|show|system|value)\\b" + }, { - "include": "#variables" + "name": "keyword.other.io.q", + "match": "\\b(dsave|get|hclose|hcount|hdel|hopen|hsym|load|read0|read1|rload|rsave|save|set)\\b" }, { - "name": "keyword.control.q", - "match": "\\b(do|if|while)\\b" + "name": "keyword.other.iterate.q", + "match": "\\b(each|over|peach|prior|scan)\\b" }, { - "name": "keyword.operator.q", - "match": "(?<=\\b|_)(abs|acos|all|and|any|asc|asin|asof|atan|attr|avg|avgs|bin|binr|ceiling|cols|cor|cos|count|cov|cross|csv|cut|deltas|desc|dev|differ|distinct|div|dsave|each|ema|enlist|eval|except|exec|exit|exp|fills|first|fkeys|flip|floor|get|getenv|group|gtime|hclose|hcount|hdel|hopen|hsym|iasc|idesc|in|inter|inv|key|keys|last|like|load|log|lower|lsq|ltime|ltrim|mavg|max|maxs|mcount|md5|mdev|med|meta|min|mins|mmax|mmin|mmu|mod|msum|neg|next|not|null|or|over|parse|peach|pj|prd|prds|prev|prior|rand|rank|ratios|raze|read0|read1|reciprocal|reval|reverse|rload|rotate|rsave|rtrim|save|scan|scov|sdev|set|setenv|show|signum|sin|sqrt|ss|ssr|string|sublist|sum|sums|sv|svar|system|tables|tan|til|trim|type|ungroup|union|upper|value|var|view|views|vs|wavg|within|wsum|xasc|xbar|xcol|xcols|xdesc|xexp|xgroup|xkey|xlog|xprev|xrank)\\b" + "name": "keyword.other.join.q", + "match": "\\b(aj|aj0|ajf|ajf0|asof|ej|ij|ijf|lj|ljf|pj|uj|ujf|wj|wj1)\\b" }, { - "name": "keyword.control.q", - "match": "\\$(?=\\[)" + "name": "keyword.other.list.q", + "match": "\\b(count|cross|cut|enlist|except|fills|first|flip|group|in|inter|last|mcount|next|prev|raze|reverse|rotate|sublist|sv|til|union|vs|where|xprev)\\b" }, { - "name": "keyword.iterator.q", - "match": "(':?|\\\\:?|/:?)" + "name": "keyword.other.logic.q", + "match": "\\b(all|and|any|not|or)\\b" }, { - "name": "keyword.other.DML.q", - "match": "\\b(select|update|delete|exec|from|by|fby|where|aj|aj0|ajf|ajf0|ej|ij|ijf|lj|ljf|uj|ujf|wj|wj1|upsert|insert)\\b" + "name": "keyword.other.math.q", + "match": "\\b(abs|acos|asin|atan|avg|avgs|ceiling|cor|cos|cov|deltas|dev|div|ema|exp|floor|inv|log|lsq|mavg|max|maxs|mdev|med|min|mins|mmax|mmin|mmu|mod|msum|neg|prd|prds|rand|ratios|reciprocal|scov|sdev|signum|sin|sqrt|sum|sums|svar|tan|var|wavg|within|wsum|xexp|xlog)\\b" }, { - "name": "keyword.operator.comparison.q", - "match": "(=|<=?|>=?|~|<>)" + "name": "keyword.other.meta.q", + "match": "\\b(attr|null|tables|type|view|views)\\b" }, { - "name": "keyword.operator.q", - "match": "[\\@\\.\\$!?+\\-\\*%|&#^,_]" + "name": "keyword.other.query.q", + "match": "\\b(delete|exec|fby|from|select|update)\\b" }, { - "name": "keyword.assign.q", - "match": "::?" - } - ] - }, - "variables": { - "patterns": [ + "name": "keyword.other.sort.q", + "match": "\\b(asc|bin|binr|desc|differ|distinct|iasc|idesc|rank|xbar|xrank)\\b" + }, { - "name": "variable.other.q", - "match": "[a-zA-Z][a-zA-Z\\d_]*" + "name": "keyword.other.table.q", + "match": "\\b(cols|csv|fkeys|insert|key|keys|meta|ungroup|upsert|xasc|xcol|xcols|xdesc|xgroup|xkey)\\b" }, { - "name": "entity.name.function.q", - "match": "(? { - //write tests for src/commands/dataSourceCommand.ts - //function to be deleted after write the tests - dataSourceCommand.renameDataSource("test", "test2"); + afterEach(() => { + sinon.restore(); + mock.restore(); + }); + + it("should add a data source", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + await assert.doesNotReject(dataSourceCommand.addDataSource()); + }); + + it("should rename a data source", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + await assert.doesNotReject( + dataSourceCommand.renameDataSource("datasource-0", "datasource-1") + ); + }); + + it("should save a data source", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + const ds = createDefaultDataSourceFile(); + ds.name = "datasource-0"; + + await assert.doesNotReject(dataSourceCommand.saveDataSource(ds)); + }); + + it("should save a data source with a different name", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + const ds = createDefaultDataSourceFile(); + ds.name = "datasource-1"; + ds.originalName = "datasource-0"; + + await assert.doesNotReject(dataSourceCommand.saveDataSource(ds)); + }); + + it("should delete a data source", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + const item = new KdbDataSourceTreeItem( + "datasource-0", + vscode.TreeItemCollapsibleState.Collapsed, + [] + ); + + await assert.doesNotReject(dataSourceCommand.deleteDataSource(item)); + }); + + it("should open a data source", async () => { + mock({ + "/temp": { + ".kdb-datasources": { + "datasource-0.ds": '{"name": "datasource-0"}', + }, + }, + }); + + ext.context = {} as vscode.ExtensionContext; + sinon.stub(ext, "context").value({ + globalStorageUri: { + fsPath: "/temp/", + }, + }); + + const item = new KdbDataSourceTreeItem( + "datasource-0", + vscode.TreeItemCollapsibleState.Collapsed, + [] + ); + + const uri = vscode.Uri.file("/temp/.kdb-datasources/datasource-0.ds"); + + await assert.doesNotReject(dataSourceCommand.openDataSource(item, uri)); + }); }); + +describe("dataSourceCommand2", () => { + let dummyDataSourceFiles: DataSourceFiles; + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + let resultsPanel: KdbResultsViewProvider; + ext.outputChannel = vscode.window.createOutputChannel("kdb"); + const view: vscode.WebviewView = { + visible: true, + // eslint-disable-next-line @typescript-eslint/no-empty-function + show: (): void => {}, + viewType: "kdb-results", + webview: { + options: {}, + html: "", + cspSource: "", + asWebviewUri: (uri: vscode.Uri) => uri, + onDidReceiveMessage: new vscode.EventEmitter().event, + postMessage: (): Thenable => { + return Promise.resolve(true); + }, + }, + onDidDispose: new vscode.EventEmitter().event, + onDidChangeVisibility: new vscode.EventEmitter().event, + }; + + beforeEach(() => { + dummyDataSourceFiles = { + name: "dummy ds", + insightsNode: "dummy insights", + dataSource: { + selectedType: DataSourceTypes.API, + api: { + selectedApi: "getData", + table: "dummy_table", + startTS: "2023-09-10T09:30", + endTS: "2023-09-19T12:30", + fill: "", + filter: [], + groupBy: [], + labels: [], + slice: [], + sortCols: [], + temporality: "", + agg: [], + }, + qsql: { + selectedTarget: "dummy_table rdb", + query: "dummy QSQL query", + }, + sql: { + query: "dummy SQL query", + }, + }, + }; + resultsPanel = new KdbResultsViewProvider(uriTest); + }); + describe("getSelectedType", () => { + it("should return selectedType if it is API", () => { + const result = dataSourceCommand.getSelectedType(dummyDataSourceFiles); + sinon.assert.match(result, "API"); + }); + + it("should return selectedType if it is QSQL", () => { + dummyDataSourceFiles.dataSource.selectedType = DataSourceTypes.QSQL; + const result2 = dataSourceCommand.getSelectedType(dummyDataSourceFiles); + sinon.assert.match(result2, "QSQL"); + }); + + it("should return selectedType if it is SQL", () => { + dummyDataSourceFiles.dataSource.selectedType = DataSourceTypes.SQL; + const result3 = dataSourceCommand.getSelectedType(dummyDataSourceFiles); + sinon.assert.match(result3, "SQL"); + }); + }); + + describe("getQuery", () => { + it("should return the correct query for API data sources", () => { + const query = dataSourceCommand.getQuery(dummyDataSourceFiles, "API"); + assert.strictEqual(query, "GetData - table: dummy_table"); + }); + + it("should return the correct query for QSQL data sources", () => { + const query = dataSourceCommand.getQuery(dummyDataSourceFiles, "QSQL"); + assert.strictEqual(query, "dummy QSQL query"); + }); + + it("should return the correct query for SQL data sources", () => { + const query = dataSourceCommand.getQuery(dummyDataSourceFiles, "SQL"); + assert.strictEqual(query, "dummy SQL query"); + }); + }); + + describe("getApiBody", () => { + it("should return the correct API body for an old data source with all fields", () => { + const api = dummyDataSourceFiles.dataSource.api; + + api.startTS = "2022-01-01T00:00:00Z"; + api.endTS = "2022-01-02T00:00:00Z"; + api.fill = "none"; + api.temporality = "1h"; + api.filter = ["col1=val1;col2=val2", "col3=val3"]; + api.groupBy = ["col1", "col2"]; + api.agg = ["sum(col3)", "avg(col4)"]; + api.sortCols = ["col1 ASC", "col2 DESC"]; + api.slice = ["10", "20"]; + api.labels = ["label1", "label2"]; + api.table = "myTable"; + const apiBody = dataSourceCommand.getApiBody(dummyDataSourceFiles); + + assert.deepStrictEqual(apiBody, { + table: "myTable", + startTS: "2022-01-01T00:00:00.000000000", + endTS: "2022-01-02T00:00:00.000000000", + }); + }); + + it("should return the correct API body for a new data source with some fields", () => { + const api = dummyDataSourceFiles.dataSource.api; + + api.startTS = "2022-01-01T00:00:00Z"; + api.endTS = "2022-01-02T00:00:00Z"; + api.fill = "zero"; + api.temporality = "snapshot"; + api.filter = ["col1=val1;col2=val2", "col3=val3"]; + api.groupBy = ["col1", "col2"]; + api.agg = ["sum(col3)", "avg(col4)"]; + api.sortCols = ["col1 ASC", "col2 DESC"]; + api.slice = ["10", "20"]; + api.labels = ["label1", "label2"]; + api.table = "myTable"; + api.optional = { + filled: true, + temporal: true, + startTS: "", + endTS: "", + filters: [], + sorts: [], + groups: [], + aggs: [], + labels: [], + }; + const apiBody = dataSourceCommand.getApiBody(dummyDataSourceFiles); + + assert.deepStrictEqual(apiBody, { + table: "myTable", + startTS: "2022-01-01T00:00:00.000000000", + endTS: "2022-01-02T00:00:00.000000000", + fill: "zero", + temporality: "snapshot", + }); + }); + + it("should return the correct API body for a new data source with slice", () => { + const api = dummyDataSourceFiles.dataSource.api; + + api.startTS = "2022-01-01T00:00:00Z"; + api.endTS = "2022-01-02T00:00:00Z"; + api.fill = "zero"; + api.temporality = "slice"; + api.filter = []; + api.groupBy = []; + api.agg = []; + api.sortCols = []; + api.slice = []; + api.labels = []; + api.table = "myTable"; + api.optional = { + filled: false, + temporal: true, + startTS: "10:00", + endTS: "11:00", + filters: [], + sorts: [], + groups: [], + aggs: [], + labels: [], + }; + const apiBody = dataSourceCommand.getApiBody(dummyDataSourceFiles); + assert.strictEqual(apiBody.temporality, "slice"); + }); + + it("should return the correct API body for a new data source with all fields", () => { + const api = dummyDataSourceFiles.dataSource.api; + + api.startTS = "2022-01-01T00:00:00Z"; + api.endTS = "2022-01-02T00:00:00Z"; + api.fill = "zero"; + api.temporality = "snapshot"; + api.filter = []; + api.groupBy = []; + api.agg = []; + api.sortCols = []; + api.slice = []; + api.labels = []; + api.table = "myTable"; + api.optional = { + filled: true, + temporal: true, + startTS: "10:00", + endTS: "11:00", + filters: [ + { active: true, column: "bid", operator: ">", values: "100" }, + ], + sorts: [{ active: true, column: "sym" }], + groups: [{ active: true, column: "bid" }], + aggs: [{ active: true, column: "ask", operator: "sum", key: "sumC" }], + labels: [{ active: true, key: "key", value: "value" }], + }; + const apiBody = dataSourceCommand.getApiBody(dummyDataSourceFiles); + + assert.deepStrictEqual(apiBody, { + table: "myTable", + startTS: "2022-01-01T00:00:00.000000000", + endTS: "2022-01-02T00:00:00.000000000", + fill: "zero", + temporality: "snapshot", + labels: { + key: "value", + }, + sortCols: ["sym"], + groupBy: ["bid"], + agg: [["sumC", "sum", "ask"]], + filter: [[">", "bid", 100]], + }); + }); + + it("should return the correct API body for a data source with only required fields", () => { + dummyDataSourceFiles.dataSource.api.startTS = "2022-01-01T00:00:00Z"; + dummyDataSourceFiles.dataSource.api.endTS = "2022-01-02T00:00:00Z"; + dummyDataSourceFiles.dataSource.api.fill = ""; + dummyDataSourceFiles.dataSource.api.temporality = ""; + dummyDataSourceFiles.dataSource.api.filter = []; + dummyDataSourceFiles.dataSource.api.groupBy = []; + dummyDataSourceFiles.dataSource.api.agg = []; + dummyDataSourceFiles.dataSource.api.sortCols = []; + dummyDataSourceFiles.dataSource.api.slice = []; + dummyDataSourceFiles.dataSource.api.labels = []; + dummyDataSourceFiles.dataSource.api.table = "myTable"; + const apiBody = dataSourceCommand.getApiBody(dummyDataSourceFiles); + assert.deepStrictEqual(apiBody, { + table: "myTable", + startTS: "2022-01-01T00:00:00.000000000", + endTS: "2022-01-02T00:00:00.000000000", + }); + }); + }); + + describe("runApiDataSource", () => { + let getApiBodyStub: sinon.SinonStub; + let checkIfTimeParamIsCorrectStub: sinon.SinonStub; + let getDataInsightsStub: sinon.SinonStub; + let handleWSResultsStub: sinon.SinonStub; + + beforeEach(() => { + getApiBodyStub = sinon.stub(dataSourceCommand, "getApiBody"); + checkIfTimeParamIsCorrectStub = sinon.stub( + dataSourceUtils, + "checkIfTimeParamIsCorrect" + ); + getDataInsightsStub = sinon.stub(srvCommand, "getDataInsights"); + handleWSResultsStub = sinon.stub(queryUtils, "handleWSResults"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should show an error message if the time parameters are incorrect", async () => { + const windowMock = sinon.mock(vscode.window); + checkIfTimeParamIsCorrectStub.returns(false); + + await dataSourceCommand.runApiDataSource(dummyDataSourceFiles); + windowMock + .expects("showErrorMessage") + .once() + .withArgs( + "The time parameters(startTS and endTS) are not correct, please check the format or if the startTS is before the endTS" + ); + sinon.assert.notCalled(getApiBodyStub); + sinon.assert.notCalled(getDataInsightsStub); + sinon.assert.notCalled(handleWSResultsStub); + }); + + it("should call the API and handle the results if the time parameters are correct", async () => { + checkIfTimeParamIsCorrectStub.returns(true); + getApiBodyStub.returns({ table: "myTable" }); + getDataInsightsStub.resolves({ arrayBuffer: true }); + handleWSResultsStub.resolves([ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + + const result = await dataSourceCommand.runApiDataSource( + dummyDataSourceFiles + ); + + sinon.assert.calledOnce(getDataInsightsStub); + sinon.assert.calledOnce(handleWSResultsStub); + assert.deepStrictEqual(result, [ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + }); + }); + + describe("runQsqlDataSource", () => { + let getDataInsightsStub: sinon.SinonStub; + let handleWSResultsStub: sinon.SinonStub; + + beforeEach(() => { + getDataInsightsStub = sinon.stub(srvCommand, "getDataInsights"); + handleWSResultsStub = sinon.stub(queryUtils, "handleWSResults"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should call the API and handle the results", async () => { + getDataInsightsStub.resolves({ arrayBuffer: true }); + handleWSResultsStub.resolves([ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + + const result = await dataSourceCommand.runQsqlDataSource( + dummyDataSourceFiles + ); + + sinon.assert.calledOnce(getDataInsightsStub); + sinon.assert.calledOnce(handleWSResultsStub); + assert.deepStrictEqual(result, [ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + }); + }); + + describe("runSqlDataSource", () => { + let getDataInsightsStub: sinon.SinonStub; + let handleWSResultsStub: sinon.SinonStub; + + beforeEach(() => { + getDataInsightsStub = sinon.stub(srvCommand, "getDataInsights"); + handleWSResultsStub = sinon.stub(queryUtils, "handleWSResults"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should call the API and handle the results", async () => { + getDataInsightsStub.resolves({ arrayBuffer: true }); + handleWSResultsStub.resolves([ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + + const result = await dataSourceCommand.runSqlDataSource( + dummyDataSourceFiles + ); + + sinon.assert.calledOnce(getDataInsightsStub); + sinon.assert.calledOnce(handleWSResultsStub); + assert.deepStrictEqual(result, [ + { a: "2", b: "3" }, + { a: "4", b: "6" }, + { a: "6", b: "9" }, + ]); + }); + }); + + describe("runDataSource", () => { + const dummyMeta = { + rc: [ + { + api: 3, + agg: 1, + assembly: 1, + schema: 1, + rc: "dummy-rc", + labels: [{ kxname: "dummy-assembly" }], + started: "2023-10-04T17:20:57.659088747", + }, + ], + dap: [ + { + assembly: "dummy-assembly", + instance: "idb", + startTS: "2023-10-25T01:40:03.000000000", + endTS: "2023-10-25T14:00:03.000000000", + }, + ], + api: [ + { + api: ".kxi.getData", + kxname: ["dummy-assembly"], + aggFn: ".sgagg.getData", + custom: false, + full: true, + metadata: { + description: "dummy desc.", + params: [ + { + name: "table", + type: -11, + isReq: true, + description: "dummy desc.", + }, + ], + return: { + type: 0, + description: "dummy desc.", + }, + misc: { safe: true }, + aggReturn: { + type: 98, + description: "dummy desc.", + }, + }, + procs: [], + }, + ], + agg: [ + { + aggFn: ".sgagg.aggFnDflt", + custom: false, + full: true, + metadata: { + description: "dummy desc.", + params: [{ description: "dummy desc." }], + return: { description: "dummy desc." }, + misc: {}, + }, + procs: [], + }, + ], + assembly: [ + { + assembly: "dummy-assembly", + kxname: "dummy-assembly", + tbls: ["dummyTbl"], + }, + ], + schema: [ + { + table: "dummyTbl", + assembly: ["dummy-assembly"], + typ: "partitioned", + pkCols: [], + prtnCol: "srcTime", + sortColsMem: [], + sortColsIDisk: [], + sortColsDisk: [], + isSplayed: true, + isPartitioned: true, + isSharded: false, + columns: [ + { + column: "sym", + typ: 10, + description: "dummy desc.", + oldName: "", + attrMem: "", + attrIDisk: "", + attrDisk: "", + isSerialized: false, + foreign: "", + anymap: false, + backfill: "", + }, + ], + }, + ], + }; + const dummyFileContent = { + name: "dummy-DS", + dataSource: { + selectedType: "QSQL", + api: { + selectedApi: "getData", + table: "dummyTbl", + startTS: "2023-09-10T09:30", + endTS: "2023-09-19T12:30", + fill: "", + temporality: "", + filter: [], + groupBy: [], + agg: [], + sortCols: [], + slice: [], + labels: [], + }, + qsql: { + query: + "n:10;\n([] date:n?(reverse .z.d-1+til 10); instance:n?`inst1`inst2`inst3`inst4; sym:n?`USD`EUR`GBP`JPY; cnt:n?10; lists:{x?10}@/:1+n?10)\n", + selectedTarget: "dummy-target", + }, + sql: { query: "test query" }, + }, + insightsNode: "dummyNode", + }; + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + ext.resultsViewProvider = new KdbResultsViewProvider(uriTest); + let isVisibleStub: sinon.SinonStub; + let getMetaStub: sinon.SinonStub; + let convertDSFormToDSFile: sinon.SinonStub; + let getSelectedTypeStub: sinon.SinonStub; + let runApiDataSourceStub: sinon.SinonStub; + let runQsqlDataSourceStub: sinon.SinonStub; + let runSqlDataSourceStub: sinon.SinonStub; + let writeQueryResultsToViewStub: sinon.SinonStub; + let writeQueryResultsToConsoleStub: sinon.SinonStub; + const appendLineSpy = sinon.spy(ext.outputChannel, "appendLine"); + // const windowErrorSpy = sinon.spy(vscode.window, "showErrorMessage"); + ext.outputChannel = vscode.window.createOutputChannel("kdb"); + + beforeEach(() => { + getMetaStub = sinon.stub(srvCommand, "getMeta"); + convertDSFormToDSFile = sinon.stub( + dataSourceUtils, + "convertDataSourceFormToDataSourceFile" + ); + isVisibleStub = sinon.stub(ext.resultsViewProvider, "isVisible"); + getSelectedTypeStub = sinon.stub(dataSourceCommand, "getSelectedType"); + runApiDataSourceStub = sinon.stub(dataSourceCommand, "runApiDataSource"); + runQsqlDataSourceStub = sinon.stub( + dataSourceCommand, + "runQsqlDataSource" + ); + runSqlDataSourceStub = sinon.stub(dataSourceCommand, "runSqlDataSource"); + writeQueryResultsToViewStub = sinon.stub( + srvCommand, + "writeQueryResultsToView" + ); + writeQueryResultsToConsoleStub = sinon.stub( + srvCommand, + "writeQueryResultsToConsole" + ); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should show an error message if not connected to an Insights server", async () => { + getMetaStub.resolves({}); + await dataSourceCommand.runDataSource({} as DataSourceFiles); + sinon.assert.notCalled(convertDSFormToDSFile); + }); + + it("should return QSQL results)", async () => { + getMetaStub.resolves(dummyMeta); + convertDSFormToDSFile.returns(dummyFileContent); + getSelectedTypeStub.returns("QSQL"); + runQsqlDataSourceStub.resolves("dummy results"); + isVisibleStub.returns(true); + await dataSourceCommand.runDataSource( + dummyFileContent as DataSourceFiles + ); + sinon.assert.calledOnce(writeQueryResultsToViewStub); + }); + + it("should return API results)", async () => { + dummyFileContent.dataSource.selectedType = "API"; + getMetaStub.resolves(dummyMeta); + convertDSFormToDSFile.returns(dummyFileContent); + getSelectedTypeStub.returns("API"); + runApiDataSourceStub.resolves("dummy results"); + isVisibleStub.returns(false); + await dataSourceCommand.runDataSource( + dummyFileContent as DataSourceFiles + ); + sinon.assert.calledOnce(writeQueryResultsToConsoleStub); + }); + + it("should return SQL results)", async () => { + dummyFileContent.dataSource.selectedType = "SQL"; + getMetaStub.resolves(dummyMeta); + convertDSFormToDSFile.returns(dummyFileContent); + getSelectedTypeStub.returns("SQL"); + runSqlDataSourceStub.resolves("dummy results"); + isVisibleStub.returns(false); + await dataSourceCommand.runDataSource( + dummyFileContent as DataSourceFiles + ); + sinon.assert.calledOnce(writeQueryResultsToConsoleStub); + }); + }); +}); + describe("installTools", () => { //write tests for src/commands/installTools.ts //function to be deleted after write the tests installTools.installTools(); }); describe("serverCommand", () => { + it("Should call new connection but not create kdb or insights", async () => { + const qpStub = sinon.stub(window, "showQuickPick").returns(undefined); + + const spy = sinon.spy(); + const kdbMock = sinon.mock(srvCommand); + kdbMock.expects("addKdbConnection").never(); + const insMock = sinon.mock(srvCommand); + insMock.expects("addInsightsConnection").never(); + + await addNewConnection(); + kdbMock.verify(); + insMock.verify(); + + assert(spy.notCalled); + + spy.resetHistory(); + insMock.restore(); + kdbMock.restore(); + qpStub.restore(); + }); + + it("Should add new kdb connection successfully", async () => { + const qpItem: QuickPickItem = { + label: "Enter a kdb endpoint", + detail: + "Enter the url, ip address, and port to connect to a kdb instance", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const kdbStub = sinon + .stub(srvCommand, "addKdbConnection") + .returns(undefined); + + await addNewConnection(); + + assert(kdbStub.notCalled); + + kdbStub.restore(); + qpStub.restore(); + }); + + it("Should add new kdb connection without existing connection", async () => { + const qpItem: QuickPickItem = { + label: "Enter a kdb endpoint", + detail: + "Enter the url, ip address, and port to connect to a kdb instance", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + + await addKdbConnection(); + + assert.strictEqual(true, true); + + qpStub.restore(); + }); + + it("Should add new insights connection successfully", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + + await addNewConnection(); + + assert(insStub.notCalled); + + insStub.restore(); + qpStub.restore(); + }); + + it("Should add new insights connection successfully", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const inpStub = sinon + .stub(window, "showInputBox") + .onFirstCall() + .resolves(undefined) + .onSecondCall() + .resolves("https://insights.test"); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + + await addNewConnection(); + + assert(insStub.notCalled); + + insStub.restore(); + inpStub.restore(); + qpStub.restore(); + }); + + it("Should add new insights connection successfully", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const inpStub = sinon + .stub(window, "showInputBox") + .onFirstCall() + .resolves("") + .onSecondCall() + .resolves("https://insights.test"); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + + await addNewConnection(); + + assert(insStub.notCalled); + + insStub.restore(); + inpStub.restore(); + qpStub.restore(); + }); + + it("Should add new insights connection successfully", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const inpStub = sinon + .stub(window, "showInputBox") + .onFirstCall() + .resolves("") + .onSecondCall() + .resolves("https://insights.test"); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + const getInsightsStub = sinon + .stub(insModule, "getInsights") + .returns(undefined); + + await addNewConnection(); + + assert(insStub.notCalled); + + getInsightsStub.restore(); + insStub.restore(); + inpStub.restore(); + qpStub.restore(); + }); + + it("Should add new insights connection with no existing connection", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const insTest: Insights = { + test: { alias: "testalias", auth: false, server: "testserver" }, + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const inpStub = sinon + .stub(window, "showInputBox") + .onFirstCall() + .resolves("test") + .onSecondCall() + .resolves("https://insights.test"); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + const getInsightsStub = sinon + .stub(insModule, "getInsights") + .returns(insTest); + + await addNewConnection(); + + assert(insStub.notCalled); + + getInsightsStub.restore(); + insStub.restore(); + inpStub.restore(); + qpStub.restore(); + }); + + it("Should add new insights connection with exiting connection", async () => { + const qpItem: QuickPickItem = { + label: "Connect to kdb Insights Enterprise", + detail: "Enter instance details", + }; + + const insTest: Insights = { + test: { + alias: "testalias", + auth: false, + server: "https://insights.test", + }, + }; + + const qpStub = sinon.stub(window, "showQuickPick").resolves(qpItem); + const inpStub = sinon + .stub(window, "showInputBox") + .onFirstCall() + .resolves("test") + .onSecondCall() + .resolves("https://insights.test"); + const insStub = sinon + .stub(srvCommand, "addInsightsConnection") + .returns(undefined); + const getInsightsStub = sinon + .stub(insModule, "getInsights") + .returns(insTest); + + await addNewConnection(); + + assert(insStub.notCalled); + + getInsightsStub.restore(); + insStub.restore(); + inpStub.restore(); + qpStub.restore(); + }); + //write tests for src/commands/serverCommand.ts //function to be deleted after write the tests - serverCommand.addNewConnection(); + //serverCommand.addNewConnection(); + describe("writeQueryResultsToView", () => { + it("should call executeCommand with correct arguments", () => { + const result = { data: [1, 2, 3] }; + const executeCommandStub = sinon.stub(vscode.commands, "executeCommand"); + + writeQueryResultsToView(result); + + sinon.assert.calledWith( + executeCommandStub.firstCall, + "kdb.resultsPanel.update", + result, + undefined + ); + + executeCommandStub.restore(); + }); + }); + describe("enableTLS", () => { + let getServersStub: sinon.SinonStub; + let updateServersStub: sinon.SinonStub; + let showErrorMessageStub: sinon.SinonStub; + + beforeEach(() => { + getServersStub = sinon.stub(coreUtils, "getServers"); + updateServersStub = sinon.stub(coreUtils, "updateServers"); + showErrorMessageStub = sinon.stub(vscode.window, "showErrorMessage"); + }); + + afterEach(() => { + getServersStub.restore(); + updateServersStub.restore(); + showErrorMessageStub.restore(); + }); + + it("should show error message when OpenSSL is not found", async () => { + ext.openSslVersion = null; + showErrorMessageStub.resolves("More Info"); + + await srvCommand.enableTLS("test"); + + sinon.assert.calledOnce(showErrorMessageStub); + sinon.assert.calledWith( + showErrorMessageStub, + "OpenSSL not found, please ensure this is installed", + "More Info", + "Cancel" + ); + sinon.assert.notCalled(updateServersStub); + }); + + it("should show error message when server is not found", async () => { + ext.openSslVersion = "1.0.2"; + getServersStub.returns({}); + + await srvCommand.enableTLS("test"); + + sinon.assert.calledOnce(showErrorMessageStub); + sinon.assert.calledWith( + showErrorMessageStub, + "Server not found, please ensure this is a correct server", + "Cancel" + ); + sinon.assert.calledOnce(getServersStub); + sinon.assert.notCalled(updateServersStub); + }); + + it("should update server with correct arguments", async () => { + const servers = { + testServer: { + serverAlias: "testServerAlias", + serverName: "testServerName", + serverPort: "5001", + tls: false, + auth: false, + managed: false, + }, + }; + const insights = { + testInsight: { + alias: "testInsightsAlias", + server: "testInsightsName", + auth: false, + }, + }; + ext.serverProvider = new KdbTreeProvider(servers, insights); + ext.openSslVersion = "1.0.2"; + getServersStub.returns({ + test: { + auth: true, + tls: false, + serverName: "test", + serverPort: "1001", + serverAlias: "testando", + managed: false, + }, + }); + await srvCommand.enableTLS("test"); + sinon.assert.calledOnce(updateServersStub); + }); + }); + + describe("writeScratchpadResult", () => { + const _console = vscode.window.createOutputChannel("q Console Output"); + const executionConsole = new ExecutionConsole(_console); + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + ext.resultsViewProvider = new KdbResultsViewProvider(uriTest); + let executionConsoleStub: sinon.SinonStub; + let scratchpadResult: ScratchpadResult; + let queryConsoleErrorStub: sinon.SinonStub; + let writeQueryResultsToViewStub: sinon.SinonStub; + let writeQueryResultsToConsoleStub: sinon.SinonStub; + let isVisibleStub: sinon.SinonStub; + + beforeEach(() => { + executionConsoleStub = sinon + .stub(ExecutionConsole, "start") + .returns(executionConsole); + scratchpadResult = { + data: "1234", + error: false, + errorMsg: "", + sessionID: "123", + }; + queryConsoleErrorStub = sinon.stub( + ExecutionConsole.prototype, + "appendQueryError" + ); + writeQueryResultsToViewStub = sinon.stub( + srvCommand, + "writeQueryResultsToView" + ); + writeQueryResultsToConsoleStub = sinon.stub( + srvCommand, + "writeQueryResultsToConsole" + ); + isVisibleStub = sinon.stub(ext.resultsViewProvider, "isVisible"); + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should write appendQueryError", () => { + scratchpadResult.error = true; + scratchpadResult.errorMsg = "error"; + srvCommand.writeScratchpadResult(scratchpadResult, "dummy query"); + sinon.assert.notCalled(writeQueryResultsToViewStub); + sinon.assert.notCalled(writeQueryResultsToConsoleStub); + }); + + it("should write to view", () => { + scratchpadResult.data = "data"; + isVisibleStub.returns(true); + srvCommand.writeScratchpadResult(scratchpadResult, "dummy query"); + sinon.assert.notCalled(writeQueryResultsToConsoleStub); + sinon.assert.notCalled(queryConsoleErrorStub); + }); + + it("should write to console", () => { + scratchpadResult.data = "data"; + isVisibleStub.returns(false); + srvCommand.writeScratchpadResult(scratchpadResult, "dummy query"); + sinon.assert.notCalled(writeQueryResultsToViewStub); + }); + }); }); + describe("walkthroughCommand", () => { //write tests for src/commands/walkthroughCommand.ts //function to be deleted after write the tests diff --git a/test/suite/kdbDataSourceView.test.mts b/test/suite/kdbDataSourceView.test.mts new file mode 100644 index 00000000..facaf6b6 --- /dev/null +++ b/test/suite/kdbDataSourceView.test.mts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import * as assert from "assert"; +import * as sinon from "sinon"; +import { KdbDataSourceView } from "../../src/webview/components/kdbDataSourceView"; + +describe("KdbDataSourceView", () => { + let view: KdbDataSourceView; + + beforeEach(async () => { + view = new KdbDataSourceView(); + }); + + afterEach(() => { + sinon.restore(); + }); + + describe("", () => { + it("should", () => { + assert.ok(view); + }); + }); +}); diff --git a/test/suite/lexer.test.ts b/test/suite/lexer.test.ts new file mode 100644 index 00000000..583e1547 --- /dev/null +++ b/test/suite/lexer.test.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import * as assert from "assert"; +import { QLexer } from "../../server/src/parser/lexer"; +import { CharLiteral } from "../../server/src/parser/literals"; + +describe("QLexer", () => { + describe("CharLiteral", () => { + it("should tokenize string", () => { + const lexed = QLexer.tokenize('"char"'); + assert.strictEqual(lexed.tokens.length, 1); + assert.strictEqual(lexed.tokens[0].tokenType, CharLiteral); + }); + + it("should tokenize empty string", () => { + const lexed = QLexer.tokenize('""'); + assert.strictEqual(lexed.tokens.length, 1); + assert.strictEqual(lexed.tokens[0].tokenType, CharLiteral); + }); + }); +}); diff --git a/test/suite/models.test.ts b/test/suite/models.test.ts new file mode 100644 index 00000000..8e541cc3 --- /dev/null +++ b/test/suite/models.test.ts @@ -0,0 +1,312 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import assert from "assert"; +import sinon from "sinon"; +import { ext } from "../../src/extensionVariables"; +import { Connection } from "../../src/models/connection"; +import { + ServerObject, + loadDictionaries, + loadFunctions, + loadNamespaces, + loadTables, + loadVariables, + loadViews, +} from "../../src/models/serverObject"; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const so = require("../../src/commands/serverCommand"); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const vw = require("../../src/models/serverObject"); + +describe("Models", () => { + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(so, "loadServerObjects").resolves(undefined); + const result = await loadNamespaces(""); + assert.strictEqual(result.length, 0, "Namespaces returned should be zero."); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test1", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + { + id: 2, + pid: 2, + name: "test", + fname: "test2", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject); + const result = await loadNamespaces(); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace (reverse sort)", async () => { + const testObject0: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + { + id: 0, + pid: 0, + name: "test", + fname: "test0", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject0); + const result = await loadNamespaces(); + assert.strictEqual( + result[0], + testObject0[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a namespace", async () => { + const testObject2: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 1, + namespace: ".", + context: {}, + isNs: true, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject2); + const result = await loadNamespaces("."); + assert.strictEqual( + result[0], + testObject2[0], + `Single server object that is a namespace should be returned: ${JSON.stringify( + result + )}` + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(so, "loadServerObjects").resolves(undefined); + const result = await loadDictionaries(""); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a dictionary", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 99, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject); + const result = await loadDictionaries("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(so, "loadServerObjects").resolves(undefined); + const result = await loadFunctions("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a function", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 100, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject); + const result = await loadFunctions("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(so, "loadServerObjects").resolves(undefined); + const result = await loadTables("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a table", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: 98, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject); + const result = await loadTables("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return empty ServerObjects array when none are loaded", async () => { + sinon.stub(so, "loadServerObjects").resolves(undefined); + const result = await loadVariables("."); + assert.strictEqual( + result.length, + 0, + "ServerObjects returned should be zero." + ); + sinon.restore(); + }); + + it("Should return a single server object that ia a variable", async () => { + const testObject: ServerObject[] = [ + { + id: 1, + pid: 1, + name: "test", + fname: "test", + typeNum: -7, + namespace: ".", + context: {}, + isNs: false, + }, + ]; + sinon.stub(so, "loadServerObjects").resolves(testObject); + sinon.stub(vw, "loadViews").resolves([]); + const result = await loadVariables("."); + assert.strictEqual( + result[0], + testObject[0], + "Single server object that is a namespace should be returned." + ); + sinon.restore(); + }); + + it("Should return sorted views", async () => { + ext.connection = new Connection("localhost:5001"); + sinon.stub(ext.connection, "executeQuery").resolves("`vw1`vw2"); + const result = await loadViews(); + assert.strictEqual(result[0], "vw1", "Should return the first view"); + sinon.restore(); + }); + + it("Should return sorted views (reverse order)", async () => { + ext.connection = new Connection("localhost:5001"); + sinon.stub(ext.connection, "executeQuery").resolves("`vw2`vw1"); + const result = await loadViews(); + assert.strictEqual(result[0], "vw1", "Should return the first view"); + sinon.restore(); + }); + + it("Should create a new connection object", () => { + const conn = new Connection("server:5001"); + assert.strictEqual( + conn.connected, + false, + "Connection should be created but not connected." + ); + }); + + it("Should create a new connection object (full options)", () => { + const conn = new Connection("server:5001", ["username", "password"], true); + assert.strictEqual( + conn.connected, + false, + "Connection should be created but not connected." + ); + }); + + it("Should create a new connection object", () => { + const conn = new Connection("server:5001"); + conn.disconnect(); + assert.strictEqual( + conn.connected, + false, + "Connection should be created but not connected." + ); + }); +}); diff --git a/test/suite/panels.test.ts b/test/suite/panels.test.ts index cb5feb75..af961d29 100644 --- a/test/suite/panels.test.ts +++ b/test/suite/panels.test.ts @@ -12,14 +12,17 @@ */ import assert from "assert"; +import * as sinon from "sinon"; import * as vscode from "vscode"; -import { defaultDataSourceFile } from "../../src/models/dataSource"; +import { ext } from "../../src/extensionVariables"; +import { createDefaultDataSourceFile } from "../../src/models/dataSource"; import { DataSourcesPanel } from "../../src/panels/datasource"; import { KdbResultsViewProvider } from "../../src/services/resultsPanelProvider"; +import * as utils from "../../src/utils/execution"; describe("WebPanels", () => { describe("DataSourcesPanel", () => { - const dsTest = defaultDataSourceFile; + const dsTest = createDefaultDataSourceFile(); const uriTest: vscode.Uri = vscode.Uri.parse("test"); beforeEach(() => { @@ -46,22 +49,12 @@ describe("WebPanels", () => { ); }); - it("should make sure the datasource is rendered, check if the tabs exists", () => { - const expectedHtmlTab1 = `API`; - const expectedHtmlTab2 = `QSQL`; - const expectedHtmlTab3 = `SQL`; + it("should make sure the datasource is rendered, check if the web component exists", () => { + const expectedHtml = ``; const actualHtml = DataSourcesPanel.currentPanel._panel.webview.html; assert.ok( - actualHtml.indexOf(expectedHtmlTab1) !== -1, - "Panel HTML should include expected TAB btn 1" - ); - assert.ok( - actualHtml.indexOf(expectedHtmlTab2) !== -1, - "Panel HTML should include expected TAB btn 2" - ); - assert.ok( - actualHtml.indexOf(expectedHtmlTab3) !== -1, - "Panel HTML should include expected TAB btn 3" + actualHtml.indexOf(expectedHtml) !== -1, + "Panel HTML should include expected web component" ); }); }); @@ -110,21 +103,172 @@ describe("WebPanels", () => { const actualString = resultsPanel.sanitizeString(inputString); assert.strictEqual(actualString, expectedString); }); + + it("should transform an array of strings into a single string", () => { + const inputString = ["test", "string", "with", "array"]; + const expectedString = "test string with array"; + const actualString = resultsPanel.sanitizeString(inputString); + assert.strictEqual(actualString, expectedString); + }); + }); + + describe("isVisible()", () => { + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + let resultsPanel: KdbResultsViewProvider; + const view: vscode.WebviewView = { + visible: true, + // eslint-disable-next-line @typescript-eslint/no-empty-function + show: (): void => {}, + viewType: "kdb-results", + webview: { + options: {}, + html: "", + cspSource: "", + asWebviewUri: (uri: vscode.Uri) => uri, + onDidReceiveMessage: new vscode.EventEmitter().event, + postMessage: (): Thenable => { + return Promise.resolve(true); + }, + }, + onDidDispose: new vscode.EventEmitter().event, + onDidChangeVisibility: new vscode.EventEmitter().event, + }; + + beforeEach(() => { + resultsPanel = new KdbResultsViewProvider(uriTest); + }); + it("should return false if the panel is not visible", () => { + const actualVisibility = resultsPanel.isVisible(); + assert.strictEqual(actualVisibility, false); + }); + + it("should return false if the panel visible", () => { + resultsPanel["_view"] = view; + const actualVisibility = resultsPanel.isVisible(); + assert.strictEqual(actualVisibility, true); + }); }); describe("convertToGrid()", () => { - it("should return '

No results to show

' if queryResult is an empty string", () => { - const inputQueryResult = ""; - const expectedOutput = "

No results to show

"; + it("should return 'gridOptions' if queryResult is an empty string", () => { + const inputQueryResult = [{ a: "1" }, { a: "2" }, { a: "3" }]; + const expectedOutput = + '{"defaultColDef":{"sortable":true,"resizable":true,"filter":true,"flex":1,"minWidth":100},"rowData":[{"a":"1"},{"a":"2"},{"a":"3"}],"columnDefs":[{"field":"a","headerName":"a"}],"domLayout":"autoHeight","pagination":true,"paginationPageSize":100,"cacheBlockSize":100,"enableCellTextSelection":true,"ensureDomOrder":true,"suppressContextMenu":true}'; const actualOutput = resultsPanel.convertToGrid(inputQueryResult); assert.strictEqual(actualOutput, expectedOutput); }); + }); + + describe("removeEndCommaFromStrings", () => { + it("should remove the comma from the end of a string if it ends with a comma", () => { + const input = ["hello,", "world,"]; + const expectedOutput = ["hello", "world"]; + const actualOutput = resultsPanel.removeEndCommaFromStrings(input); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); - it("should return a string with the query result if queryResult is a string with one value", () => { - const inputQueryResult = "test string"; - const expectedOutput = "

test string

"; - const actualOutput = resultsPanel.convertToGrid(inputQueryResult); - assert.strictEqual(actualOutput, expectedOutput); + it("should not modify a string if it does not end with a comma", () => { + const input = ["hello", "world"]; + const expectedOutput = ["hello", "world"]; + const actualOutput = resultsPanel.removeEndCommaFromStrings(input); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); + + it("should return an empty array if the input is an empty array", () => { + const input: string[] = []; + const expectedOutput: string[] = []; + const actualOutput = resultsPanel.removeEndCommaFromStrings(input); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); + }); + + describe("exportToCsv()", () => { + it("should show error message if no results to export", () => { + const windowMock = sinon.mock(vscode.window); + const workspaceMock = sinon.mock(vscode.workspace); + const exportToCsvStub = sinon.stub(utils, "exportToCsv"); + windowMock + .expects("showErrorMessage") + .once() + .withArgs("No results to export"); + + ext.resultPanelCSV = ""; + + workspaceMock.expects("getWorkspaceFolder").never(); + + resultsPanel.exportToCsv(); + + windowMock.verify(); + workspaceMock.verify(); + exportToCsvStub.notCalled; + }); + }); + + describe("convertToCsv()", () => { + it("should return string array from objects", () => { + const inputQueryResult = [ + { a: "1", b: "1" }, + { a: "2", b: "2" }, + { a: "3", b: "3" }, + ]; + const expectedOutput = ["a,b", "1,1", "2,2", "3,3"]; + const actualOutput = resultsPanel.convertToCsv(inputQueryResult); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); + }); + + describe("_getWebviewContent", () => { + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + let resultsPanel: KdbResultsViewProvider; + const view: vscode.WebviewView = { + visible: true, + // eslint-disable-next-line @typescript-eslint/no-empty-function + show: (): void => {}, + viewType: "kdb-results", + webview: { + options: {}, + html: "", + cspSource: "", + asWebviewUri: (uri: vscode.Uri) => uri, + onDidReceiveMessage: new vscode.EventEmitter().event, + postMessage: (): Thenable => { + return Promise.resolve(true); + }, + }, + onDidDispose: new vscode.EventEmitter().event, + onDidChangeVisibility: new vscode.EventEmitter().event, + }; + + beforeEach(() => { + resultsPanel = new KdbResultsViewProvider(uriTest); + resultsPanel["_view"] = view; + }); + + it("returns a table", () => { + const input = [ + { id: 1, test: "test1" }, + { id: 2, test: "test2" }, + ]; + const expectedOutput = `"rowData":[{"id":"1","test":"test1"},{"id":"2","test":"test2"}],"columnDefs":[{"field":"id","headerName":"id"},{"field":"test","headerName":"test"}]`; + const actualOutput = resultsPanel["_getWebviewContent"](input); + assert.strictEqual(typeof actualOutput, "string"); + assert.ok(actualOutput.includes(expectedOutput)); + }); + + it("returns no results", () => { + const input = "Test"; + const expectedOutput = `

Test

`; + const actualOutput = resultsPanel["_getWebviewContent"](input); + assert.strictEqual(typeof actualOutput, "string"); + assert.ok(actualOutput.includes(expectedOutput)); + }); + + it("returns no results", () => { + const input = ""; + const expectedOutput = `

No results to show

`; + const actualOutput = resultsPanel["_getWebviewContent"](input); + assert.strictEqual(typeof actualOutput, "string"); + assert.ok(actualOutput.includes(expectedOutput)); }); }); }); diff --git a/test/suite/parser.test.ts b/test/suite/parser.test.ts new file mode 100644 index 00000000..5d3aa1c3 --- /dev/null +++ b/test/suite/parser.test.ts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software 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. + */ + +import * as assert from "assert"; +import { QParser } from "../../server/src/parser/parser"; + +describe("QParser", () => { + describe("comments", () => { + it("should ignore block", () => { + QParser.parse("/\na:\n1\n\\"); + assert.deepEqual(QParser.errors, []); + }); + + it("should ignore line", () => { + QParser.parse("/a:\n"); + assert.deepEqual(QParser.errors, []); + }); + + it("should ignore inline", () => { + QParser.parse("a: 1 /a:\n"); + assert.deepEqual(QParser.errors, []); + }); + + it("should not ignore overloaded slash", () => { + QParser.parse("a: ,/ a:\n"); + assert.strictEqual(QParser.errors.length, 1); + }); + }); + + describe("script", () => { + it("should parse empty", () => { + QParser.parse(""); + assert.deepEqual(QParser.errors, []); + }); + }); + + describe("statement", () => { + it("should parse empty", () => { + QParser.parse(";\n\r\n;"); + assert.deepEqual(QParser.errors, []); + }); + }); + + describe("expression", () => { + describe("identifier", () => { + it("should parse", () => { + QParser.parse("absolute;"); + assert.deepEqual(QParser.errors, []); + }); + + it("should parse namespaced", () => { + QParser.parse(".absolute.value;"); + assert.deepEqual(QParser.errors, []); + }); + }); + + describe("assignment", () => { + it("should parse", () => { + QParser.parse("a:1;"); + assert.deepEqual(QParser.errors, []); + }); + + it("should parse multiple", () => { + QParser.parse("a:b:c:1;"); + assert.deepEqual(QParser.errors, []); + }); + + it("should parse multiline", () => { + QParser.parse("a\n :b:c:\r\n 1;"); + assert.deepEqual(QParser.errors, []); + }); + + it("should parse indexed", () => { + QParser.parse("a[1]:1;"); + assert.deepEqual(QParser.errors, []); + }); + + it("should parse infixed", () => { + QParser.parse("a[1]+:1;"); + assert.deepEqual(QParser.errors, []); + }); + }); + }); +}); diff --git a/test/suite/services.test.ts b/test/suite/services.test.ts index 893ae7cb..1153d0ab 100644 --- a/test/suite/services.test.ts +++ b/test/suite/services.test.ts @@ -12,12 +12,18 @@ */ import assert from "node:assert"; +import sinon from "sinon"; import { TreeItemCollapsibleState } from "vscode"; import { ext } from "../../src/extensionVariables"; import { Insights } from "../../src/models/insights"; -import { Server } from "../../src/models/server"; -import * as dataSourceTreeProvider from "../../src/services/dataSourceTreeProvider"; -import * as codeFlowLogin from "../../src/services/kdbInsights/codeFlowLogin"; +import { QueryHistory } from "../../src/models/queryHistory"; +import { Server, ServerType } from "../../src/models/server"; +import { + getCurrentToken, + refreshToken, + signIn, + signOut, +} from "../../src/services/kdbInsights/codeFlowLogin"; import { InsightsNode, KdbNode, @@ -26,13 +32,16 @@ import { QNamespaceNode, QServerNode, } from "../../src/services/kdbTreeProvider"; -import * as terminalProvider from "../../src/services/terminalProvider"; +import { + QueryHistoryProvider, + QueryHistoryTreeItem, +} from "../../src/services/queryHistoryProvider"; -describe("dataSourceTreeProvider", () => { - //write tests for src/services/dataSourceTreeProvider.ts - //function to be deleted after write the tests - dataSourceTreeProvider; -}); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const codeFlow = require("../../src/services/kdbInsights/codeFlowLogin"); + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const rp = require("request-promise"); describe("kdbTreeProvider", () => { let servers: Server; @@ -93,7 +102,7 @@ describe("kdbTreeProvider", () => { it("Validate refreshing KDB provider with KDB instance", () => { const kdbProvider = new KdbTreeProvider(servers, insights); - servers["testServer2"] = { + servers["testServer"] = { serverAlias: "testServer2Alias", serverName: "testServer2Name", serverPort: "5001", @@ -319,6 +328,81 @@ describe("kdbTreeProvider", () => { ); }); + it("Should add node to no tls list", () => { + ext.kdbNodesWithoutTls.length = 0; + ext.kdbNodesWithoutTls.push("testServer [testServerAlias]"); + const kdbNode = new KdbNode( + [], + "testServer", + { + serverName: "testServername", + serverAlias: "testServerAlias", + serverPort: "5001", + managed: false, + auth: false, + tls: false, + }, + TreeItemCollapsibleState.None + ); + assert.equal(ext.kdbNodesWithoutTls.length, 1); + }); + + it("Should remove node from no tls list", () => { + ext.kdbNodesWithoutTls.length = 0; + ext.kdbNodesWithoutTls.push("testServer [testServerAlias]"); + const kdbNode = new KdbNode( + [], + "testServer", + { + serverName: "testServername", + serverAlias: "testServerAlias", + serverPort: "5001", + managed: false, + auth: false, + tls: true, + }, + TreeItemCollapsibleState.None + ); + assert.equal(ext.kdbNodesWithoutTls, 0); + }); + + it("Should add node to no auth list", () => { + ext.kdbNodesWithoutAuth.length = 0; + ext.kdbNodesWithoutAuth.push("testServer [testServerAlias]"); + const kdbNode = new KdbNode( + [], + "testServer", + { + serverName: "testServername", + serverAlias: "testServerAlias", + serverPort: "5001", + managed: false, + auth: false, + tls: false, + }, + TreeItemCollapsibleState.None + ); + assert.equal(ext.kdbNodesWithoutAuth.length, 1); + }); + + it("Should remove node from no auth list", () => { + ext.kdbNodesWithoutAuth.length = 0; + ext.kdbNodesWithoutAuth.push("testServer [testServerAlias]"); + const kdbNode = new KdbNode( + [], + "testServer", + { + serverName: "testServername", + serverAlias: "testServerAlias", + serverPort: "5001", + managed: false, + auth: true, + tls: false, + }, + TreeItemCollapsibleState.None + ); + assert.equal(ext.kdbNodesWithoutAuth, 0); + }); it("Should retun a new InsightsNode", () => { const insightsNode = new InsightsNode( [], @@ -441,14 +525,174 @@ describe("kdbTreeProvider", () => { }); }); -describe("terminalProvider", () => { - //write tests for src/services/terminalProvider.ts - //function to be deleted after write the tests - terminalProvider; +describe("Code flow login service tests", () => { + const token = { + access_token: + "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiI2ZTc0MTcyYi1iZTU2LTQ4NDMtOWZmNC1lNjZhMzliYjEyZTMiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE1MzcyMzEwNDgsIm5iZiI6MTUzNzIzMTA0OCwiZXhwIjoxNTM3MjM0OTQ4LCJhaW8iOiJBWFFBaS84SUFBQUF0QWFaTG8zQ2hNaWY2S09udHRSQjdlQnE0L0RjY1F6amNKR3hQWXkvQzNqRGFOR3hYZDZ3TklJVkdSZ2hOUm53SjFsT2NBbk5aY2p2a295ckZ4Q3R0djMzMTQwUmlvT0ZKNGJDQ0dWdW9DYWcxdU9UVDIyMjIyZ0h3TFBZUS91Zjc5UVgrMEtJaWpkcm1wNjlSY3R6bVE9PSIsImF6cCI6IjZlNzQxNzJiLWJlNTYtNDg0My05ZmY0LWU2NmEzOWJiMTJlMyIsImF6cGFjciI6IjAiLCJuYW1lIjoiQWJlIExpbmNvbG4iLCJvaWQiOiI2OTAyMjJiZS1mZjFhLTRkNTYtYWJkMS03ZTRmN2QzOGU0NzQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhYmVsaUBtaWNyb3NvZnQuY29tIiwicmgiOiJJIiwic2NwIjoiYWNjZXNzX2FzX3VzZXIiLCJzdWIiOiJIS1pwZmFIeVdhZGVPb3VZbGl0anJJLUtmZlRtMjIyWDVyclYzeERxZktRIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZnFpQnFYTFBqMGVRYTgyUy1JWUZBQSIsInZlciI6IjIuMCJ9.pj4N-w_3Us9DrBLfpCt", + request_token: + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTY4ODUwMjJ9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ", + expires_in: 0, + }; + + it("Should return a correct login", async () => { + sinon.stub(codeFlow, "signIn").returns(token); + const result = await signIn("http://localhost"); + assert.strictEqual(result, token, "Invalid token returned"); + }); + + it("Should execute a correct logout", async () => { + sinon.stub(rp, "post").resolves(JSON.stringify(token)); + const result = await signOut("http://localhost", "token"); + assert.strictEqual(result, undefined, "Invalid response from logout"); + }); + + it("Should execute token refresh", async () => { + const result = await refreshToken( + "http://loclahost", + JSON.stringify(token) + ); + assert.strictEqual( + result.accessToken, + token.access_token, + "Token has not refreshed correctly" + ); + }); + + it("Should not return token from secret store", async () => { + const result = await getCurrentToken("", "testalias"); + assert.strictEqual( + result, + undefined, + "Should return undefined when server name is empty." + ); + }); + + it("Should not return token from secret store", async () => { + const result = await getCurrentToken("testserver", ""); + assert.strictEqual( + result, + undefined, + "Should return undefined when server alias is empty." + ); + }); }); -describe("codeFlowLogin", () => { - //write tests for src/services/kdbInsights/codeFlowLogin.ts - //function to be deleted after write the tests - codeFlowLogin; +describe("queryHistoryProvider", () => { + const dummyQueryHistory: QueryHistory[] = [ + { + connectionName: "testConnectionName", + time: "testTime", + query: "testQuery", + success: true, + connectionType: ServerType.INSIGHTS, + }, + { + connectionName: "testConnectionName2", + time: "testTime2", + query: "testQuery2", + success: true, + connectionType: ServerType.KDB, + }, + { + connectionName: "testConnectionName3", + time: "testTime3", + query: "testQuery3", + success: false, + connectionType: ServerType.undefined, + }, + ]; + beforeEach(() => { + ext.kdbQueryHistoryList.length = 0; + ext.kdbQueryHistoryList.push(...dummyQueryHistory); + }); + it("Should reload the provider", () => { + const queryHistoryProvider = new QueryHistoryProvider(); + queryHistoryProvider.reload(); + assert.notStrictEqual( + queryHistoryProvider, + undefined, + "queryHistoryProvider should be created." + ); + }); + it("Should refresh the provider", () => { + const queryHistoryProvider = new QueryHistoryProvider(); + queryHistoryProvider.refresh(); + assert.notStrictEqual( + queryHistoryProvider, + undefined, + "queryHistoryProvider should be created." + ); + }); + + it("Should return the KdbNode tree item element", () => { + const queryHistoryTreeItem = new QueryHistoryTreeItem( + "testLabel", + dummyQueryHistory[0], + TreeItemCollapsibleState.None + ); + const queryHistoryProvider = new QueryHistoryProvider(); + const element = queryHistoryProvider.getTreeItem(queryHistoryTreeItem); + assert.strictEqual( + element.label, + queryHistoryTreeItem.label, + "Get query history item is incorrect" + ); + }); + + it("Should return children for the tree when queryHistory has entries", async () => { + const queryHistoryProvider = new QueryHistoryProvider(); + const result = await queryHistoryProvider.getChildren(); + assert.strictEqual(result.length, 3, "Children count should be 3"); + }); + + it("Should not return children for the tree when queryHistory has no entries", async () => { + ext.kdbQueryHistoryList.length = 0; + const queryHistoryProvider = new QueryHistoryProvider(); + const result = await queryHistoryProvider.getChildren(); + assert.strictEqual(result.length, 0, "Children count should be 0"); + }); + + describe("QueryHistoryTreeItem", () => { + const sucessIcon = "testing-passed-icon"; + const failIcon = "testing-error-icon"; + it("Should return a new QueryHistoryTreeItem", () => { + const queryHistoryTreeItem = new QueryHistoryTreeItem( + "testLabel", + dummyQueryHistory[0], + TreeItemCollapsibleState.None + ); + assert.strictEqual( + queryHistoryTreeItem.label, + "testLabel", + "QueryHistoryTreeItem node creation failed" + ); + }); + it("Should return a new QueryHistoryTreeItem with sucess icom", () => { + const queryHistoryTreeItem = new QueryHistoryTreeItem( + "testLabel", + dummyQueryHistory[0], + TreeItemCollapsibleState.None + ); + const result = queryHistoryTreeItem.defineQueryIcon(true); + assert.strictEqual( + result, + sucessIcon, + "QueryHistoryTreeItem defineQueryIcon failed" + ); + }); + + it("Should return a new QueryHistoryTreeItem with sucess icom", () => { + const queryHistoryTreeItem = new QueryHistoryTreeItem( + "testLabel", + dummyQueryHistory[0], + TreeItemCollapsibleState.None + ); + const result = queryHistoryTreeItem.defineQueryIcon(false); + assert.strictEqual( + result, + failIcon, + "QueryHistoryTreeItem defineQueryIcon failed" + ); + }); + }); }); diff --git a/test/suite/utils.test.ts b/test/suite/utils.test.ts index 6e2c3450..a8f54bfc 100644 --- a/test/suite/utils.test.ts +++ b/test/suite/utils.test.ts @@ -14,10 +14,19 @@ import * as assert from "assert"; import * as sinon from "sinon"; import * as vscode from "vscode"; +import { TreeItemCollapsibleState } from "vscode"; +import { ext } from "../../src/extensionVariables"; +import * as QTable from "../../src/ipc/QTable"; import { CancellationEvent } from "../../src/models/cancellationEvent"; import { QueryResultType } from "../../src/models/queryResult"; +import { ServerType } from "../../src/models/server"; +import { InsightsNode, KdbNode } from "../../src/services/kdbTreeProvider"; +import { QueryHistoryProvider } from "../../src/services/queryHistoryProvider"; +import { KdbResultsViewProvider } from "../../src/services/resultsPanelProvider"; +import * as coreUtils from "../../src/utils/core"; import * as dataSourceUtils from "../../src/utils/dataSource"; import * as executionUtils from "../../src/utils/execution"; +import * as executionConsoleUtils from "../../src/utils/executionConsole"; import { getNonce } from "../../src/utils/getNonce"; import { getUri } from "../../src/utils/getUri"; import { openUrl } from "../../src/utils/openUrl"; @@ -49,6 +58,72 @@ describe("Utils", () => { windowMock.restore(); }); + describe("core", () => { + describe("setOutputWordWrapper", () => { + let getConfigurationStub: sinon.SinonStub; + beforeEach(() => { + getConfigurationStub = sinon.stub(vscode.workspace, "getConfiguration"); + }); + + afterEach(() => { + getConfigurationStub.restore(); + }); + it("should create wordwrapper if doesn't exist", () => { + getConfigurationStub.returns({ + get: sinon.stub().returns({ "[Log]": { "editor.wordWrap": "off" } }), + update: sinon.stub(), + }); + coreUtils.setOutputWordWrapper(); + sinon.assert.calledTwice(getConfigurationStub); + }); + + it("should let wordwrapper if it exist", () => { + getConfigurationStub.returns({ "editor.wordWrap": "on" }); + coreUtils.setOutputWordWrapper(); + sinon.assert.calledOnce(getConfigurationStub); + }); + }); + + describe("getHideDetailedConsoleQueryOutput", () => { + let getConfigurationStub: sinon.SinonStub; + + beforeEach(() => { + getConfigurationStub = sinon.stub( + vscode.workspace, + "getConfiguration" + ) as sinon.SinonStub; + }); + + afterEach(() => { + getConfigurationStub.restore(); + }); + + it("should update configuration and set hideDetailedConsoleQueryOutput to true when setting is undefined", async () => { + getConfigurationStub.returns({ + get: sinon.stub().returns(undefined), + update: sinon.stub(), + }); + + await coreUtils.getHideDetailedConsoleQueryOutput(); + + sinon.assert.calledTwice(getConfigurationStub); + assert.strictEqual(ext.hideDetailedConsoleQueryOutput, true); + }); + + it("should set hideDetailedConsoleQueryOutput to setting when setting is defined", async () => { + getConfigurationStub.returns({ + get: sinon.stub().returns(false), + update: sinon.stub(), + }); + + await coreUtils.getHideDetailedConsoleQueryOutput(); + + sinon.assert.calledOnce(getConfigurationStub); + assert.strictEqual(ext.hideDetailedConsoleQueryOutput, false); + }); + }); + }); + describe("dataSource", () => { // need check how to mock ext variables and populate it with values // it("createKdbDataSourcesFolder", () => { @@ -59,27 +134,6 @@ describe("Utils", () => { // ); // }); - it("convertDataSourceFormToDataSourceFile", () => { - const form = { - name: "test", - selectedType: "api", - selectedApi: "test", - selectedTable: "test", - startTS: "test", - endTS: "test", - fill: "test", - }; - const result = - dataSourceUtils.convertDataSourceFormToDataSourceFile(form); - assert.strictEqual(result.name, "test"); - assert.strictEqual(result.dataSource.selectedType, "api"); - assert.strictEqual(result.dataSource.api.selectedApi, "test"); - assert.strictEqual(result.dataSource.api.table, "test"); - assert.strictEqual(result.dataSource.api.startTS, "test"); - assert.strictEqual(result.dataSource.api.endTS, "test"); - assert.strictEqual(result.dataSource.api.fill, "test"); - }); - it("convertTimeToTimestamp", () => { const result = dataSourceUtils.convertTimeToTimestamp("2021-01-01"); assert.strictEqual(result, "2021-01-01T00:00:00.000000000"); @@ -121,7 +175,7 @@ describe("Utils", () => { const results = "test"; const type = QueryResultType.Error; const result = executionUtils.handleQueryResults(results, type); - assert.strictEqual(result, "!@#ERROR^&*%-test"); + assert.strictEqual(result, "test"); }); it("convertArrayStringInVector", () => { @@ -169,29 +223,215 @@ describe("Utils", () => { .toString(); assert.equal(result, expectedRes); }); + + describe("convertArrayOfArraysToObjects", () => { + it("should return an empty array if the input is not an array", () => { + const result = executionUtils.convertArrayOfArraysToObjects(null); + assert.deepStrictEqual(result, null); + }); + + it("should return the input array if it is empty", () => { + const result = executionUtils.convertArrayOfArraysToObjects([]); + assert.deepStrictEqual(result, []); + }); + + it("should return the input array if the first row is not an array", () => { + const result = executionUtils.convertArrayOfArraysToObjects([1, 2, 3]); + assert.deepStrictEqual(result, [1, 2, 3]); + }); + + it("should return the input array if the first row is empty", () => { + const result = executionUtils.convertArrayOfArraysToObjects([[]]); + assert.deepStrictEqual(result, [[]]); + }); + + it("should return an empty array if any row has a different length than the first row", () => { + const result = executionUtils.convertArrayOfArraysToObjects([ + [1, 2], + [3], + ]); + assert.deepStrictEqual(result, []); + }); + + it("should convert an array of arrays to an array of objects", () => { + const input = [ + [{ b: 0 }, { b: 1 }, { b: 2 }], + [{ a: 0 }, { a: 1 }, { a: 2 }], + ]; + const expectedOutput = [ + { b: 0, a: 0 }, + { b: 1, a: 1 }, + { b: 2, a: 2 }, + ]; + const result = executionUtils.convertArrayOfArraysToObjects(input); + assert.deepStrictEqual(result, expectedOutput); + }); + }); }); - // describe("executionConsole", () => { - // let outputChannelMock: sinon.SinonMock; - // let executionConsole: executionConsoleUtils.ExecutionConsole; + describe("executionConsole", () => { + ext.queryHistoryProvider = new QueryHistoryProvider(); - // beforeEach(() => { - // outputChannelMock = sinon.mock( - // vscode.window.createOutputChannel("Test Output Channel") - // executionConsole = new executionConsoleUtils.ExecutionConsole(); - // ); - // }); + describe("ExecutionConsole", () => { + let queryConsole: executionConsoleUtils.ExecutionConsole; + let getConfigurationStub: sinon.SinonStub; + const kdbNode = new KdbNode( + [], + "kdbnode1", + { + serverName: "kdbservername", + serverAlias: "kdbserveralias", + serverPort: "5001", + managed: false, + auth: false, + tls: false, + }, + TreeItemCollapsibleState.None + ); - // afterEach(() => { - // outputChannelMock.restore(); - // }); + const insightsNode = new InsightsNode( + [], + "insightsnode1", + { + server: "insightsservername", + alias: "insightsserveralias", + auth: true, + }, + TreeItemCollapsibleState.None + ); - // it("appendQuery", () => { - // const query = "test"; - // const result = executionConsole.appendQuery(query); - // assert.strictEqual(result, "evaluate.q"); - // }); - // }); + beforeEach(() => { + queryConsole = executionConsoleUtils.ExecutionConsole.start(); + + ext.kdbQueryHistoryList.length = 0; + }); + + it("should append and add queryHistory with kdbNode without details", () => { + getConfigurationStub = sinon.stub(vscode.workspace, "getConfiguration"); + getConfigurationStub.returns({ + get: sinon.stub().returns(true), + update: sinon.stub(), + }); + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = kdbNode; + + queryConsole.append(output, query, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, true); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.KDB + ); + + getConfigurationStub.restore(); + }); + + it("should append and add queryHistory with kdbNode with details", () => { + getConfigurationStub = sinon.stub(vscode.workspace, "getConfiguration"); + getConfigurationStub.returns({ + get: sinon.stub().returns(false), + update: sinon.stub(), + }); + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = kdbNode; + + queryConsole.append(output, query, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, true); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.KDB + ); + getConfigurationStub.restore(); + }); + + it("should append and add queryHistory with insightsNode", () => { + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = insightsNode; + + queryConsole.append(output, query, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, true); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.INSIGHTS + ); + }); + + it("should return add query history error with kdbNode", () => { + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = kdbNode; + + queryConsole.appendQueryError(query, output, true, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, false); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.KDB + ); + }); + + it("should return add query history error with insightsNode", () => { + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = insightsNode; + + queryConsole.appendQueryError(query, output, true, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, false); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.INSIGHTS + ); + }); + + it("should return add query history error with no connection", () => { + const query = "SELECT * FROM table"; + const output = "test"; + const serverName = "testServer"; + + ext.connectionNode = insightsNode; + + queryConsole.appendQueryError(query, output, false, serverName); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + assert.strictEqual(ext.kdbQueryHistoryList[0].success, false); + assert.strictEqual( + ext.kdbQueryHistoryList[0].connectionType, + ServerType.undefined + ); + }); + }); + + it("addQueryHistory", () => { + const query = "SELECT * FROM table"; + const connectionName = "test"; + const connectionType = ServerType.KDB; + + ext.kdbQueryHistoryList.length = 0; + + executionConsoleUtils.addQueryHistory( + query, + connectionName, + connectionType, + true + ); + assert.strictEqual(ext.kdbQueryHistoryList.length, 1); + }); + }); describe("getNonce", () => { it("should return a string with length 32", () => { @@ -347,10 +587,55 @@ describe("Utils", () => { assert.strictEqual(sanitizedQuery2, "select from t"); }); - it("handleWSResults", () => { - const ab = new ArrayBuffer(128); - const result = queryUtils.handleWSResults(ab); - assert.strictEqual(result, "No results found."); + describe("getValueFromArray", () => { + it("should return the value of the 'Value' property if the input is an array with a single object with a 'Value' property", () => { + const input = [{ Value: "hello" }]; + const expectedOutput = "hello"; + const actualOutput = queryUtils.getValueFromArray(input); + assert.strictEqual(actualOutput, expectedOutput); + }); + + it("should return the input array if it is not an array with a single object with a 'Value' property", () => { + const input = ["hello", "world"]; + const expectedOutput = ["hello", "world"]; + const actualOutput = queryUtils.getValueFromArray(input); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); + + it("should return the input array if it is an empty array", () => { + const input: any[] = []; + const expectedOutput: any[] = []; + const actualOutput = queryUtils.getValueFromArray(input); + assert.deepStrictEqual(actualOutput, expectedOutput); + }); + }); + + describe("handleWSResults", () => { + it("should return no results found", () => { + const ab = new ArrayBuffer(128); + const result = queryUtils.handleWSResults(ab); + assert.strictEqual(result, "No results found."); + }); + + it("should return the result of getValueFromArray if the results are an array with a single object with a 'Value' property", () => { + const ab = new ArrayBuffer(128); + const expectedOutput = "10"; + const uriTest: vscode.Uri = vscode.Uri.parse("test"); + ext.resultsViewProvider = new KdbResultsViewProvider(uriTest); + const qtableStub = sinon.stub(QTable.default, "toLegacy").returns({ + class: "203", + columns: ["Value"], + meta: { Value: 7 }, + rows: [{ Value: "10" }], + }); + const isVisibleStub = sinon + .stub(ext.resultsViewProvider, "isVisible") + .returns(true); + const convertRowsSpy = sinon.spy(queryUtils, "convertRows"); + const result = queryUtils.handleWSResults(ab); + sinon.assert.notCalled(convertRowsSpy); + assert.strictEqual(result, expectedOutput); + }); }); it("convertRows", () => { @@ -364,17 +649,30 @@ describe("Utils", () => { b: 4, }, ]; - const expectedRes = ["a,b", "1,2", "3,4"].toString(); + const expectedRes = ["a#$#;#$#b", "1#$#;#$#2", "3#$#;#$#4"].toString(); const result = queryUtils.convertRows(rows); assert.equal(result, expectedRes); }); it("convertRowsToConsole", () => { const rows = ["a,b", "1,2", "3,4"]; - const expectedRes = ["a b ", "------", "1 2 ", "3 4 "].toString(); + const expectedRes = ["a,b ", "-----", "1,2 ", "3,4 "].toString(); const result = queryUtils.convertRowsToConsole(rows); assert.equal(result, expectedRes); }); + + it("getConnectionType", () => { + const params: ServerType[] = [ + ServerType.INSIGHTS, + ServerType.KDB, + ServerType.undefined, + ]; + const expectedRes = ["insights", "kdb", "undefined"]; + for (let i = 0; i < params.length; i++) { + const result = queryUtils.getConnectionType(params[i]); + assert.equal(result, expectedRes[i]); + } + }); }); describe("Registration", () => { diff --git a/test/suite/validators.test.ts b/test/suite/validators.test.ts index 15750339..d0f908cf 100644 --- a/test/suite/validators.test.ts +++ b/test/suite/validators.test.ts @@ -11,98 +11,298 @@ * specific language governing permissions and limitations under the License. */ -import * as azureValidator from "../../src/validators/azureValidator"; -import * as index from "../../src/validators/debounceValidation/index"; -import * as interfaceValidator from "../../src/validators/interfaceValidator"; -import * as kdbValidator from "../../src/validators/kdbValidator"; -import * as rule from "../../src/validators/rule"; -import * as hasLowerCase from "../../src/validators/validationFunctions/hasLowerCase"; -import * as hasNoForbiddenChar from "../../src/validators/validationFunctions/hasNoForbiddenChar"; -import * as hasSpecialChar from "../../src/validators/validationFunctions/hasSpecialChar"; -import * as hasUpperCase from "../../src/validators/validationFunctions/hasUpperCase"; -import * as isAvailable from "../../src/validators/validationFunctions/isAvailable"; -import * as isNotEmpty from "../../src/validators/validationFunctions/isNotEmpty"; -import * as lengthRange from "../../src/validators/validationFunctions/lengthRange"; -import * as validator from "../../src/validators/validator"; - -describe("azureValidator", () => { - //write tests for src/validators/azureValidator.ts - //function to be deleted after write the tests - azureValidator; -}); +import assert from "assert"; +import { validateScratchpadOutputVariableName } from "../../src/validators/interfaceValidator"; +import { + validateServerAlias, + validateServerName, + validateServerPassword, + validateServerPort, + validateServerUsername, + validateTls, +} from "../../src/validators/kdbValidator"; +import { Validator } from "../../src/validators/validator"; + +describe("Interface validation tests", () => { + it("Should return successful scratchpad variable output name", () => { + const result = validateScratchpadOutputVariableName("test"); + assert.strictEqual( + result, + undefined, + "Correct input value should return success." + ); + }); -describe("interfaceValidator", () => { - //write tests for src/validators/interfaceValidator.ts - //function to be deleted after write the tests - interfaceValidator; + it("Should return failed validation with invalid scratchpad variable output name", () => { + const result = validateScratchpadOutputVariableName( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt" + ); + assert.strictEqual( + result, + "Input value must be between 1 and 64 alphanumeric characters in length.", + "Invalid input value should return fail." + ); + }); }); describe("kdbValidator", () => { - //write tests for src/validators/kdbValidator.ts - //function to be deleted after write the tests - kdbValidator; -}); + it("Should return fail for server alias that is blank or undefined", () => { + const result = validateServerAlias(undefined); + assert.strictEqual( + result, + undefined, + "Server alias that is undefined should validate as undefined" + ); + }); -describe("rule", () => { - //write tests for src/validators/rule.ts - //function to be deleted after write the tests - rule; -}); + it("Should return fail for server alias that starts with a space", () => { + const result = validateServerAlias(" test"); + assert.strictEqual( + result, + "Input value cannot start with a space.", + "Input started with a space and should fail validation." + ); + }); -describe("validator", () => { - //write tests for src/validators/validator.ts - //function to be deleted after write the tests - validator; -}); + it("Should return fail for server alias that is outside the size limits", () => { + const result = validateServerAlias( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt" + ); + assert.strictEqual( + result, + "Input value must be between 1 and 64 alphanumeric characters in length.", + "Input was outside the size limits." + ); + }); + + it("Should return fail for server alias should not contain special chars", () => { + const result = validateServerAlias("test!"); + assert.strictEqual( + result, + "Input value must contain only alphanumeric characters and hypens only", + "Input contained special chars" + ); + }); + + it("Should return fail if using restricted keyword", () => { + const result = validateServerAlias("InsightsEnterprise"); + assert.strictEqual( + result, + "Input value using restricted keywords of Insights Enterprise", + "Input contained restricted keyword." + ); + }); + + it("Should return fail for server name that is blank or undefined", () => { + const result = validateServerName(undefined); + assert.strictEqual( + result, + undefined, + "Server name that is undefined should validate as undefined" + ); + }); + + it("Should return fail for server name that is outside the size limits", () => { + const result = validateServerName( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt" + ); + assert.strictEqual( + result, + "Input value must be between 1 and 64 alphanumeric characters in length.", + "Input was outside the size limits." + ); + }); + + it("Should return fail for server port that is blank or undefined", () => { + const result = validateServerPort(undefined); + assert.strictEqual( + result, + undefined, + "Server port that is undefined should validate as undefined" + ); + }); + + it("Should return fail for server port that is not a number", () => { + const result = validateServerPort("test"); + assert.strictEqual( + result, + "Input value must be a number.", + "Input was not a number for server port." + ); + }); + + it("Should return fail for server port that is outside of range", () => { + const result = validateServerPort("65537"); + assert.strictEqual( + result, + "Invalid port number, valid range is 1-65536", + "input was not in valid port range" + ); + }); + + it("Should return success for server port that is valid", () => { + const result = validateServerPort("5001"); + assert.strictEqual(result, undefined, "Server port was valid"); + }); + + it("Should return fail for server username that is blank or undefined", () => { + const result = validateServerUsername(undefined); + assert.strictEqual( + result, + undefined, + "Server username that is undefined should validate as undefined." + ); + }); + + it("Should return fail for server username that is outside the size limits", () => { + const result = validateServerUsername( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt" + ); + assert.strictEqual( + result, + "Input value must be between 1 and 64 alphanumeric characters in length.", + "Input was outside the size limits." + ); + }); + + it("Should return fail for server password that is blank or undefined", () => { + const result = validateServerPassword(undefined); + assert.strictEqual( + result, + undefined, + "Server password that is undefined should validate as undefined." + ); + }); -describe("debounceValidation", () => { - describe("index", () => { - //write tests for src/validators/debounceValidation/index.ts - //function to be deleted after write the tests - index; + it("Should return fail for server password that is outside the size limits", () => { + const result = validateServerPassword( + "ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt" + ); + assert.strictEqual( + result, + "Input value must be between 1 and 64 alphanumeric characters in length.", + "Input was outside the size limits." + ); + }); + + it("Should return fail for server tls that is blank or undefined", () => { + const result = validateTls(undefined); + assert.strictEqual( + result, + undefined, + "Server tls that is undefined should validate as undefined." + ); + }); + + it("Should return fail for server tls that is not true or false", () => { + const result = validateTls("test"); + assert.strictEqual( + result, + "Input value must be a boolean (true or false)", + "Server tls should be boolean" + ); + }); + + it("Should return success for server tls that is true", () => { + const result = validateTls("true"); + assert.strictEqual(result, undefined, "Server tls is valid boolean"); }); }); -describe("validationFunctions", () => { - describe("hasLowerCase", () => { - //write tests for src/validators/validationFunctions/hasLowerCase.ts - //function to be deleted after write the tests - hasLowerCase; +describe("Validation functions", () => { + it("Should return validated empty object", () => { + const vTest = new Validator(""); + const result = vTest.isNotEmpty(); + assert.strictEqual( + result.getErrors(), + "Value cannot be empty.", + "Empty value should return validation error" + ); + }); + + it("Should return validated success for special char", () => { + const vTest = new Validator("t*st"); + const result = vTest.hasSpecialChar(new RegExp("\\*")); + assert.strictEqual( + result.getErrors(), + null, + "String passed contains the special chars and didn't pass validation." + ); + }); + + it("Should return validated fail for special char", () => { + const vTest = new Validator("t*st"); + const result = vTest.hasSpecialChar(new RegExp("\\!")); + assert.strictEqual( + result.getErrors(), + "Password must have 1 special character.", + "String passed does not contain the special chars and should not pass." + ); }); - describe("hasNoForbiddenChar", () => { - //write tests for src/validators/validationFunctions/hasNoForbiddenChar.ts - //function to be deleted after write the tests - hasNoForbiddenChar; + it("Should return validated success for forbidden chars", () => { + const vTest = new Validator("t*est"); + const result = vTest.hasNoForbiddenChar( + new RegExp("\\!"), + "Forbidden char found" + ); + assert.strictEqual( + result.getErrors(), + null, + "String passsed does not contain forbidden characters" + ); }); - describe("hasSpecialChar", () => { - //write tests for src/validators/validationFunctions/hasSpecialChar.ts - //function to be deleted after write the tests - hasSpecialChar; + it("Should return validated fail for forbidden chars", () => { + const vTest = new Validator("t*est"); + const result = vTest.hasNoForbiddenChar( + new RegExp("\\*"), + "Forbidden char found" + ); + assert.strictEqual( + result.getErrors(), + "Forbidden char found", + "String passsed does not contain forbidden characters" + ); }); - describe("hasUpperCase", () => { - //write tests for src/validators/validationFunctions/hasUpperCase.ts - //function to be deleted after write the tests - hasUpperCase; + it("Should return validated success for length", () => { + const vTest = new Validator("test"); + const result = vTest.inLengthRange(1, 4); + assert.strictEqual( + result.getErrors(), + null, + "Length of string is in range" + ); }); - describe("isAvailable", () => { - //write tests for src/validators/validationFunctions/isAvailable.ts - //function to be deleted after write the tests - isAvailable; + it("Should return validated failed for length", () => { + const vTest = new Validator("test"); + const result = vTest.inLengthRange(1, 3); + assert.strictEqual( + result.getErrors(), + "Length must be between 1 and 3 characters", + "Length of string is not in range" + ); }); - describe("isNotEmpty", () => { - //write tests for src/validators/validationFunctions/isNotEmpty.ts - //function to be deleted after write the tests - isNotEmpty; + it("Should return validated success for lower case", () => { + const vTest = new Validator("test"); + const result = vTest.hasLowerCase(); + assert.strictEqual( + result.getErrors(), + null, + `String contains at least one lower case char: ${result.getErrors()}` + ); }); - describe("lengthRange", () => { - //write tests for src/validators/validationFunctions/lengthRange.ts - //function to be deleted after write the tests - lengthRange; + it("Should return validated fail for lower case", () => { + const vTest = new Validator("TEST"); + const result = vTest.hasLowerCase(); + assert.strictEqual( + result.getErrors(), + "Password should have at least one lowercase letter from a to z.", + "String contains both cases" + ); }); }); diff --git a/test/tsconfig.json b/test/tsconfig.json index 30b2ad59..bceb5d8b 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,12 +3,14 @@ "module": "commonjs", "target": "ES2019", "outDir": "../out", - "lib": ["ES2019", "WebWorker", "DOM"], + "lib": ["ES2019", "WebWorker", "DOM", "DOM.Iterable"], "sourceMap": true, "esModuleInterop": true, + "allowSyntheticDefaultImports": true, "strict": false, "noImplicitAny": false, - "skipLibCheck": true + "skipLibCheck": true, + "experimentalDecorators": true }, "include": ["./**/*", "../src/**/*"], "exclude": ["node_modules", ".vscode-test"] diff --git a/tsconfig.json b/tsconfig.json index 9e74c633..7e3570c1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,14 +3,15 @@ "module": "commonjs", "target": "ES2019", "outDir": "out", - "lib": ["ES2019", "WebWorker", "DOM"], + "lib": ["ES2019", "WebWorker", "DOM", "DOM.Iterable"], "sourceMap": true, "rootDir": "src", "strict": true, "noFallthroughCasesInSwitch": true, "noUnusedParameters": true, "esModuleInterop": true, - "skipLibCheck": true + "skipLibCheck": true, + "experimentalDecorators": true }, "include": ["src/**/*"], "exclude": ["node_modules", ".vscode-test"]