diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index acfdb2c6..00000000 --- a/.eslintignore +++ /dev/null @@ -1,2 +0,0 @@ -locales/ -tests/resources/ diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 7bd46e54..00000000 --- a/.eslintrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": [ "axway/env-node", "axway/+mocha"], - "parserOptions": { - "ecmaVersion": 2015, - "sourceType": "script" - }, - "rules": { - "no-empty": ["error", { "allowEmptyCatch": true }], - "no-implicit-globals": "off" - }, - "overrides": [ - { - "files": [ "dangerfile.js" ], - "parserOptions": { - "ecmaVersion": 2017, - "sourceType": "module" - }, - }, - ] -} diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..b30cb73b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,44 @@ +# .gitattributes snippet to force users to use same line endings for project. +# +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + + +# These files are text and should be normalized (Convert crlf => lf) +*.php text +*.css text +*.js text eol=lf +*.json text +*.htm text +*.html text +*.xml text +*.txt text +*.ini text +*.inc text +*.pl text +*.rb text +*.py text +*.scm text +*.sql text +.htaccess text +*.sh text + +# These files are binary and should be left untouched +# (binary is a macro for -text -diff) +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.pyc binary diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e483caeb..997eb165 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,7 +1,37 @@ version: 2 updates: -- package-ecosystem: npm - directory: "/" - schedule: - interval: weekly - open-pull-requests-limit: 10 + - package-ecosystem: 'npm' + directory: '/' + labels: + - 'dependencies' + schedule: + interval: 'weekly' + day: 'thursday' + time: '02:34' + groups: + production: + dependency-type: 'production' + patterns: + - '*' + update-types: + - 'major' + - 'minor' + - 'patch' + development: + dependency-type: 'development' + patterns: + - '*' + update-types: + - 'major' + - 'minor' + - 'patch' + commit-message: + include: 'scope' + prefix: 'chore(deps): ' + allow: + - dependency-type: 'all' + cooldown: + default-days: 5 + semver-major-days: 30 + semver-minor-days: 7 + semver-patch-days: 3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 5c3f022a..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Build -on: - push: - branches: - - master - - "[0-9]+_[0-9]+_X" - pull_request: -env: - ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: 2000 # Default is 20 -jobs: - build: - runs-on: macos-13 - strategy: - matrix: - node: [ '22' ] - name: Node ${{ matrix.node }} - steps: - - uses: actions/checkout@v4 - - - name: Setup node - uses: actions/setup-node@v4 - with: - node-version: ${{ matrix.node }} - - - name: Cache Node.js modules - id: node-cache - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.OS }}-node-modules-${{ hashFiles('package-lock.json') }} - restore-keys: | - ${{ runner.OS }}-node-modules- - ${{ runner.OS }}- - - - run: npm ci - name: Install dependencies - if: steps.node-cache.outputs.cache-hit != 'true' - - - run: npm run lint - name: Lint - - # - name: Build and Test - # uses: reactivecircus/android-emulator-runner@v2 - # with: - # api-level: 29 - # target: playstore - # script: npm run unit-test - # emulator-options: -no-window -noaudio -no-boot-anim - # disable-animations: true # defaulting to true, the commands sent to emulator to do this sometimes run too quickly after boot and cause "adb: device offline" failures - - - run: npm pack - name: Package - if: matrix.node == '22' - - - uses: actions/upload-artifact@v4 - if: matrix.node == '22' - with: - name: node-titanium-sdk - path: node-titanium-sdk-*.tgz diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index bbfcc73f..d660e1da 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -8,6 +8,6 @@ jobs: name: Verify contributor steps: - - uses: tidev/tidev-cla-action@v2 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} + - uses: tidev/tidev-cla-action@v2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index d399722d..0ff9b256 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,7 +1,8 @@ name: Publish + on: release: - types: [ created ] + types: [created] jobs: publish: @@ -9,54 +10,54 @@ jobs: name: Publish steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Setup node - uses: actions/setup-node@v4 - with: - node-version: 22 - registry-url: 'https://registry.npmjs.org' - - - name: Install dependencies - run: npm ci - if: steps.node-cache.outputs.cache-hit != 'true' - - - name: Publish to npm - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npm publish --tag ${{ github.event.release.prerelease && 'next' || 'latest' }} - - - name: Get package.json info - id: get-package-info - run: | - echo "name=$(node -p "require('./package.json').name")" >> $GITHUB_OUTPUT - echo "homepage=$(node -p "require('./package.json').homepage")" >> $GITHUB_OUTPUT - echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT - - - name: Send Slack notification - uses: slackapi/slack-github-action@v2.1.1 - with: - method: chat.postMessage - token: ${{ secrets.SLACK_BOT_TOKEN }} - payload: | - { - "channel": "${{ secrets.SLACK_CHANNEL_ID }}", - "text": "Published ${{ steps.get-package-info.outputs.name }}@${{ steps.get-package-info.outputs.version }}", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": "Published ${{ steps.get-package-info.outputs.name }}@${{ steps.get-package-info.outputs.version }}" - } - }, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ steps.get-package-info.outputs.homepage }}/releases/tag/v${{ steps.get-package-info.outputs.version }}" + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup node + uses: actions/setup-node@v6 + with: + node-version: 24 + registry-url: 'https://registry.npmjs.org' + + - name: Install dependencies + run: npm ci + if: steps.node-cache.outputs.cache-hit != 'true' + + - name: Publish to npm + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npm publish --tag ${{ github.event.release.prerelease && 'next' || 'latest' }} + + - name: Get package.json info + id: get-package-info + run: | + echo "name=$(node -p "require('./package.json').name")" >> $GITHUB_OUTPUT + echo "homepage=$(node -p "require('./package.json').homepage")" >> $GITHUB_OUTPUT + echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT + + - name: Send Slack notification + uses: slackapi/slack-github-action@v2.1.1 + with: + method: chat.postMessage + token: ${{ secrets.SLACK_BOT_TOKEN }} + payload: | + { + "channel": "${{ secrets.SLACK_CHANNEL_ID }}", + "text": "Published ${{ steps.get-package-info.outputs.name }}@${{ steps.get-package-info.outputs.version }}", + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "Published ${{ steps.get-package-info.outputs.name }}@${{ steps.get-package-info.outputs.version }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ steps.get-package-info.outputs.homepage }}/releases/tag/v${{ steps.get-package-info.outputs.version }}" + } } - } - ] - } + ] + } diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..5fb9c8c8 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,148 @@ +name: Tests + +on: + pull_request: + push: + branches: + - main + - '[0-9]+_[0-9]+_X' + +concurrency: + cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + +jobs: + checks: + name: Check + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: Use Node.js 24 + uses: actions/setup-node@v6 + with: + node-version: 24 + + - name: Install dependencies + shell: bash + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: Check + run: pnpm check + + node-test: + name: Test on Node.js ${{ matrix.node }} and ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + node: [20, 22, 24] + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node }} + + - name: Install dependencies + shell: bash + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: Build + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm build + + - name: Run tests + run: pnpm coverage + + bun-test: + name: Test on Bun + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: Install Bun + uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + - name: Install dependencies + shell: bash + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: Build + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm build + + - name: Run tests on Bun + run: pnpm test:bun + + deno-test: + name: Test on Deno + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + + - name: Install Deno + uses: denoland/setup-deno@v2 + with: + deno-version: latest + + - name: Install dependencies + shell: bash + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm install --frozen-lockfile --ignore-scripts + + - name: Build + env: + GH_TOKEN: ${{ secrets.GH_TOKEN }} + run: pnpm build + + - name: Run tests on Deno + run: pnpm test:deno diff --git a/.gitignore b/.gitignore index 2a735a05..b1829738 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ -junit_report.xml -node_modules/ -.DS_Store -coverage/ -.nyc_output/ \ No newline at end of file +._* +.DS_Store* +coverage +dist +/node_modules +tmp +.pnpm-debug.log +*.tsbuildinfo +*.tgz diff --git a/.husky/.gitignore b/.husky/.gitignore deleted file mode 100644 index 31354ec1..00000000 --- a/.husky/.gitignore +++ /dev/null @@ -1 +0,0 @@ -_ diff --git a/.husky/commit-msg b/.husky/commit-msg deleted file mode 100755 index 49ef33e4..00000000 --- a/.husky/commit-msg +++ /dev/null @@ -1,5 +0,0 @@ - -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx --no-install commitlint --edit $1 diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index d37daa07..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -. "$(dirname "$0")/_/husky.sh" - -npx --no-install lint-staged diff --git a/.npmignore b/.npmignore deleted file mode 100644 index ca599ebc..00000000 --- a/.npmignore +++ /dev/null @@ -1,13 +0,0 @@ -tests/ -Jenkinsfile -yarn.lock -junit_report.xml -coverage/ -.nyc_output/ -dangerfile.js -Jenkinsfile -.eslintrc -.eslintignore -.gitignore -.github/ -.husky/ diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 00000000..94a4f79b --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,39 @@ +{ + "$schema": "./node_modules/oxfmt/configuration_schema.json", + "arrowParens": "always", + "bracketSameLine": false, + "bracketSpacing": true, + "embeddedLanguageFormatting": "auto", + "endOfLine": "lf", + "experimentalSortImports": { + "customGroups": [], + "groups": [], + "ignoreCase": true, + "internalPattern": ["~/", "@/"], + "newlinesBetween": true, + "order": "asc", + "partitionByComment": false, + "partitionByNewline": false, + "sortSideEffects": false + }, + "experimentalSortPackageJson": true, + "ignorePatterns": ["lib/**", "test-old/**", "test/**/mocks/**"], + "insertFinalNewline": true, + "objectWrap": "preserve", + "overrides": [ + { + "files": ["**/*.json"], + "options": { + "useTabs": false, + "tabWidth": 2 + } + } + ], + "printWidth": 100, + "proseWrap": "preserve", + "quoteProps": "as-needed", + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "useTabs": true +} diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 00000000..2e85a62b --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,15 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "env": { + "node": true, + "es2024": true + }, + "ignorePatterns": [ + "coverage/**", + "dist/**", + "lib/**", + "test/resources/**", + "test/**/mocks/**", + "test-old/**" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..3441d7ee --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..2b53020f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# 7.0.0 + +- BREAKING CHANGE: Drop Node.js 18 and older +- BREAKING CHNAGE: Refactor to ESM +- BREAKING CHANGE: Several APIs removed or now async + - `validatePlatformOptions()` now async +- Refactored to TypeScript +- Consolidated `androidlib`, `ioslib`, `jdklib`, `node-appc`, `titaniumlib` +- Updated NPM dependencies diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..ad68abac --- /dev/null +++ b/LICENSE @@ -0,0 +1,222 @@ +====================================== +Titanium CLI +Copyright TiDev, Inc. 04/07/2022-Present +====================================== + + 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 + + (or the full text of the license is below) + + 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. + + + + 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 8580b069..2aacd503 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ -## Titanium-SDK - -[![Greenkeeper badge](https://badges.greenkeeper.io/appcelerator/node-titanium-sdk.svg)](https://greenkeeper.io/) +## node-titanium-sdk This is the Titanium SDK common library used for all SDK specific CLI commands. ## Legal -Titanium is a registered trademark of TiDev Inc. All Titanium trademark and patent rights were transferred and assigned to TiDev Inc. on 4/7/2022. Please see the LEGAL information about using our trademarks, privacy policy, terms of usage and other legal information at https://tidev.io/legal. +Titanium is a registered trademark of TiDev Inc. All Titanium trademark and +patent rights were transferred and assigned to TiDev Inc. on 4/7/2022. Please +see the LEGAL information about using our trademarks, privacy policy, terms of +usage and other legal information at https://tidev.io/legal. diff --git a/bin/detect.mjs b/bin/detect.mjs new file mode 100644 index 00000000..631769c4 --- /dev/null +++ b/bin/detect.mjs @@ -0,0 +1,29 @@ +import { detectAndroidSDKs, detectAndroidNDKs } from '../dist/android/index.mjs'; +import { detectJDKs } from '../dist/jdk.mjs'; +import { detectTitaniumSDKs } from '../dist/titanium/index.mjs'; + +const type = process.argv[2]; + +if (!type || type === 'android-sdk') { + console.log('== Android SDKs '.padEnd(80, '=')); + const androidSDKs = await detectAndroidSDKs(); + console.log(androidSDKs); +} + +if (!type || type === 'android-ndk') { + console.log('\n== Android NDKs '.padEnd(80, '=')); + const androidNDKs = await detectAndroidNDKs(); + console.log(androidNDKs); +} + +if (!type || type === 'jdk') { + console.log('\n== JDKs '.padEnd(80, '=')); + const jdk = await detectJDKs(); + console.log(jdk); +} + +if (!type || type === 'titanium-sdk') { + console.log('\n== Titanium SDKs '.padEnd(80, '=')); + const titaniumSDKs = await detectTitaniumSDKs(); + console.log(titaniumSDKs); +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 00000000..fe199858 --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[test] +root = "test" diff --git a/dangerfile.js b/dangerfile.js deleted file mode 100644 index de93c78d..00000000 --- a/dangerfile.js +++ /dev/null @@ -1,20 +0,0 @@ -/* global fail */ - -// requires -const eslint = require('@seadub/danger-plugin-eslint').default; -const junit = require('@seadub/danger-plugin-junit').default; -const dependencies = require('@seadub/danger-plugin-dependencies').default; - -async function main() { - await Promise.all([ - eslint(), - junit({ pathToReport: './junit_report.xml' }), - dependencies({ type: 'npm' }), - ]); -} -main() - .then(() => process.exit(0)) - .catch(err => { - fail(err.toString()); - process.exit(1); - }); diff --git a/lefthook.yml b/lefthook.yml new file mode 100644 index 00000000..382cc11b --- /dev/null +++ b/lefthook.yml @@ -0,0 +1,6 @@ +pre-commit: + parallel: true + commands: + check: + glob: '*.{js,ts,jsx,tsx}' + run: pnpm fmt && pnpm check && git update-index --again diff --git a/lib/adb.js b/lib/adb.js index 8168114f..7c16b0e4 100644 --- a/lib/adb.js +++ b/lib/adb.js @@ -1,40 +1,18 @@ -/** - * A library for interacting with the Android Debug Bridge (adb). - * - * This library directly communicates over TCP/IP with the adb server using the - * service commands found here: - * {@link https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT} - * - * @module adb - * - * @copyright - * Copyright (c) 2009-2017 by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const appc = require('node-appc'); -const __ = appc.i18n(__dirname).__; -const async = require('async'); -const fs = require('fs-extra'); -const net = require('net'); -const path = require('path'); -const spawn = require('child_process').spawn; // eslint-disable-line security/detect-child-process -const StreamSplitter = require('stream-splitter'); - -require('colors'); +import fs from 'node:fs'; +import net from 'node:net'; +import path from 'node:path'; +import StreamSplitter from 'stream-splitter'; +import { expand } from './util/expand.js'; +import { detect as detectAndroid } from './android.js'; +import { spawn } from 'node:child_process'; +import { EmulatorManager } from './emulator.js'; let connCounter = 0; -module.exports = ADB; - /** * Debug flag that is enabled via the android.debugadb setting. */ -var DEBUG = false; +let DEBUG = false; /** * @constant @@ -70,848 +48,769 @@ const BUFFER_UNTIL_CLOSE = 3; */ const WAIT_FOR_RESPONSE = 4; -/** - * @typedef {Function} ConfigGetFunction - * @param {string} key key of the value to retrieve - * @param {*} [defaultValue=undefined] default value to return if not in config - * @returns {*} - */ +export class Connection { + /** + * Creates an Connection object. + * @param {ADB} adb - The ADB instance + */ + constructor(adb) { + this.adb = adb; + this.port = adb.config && adb.config.get('android.adb.port') || 5037; + this.socket = null; + this.state = DO_NOTHING; + this.connNum = ++connCounter; + } -/** - * CLI Config - * @typedef {Object} Config - * @property {ConfigGetFunction} get method to retrieve config values - */ + /** + * Executes a command. If there is no connection to the ADB server, it will + * connect to it, then run the command. + * @param {String} cmd - The command to run + * @param {Object} [opts] - Execute options + * @param {Boolean} [opts.bufferUntilClose=false] - Buffers all received data until ADB closes the connection + */ + exec(cmd, opts) { + return new Promise((resolve, reject) => { + let socket = this.socket; + const doSend = !!socket; + let buffer = null; + let len = null; + + const send = () => { + if (DEBUG) { + console.log(`[${this.connNum}] SENDING ${cmd}`); + } + conn.state = WAIT_FOR_COMMAND_RESULT; + buffer = null; + socket.write(('0000' + cmd.length.toString(16)).substr(-4).toUpperCase() + cmd); + }; -/** - * Creates an Connection object. - * @class - * @classdesc Manages the connection and communcations with the ADB server. - * @constructor - * @param {ADB} adb - The ADB instance - */ -function Connection(adb) { - this.adb = adb; - this.port = adb.config && adb.config.get('android.adb.port') || 5037; - this.socket = null; - this.state = DO_NOTHING; - this.connNum = ++connCounter; -} + this.opts = opts || {}; -/** - * Executes a command. If there is no connection to the ADB server, it will - * connect to it, then run the command. - * @param {String} cmd - The command to run - * @param {Connection~execCallback} callback - A function to call when the command is finished executing - * @param {Object} [opts] - Execute options - * @param {Boolean} [opts.bufferUntilClose=false] - Buffers all received data until ADB closes the connection - */ -Connection.prototype.exec = function exec(cmd, callback, opts) { - var conn = this, - socket = this.socket, - doSend = !!socket, - buffer = null, - len = null; - function send () { - DEBUG && console.log('[' + conn.connNum + '] SENDING ' + cmd); - conn.state = WAIT_FOR_COMMAND_RESULT; - buffer = null; - socket.write(('0000' + cmd.length.toString(16)).substr(-4).toUpperCase() + cmd); - } - - this.opts = opts || {}; + if (!socket) { + socket = this.socket = net.connect({ + port: this.port, + family: 4 + }, () => { + if (DEBUG) { + console.log(`[${this.connNum}] CONNECTED`); + } - if (!socket) { - socket = this.socket = net.connect({ - port: this.port, - family: 4 - }, function () { - DEBUG && console.log('[' + this.connNum + '] CONNECTED'); + // TIMOB-24906: in some circumstances sending a command to adb right away + // can yield no response. So we allow 200ms before sending the initial command + setTimeout(() => send(), 200); + }); - // TIMOB-24906: in some circumstances sending a command to adb right away - // can yield no response. So we allow 200ms before sending the initial command - setTimeout(function () { - send(); - }, 200); - }.bind(this)); - - socket.setKeepAlive(true); - socket.setNoDelay(true); - } else { - DEBUG && console.log('[' + this.connNum + '] SOCKET ALREADY OPEN, RE-LISTENING AND SENDING NEW COMMAND "' + cmd + '"'); - socket.removeAllListeners('data'); - socket.removeAllListeners('end'); - socket.removeAllListeners('error'); - } + socket.setKeepAlive(true); + socket.setNoDelay(true); + } else { + if (DEBUG) { + console.log(`[${this.connNum}] SOCKET ALREADY OPEN, RE-LISTENING AND SENDING NEW COMMAND "${cmd}"`); + } + socket.removeAllListeners('data'); + socket.removeAllListeners('end'); + socket.removeAllListeners('error'); + } - socket.on('data', function (data) { - DEBUG && console.log('[' + this.connNum + '] RECEIVED ' + data.length + ' BYTES (state=' + this.state + ') (cmd=' + cmd + ')'); + socket.on('data', (data) => { + if (DEBUG) { + console.log(`[${this.connNum}] RECEIVED ${data.length} BYTES (state=${this.state}) (cmd=${cmd})`); + } - if (this.state === DO_NOTHING) { - return; - } + if (this.state === DO_NOTHING) { + return; + } - if (!buffer || buffer.length === 0) { - buffer = data; - } else { - buffer += data; - } + if (!buffer || buffer.length === 0) { + buffer = data; + } else { + buffer += data; + } - DEBUG && console.log('[' + this.connNum + '] BUFFER LENGTH = ' + buffer.length); + if (DEBUG) { + console.log(`[${this.connNum}] BUFFER LENGTH = ${buffer.length}`); + } - while (1) { - switch (this.state) { - case WAIT_FOR_COMMAND_RESULT: - const result = buffer.slice(0, 4).toString(); - DEBUG && console.log('[' + this.connNum + '] RESULT ' + result); - if (!/^OKAY|FAIL$/.test(result)) { - callback(new Error(__('Unknown adb result "%s"', result))); - return; - } - buffer = buffer.slice(4); - - // did we fail? - if (result === 'FAIL') { - len = 0; - if (buffer.length >= 4) { - len = parseInt(buffer.slice(0, 4), 16); - isNaN(len) && (len = 0); + while (true) { + switch (this.state) { + case WAIT_FOR_COMMAND_RESULT: + const result = buffer.slice(0, 4).toString(); + if (DEBUG) { + console.log(`[${this.connNum}] RESULT "${result}"`); + } + if (!/^OKAY|FAIL$/.test(result)) { + reject(new Error(`Unknown adb result "${result}"`)); + return; + } buffer = buffer.slice(4); - } - len && (buffer = buffer.slice(0, len)); - DEBUG && console.log('[' + this.connNum + '] ERROR! ' + buffer.toString()); - this.state = DO_NOTHING; - - // copy the buffer into an error so we can free up the buffer - var err = new Error(buffer.toString()); - buffer = null; - callback(err); - conn.end(); - return; - } - // if there's no more data, then we're done - if (buffer.length === 0) { - if (this.opts.bufferUntilClose) { - DEBUG && console.log('[' + this.connNum + '] DONE, SETTING STATE TO BUFFER_UNTIL_CLOSE'); - this.state = BUFFER_UNTIL_CLOSE; - } else if (this.opts.waitForResponse) { - DEBUG && console.log('[' + this.connNum + '] DONE, SETTING STATE TO WAIT_FOR_NEW_DATA'); - this.state = WAIT_FOR_NEW_DATA; - } else { - DEBUG && console.log('[' + this.connNum + '] DONE, SETTING STATE TO DO_NOTHING'); - this.state = DO_NOTHING; - callback(); - } - return; - } + // did we fail? + if (result === 'FAIL') { + len = 0; + if (buffer.length >= 4) { + len = Number.parseInt(buffer.slice(0, 4), 16); + if (Number.isNaN(len)) { + len = 0; + } + buffer = buffer.slice(4); + } + if (len) { + buffer = buffer.slice(0, len); + } + if (DEBUG) { + console.log(`[${this.connNum}] ERROR! "${buffer.toString()}"`); + } + this.state = DO_NOTHING; + + // copy the buffer into an error so we can free up the buffer + const err = new Error(buffer.toString()); + buffer = null; + reject(err); + conn.end(); + return; + } - // if we aren't expecting the data to have a length (i.e. the shell command), - // then buffer immediately - if (this.opts.noLength) { - DEBUG && console.log('[' + this.connNum + '] PUSHING REMAINING DATA INTO BUFFER AND SETTING STATE TO BUFFER_UNTIL_CLOSE'); - this.state = BUFFER_UNTIL_CLOSE; - return; - } + // if there's no more data, then we're done + if (buffer.length === 0) { + if (this.opts.bufferUntilClose) { + if (DEBUG) { + console.log(`[${this.connNum}] DONE, SETTING STATE TO BUFFER_UNTIL_CLOSE`); + } + this.state = BUFFER_UNTIL_CLOSE; + } else if (this.opts.waitForResponse) { + if (DEBUG) { + console.log(`[${this.connNum}] DONE, SETTING STATE TO WAIT_FOR_NEW_DATA`); + } + this.state = WAIT_FOR_NEW_DATA; + } else { + if (DEBUG) { + console.log(`[${this.connNum}] DONE, SETTING STATE TO DO_NOTHING`); + } + this.state = DO_NOTHING; + resolve(); + } + return; + } - this.state = WAIT_FOR_NEW_DATA; - len = null; // we don't know the length yet - // purposely fall through - - case WAIT_FOR_NEW_DATA: - // find how many bytes we are waiting for - if (len === null && buffer.length >= 4) { - len = parseInt(buffer.slice(0, 4), 16); - DEBUG && console.log('[' + this.connNum + '] DETERMINING EXPECTED LENGTH...'); - isNaN(len) && (len = null); - buffer = buffer.slice(4); - } + // if we aren't expecting the data to have a length (i.e. the shell command), + // then buffer immediately + if (this.opts.noLength) { + if (DEBUG) { + console.log(`[${this.connNum}] PUSHING REMAINING DATA INTO BUFFER AND SETTING STATE TO BUFFER_UNTIL_CLOSE`); + } + this.state = BUFFER_UNTIL_CLOSE; + return; + } - // if there's no length, then let's fire the callback or wait until the socket closes - if (len === 0) { - DEBUG && console.log('[' + this.connNum + '] NO EXPECTED LENGTH, FIRING CALLBACK'); - callback(); - buffer = null; - len = null; - return; - } else if (len === null) { - DEBUG && console.log('[' + this.connNum + '] NO EXPECTED LENGTH'); - if (this.opts.bufferUntilClose) { - DEBUG && console.log('[' + this.connNum + '] BUFFERING DATA UNTIL SOCKET CLOSE'); - this.state = BUFFER_UNTIL_CLOSE; - } else { - buffer = null; - len = null; this.state = WAIT_FOR_NEW_DATA; - callback(); - } - return; - } + len = null; // we don't know the length yet + // purposely fall through + + case WAIT_FOR_NEW_DATA: + // find how many bytes we are waiting for + if (len === null && buffer.length >= 4) { + len = Number.parseInt(buffer.slice(0, 4), 16); + if (DEBUG) { + console.log(`[${this.connNum}] DETERMINING EXPECTED LENGTH...`); + } + if (Number.isNaN(len)) { + len = null; + } + buffer = buffer.slice(4); + } - DEBUG && console.log('[' + this.connNum + '] EXPECTED LENGTH = ' + len); - DEBUG && console.log('[' + this.connNum + '] BUFFER LENGTH = ' + buffer.length); - - // do we have enough bytes? - if (buffer.length >= len) { - // yup - const result = buffer.slice(0, len); - buffer = buffer.slice(len); - DEBUG && console.log('[' + this.connNum + '] SUCCESS AND JUST THE RIGHT AMOUNT OF BYTES (' + len + ') WITH ' + buffer.length + ' BYTES LEFT'); - if (this.opts.bufferUntilClose) { - this.state = BUFFER_UNTIL_CLOSE; - } else { - this.state = WAIT_FOR_NEW_DATA; - len = null; - buffer = null; - callback(null, result); - } - } else { - // we need more data! - DEBUG && console.log('[' + this.connNum + '] WAITING FOR MORE DATA'); - } - return; + // if there's no length, then let's fire the callback or wait until the socket closes + if (len === 0) { + if (DEBUG) { + console.log(`[${this.connNum}] NO EXPECTED LENGTH, FIRING CALLBACK`); + } + resolve(); + buffer = null; + len = null; + return; + } else if (len === null) { + if (DEBUG) { + console.log(`[${this.connNum}] NO EXPECTED LENGTH`); + } + if (this.opts.bufferUntilClose) { + if (DEBUG) { + console.log(`[${this.connNum}] BUFFERING DATA UNTIL SOCKET CLOSE`); + } + this.state = BUFFER_UNTIL_CLOSE; + } else { + buffer = null; + len = null; + this.state = WAIT_FOR_NEW_DATA; + resolve(); + } + return; + } - case BUFFER_UNTIL_CLOSE: - // we've already added data to the buffer - return; - case WAIT_FOR_RESPONSE: - DEBUG && console.log('[' + this.connNum + '] DONE, RECEIVED RESPONSE'); - this.state = DO_NOTHING; - callback(null, buffer); - return; - } - } - }.bind(this)); + if (DEBUG) { + console.log(`[${this.connNum}] EXPECTED LENGTH = ${len}`); + console.log(`[${this.connNum}] BUFFER LENGTH = ${buffer.length}`); + } - socket.on('end', function () { - DEBUG && console.log('[' + this.connNum + '] SOCKET CLOSED BY SERVER', (buffer && buffer.length)); - if (buffer) { - if (!this.opts.waitForResponse) { - callback(null, buffer); - } - buffer = null; - } - this.end(); - }.bind(this)); + // do we have enough bytes? + if (buffer.length >= len) { + // yup + const result = buffer.slice(0, len); + buffer = buffer.slice(len); + if (DEBUG) { + console.log(`[${this.connNum}] SUCCESS AND JUST THE RIGHT AMOUNT OF BYTES (${len}) WITH ${buffer.length} BYTES LEFT`); + } + if (this.opts.bufferUntilClose) { + this.state = BUFFER_UNTIL_CLOSE; + } else { + this.state = WAIT_FOR_NEW_DATA; + len = null; + buffer = null; + resolve(result); + } + } else { + // we need more data! + if (DEBUG) { + console.log(`[${this.connNum}] WAITING FOR MORE DATA`); + } + } + return; - socket.on('error', function (err) { - this.end(); + case BUFFER_UNTIL_CLOSE: + // we've already added data to the buffer + return; - if (!err.code || err.code !== 'ECONNREFUSED') { - return callback(err); - } + case WAIT_FOR_RESPONSE: + if (DEBUG) { + console.log(`[${this.connNum}] DONE, RECEIVED RESPONSE`); + } + this.state = DO_NOTHING; + resolve(buffer); + return; + } + } + }); - this.adb.startServer(function (code) { - if (code) { - callback(new Error(__('Unable to start Android Debug Bridge server (exit code %s)', code))); - } else { - this.exec(cmd, callback, this.opts); - } - }.bind(this)); - }.bind(this)); + socket.on('end', () => { + if (DEBUG) { + console.log(`[${this.connNum}] SOCKET CLOSED BY SERVER ${buffer && buffer.length}`); + } + if (buffer) { + if (!this.opts.waitForResponse) { + resolve(buffer); + } + buffer = null; + } + this.end(); + }); - doSend && send(); -}; + socket.on('error', (err) => { + this.end(); -/** - * Closes the connection and resets the socket and state. - */ -Connection.prototype.end = function end() { - if (this.socket) { - try { - this.socket.end(); - } catch (ex) { - // ignore - } - this.socket = null; + if (!err.code || err.code !== 'ECONNREFUSED') { + return reject(err); + } + + this.adb.startServer() + .then(() => this.exec(cmd, this.opts)) + .then(resolve) + .catch(reject); + }); + + if (doSend) { + send(); + } + }); } - this.state = DO_NOTHING; -}; -/** - * Creates an ADB object. - * @class - * @classdesc Provides methods to interact with the Android Debug Bridge (ADB). - * @constructor - * @param {Config} [config] cli config - */ -function ADB(config) { - this.config = config; - if (config && config.get('android.debugadb', false)) { - DEBUG = true; + /** + * Closes the connection and resets the socket and state. + */ + end() { + if (this.socket) { + try { + this.socket.end(); + } catch { + // ignore + } + this.socket = null; + } + this.state = DO_NOTHING; } } -/** - * Returns the version of the ADB server. - * @param {ADB~versionCallback} callback - A function to call when the version has been retreived - */ -ADB.prototype.version = function version(callback) { - const conn = new Connection(this); - conn.exec('host:version', function (err, data) { - if (err) { - return callback(err); +export class ADB { + /** + * Creates an ADB object. + * @class + * @classdesc Provides methods to interact with the Android Debug Bridge (ADB). + * @constructor + * @param {Config} [config] cli config + */ + constructor(config) { + this.config = config; + if (config?.get('android.debugadb', false)) { + DEBUG = true; } + } + + /** + * Returns the version of the ADB server. + */ + async version() { + const conn = new Connection(this); + const data = await conn.exec('host:version'); if (data === null || data === undefined) { - return callback(new Error(`Unable to get adb version, received value ${data}`)); + throw new Error(`Unable to get adb version, received value ${data}`); + } + const version = Number.parseInt(data, 16); + if (Number.isNaN(version)) { + throw new Error(`Unable to get adb version, received value ${data}`); } - // Check if parseInt result is NaN? - callback(null, '1.0.' + parseInt(data, 16)); - }); -}; + return `1.0.${version}`; + } -/** - * Parses the device list, then fetches additional device info. - * @param {ADB} adb - The ADB instance - * @param {Function} callback - A function to call when the devices have been parsed - * @param {Error} err - An error if the list devices call failed - * @param {Buffer|String} data - The buffer containing the list of devices - */ -function parseDevices(adb, callback, err, data) { - if (err) { - callback(err); - return; + async devices() { + const data = await new Connection(this).exec('host:devices', { waitForResponse: true }); + return this.parseDevices(data); } - var EmulatorManager = require('./emulator'), - emuMgr = new EmulatorManager(adb.config); + /** + * Parses the device list, then fetches additional device info. + * @param {Buffer|String} data - The buffer containing the list of devices + */ + async parseDevices(data) { + const emuMgr = new EmulatorManager(this.config); - async.series((data || '').toString().split('\n').map(function (line) { - return function (done) { - var p = line.split(/\s+/); + const results = await Promise.all(data.toString().split('\n').map(async line => { + const p = line.split(/\s+/); if (p.length <= 1) { - return done(); + return; } - var info = { + const info = { id: p.shift(), state: p.shift() }; if (info.state !== 'device') { - emuMgr.isEmulator(info.id, function (err, emu) { + emuMgr.isEmulator(info.id, (_err, emu) => { info.emulator = emu || false; done(null, info); }); return; } - adb.shell(info.id, 'getprop', function (err, data) { - if (!err && data) { - const re = /^\[([^\]]*)\]: \[(.*)\]\s*$/; - data.toString().split('\n').forEach(function (line) { - const m = line.match(re); - if (m) { - const key = m[1]; - const value = m[2]; - - switch (key) { - case 'ro.product.model.internal': - info.modelnumber = value; - break; - case 'ro.build.version.release': - case 'ro.build.version.sdk': - case 'ro.product.brand': - case 'ro.product.device': - case 'ro.product.manufacturer': - case 'ro.product.model': - case 'ro.product.name': - info[key.split('.').pop()] = value; - break; - default: - if (key.indexOf('ro.product.cpu.abi') === 0) { - Array.isArray(info.abi) || (info.abi = []); - value.split(',').forEach(function (abi) { - abi = abi.trim(); - if (abi && info.abi.indexOf(abi) === -1) { - info.abi.push(abi); + return new Promise((resolve) => { + this.shell(info.id, 'getprop', (err, data) => { + if (!err && data) { + const re = /^\[([^\]]*)\]: \[(.*)\]\s*$/; + data.toString().split('\n').forEach(line => { + const m = line.match(re); + if (m) { + const key = m[1]; + const value = m[2]; + + switch (key) { + case 'ro.product.model.internal': + info.modelnumber = value; + break; + case 'ro.build.version.release': + case 'ro.build.version.sdk': + case 'ro.product.brand': + case 'ro.product.device': + case 'ro.product.manufacturer': + case 'ro.product.model': + case 'ro.product.name': + info[key.split('.').pop()] = value; + break; + default: + if (key.startsWith('ro.product.cpu.abi')) { + if (!Array.isArray(info.abi)) { + info.abi = []; } - }); - } - break; + for (const abi of value.split(',').map(abi => abi.trim())) { + if (abi && !info.abi.includes(abi)) { + info.abi.push(abi); + } + } + } + break; + } } - } - }); - } + }); + } - emuMgr.isEmulator(info.id, function (err, emu) { - info.emulator = emu || false; - done(null, info); + emuMgr.isEmulator(info.id, (_err, emu) => { + info.emulator = emu || false; + resolve(info); + }); }); }); - }; - }), function (err, results) { - callback(null, results.filter(device => !!device)); - }); -} + })); -/** - * Retrieves a list of all devices and emulators. - * @param {ADB~devicesCallback} callback - A function that is called with the list of devices - */ -ADB.prototype.devices = function devices(callback) { - new Connection(this).exec('host:devices', function (err, data) { - parseDevices(this, callback, err, data); - }.bind(this), { waitForResponse: true }); -}; + return results.filter(Boolean); + } -/** - * Retrieves a list of all devices and emulators, then listens for changes to devices. - * @param {ADB~trackDevicesCallback} callback - A function that is continually called with the list of devices - * @returns {Connection} The connection so you can end() it. - */ -ADB.prototype.trackDevices = function trackDevices(callback) { - var conn = new Connection(this), - _t = this, - queue = async.queue(function (task, next) { - parseDevices(_t, function (err, results) { + /** + * Retrieves a list of all devices and emulators, then listens for changes to devices. + * @param {ADB~trackDevicesCallback} callback - A function that is continually called with the list of devices + * @returns {Connection} The connection so you can end() it. + */ + trackDevices(callback) { + const conn = new Connection(this); + + let isProcessing = false; + const taskQueue = []; + + const processNext = () => { + if (isProcessing || taskQueue.length === 0) { + return; + } + + isProcessing = true; + const task = taskQueue.shift(); + + this.parseDevices((err, results) => { callback(err, results); - next(); + isProcessing = false; + processNext(); }, task.err, task.data); - }, 1); + }; - conn.exec('host:track-devices', function (err, data) { - queue.push({ err: err, data: data }); - }, { waitForResponse: true }); + conn.exec('host:track-devices', (err, data) => { + taskQueue.push({ err, data }); + processNext(); + }, { waitForResponse: true }); - return conn; -}; + return conn; + } -/** - * Helper function that loads the Android detection library and detects the adb settings. - * @param {Config} config CLI config - * @param {Function} callback async callback - */ -function androidDetect(config, callback) { - (require('./android')).detect(config, null, function (results) { - if (results.sdk && results.sdk.executables.adb) { - callback(null, results); - } else { - callback(new Error(__('Android SDK not found'))); + /** + * Attempts to find the adb executable, then start the adb server. + */ + async startServer() { + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); } - }); -} + const child = spawn(androidEnv.sdk.executables.adb, 'start-server', { stdio: ['ignore', 'ignore', 'pipe'] }); + let stderr = ''; + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + return new Promise((resolve, reject) => { + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to start ADB (code ${code}): ${stderr}`)); + } else { + resolve(); + } + }); + }); + } -/** - * Attempts to find the adb executable, then start the adb server. - * @param {ADB~startServerCallback} callback - A function that is called when the server has started - */ -ADB.prototype.startServer = function startServer(callback) { - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); + /** + * Attempts to find the adb executable, then stop the adb server. + */ + async stopServer() { + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); } - appc.subprocess.run(results.sdk.executables.adb, 'start-server', function (code, out, err) { - callback(code ? new Error(__('Failed to start ADB (code %s): %s', code, err)) : null); + const child = spawn(androidEnv.sdk.executables.adb, 'kill-server', { stdio: 'ignore' }); + return new Promise((resolve, reject) => { + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to stop ADB (code ${code})`)); + } else { + resolve(); + } + }); }); - }); -}; + } -/** - * Attempts to find the adb executable, then stop the adb server. - * @param {ADB~stopServerCallback} callback - A callback that is fired when the server has stopped - */ -ADB.prototype.stopServer = function stopServer(callback) { - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); - } - appc.subprocess.run(results.sdk.executables.adb, 'kill-server', function (code, _out, _err) { - callback(code); + /** + * Runs the specified command on the Android emulator/device. Note that ADB + * converts all \n to \r\n. So data will probably be larger than the original + * output on the device. + * @param {String} deviceId - android emulator id (of form 'android-5554', gotten from emulator.id after starting it (not to be confused with ids from emulator.detect listing)) + * @param {String} cmd - The command to run + */ + async shell(deviceId, cmd) { + const conn = new Connection(this); + return new Promise((resolve, reject) => { + conn.exec(`host:transport:${deviceId}`, (err, _data) => { + if (err) { + reject(err); + } else { + conn.exec(`shell:${cmd.replace(/^shell:/, '')}`, (err, result) => { + if (err) { + reject(err); + } else { + resolve(result); + } + }, { bufferUntilClose: true, noLength: true }); + } + }); }); - }); -}; + } -/** - * Runs the specified command on the Android emulator/device. Note that ADB - * converts all \n to \r\n. So data will probably be larger than the original - * output on the device. - * @param {String} deviceId - android emulator id (of form 'android-5554', gotten from emulator.id after starting it (not to be confused with ids from emulator.detect listing)) - * @param {String} cmd - The command to run - * @param {ADB~shellCallback} callback - A callback that is fired when the command has completed - */ -ADB.prototype.shell = function shell(deviceId, cmd, callback) { - var conn = new Connection(this); - conn.exec('host:transport:' + deviceId, function (err, _data) { - if (err) { - callback(err); - } else { - conn.exec('shell:' + cmd.replace(/^shell:/, ''), function (err, result) { - callback(err, result); - }, { bufferUntilClose: true, noLength: true }); + /** + * Installs an app to the specified device/emulator. + * @param {String} deviceId - The id of the device or emulator + * @param {String} apkFile - The application apk file to install + * @param {Object} [opts] - Install options + * @param {Object} [opts.logger] - A logger instance + */ + async installApp(deviceId, apkFile, opts) { + apkFile = expand(apkFile); + if (!fs.existsSync(apkFile)) { + throw new Error(`APK file "${apkFile}" does not exist`); } - }); -}; -/** - * Installs an app to the specified device/emulator. - * @param {String} deviceId - The id of the device or emulator - * @param {String} apkFile - The application apk file to install - * @param {Object} [opts] - Install options - * @param {Object} [opts.logger] - A logger instance - * @param {ADB~installAppCallback} callback - A callback that is fired when the application has been installed - */ -ADB.prototype.installApp = function installApp(deviceId, apkFile, opts, callback) { - if (typeof opts === 'function') { - callback = opts; - opts = {}; - } - apkFile = appc.fs.resolvePath(apkFile); - if (!fs.existsSync(apkFile)) { - callback(new Error(__('APK file "%s" does not exist', apkFile))); - return; - } + const devices = await this.devices(); - this.devices(function (err, devices) { - if (err) { - return callback(err); + // Fetch info about the device we're installing to. + const device = devices.find(d => d.id === deviceId); + if (!device) { + throw new Error('device not found'); } - // Fetch info about the device we're installing to. - devices = devices.filter(d => d.id === deviceId); - if (devices.length < 1) { - return callback(new Error(__('device not found'))); + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); } - const deviceInfo = devices[0]; - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); + // Fetch the device's API Level. + let deviceApiLevel = null; + if (device.sdk) { + const value = Number.parseInt(device.sdk); + if (!Number.isNaN(value)) { + deviceApiLevel = value; } + } - // Fetch the device's API Level. - let deviceApiLevel = 1; - if (deviceInfo.sdk) { - const value = parseInt(deviceInfo.sdk); - if (!isNaN(value)) { - deviceApiLevel = value; - } - } + // Set up the 'adb' arguments array. + const args = [ + '-s', deviceId, + 'install', + '-r', + ]; + if (deviceApiLevel >= 17) { + // Allow installation of an older APK version over a newer one. + // Note: Only supported on Android 4.2 (API Level 17) and higher. + args.push('-d'); + } + args.push(apkFile); - // Set up the 'adb' arguments array. - const args = []; - args.push('-s', deviceId); - args.push('install'); - args.push('-r'); - if (deviceApiLevel >= 17) { - // Allow installation of an older APK version over a newer one. - // Note: Only supported on Android 4.2 (API Level 17) and higher. - args.push('-d'); - } - args.push(apkFile); - - // Run the adb install command. - opts.logger && opts.logger.trace(__('Executing: %s', [ results.sdk.executables.adb ].concat(args).join(' ').cyan)); - appc.subprocess.run(results.sdk.executables.adb, args, function (code, out, err) { - var m = out.match(/^Failure \[(.+)\]$/m); - if ((code && err.indexOf('No space left on device') !== -1) || (!code && m && m[1] === 'INSTALL_FAILED_INSUFFICIENT_STORAGE')) { - callback(new Error(__('Not enough free space on device'))); + // Run the adb install command. + opts.logger?.trace(`Executing: ${[ androidEnv.sdk.executables.adb ].concat(args).join(' ')}`); + + await new Promise((resolve, reject) => { + const child = spawn(androidEnv.sdk.executables.adb, args, { stdio: ['ignore', 'pipe', 'pipe'] }); + let stdout = ''; + let stderr = ''; + child.stdout.on('data', (data) => { + stdout += data.toString(); + }); + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + child.on('close', (code) => { + const m = stdout.match(/^Failure \[(.+)\]$/m); + if ((code && stderr.includes('No space left on device')) || (!code && m?.[1] === 'INSTALL_FAILED_INSUFFICIENT_STORAGE')) { + reject(new Error('Not enough free space on device')); } else if (m && m[1] === 'INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES') { - callback(__('The app is already installed, but signed with a different certificate') + '\n' - + __('You need to either manually uninstall the app or rebuild using the same certificate that was used to sign the installed app')); + reject(new Error(`The app is already installed, but signed with a different certificate\nYou need to either manually uninstall the app or rebuild using the same certificate that was used to sign the installed app`)); } else if (m) { - callback(new Error(m[1])); + reject(new Error(m[1])); } else if (code) { - callback(new Error(out.trim() + '\n' + err.trim())); + reject(new Error(`${stdout.trim()}\n${stderr.trim()}`)); } else { // no obvious errors, now we need to check stdout - m = out.match(/^Error: (.+)$/m); + const m = stdout.match(/^Error: (.+)$/m); if (m) { - callback(new Error(m[1])); + reject(new Error(m[1])); } else { - callback(); + resolve(); } } }); }); - }.bind(this)); -}; + } -/** - * Returns the ps output of the specified app and device/emulator, if running. - * @param {String} deviceId - The id of the device or emulator - * @param {ADB~psCallback} callback - A callback that is fired once ps is executed - */ -ADB.prototype.ps = function ps(deviceId, callback) { - var outputCallback = function (err, data) { - if (err) { - callback(err); - } else { - // old ps, does not support '-A' parameter - var dataStr = data.toString().trim(); - if (dataStr.startsWith('bad pid \'-A\'') || dataStr.endsWith('NAME')) { - this.shell(deviceId, 'ps', outputCallback); - } else { - callback(null, data); - } + /** + * Returns the ps output of the specified app and device/emulator, if running. + * @param {String} deviceId - The id of the device or emulator + */ + async ps(deviceId) { + let data = await this.shell(deviceId, 'ps -A'); + const dataStr = data.toString().trim(); + // old ps, does not support '-A' parameter + if (dataStr.startsWith('bad pid \'-A\'') || dataStr.endsWith('NAME')) { + data = await this.shell(deviceId, 'ps'); } - }.bind(this); - this.shell(deviceId, 'ps -A', outputCallback); -}; + return data; + } -/** - * Returns the pid of the specified app and device/emulator, if running. - * @param {String} deviceId - The id of the device or emulator - * @param {String} appid - The application's id - * @param {ADB~getPidCallback} callback - A callback that is fired once the pid has been determined - */ -ADB.prototype.getPid = function getPid(deviceId, appid, callback) { - this.ps(deviceId, function (err, data) { - if (err) { - callback(err); - } else { - var lines = data.toString().split('\n'), - i = 0, - len = lines.length, - columns; - for (; i < len; i++) { - columns = lines[i].trim().split(/\s+/); - if (columns.pop() == appid) { // eslint-disable-line eqeqeq - callback(null, parseInt(columns[1])); - return; - } + /** + * Returns the pid of the specified app and device/emulator, if running. + * @param {String} deviceId - The id of the device or emulator + * @param {String} appid - The application's id + */ + async getPid(deviceId, appid) { + const data = await this.ps(deviceId); + const lines = data.toString().split('\n'); + let columns; + for (let i = 0, len = lines.length; i < len; i++) { + columns = lines[i].trim().split(/\s+/); + if (columns.pop() == appid) { + return Number.parseInt(columns[1]); } - callback(null, 0); } - }); -}; + throw new Error(`Application "${appid}" is not running`); + } -/** - * Starts an application on the specified device/emulator. - * @param {String} deviceId - The id of the device or emulator - * @param {String} appid - The application's id - * @param {String} activity - The name of the activity to run - * @param {ADB~startAppCallback} callback - A function that is called once the application has been started - */ -ADB.prototype.startApp = function startApp(deviceId, appid, activity, callback) { - // This launches the app via an intent just like how the Android OS would do it when tapping on the app. - // Notes: - // - The "-n" sets the intent's component name. Needed by explicit intents. - // - The "-a" sets the intent's action. - // - The "-c" sets the intent's category. - // - The "-f 0x10200000" sets intent flags: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED - this.shell(deviceId, 'am start -n ' + appid + '/.' + activity.replace(/^\./, '') + ' -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000', callback); -}; + /** + * Starts an application on the specified device/emulator. + * @param {String} deviceId - The id of the device or emulator + * @param {String} appid - The application's id + * @param {String} activity - The name of the activity to run + */ + async startApp(deviceId, appid, activity) { + // This launches the app via an intent just like how the Android OS would do it when tapping on the app. + // Notes: + // - The "-n" sets the intent's component name. Needed by explicit intents. + // - The "-a" sets the intent's action. + // - The "-c" sets the intent's category. + // - The "-f 0x10200000" sets intent flags: FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_RESET_TASK_IF_NEEDED + await this.shell(deviceId, `am start -n ${appid}/.${activity.replace(/^\./, '')} -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000`); + } -/** - * Stops an application on the specified device/emulator. - * @param {String} deviceId - The id of the device or emulator - * @param {String} appid - The application's id - * @param {ADB~stopAppCallback} callback - A function that is called once the application has been stopped - */ -ADB.prototype.stopApp = function stopApp(deviceId, appid, callback) { - this.getPid(deviceId, appid, function (err, pid) { - if (!err && pid) { - this.shell(deviceId, 'am force-stop ' + appid, function (err, data) { - if (data.toString().indexOf('Unknown command: force-stop') !== -1) { - this.shell(deviceId, 'kill ' + pid, callback); - } else { - callback(err, data); - } - }.bind(this)); - return; + /** + * Stops an application on the specified device/emulator. + * @param {String} deviceId - The id of the device or emulator + * @param {String} appid - The application's id + */ + async stopApp(deviceId, appid) { + const pid = await this.getPid(deviceId, appid); + if (!pid) { + throw new Error(`Application "${appid}" is not running`); } - callback(new Error(__('Application "%s" is not running', appid))); - }.bind(this)); -}; - -/** - * Forwards the specified device/emulator's socket connections to the destination. - * @param {String} deviceId - The id of the device or emulator - * @param {String} src - The source port in the format "tcp:" - * @param {String} dest - The destination port in the format "tcp:" or "jdwp:" - * @param {ADB~forwardCallback} callback - A function that is called once the sockets have been forwarded - */ -ADB.prototype.forward = function forward(deviceId, src, dest, callback) { - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); + const data = await this.shell(deviceId, `am force-stop ${appid}`); + if (data.toString().includes('Unknown command: force-stop')) { + await this.shell(deviceId, `kill ${pid}`); + } else { + return data; } - appc.subprocess.run(results.sdk.executables.adb, [ '-s', deviceId, 'forward', src, dest ], function (code, _out, _err) { - callback(code); - }); - }); -}; + } -/** - * Pushes a single file to a device or emulator. - * @param {String} deviceId - The id of the device or emulator - * @param {String} src - The source file to copy to the device - * @param {String} dest - The destination to write the file - * @param {ADB~pushCallback} callback - A function that is called once the file has been copied - */ -ADB.prototype.push = function push(deviceId, src, dest, callback) { - src = appc.fs.resolvePath(src); - if (!fs.existsSync(src)) { - callback(new Error(__('Source file "%s" does not exist', src))); - } else { - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); - } - appc.subprocess.run(results.sdk.executables.adb, [ '-s', deviceId, 'push', src, dest ], function (code, _out, _err) { - callback(code); + /** + * Forwards the specified device/emulator's socket connections to the destination. + * @param {String} deviceId - The id of the device or emulator + * @param {String} src - The source port in the format "tcp:" + * @param {String} dest - The destination port in the format "tcp:" or "jdwp:" + */ + async forward(deviceId, src, dest) { + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); + } + await new Promise((resolve, reject) => { + const child = spawn(androidEnv.sdk.executables.adb, [ '-s', deviceId, 'forward', src, dest ], { stdio: 'ignore' }); + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to forward sockets (code ${code})`)); + } else { + resolve(); + } }); }); } -}; -/** - * Pulls a single file from a device or emulator. - * @param {String} deviceId - The id of the device or emulator - * @param {String} src - The source file to copy from the device - * @param {String} dest - The destination to write the file - * @param {ADB~pullCallback} callback - A function that is called once the file has been copied - */ -ADB.prototype.pull = function pull(deviceId, src, dest, callback) { - dest = appc.fs.resolvePath(dest); - var destDir = path.dirname(dest); + /** + * Pushes a single file to a device or emulator. + * @param {String} deviceId - The id of the device or emulator + * @param {String} src - The source file to copy to the device + * @param {String} dest - The destination to write the file + */ + async push(deviceId, src, dest) { + src = expand(src); + if (!fs.existsSync(src)) { + throw new Error(`Source file "${src}" does not exist`); + } - try { - fs.ensureDirSync(destDir); + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); + } - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); - } - appc.subprocess.run(results.sdk.executables.adb, [ '-s', deviceId, 'pull', src, dest ], function (code, _out, _err) { - callback(code); + await new Promise((resolve, reject) => { + const child = spawn(androidEnv.sdk.executables.adb, [ '-s', deviceId, 'push', src, dest ], { stdio: 'ignore' }); + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to push file (code ${code})`)); + } else { + resolve(); + } }); }); - } catch (ex) { - callback(new Error(__('Failed to create destination directory "%s"', destDir))); } -}; -/** - * Streams output from logcat into the specified handler until the adb logcat - * process ends. - * @param {String} deviceId - The id of the device or emulator - * @param {Function} handler - A function to call whenever data becomes available - * @param {Function} callback - A function that is called once 'adb logcat' exits - */ -ADB.prototype.logcat = function logcat(deviceId, handler, callback) { - androidDetect(this.config, function (err, results) { - if (err) { - return callback(err); + /** + * Pulls a single file from a device or emulator. + * @param {String} deviceId - The id of the device or emulator + * @param {String} src - The source file to copy from the device + * @param {String} dest - The destination to write the file + */ + async pull(deviceId, src, dest) { + dest = expand(dest); + const destDir = path.dirname(dest); + fs.mkdirSync(destDir, { recursive: true }); + + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); } - var child = spawn(results.sdk.executables.adb, [ '-s', deviceId, 'logcat', '-v', 'brief', '-b', 'main' ]), // , '-s', '*:d,*,TiAPI:V']); - splitter = child.stdout.pipe(StreamSplitter('\n')); - - // Set encoding on the splitter Stream, so tokens come back as a String. - splitter.encoding = 'utf8'; - splitter.on('token', function (data) { - handler(data); - }); - - child.on('close', function () { - callback(); + await new Promise((resolve, reject) => { + const child = spawn(androidEnv.sdk.executables.adb, [ '-s', deviceId, 'pull', src, dest ], { stdio: 'ignore' }); + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to pull file (code ${code})`)); + } else { + resolve(); + } + }); }); - }); -}; - -/** - * A function to call when the version has been retreived. - * @callback ADB~versionCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {String} version - The version of the adb server - */ - -/** - * A function to call when the command is finished executing. - * @callback Connection~execCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Buffer} data - The output from the executed command - */ - -/** - * A function that is called with the list of devices. - * @callback ADB~devicesCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Array} devices - An array of devices and emulators found - */ - -/** - * A function that is continually called with the list of devices when the state - * of any devices or emulators. - * @callback ADB~trackDevicesCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Array} devices - An array of devices and emulators found - */ - -/** - * A function that is called when the adb start-server has completed. - * @callback ADB~startServerCallback - * @param {Number|Error} err - The exit code from adb start-server command or an exception - */ - -/** - * A function that is called when the adb kill-server has completed. - * @callback ADB~stopServerCallback - * @param {Number|Error} err - The exit code from adb kill-server command or an exception - */ - -/** - * A function that is called when the shell command has completed. - * Called after the shell command completes. - * @callback ADB~shellCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Buffer} data - The output from the executed command - */ - -/** - * A function that is called when the application has been installed. - * @callback ADB~installAppCallback - * @param {Number|Error} err - The exit code from adb install command or an exception - */ - -/** - * A callback that is fired once the pid has been determined. - * @callback ADB~getPidCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Number} pid - The pid or zero if the process is not found - */ - -/** - * A function that is called when the application has been started. - * @callback ADB~startAppCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Buffer} data - The output from the executed command - */ - -/** - * A function that is called when the application has been stopped. - * @callback ADB~stopAppCallback - * @param {Error} err - In the event of an error, an exception, otherwise falsey - * @param {Buffer} data - The output from the executed command - */ - -/** - * A function that is called once the sockets have been forwarded. - * @callback ADB~forwardCallback - * @param {Number|Error} err - The exit code from adb forward command or an exception - */ + } -/** - * A function that is called once the file has been copied. - * @callback ADB~pushCallback - * @param {Number|Error} err - The exit code from adb forward command or an exception - */ + /** + * Streams output from logcat into the specified handler until the adb logcat + * process ends. + * @param {String} deviceId - The id of the device or emulator + * @param {Function} handler - A function to call whenever data becomes available + */ + async logcat(deviceId, handler) { + const androidEnv = await detectAndroid(this.config); + if (!androidEnv.sdk?.executables?.adb) { + throw new Error('Android SDK not found'); + } -/** - * A function that is called once the file has been copied. - * @callback ADB~pullCallback - * @param {Number|Error} err - The exit code from adb forward command or an exception - */ + await new Promise((resolve, reject) => { + const child = spawn(androidEnv.sdk.executables.adb, [ '-s', deviceId, 'logcat', '-v', 'brief', '-b', 'main' ]); // , '-s', '*:d,*,TiAPI:V']); + const splitter = child.stdout.pipe(StreamSplitter('\n')); -/** - * A function to call whenever data becomes available. - * @callback ADB~logcatHandler - * @param {String} data - One or more lines of logcat output - */ + // Set encoding on the splitter Stream, so tokens come back as a String. + splitter.encoding = 'utf8'; + splitter.on('token', (data) => handler(data)); -/** - * A function that is called once 'adb logcat' exits - * @callback ADB~logcatCallback - */ + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to logcat (code ${code})`)); + } else { + resolve(); + } + }); + }); + } +} diff --git a/lib/android.js b/lib/android.js index eea14dac..e87b13ff 100644 --- a/lib/android.js +++ b/lib/android.js @@ -1,36 +1,20 @@ -/** - * Detects the Android development environment and its dependencies. - * - * @module lib/android - * - * @copyright - * Copyright (c) 2009-2017 by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const fs = require('fs'), - path = require('path'), - async = require('async'), - appc = require('node-appc'), - manifestJson = appc.pkginfo.manifest(module), - i18n = appc.i18n(__dirname), - __ = i18n.__, - __n = i18n.__n, - afs = appc.fs, - run = appc.subprocess.run, - findExecutable = appc.subprocess.findExecutable, - exe = process.platform === 'win32' ? '.exe' : '', - cmd = process.platform === 'win32' ? '.cmd' : '', - commandPrefix = process.env.APPC_ENV ? 'appc ' : '', - requiredSdkTools = { - adb: exe, - emulator: exe - }, - pkgPropRegExp = /^([^=]*)=\s*(.+)$/; +import fs from 'node:fs'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { detect as detectJDK } from './jdk.js'; +import { expand } from './util/expand.js'; +import { loadManifestJson } from './util/load-manifest-json.js'; +import which from 'which'; +import * as version from './util/version.js'; + +const exe = process.platform === 'win32' ? '.exe' : ''; +const cmd = process.platform === 'win32' ? '.cmd' : ''; +const commandPrefix = process.env.APPC_ENV ? 'appc ' : ''; +const requiredSdkTools = { + adb: exe, + emulator: exe +}; +const pkgPropRegExp = /^([^=]*)=\s*(.+)$/; let envCache; @@ -47,673 +31,543 @@ const dirs = process.platform === 'win32' '~/Library/Android' // Android Studio installs the NDK to ~/Library/Android/Sdk/ndk-bundle ]; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// find the SDK's manifest.json file +let manifestJson = loadManifestJson(__dirname); + // need to find the android module and its package.json let androidPackageJson = {}; -const { root } = path.parse(__dirname); -(function findPackageJson(dir) { - if (dir !== root) { - const file = path.join(dir, 'android', 'package.json'); +{ + const { root } = path.parse(__dirname); + let currentDir = path.join(__dirname, '..', '..', '..'); + + while (currentDir !== root) { + const file = path.join(currentDir, 'android', 'package.json'); if (fs.existsSync(file)) { - androidPackageJson = require(file); - } else { - findPackageJson(path.dirname(dir)); + androidPackageJson = JSON.parse(fs.readFileSync(file, 'utf8')); + break; } + currentDir = path.dirname(currentDir); } -}(path.join(__dirname, '..', '..', '..'))); +} + // allow overridding for tests -exports.androidPackageJson = function (json) { +export function setAndroidPackageJson(json) { androidPackageJson = json; -}; - -/** - * Detects current Android environment. - * @param {Object} config - The CLI config object - * @param {Object} opts - Detect options - * @param {Boolean} [opts.bypassCache=false] - Bypasses the Android environment detection cache and re-queries the system - * @param {Function} finished - Callback when detection is finished - * @returns {void} - */ -exports.detect = function detect(config, opts, finished) { - opts || (opts = {}); +} - if (envCache && !opts.bypassCache) { - return finished(envCache); +async function detectSDK(config) { + // first let's check the config's value + let sdk = await findSDK(config.get('android.sdkPath'), config, androidPackageJson); + if (sdk) { + return sdk; } - async.parallel({ - jdk: function (next) { - appc.jdk.detect(config, opts, function (results) { - next(null, results); - }); - }, + sdk = await findSDK(process.env.ANDROID_SDK_ROOT, config, androidPackageJson); + if (sdk) { + return sdk; + } - sdk: function (next) { - var queue = async.queue(function (task, callback) { - task(function (err, result) { - if (err) { - callback(); // go to next item in the queue - } else { - next(null, result); - } - }); - }, 1); + sdk = await findSDK(process.env.ANDROID_SDK, config, androidPackageJson); + if (sdk) { + return sdk; + } - queue.drain(function () { - // we have completely exhausted all search paths - next(null, null); - }); + let adb = config.get('android.executables.adb'); + if (adb) { + adb = await which(adb, { nothrow: true }); + } + if (!adb) { + adb = await which('adb', { nothrow: true }); + } + console.log('adb', adb); + if (adb) { + sdk = await findSDK(expand(adb, '..', '..'), config, androidPackageJson); + if (sdk) { + return sdk; + } + } - queue.push([ - // first let's check the config's value - function (cb) { - findSDK(config.get('android.sdkPath'), config, androidPackageJson, cb); - }, - // try the environment variables - function (cb) { - findSDK(process.env.ANDROID_SDK_ROOT, config, androidPackageJson, cb); - }, - function (cb) { - findSDK(process.env.ANDROID_SDK, config, androidPackageJson, cb); - }, - // try finding the 'adb' executable - function (cb) { - findExecutable([ config.get('android.executables.adb'), 'adb' + exe ], function (err, result) { - if (err) { - cb(err); - } else { - findSDK(path.resolve(result, '..', '..'), config, androidPackageJson, cb); + for (let dir of dirs) { + dir = expand(dir); + try { + if (fs.existsSync(dir)) { + for (const name of fs.readdirSync(dir)) { + const subdir = path.join(dir, name); + if (/android|sdk/i.test(name) && fs.existsSync(subdir) && fs.statSync(subdir).isDirectory()) { + sdk = await findSDK(subdir, config, androidPackageJson); + if (sdk) { + return sdk; } - }); - } - ]); - - dirs.forEach(function (dir) { - dir = afs.resolvePath(dir); - try { - fs.existsSync(dir) && fs.readdirSync(dir).forEach(function (name) { - var subdir = path.join(dir, name); - if (/android|sdk/i.test(name) && fs.existsSync(subdir) && fs.statSync(subdir).isDirectory()) { - queue.push(function (cb) { - findSDK(subdir, config, androidPackageJson, cb); - }); - - // this dir may be the Android SDK, but just in case, - // let's see if there's an Android folder in this one - fs.statSync(subdir).isDirectory() && fs.readdirSync(subdir).forEach(function (name) { + + // this dir may be the Android SDK, but just in case, + // let's see if there's an Android folder in this one + if (fs.statSync(subdir).isDirectory()) { + for (const name of fs.readdirSync(subdir)) { if (/android/i.test(name)) { - queue.push(function (cb) { - findSDK(path.join(subdir, name), config, androidPackageJson, cb); - }); + sdk = await findSDK(path.join(subdir, name), config, androidPackageJson); + if (sdk) { + return sdk; + } } - }); + } } - }); - } catch (e) { - // Ignore + } } - }); - }, + } + } catch { + // Ignore + } + } - ndk: function (next) { - var queue = async.queue(function (task, callback) { - task(function (err, result) { - if (err) { - callback(); // go to next item in the queue - } else { - next(null, result); - } - }); - }, 1); + return null; +} - queue.drain(function () { - // we have completely exhausted all search paths - next(null, null); - }); - queue.push([ - // first let's check the config's value - function (cb) { - findNDK(config.get('android.ndkPath'), config, cb); - }, - // try the environment variable - function (cb) { - findNDK(process.env.ANDROID_NDK, config, cb); - }, - // try finding the 'ndk-build' executable - function (cb) { - findExecutable([ config.get('android.executables.ndkbuild'), 'ndk-build' + cmd ], function (err, result) { - if (err) { - cb(err); - } else { - findNDK(path.dirname(result), config, cb); - } - }); - } - ]); - - dirs.forEach(function (dir) { - dir = afs.resolvePath(dir); - try { - fs.existsSync(dir) && fs.readdirSync(dir).forEach(function (name) { - var subdir = path.join(dir, name); - if (/android|sdk/i.test(name)) { - queue.push(function (cb) { - findNDK(subdir, config, cb); - }); - - // Check under NDK side-by-side directory which contains multiple NDK installations. - // Each subfolder is named after the version of NDK installed under it. Favor newest version. - const ndkSideBySidePath = path.join(subdir, 'ndk'); - if (fs.existsSync(ndkSideBySidePath) && fs.statSync(ndkSideBySidePath).isDirectory()) { - const fileNames = fs.readdirSync(ndkSideBySidePath); - fileNames.sort((text1, text2) => { - // Flip result to sort in descending order. (ie: Highest version is first.) - return versionStringComparer(text1, text2) * (-1); - }); - for (const nextFileName of fileNames) { - const nextFilePath = path.join(ndkSideBySidePath, nextFileName); - queue.push(function (cb) { - findNDK(nextFilePath, config, cb); - }); - } - } +/** + * Detects current Android environment. + * @param {Object} config - The CLI config object + * @param {Object} opts - Detect options + * @param {Boolean} [opts.bypassCache=false] - Bypasses the Android environment detection cache and re-queries the system + */ +export async function detect(config, opts = {}) { + if (envCache && !opts.bypassCache) { + return envCache; + } - // Android Studio used to install under Android SDK subfolder "ndk-bundle". (Deprecated in 2019.) - const ndkBundlePath = path.join(subdir, 'ndk-bundle'); - if (fs.existsSync(ndkBundlePath) && fs.statSync(ndkBundlePath).isDirectory()) { - queue.push(function (cb) { - findNDK(ndkBundlePath, config, cb); - }); - } - } - }); - } catch (e) { - // Ignore - } - }); - }, + const results = {}; - linux64bit: function (next) { - // detect if we're using a 64-bit Linux OS that's missing 32-bit libraries - if (process.platform === 'linux' && process.arch === 'x64') { - var result = { - libGL: fs.existsSync('/usr/lib/libGL.so'), - i386arch: null, - 'libc6:i386': null, - 'libncurses5:i386': null, - 'libstdc++6:i386': null, - 'zlib1g:i386': null, - }; - async.parallel([ - function (cb) { - findExecutable([ config.get('linux.dpkg'), 'dpkg' ], function (err, dpkg) { - if (err || !dpkg) { - return cb(); - } + await Promise.all([ + detectJDK(config, opts).then(jdk => results.jdk = jdk), + detectSDK(config).then(sdk => results.sdk = sdk), + detectNDK(config).then(ndk => results.ndk = ndk), + ]); - var archs = {}; - run(dpkg, '--print-architecture', function (code, stdout, _stderr) { - stdout.split('\n').forEach(function (line) { - (line = line.trim()) && (archs[line] = 1); - }); - run(dpkg, '--print-foreign-architectures', function (code, stdout, _stderr) { - stdout.split('\n').forEach(function (line) { - (line = line.trim()) && (archs[line] = 1); - }); - - // now that we have the architectures, make sure we have the i386 architecture - result.i386arch = !!archs.i386; - cb(); - }); - }); - }); - }, - function (cb) { - findExecutable([ config.get('linux.dpkgquery'), 'dpkg-query' ], function (err, dpkgquery) { - if (err || !dpkgquery) { - return cb(); - } + const sdkHome = process.env.ANDROID_SDK_HOME && expand(process.env.ANDROID_SDK_HOME); + const jdkInfo = results.jdk; - async.each( - [ 'libc6:i386', 'libncurses5:i386', 'libstdc++6:i386', 'zlib1g:i386' ], - function (pkg, next) { - run(dpkgquery, [ '-l', pkg ], function (code, out, _err) { - result[pkg] = false; - if (!code) { - var lines = out.split('\n'), - i = 0, - l = lines.length; - for (; i < l; i++) { - if (lines[i].indexOf(pkg) !== -1) { - // we look for "ii" which means we want the "desired action" - // to be "installed" and the "status" to be "installed" - if (lines[i].indexOf('ii') === 0) { - result[pkg] = true; - } - break; - } - } - } - next(); - }); - }, - function () { - cb(); - } - ); - }); - } - ], function () { - next(null, result); - }); - } else { - next(null, null); - } - } + delete results.jdk; - }, function (err, results) { - var sdkHome = process.env.ANDROID_SDK_HOME && afs.resolvePath(process.env.ANDROID_SDK_HOME), - jdkInfo = results.jdk; + results.home = sdkHome && fs.existsSync(sdkHome) && fs.statSync(sdkHome).isDirectory() ? sdkHome : expand('~/.android'); + results.detectVersion = '2.0'; + results.vendorDependencies = androidPackageJson.vendorDependencies; + results.targets = {}; + results.avds = []; + results.issues = []; - delete results.jdk; + envCache = results; - results.home = sdkHome && fs.existsSync(sdkHome) && fs.statSync(sdkHome).isDirectory() ? sdkHome : afs.resolvePath('~/.android'); - results.detectVersion = '2.0'; - results.vendorDependencies = androidPackageJson.vendorDependencies; - results.targets = {}; - results.avds = []; - results.issues = []; + if (!jdkInfo.home) { + results.issues.push({ + id: 'ANDROID_JDK_NOT_FOUND', + type: 'error', + message: `JDK (Java Development Kit) not found. +If you already have installed the JDK, verify your __JAVA_HOME__ environment variable is correctly set. +The JDK can be downloaded and installed from __https://www.oracle.com/java/technologies/downloads/__ +or __https://jdk.java.net/archive/__.` + }); + results.sdk = null; + return results; + } - function finalize() { - finished(envCache = results); - } + if (process.platform !== 'win32' && jdkInfo.home.includes('&')) { + results.issues.push({ + id: 'ANDROID_JDK_PATH_CONTAINS_AMPERSANDS', + type: 'error', + message: `The JDK (Java Development Kit) path must not contain ampersands (&) on Windows. +Please move the JDK into a path without an ampersand and update the __JAVA_HOME__ environment variable.` + }); + results.sdk = null; + return results; + } - if (!jdkInfo.home) { - results.issues.push({ - id: 'ANDROID_JDK_NOT_FOUND', - type: 'error', - message: __('JDK (Java Development Kit) not found.') + '\n' - + __('If you already have installed the JDK, verify your __JAVA_HOME__ environment variable is correctly set.') + '\n' - + __('The JDK can be downloaded and installed from %s', '__https://www.oracle.com/java/technologies/downloads/__') + '\n' - + __('or %s.', '__https://jdk.java.net/archive/__') - }); - results.sdk = null; - return finalize(); - } + // if we don't have an android sdk, then nothing else to do + if (!results.sdk) { + results.issues.push({ + id: 'ANDROID_SDK_NOT_FOUND', + type: 'error', + message: `Unable to locate an Android SDK. +If you have already downloaded and installed the Android SDK, you can tell Titanium where the Android SDK is located by running '__${ +commandPrefix +}ti config android.sdkPath /path/to/android-sdk__', otherwise you can install it by running '__${ +commandPrefix +}ti setup android__' or manually downloading from ${ +`__https://developer.android.com/studio__` +}.` + }); + return results; + } - if (process.platform === 'win32' && jdkInfo.home.indexOf('&') !== -1) { - results.issues.push({ - id: 'ANDROID_JDK_PATH_CONTAINS_AMPERSANDS', - type: 'error', - message: __('The JDK (Java Development Kit) path must not contain ampersands (&) on Windows.') + '\n' - + __('Please move the JDK into a path without an ampersand and update the __JAVA_HOME__ environment variable.') - }); - results.sdk = null; - return finalize(); - } + if (results.sdk.buildTools.tooNew === 'maybe') { + results.issues.push({ + id: 'ANDROID_BUILD_TOOLS_TOO_NEW', + type: 'warning', + message: ` +Android Build Tools ${results.sdk.buildTools.version} are too new and may or may not work with Titanium. +If you encounter problems, select a supported version with: +__${commandPrefix} ti config android.buildTools.selectedVersion ##.##.##__ +where ##.##.## is a version in ${results.sdk.buildTools.path.split('/').slice(0, -1).join('/')} that is ${results.sdk.buildTools.maxSupported}` + }); + } - // if we don't have an android sdk, then nothing else to do - if (!results.sdk) { - results.issues.push({ - id: 'ANDROID_SDK_NOT_FOUND', - type: 'error', - message: __('Unable to locate an Android SDK.') + '\n' - + __('If you have already downloaded and installed the Android SDK, you can tell Titanium where the Android SDK is located by running \'%s\', otherwise you can install it by running \'%s\' or manually downloading from %s.', - '__' + commandPrefix + 'titanium config android.sdkPath /path/to/android-sdk__', - '__' + commandPrefix + 'titanium setup android__', - '__https://developer.android.com/studio__') - }); - return finalize(); + const createAndroidSdkInstallationErrorMessage = (message) => { + if (!message) { + message = ''; + } else if (message.length > 0) { + message += '\n'; } + message += `Current installed Android SDK tools: +Android SDK Tools: ${results.sdk.tools.version || 'not installed'} (Supported: ${androidPackageJson.vendorDependencies['android tools']}) +Android SDK Platform Tools: ${results.sdk.platformTools.version || 'not installed'} (Supported: ${androidPackageJson.vendorDependencies['android platform tools']} +Android SDK Build Tools: ${results.sdk.buildTools.version || 'not installed'} (Supported: ${androidPackageJson.vendorDependencies['android build tools']} + +Make sure you have the latest Android SDK Tools, Platform Tools, and Build Tools installed. +`; + return message; + }; - if (results.sdk.buildTools.tooNew === 'maybe') { - results.issues.push({ - id: 'ANDROID_BUILD_TOOLS_TOO_NEW', - type: 'warning', - message: '\n' + __('Android Build Tools %s are too new and may or may not work with Titanium.', results.sdk.buildTools.version) + '\n' - + __('If you encounter problems, select a supported version with:') + '\n' - + ' __' + commandPrefix + 'ti config android.buildTools.selectedVersion ##.##.##__' - + __('\n where ##.##.## is a version in ') + results.sdk.buildTools.path.split('/').slice(0, -1).join('/') + __(' that is ') + results.sdk.buildTools.maxSupported - }); - } + if (!results.sdk.buildTools.supported) { + results.issues.push({ + id: 'ANDROID_BUILD_TOOLS_NOT_SUPPORTED', + type: 'error', + message: createAndroidSdkInstallationErrorMessage(`Android Build Tools ${results.sdk.buildTools.version} are not supported by Titanium`) + }); + } - if (!results.sdk.buildTools.supported) { - results.issues.push({ - id: 'ANDROID_BUILD_TOOLS_NOT_SUPPORTED', - type: 'error', - message: createAndroidSdkInstallationErrorMessage(__('Android Build Tools %s are not supported by Titanium', results.sdk.buildTools.version)) + if (results.sdk.buildTools.notInstalled) { + results.issues.push({ + id: 'ANDROID_BUILD_TOOLS_CONFIG_SETTING_NOT_INSTALLED', + type: 'error', + message: createAndroidSdkInstallationErrorMessage(`The selected version of Android SDK Build Tools (${ + results.sdk.buildTools.version + }) are not installed. Please either remove the setting using ${ + commandPrefix + } ti config --remove android.buildTools.selectedVersion or install it`) + }); + } - }); - } + // check if we're running Windows and if the sdk path contains ampersands + if (process.platform === 'win32' && results.sdk.path.includes('&')) { + results.issues.push({ + id: 'ANDROID_SDK_PATH_CONTAINS_AMPERSANDS', + type: 'error', + message: `The Android SDK path must not contain ampersands (&) on Windows. +Please move the Android SDK into a path without an ampersand and re-run __${commandPrefix} ti setup android__.` + }); + results.sdk = null; + return results; + } - if (results.sdk.buildTools.notInstalled) { - results.issues.push({ - id: 'ANDROID_BUILD_TOOLS_CONFIG_SETTING_NOT_INSTALLED', - type: 'error', - message: createAndroidSdkInstallationErrorMessage(__('The selected version of Android SDK Build Tools (%s) are not installed. Please either remove the setting using %s or install it', results.sdk.buildTools.version, `${commandPrefix} ti config --remove android.buildTools.selectedVersion`)) - }); - } + // check if the sdk is missing any commands + const missing = Object.keys(requiredSdkTools).filter(cmd => !results.sdk.executables[cmd]); + if (missing.length && results.sdk.buildTools.supported) { + const dummyPath = path.join(expand('/'), 'path', 'to', 'android-sdk'); + let msg = ''; - // check if we're running Windows and if the sdk path contains ampersands - if (process.platform === 'win32' && results.sdk.path.indexOf('&') !== -1) { - results.issues.push({ - id: 'ANDROID_SDK_PATH_CONTAINS_AMPERSANDS', - type: 'error', - message: __('The Android SDK path must not contain ampersands (&) on Windows.') + '\n' - + __('Please move the Android SDK into a path without an ampersand and re-run __' + commandPrefix + 'titanium setup android__.') - }); - results.sdk = null; - return finalize(); + if (missing.length) { + msg += `Missing required Android SDK tool${missing.length !== 1 ? 's' : ''}: __${missing.join(', ')}__\n\n`; } - // check if the sdk is missing any commands - var missing = Object.keys(requiredSdkTools).filter(cmd => !results.sdk.executables[cmd]); - if (missing.length && results.sdk.buildTools.supported) { - var dummyPath = path.join(path.resolve('/'), 'path', 'to', 'android-sdk'), - msg = ''; + msg = createAndroidSdkInstallationErrorMessage(msg); - if (missing.length) { - msg += __n('Missing required Android SDK tool: %%s', 'Missing required Android SDK tools: %%s', missing.length, '__' + missing.join(', ') + '__') + '\n\n'; + if (missing.length) { + msg += '\nYou can also specify the exact location of these required tools by running:\n'; + for (const m of missing) { + msg += ` ${commandPrefix} ti config android.executables.${m} "${path.join(dummyPath, m + requiredSdkTools[m])}"\n`; } + } - msg = createAndroidSdkInstallationErrorMessage(msg); + msg += `\nIf you need to, run "${commandPrefix} ti setup android" to reconfigure the Titanium Android settings.`; + + results.issues.push({ + id: 'ANDROID_SDK_MISSING_PROGRAMS', + type: 'error', + message: msg + }); + } - if (missing.length) { - msg += '\n' + __('You can also specify the exact location of these required tools by running:') + '\n'; - missing.forEach(function (m) { - msg += ' ' + commandPrefix + 'ti config android.executables.' + m + ' "' + path.join(dummyPath, m + requiredSdkTools[m]) + '"\n'; - }); + /** + * Detect system images + */ + const systemImages = {}; + const systemImagesByPath = {}; + const systemImagesDir = path.join(results.sdk.path, 'system-images'); + if (isDir(systemImagesDir)) { + for (const platform of fs.readdirSync(systemImagesDir)) { + const platformDir = path.join(systemImagesDir, platform); + if (!isDir(platformDir)) { + continue; } - msg += '\n' + __('If you need to, run "%s" to reconfigure the Titanium Android settings.', commandPrefix + 'titanium setup android'); + for (const tag of fs.readdirSync(platformDir)) { + const tagDir = path.join(platformDir, tag); + if (!isDir(tagDir)) { + continue; + } - results.issues.push({ - id: 'ANDROID_SDK_MISSING_PROGRAMS', - type: 'error', - message: msg - }); - } + for (const abi of fs.readdirSync(tagDir)) { + const abiDir = path.join(tagDir, abi); + const props = readPropertiesFile(path.join(abiDir, 'source.properties')); + if (props && props['AndroidVersion.ApiLevel'] && props['SystemImage.TagId'] && props['SystemImage.Abi']) { + const id = `android-${props['AndroidVersion.CodeName'] || props['AndroidVersion.ApiLevel']}`; + const tag = props['SystemImage.TagId']; + const skinsDir = path.join(abiDir, 'skins'); - /** - * Detect system images - */ - var systemImages = {}; - var systemImagesByPath = {}; - var systemImagesDir = path.join(results.sdk.path, 'system-images'); - if (isDir(systemImagesDir)) { - fs.readdirSync(systemImagesDir).forEach(function (platform) { - var platformDir = path.join(systemImagesDir, platform); - if (isDir(platformDir)) { - fs.readdirSync(platformDir).forEach(function (tag) { - var tagDir = path.join(platformDir, tag); - if (isDir(tagDir)) { - fs.readdirSync(tagDir).forEach(function (abi) { - var abiDir = path.join(tagDir, abi); - var props = readProps(path.join(abiDir, 'source.properties')); - if (props && props['AndroidVersion.ApiLevel'] && props['SystemImage.TagId'] && props['SystemImage.Abi']) { - var id = 'android-' + (props['AndroidVersion.CodeName'] || props['AndroidVersion.ApiLevel']); - var tag = props['SystemImage.TagId']; - var skinsDir = path.join(abiDir, 'skins'); - - systemImages[id] || (systemImages[id] = {}); - systemImages[id][tag] || (systemImages[id][tag] = []); - systemImages[id][tag].push({ - abi: props['SystemImage.Abi'], - skins: isDir(skinsDir) ? fs.readdirSync(skinsDir).map(name => { - return isFile(path.join(skinsDir, name, 'hardware.ini')) ? name : null; - }).filter(x => x) : [] - }); - - systemImagesByPath[path.relative(results.sdk.path, abiDir)] = { - id: id, - tag: tag, - abi: abi - }; + if (!systemImages[id]) { + systemImages[id] = {}; + } + if (!systemImages[id][tag]) { + systemImages[id][tag] = []; + } + + const skins = []; + if (isDir(skinsDir)) { + for (const name of fs.readdirSync(skinsDir)) { + if (isFile(path.join(skinsDir, name, 'hardware.ini'))) { + skins.push(name); } - }); + } } - }); - } - }); - } - /** - * Detect targets - */ - var platformsDir = path.join(results.sdk.path, 'platforms'); - var platforms = []; - var platformsById = {}; - if (isDir(platformsDir)) { - fs.readdirSync(platformsDir).forEach(function (name) { - var info = loadPlatform(path.join(platformsDir, name), systemImages); - if (info) { - platforms.push(info); - platformsById[info.id] = info; + systemImages[id][tag].push({ + abi: props['SystemImage.Abi'], + skins + }); + + systemImagesByPath[path.relative(results.sdk.path, abiDir)] = { + id: id, + tag: tag, + abi: abi + }; + } } - }); + } } + } - var addonsDir = path.join(results.sdk.path, 'add-ons'); - var addons = []; - if (isDir(addonsDir)) { - fs.readdirSync(addonsDir).forEach(function (name) { - var info = loadAddon(path.join(addonsDir, name), platforms, systemImages); - info && addons.push(info); - }); + /** + * Detect targets + */ + const platformsDir = path.join(results.sdk.path, 'platforms'); + const platforms = []; + const platformsById = {}; + if (isDir(platformsDir)) { + for (const name of fs.readdirSync(platformsDir)) { + const info = loadPlatform(path.join(platformsDir, name), systemImages); + if (info) { + platforms.push(info); + platformsById[info.id] = info; + } } + } - function sortFn(a, b) { - if (a.codename === null) { - if (b.codename !== null && a.apiLevel === b.apiLevel) { - // sort GA releases before preview releases - return -1; - } - } else if (a.apiLevel === b.apiLevel) { - return b.codename === null ? 1 : a.codename.localeCompare(b.codename); + const addonsDir = path.join(results.sdk.path, 'add-ons'); + const addons = []; + if (isDir(addonsDir)) { + for (const name of fs.readdirSync(addonsDir)) { + const info = loadAddon(path.join(addonsDir, name), platforms, systemImages); + if (info) { + addons.push(info); } - - return a.apiLevel - b.apiLevel; } + } - var index = 1; - platforms.sort(sortFn).concat(addons.sort(sortFn)).forEach(function (platform) { - var abis = []; - if (platform.abis) { - Object.keys(platform.abis).forEach(function (type) { - platform.abis[type].forEach(function (abi) { - if (abis.indexOf(abi) === -1) { - abis.push(abi); - } - }); - }); + const sortFn = (a, b) => { + if (a.codename === null) { + if (b.codename !== null && a.apiLevel === b.apiLevel) { + // sort GA releases before preview releases + return -1; } + } else if (a.apiLevel === b.apiLevel) { + return b.codename === null ? 1 : a.codename.localeCompare(b.codename); + } - var info = { - id: platform.id, - abis: abis, - skins: platform.skins, - name: platform.name, - type: platform.type, - path: platform.path, - revision: platform.revision, - androidJar: platform.androidJar, - aidl: platform.aidl - }; + return a.apiLevel - b.apiLevel; + }; - if (platform.type === 'platform') { - info['api-level'] = platform.apiLevel; - info.sdk = platform.apiLevel; - info.version = platform.version; - info.supported = !~~platform.apiLevel || appc.version.satisfies(platform.apiLevel, androidPackageJson.vendorDependencies['android sdk'], true); - } else if (platform.type === 'add-on' && platform.basedOn) { - info.vendor = platform.vendor; - info.description = platform.description; - info.version = platform.basedOn.version || parseInt(String(platform.basedOn).replace(/^android-/, '')) || null; - info['based-on'] = { - 'android-version': platform.basedOn.version, - 'api-level': platform.basedOn.apiLevel - }; - info.supported = !~~platform.basedOn.apiLevel || appc.version.satisfies(platform.basedOn.apiLevel, androidPackageJson.vendorDependencies['android sdk'], true); - info.libraries = {}; // not supported any more + let index = 1; + const sortedPlatforms = platforms.sort(sortFn).concat(addons.sort(sortFn)); + for (const platform of sortedPlatforms) { + const abis = []; + if (platform.abis) { + for (const type of Object.keys(platform.abis)) { + for (const abi of platform.abis[type]) { + if (!abis.includes(abi)) { + abis.push(abi); + } + } } + } - results.targets[index++] = info; - - if (!info.supported) { - results.issues.push({ - id: 'ANDROID_API_TOO_OLD', - type: 'warning', - message: __('Android API %s is too old and is no longer supported by Titanium SDK %s.', '__' + info.name + ' (' + info.id + ')__', manifestJson.version) + '\n' - + __('The minimum supported Android API level by Titanium SDK %s is API level %s.', manifestJson.version, appc.version.parseMin(androidPackageJson.vendorDependencies['android sdk'])) - }); - } else if (info.supported === 'maybe') { - results.issues.push({ - id: 'ANDROID_API_TOO_NEW', - type: 'warning', - message: __('Android API %s is too new and may or may not work with Titanium SDK %s.', '__' + info.name + ' (' + info.id + ')__', manifestJson.version) + '\n' - + __('The maximum supported Android API level by Titanium SDK %s is API level %s.', manifestJson.version, appc.version.parseMax(androidPackageJson.vendorDependencies['android sdk'])) - }); - } - }); + const info = { + id: platform.id, + abis: abis, + skins: platform.skins, + name: platform.name, + type: platform.type, + path: platform.path, + revision: platform.revision, + androidJar: platform.androidJar, + aidl: platform.aidl + }; - // check that we found at least one target - if (!Object.keys(results.targets).length) { - results.issues.push({ - id: 'ANDROID_NO_APIS', - type: 'error', - message: __('No Android APIs found.') + '\n' - + __('Run \'%s\' to install the latest Android APIs.', 'Android Studio') - }); + if (platform.type === 'platform') { + info['api-level'] = platform.apiLevel; + info.sdk = platform.apiLevel; + info.version = platform.version; + info.supported = !~~platform.apiLevel || version.satisfies(platform.apiLevel, androidPackageJson.vendorDependencies['android sdk'], true); + } else if (platform.type === 'add-on' && platform.basedOn) { + info.vendor = platform.vendor; + info.description = platform.description; + info.version = platform.basedOn.version || Number.parseInt(String(platform.basedOn).replace(/^android-/, '')) || null; + info['based-on'] = { + 'android-version': platform.basedOn.version, + 'api-level': platform.basedOn.apiLevel + }; + info.supported = !Number.parseInt(platform.basedOn.apiLevel) || version.satisfies(platform.basedOn.apiLevel, androidPackageJson.vendorDependencies['android sdk'], true); + info.libraries = {}; // not supported any more } - // check that we found at least one valid target - if (!Object.keys(results.targets).some(t => !!results.targets[t].supported)) { + results.targets[index++] = info; + + if (!info.supported) { results.issues.push({ - id: 'ANDROID_NO_VALID_APIS', + id: 'ANDROID_API_TOO_OLD', type: 'warning', - message: __('No valid Android APIs found that are supported by Titanium SDK %s.', manifestJson.version) + '\n' - + __('Run \'%s\' to install the latest Android APIs.', 'Android Studio') + message: `Android API __${info.name} (${info.id})__ is too old and is no longer supported by Titanium SDK ${manifestJson.version} +The minimum supported Android API level by Titanium SDK ${manifestJson.version} is API level ${version.parseMin(androidPackageJson.vendorDependencies['android sdk'])}` + }); + } else if (info.supported === 'maybe') { + results.issues.push({ + id: 'ANDROID_API_TOO_NEW', + type: 'warning', + message: `Android API __${info.name} (${info.id})__ is too new and may or may not work with Titanium SDK ${manifestJson.version} +The maximum supported Android API level by Titanium SDK ${manifestJson.version} is API level ${version.parseMax(androidPackageJson.vendorDependencies['android sdk'])}` }); } + } - // parse the avds - var avdDir = afs.resolvePath('~/.android/avd'); - var iniRegExp = /^(.+)\.ini$/; - if (isDir(avdDir)) { - fs.readdirSync(avdDir).forEach(function (name) { - var m = name.match(iniRegExp); - if (!m) { - return; - } - - var ini = readProps(path.join(avdDir, name)); - if (!ini) { - return; - } + // check that we found at least one target + if (!Object.keys(results.targets).length) { + results.issues.push({ + id: 'ANDROID_NO_APIS', + type: 'error', + message: `No Android APIs found. +Run 'Android Studio' to install the latest Android APIs.` + }); + } - var q; - var p = isDir(ini.path) ? ini.path : (ini['path.rel'] && isDir(q = path.join(avdDir, ini['path.rel'])) ? q : null); - if (!p) { - return; - } + // check that we found at least one valid target + if (!Object.keys(results.targets).some(t => !!results.targets[t].supported)) { + results.issues.push({ + id: 'ANDROID_NO_VALID_APIS', + type: 'warning', + message: `No valid Android APIs found that are supported by Titanium SDK ${manifestJson.version}. +Run 'Android Studio' to install the latest Android APIs.` + }); + } - var config = readProps(path.join(p, 'config.ini')); - if (!config) { - return; - } + // parse the avds + const avdDir = expand('~/.android/avd'); + const iniRegExp = /^(.+)\.ini$/; + if (isDir(avdDir)) { + for (const name of fs.readdirSync(avdDir)) { + const m = name.match(iniRegExp); + if (!m) { + return; + } - var sdcard = path.join(p, 'sdcard.img'); - var target = null; - var sdk = null; - var apiLevel = null; - - var info = config['image.sysdir.1'] && systemImagesByPath[config['image.sysdir.1'].replace(/\/$/, '')]; - if (info) { - var platform = platformsById[info.id]; - if (platform) { - target = platform.name + ' (API level ' + platform.apiLevel + ')'; - sdk = platform.version; - apiLevel = platform.apiLevel; - } - } + const ini = readPropertiesFile(path.join(avdDir, name)); + if (!ini) { + return; + } - results.avds.push({ - type: 'avd', - id: config['AvdId'] || m[1], - name: config['avd.ini.displayname'] || m[1], - device: config['hw.device.name'] + ' (' + config['hw.device.manufacturer'] + ')', - path: p, - target: target, - abi: config['abi.type'], - skin: config['skin.name'], - sdcard: config['hw.sdCard'] === 'yes' && isFile(sdcard) ? sdcard : null, - googleApis: config['tag.id'] === 'google_apis', - 'sdk-version': sdk, - 'api-level': apiLevel - }); - }); - } + let q; + const p = isDir(ini.path) ? ini.path : (ini['path.rel'] && isDir(q = path.join(avdDir, ini['path.rel'])) ? q : null); + if (!p) { + return; + } - finalize(); + const config = readPropertiesFile(path.join(p, 'config.ini')); + if (!config) { + return; + } - function createAndroidSdkInstallationErrorMessage(message) { - if (!message) { - message = ''; - } else if (message.length > 0) { - message += '\n'; + const sdcard = path.join(p, 'sdcard.img'); + let target = null; + let sdk = null; + let apiLevel = null; + + const info = config['image.sysdir.1'] && systemImagesByPath[config['image.sysdir.1'].replace(/\/$/, '')]; + if (info) { + const platform = platformsById[info.id]; + if (platform) { + target = `${platform.name} (API level ${platform.apiLevel})`; + sdk = platform.version; + apiLevel = platform.apiLevel; + } } - message += __('Current installed Android SDK tools:') + '\n' - + ' Android SDK Tools: ' + (results.sdk.tools.version || 'not installed') + ' (Supported: ' + androidPackageJson.vendorDependencies['android tools'] + ')\n' - + ' Android SDK Platform Tools: ' + (results.sdk.platformTools.version || 'not installed') + ' (Supported: ' + androidPackageJson.vendorDependencies['android platform tools'] + ')\n' - + ' Android SDK Build Tools: ' + (results.sdk.buildTools.version || 'not installed') + ' (Supported: ' + androidPackageJson.vendorDependencies['android build tools'] + ')\n\n' - + __('Make sure you have the latest Android SDK Tools, Platform Tools, and Build Tools installed.') + '\n'; - return message; + + results.avds.push({ + type: 'avd', + id: config['AvdId'] || m[1], + name: config['avd.ini.displayname'] || m[1], + device: `${config['hw.device.name']} (${config['hw.device.manufacturer']})`, + path: p, + target: target, + abi: config['abi.type'], + skin: config['skin.name'], + sdcard: config['hw.sdCard'] === 'yes' && isFile(sdcard) ? sdcard : null, + googleApis: config['tag.id'] === 'google_apis', + 'sdk-version': sdk, + 'api-level': apiLevel + }); } - }); -}; + } -exports.findSDK = findSDK; + return results; +} -function findSDK(dir, config, androidPackageJson, callback) { +export async function findSDK(dir, config, androidPackageJson) { if (!dir) { - return callback(true); + return null; } - dir = afs.resolvePath(dir); + dir = expand(dir); // check if the supplied directory exists and is actually a directory if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) { - return callback(true); - } - - const emulatorPath = path.join(dir, 'emulator', `emulator${exe}`), - result = { - path: dir, - executables: { - adb: path.join(dir, 'platform-tools', 'adb' + exe), - emulator: fs.existsSync(emulatorPath) ? emulatorPath : path.join(dir, 'emulator', 'emulator' + exe) - }, - proguard: null, - tools: { - path: null, - supported: null, - version: null - }, - platformTools: { - path: null, - supported: null, - version: null - }, - buildTools: { - path: null, - supported: null, - version: null, - tooNew: null, - maxSupported: null - } + return null; + } + + const emulatorPath = path.join(dir, 'emulator', `emulator${exe}`); + const result = { + path: dir, + executables: { + adb: path.join(dir, 'platform-tools', 'adb' + exe), + emulator: fs.existsSync(emulatorPath) ? emulatorPath : path.join(dir, 'emulator', 'emulator' + exe) + }, + proguard: null, + tools: { + path: null, + supported: null, + version: null }, - tasks = {}, - buildToolsDir = path.join(dir, 'build-tools'); + platformTools: { + path: null, + supported: null, + version: null + }, + buildTools: { + path: null, + supported: null, + version: null, + tooNew: null, + maxSupported: null + } + }; + const buildToolsDir = path.join(dir, 'build-tools'); /* Determine build tools version to use based on either config setting @@ -730,7 +584,7 @@ function findSDK(dir, config, androidPackageJson, callback) { const len = files.length; let i = 0; for (; i < len; i++) { - var isSupported = appc.version.satisfies(files[i], androidPackageJson.vendorDependencies['android build tools'], true); + const isSupported = version.satisfies(files[i], androidPackageJson.vendorDependencies['android build tools'], true); if (isSupported) { buildToolsSupported = isSupported; ver = files[i]; @@ -752,14 +606,14 @@ function findSDK(dir, config, androidPackageJson, callback) { // A selectedVersion specified or supported version has been found let file = path.join(buildToolsDir, ver, 'source.properties'); if (fs.existsSync(file) && fs.statSync(path.join(buildToolsDir, ver)).isDirectory()) { - var m = fs.readFileSync(file).toString().match(/Pkg\.Revision\s*?=\s*?([^\s]+)/); + const m = fs.readFileSync(file, 'utf8').match(/Pkg\.Revision\s*?=\s*?([^\s]+)/); if (m) { result.buildTools = { path: path.join(buildToolsDir, ver), - supported: appc.version.satisfies(m[1], androidPackageJson.vendorDependencies['android build tools'], true), + supported: version.satisfies(m[1], androidPackageJson.vendorDependencies['android build tools'], true), version: m[1], tooNew: buildToolsSupported, - maxSupported: appc.version.parseMax(androidPackageJson.vendorDependencies['android build tools'], true) + maxSupported: version.parseMax(androidPackageJson.vendorDependencies['android build tools'], true) }; } } else { @@ -774,157 +628,80 @@ function findSDK(dir, config, androidPackageJson, callback) { } // see if this sdk has all the executables we need - Object.keys(requiredSdkTools).forEach(function (cmd) { - tasks[cmd] = function (next) { - findExecutable([ - config.get('android.executables.' + cmd), - result.executables[cmd] - ], function (err, r) { - next(null, !err && r ? r : null); - }); - }; - }); - - async.parallel(tasks, function (err, executables) { - appc.util.mix(result.executables, executables); - - // check that we have all required sdk programs - if (Object.keys(requiredSdkTools).every(cmd => !executables[cmd])) { - return callback(true); - } - - var file = path.join(dir, 'platform-tools', 'source.properties'); - - // check if this directory contains an android sdk - if (!fs.existsSync(executables.adb) || !fs.existsSync(file)) { - return callback(true); - } - - if (fs.existsSync(file)) { - const m = fs.readFileSync(file).toString().match(/Pkg\.Revision\s*?=\s*?([^\s]+)/); - if (m) { - result.platformTools = { - path: path.join(dir, 'platform-tools'), - supported: appc.version.satisfies(m[1], androidPackageJson.vendorDependencies['android platform tools'], true), - version: m[1] - }; + const tasks = {}; + for (const cmd of Object.keys(requiredSdkTools)) { + tasks[cmd] = (async () => { + let bin = config.get(`android.executables.${cmd}`); + if (bin) { + bin = await which(bin, { nothrow: true }); } - } - - callback(null, result); - }); -} - -function findNDK(dir, config, callback) { - if (!dir) { - return callback(true); - } - - // check if the supplied directory exists and is actually a directory - dir = afs.resolvePath(dir); - - if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) { - return callback(true); - } - - // check that the ndk files/folders exist - const things = [ 'ndk-build' + cmd, 'build', 'prebuilt', 'platforms' ]; - if (!things.every(thing => fs.existsSync(path.join(dir, thing)))) { - return callback(true); - } - - // try to determine the version - let version; - const sourceProps = path.join(dir, 'source.properties'); - if (fs.existsSync(sourceProps)) { - const m = fs.readFileSync(sourceProps).toString().match(/Pkg\.Revision\s*=\s*(.+)/m); - if (m && m[1]) { - version = m[1].trim(); - } - } - - if (!version) { - // try the release.txt - let releasetxt; - fs.readdirSync(dir).some(function (file) { - if (file.toLowerCase() === 'release.txt') { - releasetxt = path.join(dir, file); - return true; + if (!bin) { + bin = await which(result.executables[cmd], { nothrow: true }); } - return false; - }); - - if (releasetxt && fs.existsSync(releasetxt)) { - version = fs.readFileSync(releasetxt).toString().split(/\r?\n/).shift().trim(); - } - } - - if (!version) { - // no version, not an ndk - return callback(true); + if (!bin) { + throw new Error(`Unable to find "${cmd}" executable`); + } + return { [cmd]: bin }; + })(); } - callback(null, { - path: dir, - executables: { - ndkbuild: path.join(dir, 'ndk-build' + cmd) - }, - version: version - }); -} + const executables = await Promise.all(Object.values(tasks)); + Object.assign(result.executables, executables); -function isDir(dir) { - try { - return fs.statSync(dir).isDirectory(); - } catch (e) { - // squeltch + // check that we have all required sdk programs + if (Object.keys(requiredSdkTools).every(cmd => !executables[cmd])) { + return null; } - return false; -} -function isFile(file) { - try { - return fs.statSync(file).isFile(); - } catch (e) { - // squeltch - } - return false; -} + const file = path.join(dir, 'platform-tools', 'source.properties'); -function readProps(file) { - if (!isFile(file)) { + // check if this directory contains an android sdk + if (!fs.existsSync(executables.adb) || !fs.existsSync(file)) { return null; } - const props = {}; - fs.readFileSync(file).toString().split(/\r?\n/).forEach(function (line) { - const m = line.match(pkgPropRegExp); + if (fs.existsSync(file)) { + const m = fs.readFileSync(file, 'utf8').match(/Pkg\.Revision\s*?=\s*?([^\s]+)/); if (m) { - props[m[1].trim()] = m[2].trim(); + result.platformTools = { + path: path.join(dir, 'platform-tools'), + supported: version.satisfies(m[1], androidPackageJson.vendorDependencies['android platform tools'], true), + version: m[1] + }; } - }); + } - return props; + return result; } + function loadPlatform(dir, systemImages) { // read in the properties - const sourceProps = readProps(path.join(dir, 'source.properties')); - const apiLevel = sourceProps ? ~~sourceProps['AndroidVersion.ApiLevel'] : null; + const sourceProps = readPropertiesFile(path.join(dir, 'source.properties')); + const apiLevel = sourceProps ? Number.parseInt(sourceProps['AndroidVersion.ApiLevel']) : null; if (!sourceProps || !apiLevel || !isFile(path.join(dir, 'build.prop'))) { return null; } // read in the sdk properties, if exists - const sdkProps = readProps(path.join(dir, 'sdk.properties')); + const sdkProps = readPropertiesFile(path.join(dir, 'sdk.properties')); // detect the available skins const skinsDir = path.join(dir, 'skins'); - const skins = isDir(skinsDir) ? fs.readdirSync(skinsDir).map(name => { - return isFile(path.join(skinsDir, name, 'hardware.ini')) ? name : null; - }).filter(x => x) : []; - let defaultSkin = sdkProps && sdkProps['sdk.skin.default']; - if (skins.indexOf(defaultSkin) === -1 && skins.indexOf(defaultSkin = 'WVGA800') === -1) { + const skins = []; + if (isDir(skinsDir)) { + for (const name of fs.readdirSync(skinsDir)) { + if (isFile(path.join(skinsDir, name, 'hardware.ini'))) { + skins.push(name); + } + } + } + + let defaultSkin = sdkProps?.['sdk.skin.default']; + if (defaultSkin && !skins.includes(defaultSkin)) { + defaultSkin = 'WVGA800'; + } + if (defaultSkin && !skins.includes(defaultSkin)) { defaultSkin = skins[skins.length - 1] || null; } @@ -933,34 +710,35 @@ function loadPlatform(dir, systemImages) { const abis = {}; if (systemImages[id]) { - Object.keys(systemImages[id]).forEach(function (type) { - systemImages[id][type].forEach(function (info) { - abis[type] || (abis[type] = []); + for (const type of Object.keys(systemImages[id])) { + for (const info of systemImages[id][type]) { + if (!abis[type]) { + abis[type] = []; + } abis[type].push(info.abi); - - info.skins.forEach(function (skin) { - if (skins.indexOf(skin) === -1) { + for (const skin of info.skins) { + if (!skins.includes(skin)) { skins.push(skin); } - }); - }); - }); + } + } + } } let tmp; return { id: id, - name: 'Android ' + sourceProps['Platform.Version'] + (sourceProps['AndroidVersion.CodeName'] ? ' (Preview)' : ''), + name: `Android ${sourceProps['Platform.Version']} ${sourceProps['AndroidVersion.CodeName'] ? ' (Preview)' : ''}`, type: 'platform', apiLevel: apiLevel, codename: sourceProps['AndroidVersion.CodeName'] || null, - revision: +sourceProps['Layoutlib.Revision'] || null, + revision: Number.parseInt(sourceProps['Layoutlib.Revision']) || null, path: dir, version: sourceProps['Platform.Version'], abis: abis, skins: skins, defaultSkin: defaultSkin, - minToolsRev: +sourceProps['Platform.MinToolsRev'] || null, + minToolsRev: Number.parseInt(sourceProps['Platform.MinToolsRev']) || null, androidJar: isFile(tmp = path.join(dir, 'android.jar')) ? tmp : null, aidl: isFile(tmp = path.join(dir, 'framework.aidl')) ? tmp : null }; @@ -968,8 +746,8 @@ function loadPlatform(dir, systemImages) { function loadAddon(dir, platforms, _systemImages) { // read in the properties - const sourceProps = readProps(path.join(dir, 'source.properties')); - const apiLevel = sourceProps ? ~~sourceProps['AndroidVersion.ApiLevel'] : null; + const sourceProps = readPropertiesFile(path.join(dir, 'source.properties')); + const apiLevel = sourceProps ? Number.parseInt(sourceProps['AndroidVersion.ApiLevel']) : null; if (!sourceProps || !apiLevel || !sourceProps['Addon.VendorDisplay'] || !sourceProps['Addon.NameDisplay']) { return null; } @@ -977,13 +755,13 @@ function loadAddon(dir, platforms, _systemImages) { const basedOn = platforms.find(p => p.codename === null && p.apiLevel === apiLevel); return { - id: sourceProps['Addon.VendorDisplay'] + ':' + sourceProps['Addon.NameDisplay'] + ':' + apiLevel, + id: `${sourceProps['Addon.VendorDisplay']}:${sourceProps['Addon.NameDisplay']}:${apiLevel}`, name: sourceProps['Addon.NameDisplay'], type: 'add-on', vendor: sourceProps['Addon.VendorDisplay'], description: sourceProps['Pkg.Desc'], apiLevel: apiLevel, - revision: +sourceProps['Pkg.Revision'] || null, + revision: Number.parseInt(sourceProps['Pkg.Revision']) || null, codename: sourceProps['AndroidVersion.CodeName'] || null, path: dir, basedOn: basedOn ? { @@ -998,22 +776,3 @@ function loadAddon(dir, platforms, _systemImages) { aidl: basedOn && basedOn.aidl || null }; } - -function versionStringComparer(text1, text2) { - // Split strings into version component arrays. Example: '1.2.3' -> ['1', '2', '3'] - const array1 = text1.split('.'); - const array2 = text2.split('.'); - - // Compare the 2 given strings by their numeric components. - // If they match numerically, then do a string comparison. - const maxLength = Math.max(array1.length, array2.length); - for (let index = 0; index < maxLength; index++) { - const value1 = (index < array1.length) ? (Number.parseInt(array1[index], 10) || 0) : 0; - const value2 = (index < array2.length) ? (Number.parseInt(array2[index], 10) || 0) : 0; - const delta = value1 - value2; - if (delta !== 0) { - return delta; - } - } - return text1.localeCompare(text2); -} diff --git a/lib/babel-plugins/global-this.js b/lib/babel-plugins/global-this.js deleted file mode 100644 index 2040039d..00000000 --- a/lib/babel-plugins/global-this.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; - -const THIS_BREAK_KEYS = [ 'FunctionExpression', 'FunctionDeclaration', 'ClassProperty', - 'ClassMethod', 'ObjectMethod' ]; - -// Walk the AST looking for 'this' references intended to be references to global -// Replace them with an explicit 'global' reference -module.exports = function (_ref) { - const t = _ref.types; - return { - visitor: { - ThisExpression(path, state) { - if ( - state.opts.allowTopLevelThis !== true - && !path.findParent((path) => !path.is('shadow') - && THIS_BREAK_KEYS.indexOf(path.type) >= 0) - ) { - // TODO: Spit out a warning/deprecation notice? - path.replaceWith(t.identifier('global')); - } - } - } - }; -}; diff --git a/lib/babel-plugins/ti-api.js b/lib/babel-plugins/ti-api.js deleted file mode 100644 index ead0f386..00000000 --- a/lib/babel-plugins/ti-api.js +++ /dev/null @@ -1,111 +0,0 @@ -'use strict'; - -/** - * Keeps track of the Titanium APIs used globally (across the whoel build, so implicitly "per-project"). - */ -const apiUsage = {}; - -/** - * Keeps track of the Titanium APIs used for a given files. - */ -const symbols = new Set(); - -/** - * The actual Babel plugin definition. This plugin does not transform anything in the AST/code, - * but instead tracks usage of our Titanium APIs for our own analytics as well as to help - * pare production builds down to only include the Titanium APIs/modules/frameworks used by the app. - * @param {object} _ref object containing references for babel plugins to make use of - * @param {object} _ref.types instance of @babel/types - * @returns {object} the instance of the plugin used by Babel during transforms - */ -function plugin(_ref) { - const types = _ref.types; - /** - * Returns the name of identifiers, value of string literals, or `'obj.value'` of member expressions. - * @param {object} node an AST node from Babel - * @returns {string|null} value of a given node. - */ - function getMemberValue(node) { - if (types.isIdentifier(node)) { - return node.name; - } - - if (types.isStringLiteral(node)) { - return node.value; - } - - if (!types.isMemberExpression(node)) { - return null; - } - - if (node.computed && !types.isStringLiteral(node.property)) { - return null; - } - - const objVal = getMemberValue(node.object); - if (objVal === null) { - return null; - } - - const propVal = getMemberValue(node.property); - if (propVal === null) { - return null; - } - return objVal + '.' + propVal; - } - - /** - * Given a MemberExpression node, returns the expression as a String if possible - * (if composed of literals/identifiers) - * @param {object} member an AST node (MemberExpression) from Babel - * @returns {string|null} - */ - function getTitaniumExpression(member) { - - if (types.isStringLiteral(member.object)) { - // Prevent picking up strings in evaluation. - // e.g: "Ti.Test".toUpperCase(); - return null; - } - - const value = getMemberValue(member); - if (value === null) { - return null; - } - - // Ensure this is a namespace and not a string starting with Ti. or Titanium. - const tiNodeRegExp = /^Ti(tanium)?[.\w+]+$/; - if (tiNodeRegExp.test(value)) { - // Normalize 'Ti.*' to 'Titanium.*' - if (value.startsWith('Ti.')) { - return `Titanium.${value.substring(3)}`; - } - return value; - } - return null; - } - return { - pre() { - symbols.clear(); // wipe symbols before each AST, gather these "per-file" - }, - visitor: { - MemberExpression(path, state) { - const memberExpr = getTitaniumExpression(path.node); - if (memberExpr) { - symbols.add(memberExpr.substring(9)); // Drop leading 'Titanium.' - if (!state.opts.skipStats) { - if (apiUsage[memberExpr] === undefined) { - apiUsage[memberExpr] = 1; - } else { - apiUsage[memberExpr]++; - } - } - } - } - } - }; -} -plugin.apiUsage = apiUsage; // expose the apiUsage -plugin.symbols = symbols; // expose the symbol usage - -module.exports = plugin; diff --git a/lib/builder.js b/lib/builder.js deleted file mode 100644 index 141df10f..00000000 --- a/lib/builder.js +++ /dev/null @@ -1,524 +0,0 @@ -/** - * @overview - * The base class for platform specific build commands. This ensures some - * commonality between build commands so that hooks can consistently - * access build properties. - * - * @copyright - * Copyright (c) 2009-2015 by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const - appc = require('node-appc'), - crypto = require('crypto'), - fs = require('fs-extra'), - path = require('path'), - ti = require('./titanium'), - i18n = appc.i18n(__dirname), - __ = i18n.__, - __n = i18n.__n; - -// shim String.prototype.normalize() -require('unorm'); - -/** - * The base class for platform specific build commands. This ensures some - * commonality between build commands so that hooks can consistently - * access build properties. - * - * General usage is to extend the Builder class and override the config(), - * validate(), and run() methods: - * - * var Builder = require('node-titanium-sdk/lib/builder'); - * var util = require('util'); - * - * function SomePlatformBuilder() { - * Builder.apply(this, arguments); - * } - * - * util.inherits(SomePlatformBuilder, Builder); - * - * SomePlatformBuilder.prototype.config = function config(logger, config, cli) { - * Builder.prototype.config.apply(this, arguments); - * // TODO - * }; - * - * SomePlatformBuilder.prototype.validate = function validate(logger, config, cli) { - * // TODO - * }; - * - * SomePlatformBuilder.prototype.run = function run(logger, config, cli, finished) { - * Builder.prototype.run.apply(this, arguments); - * // TODO - * finished(); - * }; - * - * @module lib/builder - */ - -module.exports = Builder; - -/** - * Constructs the build state. This needs to be explicitly called from the - * derived builder's constructor. - * - * @class - * @classdesc Base class for all build states. - * @constructor - * - * @param {Module} buildModule The "module" variable from the build command file - */ -function Builder(buildModule) { - this.titaniumSdkPath = (function scan(dir) { - const file = path.join(dir, 'manifest.json'); - if (fs.existsSync(file)) { - return dir; - } - dir = path.dirname(dir); - return dir !== '/' && scan(dir); - }(__dirname)); - - this.titaniumSdkName = path.basename(this.titaniumSdkPath); - - this.titaniumSdkVersion = ti.manifest.version; - - this.platformPath = (function scan(dir) { - const file = path.join(dir, 'package.json'); - if (fs.existsSync(file)) { - return dir; - } - dir = path.dirname(dir); - return dir !== '/' && scan(dir); - }(path.dirname(buildModule.filename))); - - this.platformName = path.basename(this.platformPath); - - this.globalModulesPath = path.join(this.titaniumSdkPath, '..', '..', '..', 'modules'); - - this.packageJson = require(path.join(this.platformPath, 'package.json')); - - this.conf = {}; - - this.buildDirFiles = {}; -} - -/** - * Defines common variables prior to running the build's config(). This super - * function should be called prior to the platform-specific build command's config(). - * - * @param {Object} logger - The logger instance - * @param {Object} config - The CLI config - * @param {Object} cli - The CLI instance - */ -Builder.prototype.config = function config(logger, config, cli) { - // note: this function must be sync! - this.logger = logger; - this.config = config; - this.cli = cli; - this.symlinkFilesOnCopy = false; - this.ignoreDirs = new RegExp(config.get('cli.ignoreDirs')); - this.ignoreFiles = new RegExp(config.get('cli.ignoreFiles')); -}; - -/** - * Validation stub function. Meant to be overwritten. - * - * @param {Object} logger - The logger instance - * @param {Object} config - The CLI config - * @param {Object} cli - The CLI instance - */ -Builder.prototype.validate = function validate(logger, config, cli) { - // note: this function must be sync! - - this.tiapp = cli.tiapp; - this.timodule = cli.timodule; - this.projectDir = cli.argv['project-dir']; - this.buildDir = path.join(this.projectDir, 'build', this.platformName); - - this.defaultIcons = [ - path.join(this.projectDir, 'DefaultIcon-' + this.platformName + '.png'), - path.join(this.projectDir, 'DefaultIcon.png') - ]; -}; - -/** - * Defines common variables prior to running the build. This super function - * should be called prior to the platform-specific build command's run(). - * - * @param {Object} _logger - The logger instance - * @param {Object} _config - The CLI config - * @param {Object} _cli - The CLI instance - * @param {Function} _finished - A function to call after the function finishes - */ -Builder.prototype.run = function run(_logger, _config, _cli, _finished) { - // note: this function must be sync! - - var buildDirFiles = this.buildDirFiles = {}; - - // walk the entire build dir and build a map of all files - if (fs.existsSync(this.buildDir)) { - this.logger.trace(__('Snapshotting build directory')); - (function walk(dir) { - fs.readdirSync(dir).forEach(function (name) { - var file = path.join(dir, name).normalize(); - try { - var stat = fs.lstatSync(file); - if (stat.isDirectory()) { - walk(file); - } else { - buildDirFiles[file] = stat; - } - } catch (ex) { - buildDirFiles[file] = true; - } - }); - }(this.buildDir)); - } -}; - -/** - * Removes a file from the buildDirFiles map. - * - * @param {String} file - The file to unmark. - */ -Builder.prototype.unmarkBuildDirFile = function unmarkBuildDirFile(file) { - delete this.buildDirFiles[file.normalize()]; -}; - -/** - * Removes all paths from the buildDirFiles map that start with the specified path. - * - * @param {String} dir - The path prefix to unmark files. - */ -Builder.prototype.unmarkBuildDirFiles = function unmarkBuildDirFiles(dir) { - if (/\*$/.test(dir)) { - dir = dir.substring(0, dir.length - 1); - } else if (!/\/$/.test(dir)) { - dir += '/'; - } - dir = dir.normalize(); - Object.keys(this.buildDirFiles).forEach(function (file) { - if (file.indexOf(dir) === 0) { - delete this.buildDirFiles[file]; - } - }, this); -}; - -/** - * Copies or symlinks a file to the specified destination. - * - * @param {String} src - The file to copy. - * @param {String} dest - The destination of the file. - * @param {Object} [opts] - An object containing various options. - * @param {Boolean} [opts.forceCopy] - When true, forces the file to be copied and not symlinked. - * @param {Boolean} [opts.forceSymlink] - When true, ignores `opts.contents` and `opts.forceCopy` and symlinks the `src` to the `dest`. - * @param {Buffer|String} [opts.contents] - The contents to write to the file instead of reading the specified source file. - */ -Builder.prototype.copyFileSync = function copyFileSync(src, dest, opts) { - var parent = path.dirname(dest), - exists = fs.existsSync(dest); - - opts && typeof opts === 'object' || (opts = {}); - - fs.ensureDirSync(parent); - - if (!opts.forceSymlink && (opts.forceCopy || !this.symlinkFilesOnCopy || opts.contents)) { - if (exists) { - this.logger.debug(__('Overwriting %s => %s', src.cyan, dest.cyan)); - fs.unlinkSync(dest); - } else { - this.logger.debug(__('Copying %s => %s', src.cyan, dest.cyan)); - } - fs.writeFileSync(dest, opts.contents || fs.readFileSync(src)); - return true; - - } else if (!exists || (fs.lstatSync(dest).isSymbolicLink() && fs.realpathSync(dest) !== src)) { - exists && fs.unlinkSync(dest); - this.logger.debug(__('Symlinking %s => %s', src.cyan, dest.cyan)); - fs.symlinkSync(src, dest); - return true; - } -}; - -/** - * Copies or symlinks a file to the specified destination. - * - * @param {String} src - The directory to copy. - * @param {String} dest - The destination of the files. - * @param {Object} [opts] - An object containing various options. - * @param {RegExp} [opts.rootIgnoreDirs] - A regular expression of directories to ignore only in the root directory. - * @param {RegExp} [opts.ignoreDirs] - A regular expression of directories to ignore. - * @param {RegExp} [opts.ignoreFiles] - A regular expression of files to ignore. - * @param {Function} [opts.beforeCopy] - A function called before copying the file. This function can abort the copy or modify the contents being copied. - * @param {Boolean} [opts.forceCopy] - When true, forces the file to be copied and not symlinked. - * @param {Function} [opts.afterCopy] - A function called with the result of the file being copied. - */ -Builder.prototype.copyDirSync = function copyDirSync(src, dest, opts) { - if (!fs.existsSync(src)) { - return; - } - - opts && typeof opts === 'object' || (opts = {}); - - (function copy(src, dest, isRootDir) { - fs.ensureDirSync(dest); - - fs.readdirSync(src).forEach(function (name) { - const srcFile = path.join(src, name); - const destFile = path.join(dest, name); - - // skip broken symlinks - if (!fs.existsSync(srcFile)) { - return; - } - - const srcStat = fs.statSync(srcFile); - if (srcStat.isDirectory()) { - // we are copying a subdirectory - if ((isRootDir && opts.rootIgnoreDirs && opts.rootIgnoreDirs.test(name)) || (opts.ignoreDirs && opts.ignoreDirs.test(name))) { - // ignoring directory - } else { - copy.call(this, srcFile, destFile); - } - return; - } - - // we're copying a file, check if we should ignore it - if (opts.ignoreFiles && opts.ignoreFiles.test(name)) { - return; - } - - if (typeof opts.beforeCopy === 'function') { - const result = opts.beforeCopy(srcFile, destFile, srcStat); - if (result === null) { - return; // skip - } else if (result !== undefined) { - this.logger.debug(__('Writing %s => %s', srcFile.cyan, destFile.cyan)); - fs.writeFileSync(destFile, result); - return; - } - // fall through and copy the file normally - } - - const result = this.copyFileSync(srcFile, destFile, opts); - if (typeof opts.afterCopy === 'function') { - opts.afterCopy(srcFile, destFile, srcStat, result); - } - }, this); - }).call(this, src, dest, true); -}; - -/** - * Validates that all required Titanium Modules defined in the tiapp.xml are - * installed. - * - * This function is intended to be called asynchronously from the validate() - * implementation. In other words, validate() should return a function that - * calls this function. - * - * Note: This function will forcefully exit the application on error! - * - * @example - * SomePlatformBuilder.prototype.validate = function validate(logger, config, cli) { - * Builder.prototype.validate.apply(this, arguments); - * - * // TODO: synchronous platform specific validation code goes here - * - * return function (callback) { - * // TODO: asynchronous platform specific validation code goes here - * - * this.validateTiModules(callback); - * }.bind(this); - * }; - * - * @param {String|Array} platformName - One or more platform names to use when finding Titanium modules - * @param {String} deployType - The deployment type (development, test, production) - * @param {Function} callback(err) - A function to call after the function finishes - */ -Builder.prototype.validateTiModules = function validateTiModules(platformName, deployType, callback) { - var moduleSearchPaths = [ this.projectDir ], - customSDKPaths = this.config.get('paths.sdks'), - customModulePaths = this.config.get('paths.modules'); - - function addSearchPath(p) { - p = appc.fs.resolvePath(p); - if (fs.existsSync(p) && moduleSearchPaths.indexOf(p) === -1) { - moduleSearchPaths.push(p); - } - } - - this.cli.env.os.sdkPaths.forEach(addSearchPath); - Array.isArray(customSDKPaths) && customSDKPaths.forEach(addSearchPath); - Array.isArray(customModulePaths) && customModulePaths.forEach(addSearchPath); - - appc.timodule.find(this.cli.tiapp.modules, platformName, deployType, ti.manifest, moduleSearchPaths, this.logger, function (modules) { - if (modules.missing.length) { - this.logger.error(__('Could not find all required Titanium Modules:')); - modules.missing.forEach(function (m) { - this.logger.error(' id: ' + m.id + '\t version: ' + (m.version || 'latest') + '\t platform: ' + m.platform + '\t deploy-type: ' + m.deployType); - }, this); - this.logger.log(); - process.exit(1); - } - - if (modules.incompatible.length) { - this.logger.error(__('Found incompatible Titanium Modules:')); - modules.incompatible.forEach(function (m) { - this.logger.error(' id: ' + m.id + '\t version: ' + (m.version || 'latest') + '\t platform: ' + m.platform + '\t min sdk: ' + (m.manifest && m.manifest.minsdk || '?')); - }, this); - this.logger.log(); - process.exit(1); - } - - if (modules.conflict.length) { - this.logger.error(__('Found conflicting Titanium modules:')); - modules.conflict.forEach(function (m) { - this.logger.error(' ' + __('Titanium module "%s" requested for both Android and CommonJS platforms, but only one may be used at a time.', m.id)); - }, this); - this.logger.log(); - process.exit(1); - } - - callback(null, modules); - }.bind(this)); // end timodule.find() -}; - -/** - * Returns the hexadecimal md5 hash of a string. - * - * @param {String} str - The string to hash - * - * @returns {String} - */ -Builder.prototype.hash = function hash(str) { - return crypto.createHash('md5').update(str || '').digest('hex'); -}; - -/** - * Generates missing app icons based on the DefaultIcon.png. - * - * @param {Array} icons - An array of objects describing the icon size to generate and the destination - * @param {Function} callback - A function to call after the icons have been generated - */ -Builder.prototype.generateAppIcons = function generateAppIcons(icons, callback) { - const requiredMissing = icons.filter(icon => icon.required).length; - let size = null; - var fail = function () { - this.logger.error(__('Unable to create missing icons:')); - printMissing(this.logger.error); - callback(true); - }.bind(this); - - function printMissing(logger, all) { - icons.forEach(function (icon) { - if (all || size === null || icon.width > size.width) { - logger(' ' - + __('%s - size: %sx%s', - icon.description, - icon.width, - icon.height - ) - ); - } - }); - } - - let iconLabels; - if (this.defaultIcons.length > 2) { - const labels = this.defaultIcons.map(icon => '"' + path.basename(icon) + '"'); - const last = labels.pop(); - iconLabels = labels.join(', ') + ', or ' + last; - } else { - iconLabels = this.defaultIcons.map(icon => '"' + path.basename(icon) + '"').join(' or '); - } - - const defaultIcon = this.defaultIcons.find(icon => fs.existsSync(icon)); - - if (!defaultIcon) { - if (requiredMissing === 0) { - this.logger.warn(__n('There is a missing app icon, but it is not required', 'There are missing app icons, but they are not required', icons.length)); - this.logger.warn(__('You can either create the missing icons below or create an image named %s in the root of your project', iconLabels)); - this.logger.warn(__('If the DefaultIcon.png image is present, the build will use it to generate all missing icons')); - this.logger.warn(__('It is highly recommended that the DefaultIcon.png be 1024x1024')); - printMissing(this.logger.warn); - return callback(); - } - - this.logger.error(__n('There is a missing required app icon', 'There are missing required app icons', icons.length)); - this.logger.error(__('You must either create the missing icons below or create an image named %s in the root of your project', iconLabels)); - this.logger.error(__('If the DefaultIcon.png image is present, the build will use it to generate all missing icons')); - this.logger.error(__('It is highly recommended that the DefaultIcon.png be 1024x1024')); - return fail(); - } - - const contents = fs.readFileSync(defaultIcon); - size = appc.image.pngInfo(contents); - - if (size.width !== size.height) { - this.logger.error(__('The %s is %sx%s, however the width and height must be equal', defaultIcon, size.width, size.height)); - this.logger.error(__('It is highly recommended that the %s be 1024x1024', defaultIcon)); - return fail(); - } - - this.logger.debug(__('Found %s (%sx%s)', defaultIcon.cyan, size.width, size.height)); - this.logger.info(__n( - 'Missing %s app icon, generating missing icon', - 'Missing %s app icons, generating missing icons', - icons.length - )); - printMissing(this.logger.info, true); - - const rename = []; - let minRequiredSize = null; - let minSize = null; - for (let i = 0; i < icons.length; i++) { - const icon = icons[i]; - if (icon.required) { - if (minRequiredSize === null || icon.width > minRequiredSize) { - minRequiredSize = icon.width; - } - } else if (icon.width > size.width) { - // default icon isn't big enough, so we just skip this image - this.logger.warn(__('%s (%sx%s) is not large enough to generate missing icon "%s" (%sx%s), skipping', defaultIcon, size.width, size.height, path.basename(icon.file), icon.width, icon.height)); - icons.splice(i--, 1); - continue; - } - if (minSize === null || icon.width > minSize) { - minSize = icon.width; - } - if (!path.extname(icon.file)) { - // the file doesn't have an extension, so we need to temporarily set - // one so that the image resizer doesn't blow up - rename.push({ - from: icon.file + '.png', - to: icon.file - }); - icon.file += '.png'; - } - } - - if (minRequiredSize !== null && size.width < minRequiredSize) { - this.logger.error(__('The %s must be at least %sx%s', defaultIcon, minRequiredSize, minRequiredSize)); - this.logger.error(__('It is highly recommended that the %s be 1024x1024', defaultIcon)); - return fail(); - } - - appc.image.resize(defaultIcon, icons, function (error, _stdout, _stderr) { - if (error) { - this.logger.error(error); - this.logger.log(); - process.exit(1); - } - - rename.forEach(function (file) { - fs.renameSync(file.from, file.to); - }); - - callback(); - }.bind(this), this.logger); -}; diff --git a/lib/emulator.js b/lib/emulator.js index 5c803f70..35dec04c 100644 --- a/lib/emulator.js +++ b/lib/emulator.js @@ -1,454 +1,576 @@ -/** - * @overview - * Library for controlling an Android Emulator. - * - * @module lib/emulator - * - * @copyright - * Copyright (c) 2009-2014 by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const android = require('./android'), - appc = require('node-appc'), - __ = appc.i18n(__dirname).__, - ADB = require('./adb'), - async = require('async'), - events = require('events'), - fs = require('fs'), - path = require('path'), - util = require('util'); -require('colors'); - -module.exports = EmulatorManager; - -/** - * Creates an Emulator instace. - * @class - * @extends EventEmitter - * @classdesc Simple object that contains the avd settings and exposes event - * methods. - * @constructor - */ -function Emulator() {} -util.inherits(EmulatorManager.Emulator = Emulator, events.EventEmitter); - -/** - * Creates an EmulatorManager instance. - * @class - * @classdesc Manages emulator implementations and responsible for launching and - * killing emulators. - * @constructor - * @param {Object} config - The CLI config object - */ -function EmulatorManager(config) { - this.config = config; -} +import { detect as detectAndroid } from './android.js'; +import { ADB } from './adb.js'; +import { EventEmitter } from 'node:events'; + +export class Emulator extends EventEmitter {} + +export class EmulatorManager { + Emulator = Emulator; -/** - * Loads emulator implementation modules and detects all available emulators. - * @param {Object} [opts] - Detection options - * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all - * @param {Function} callback - A function to call when the detection has completed - */ -EmulatorManager.prototype.detect = function detect(opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; + constructor(config) { + this.config = config; } - var files = opts && opts.type ? [ opts.type + '.js' ] : fs.readdirSync(path.join(__dirname, 'emulators')), - re = /\.js$/, - config = this.config; - - async.parallel(files.map(function (filename) { - return function (next) { - var file = path.join(__dirname, 'emulators', filename); - if (re.test(filename) && fs.existsSync(file)) { - var module = require(file); - if (typeof module.detect === 'function') { - module.detect(config, opts, next); - return; - } + /** + * Loads emulator implementation modules and detects all available emulators. + * @param {Object} [opts] - Detection options + * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all + */ + async detect(opts = {}) { + const androidEnv = await detectAndroid(this.config, opts); + const ver2api = {}; + const emus = []; + + for (const id of Object.keys(androidEnv.targets)) { + if (androidEnv.targets[id].type === 'platform') { + ver2api[androidEnv.targets[id].version] = androidEnv.targets[id].sdk; } - next(); - }; - }), function (err, results) { - if (err) { - return callback(err); } - android.detect(this.config, opts, function (androidEnv) { - var ver2api = {}, - emus = []; - - Object.keys(androidEnv.targets).forEach(function (id) { - if (androidEnv.targets[id].type === 'platform') { - ver2api[androidEnv.targets[id].version] = androidEnv.targets[id].sdk; + if (Array.isArray(androidEnv.avds)) { + for (const avd of androidEnv.avds) { + if (!avd['api-level']) { + avd['api-level'] = ver2api[avd['sdk-version']] || null; } - }); - - results.forEach(function (r) { - if (r && Array.isArray(r.avds)) { - r.avds.forEach(function (avd) { - if (!avd['api-level']) { - avd['api-level'] = ver2api[avd['sdk-version']] || null; - } - if (!avd.id) { - avd.id = avd.name; - } - emus.push(avd); - }); + if (!avd.id) { + avd.id = avd.name; } - }); + emus.push(avd); + } + } - opts.logger && opts.logger.trace(__('Found %s emulators', String(emus.length).cyan)); - callback(null, emus); - }); - }.bind(this)); -}; - -/** - * Detects if a specific Android emulator is running. - * @param {String} id - The id of the emulator - * @param {Object} [opts] - Detection options - * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all - * @param {Function} callback - A function to call when the detection has completed - */ -EmulatorManager.prototype.isRunning = function isRunning(id, opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; + opts.logger?.trace(`Found ${emus.length} emulators`); + return emus; } - opts.logger && opts.logger.trace(__('Detecting if %s exists...', id.cyan)); + /** + * Detects if a specific Android emulator is running. + * @param {String} id - The id of the emulator + * @param {Object} [opts] - Detection options + * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all + */ + async isRunning(id, opts) { + opts.logger?.trace(`Detecting if ${id} exists...`); + + const emus = await this.detect(opts); + const emu = emus.filter(e => e && e.id === id).shift(); + if (!emu) { + throw new Error(`Invalid emulator "${id}"`); + } - this.detect(opts, function (err, emus) { - if (err) { - return callback(err); + opts.logger?.trace('Emulator exists, detecting all running emulators and connected devices...'); + + // need to see if the emulator is running + const adb = new ADB(this.config); + const devices = await adb.devices(); + opts.logger?.trace(`Detected ${devices.length} running emulators and connected devices`); + + // if there are no devices, then it can't possibly be running + if (!devices.length) { + return false; } - const emu = emus.filter(e => e && e.id == id).shift(); // eslint-disable-line eqeqeq + opts.logger?.trace(`Checking ${devices.length} devices to see if it's the emulator we want`); - if (!emu) { - return callback(new Error(__('Invalid emulator "%s"', id)), null); + if (emu.type !== 'avd') { + return false; } - opts.logger && opts.logger.trace(__('Emulator exists, detecting all running emulators and connected devices...')); + const emuRegExp = /^emulator-(\d+)$/; + const device = devices.find(d => { + return d.id.match(emuRegExp) && d.emulator.id === emu.id; + }); - // need to see if the emulator is running - const adb = new ADB(this.config); - adb.devices(function (err, devices) { - if (err) { - return callback(err); - } + if (device) { + opts.logger?.trace('The emulator is running'); + } else { + opts.logger?.trace('The emulator is NOT running'); + } - opts.logger && opts.logger.trace(__('Detected %s running emulators and connected devices', String(devices.length).cyan)); + return device; + } - // if there are no devices, then it can't possibly be running - if (!devices.length) { - return callback(null, null); + /** + * Determines if the specified "device name" is an emulator or a device. + * @param {String} device - The name of the device returned from 'adb devices' + * @param {Object} [opts] - Detection options + * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all + */ + async isEmulator(device, opts) { + try { + const port = device.match(/^emulator-(\d+)$/); + if (!port) { + return false; } - opts.logger && opts.logger.trace(__('Checking %s devices to see if it\'s the emulator we want', String(devices.length).cyan)); + const [avdName, androidInfo] = await Promise.all([ + this.getAvdName(port[1]), + detectAndroid(this.config, opts), + ]); - require(path.join(__dirname, 'emulators', emu.type + '.js')).isRunning(this.config, emu, devices, function (err, device) { - if (err) { - opts.logger && opts.logger.trace(__('Failed to check if the emulator was running: %s', err)); - } else if (device) { - opts.logger && opts.logger.trace(__('The emulator is running')); - } else { - opts.logger && opts.logger.trace(__('The emulator is NOT running')); + return androidInfo.avds.find(e => e.id === avdName); + } catch { + throw new Error(`Unable to find device "${device}"`); + } + } + + getAvdName(port) { + return new Promise((resolve, reject) => { + let state = 'connecting'; + let avdName = null; + let buffer = ''; + const responseRegExp = /(.*)\r\nOK\r\n/; + const socket = net.connect({ port: port }); + + socket.on('data', (data) => { + buffer += data.toString(); + const m = buffer.match(responseRegExp); + if (!m || state === 'done') { + // do nothing + } else if (state === 'connecting') { + state = 'sending command'; + buffer = ''; + socket.write('avd name\n'); + } else if (state === 'sending command') { + state = 'done'; + avdName = m[1].trim(); + socket.end('quit\n'); } - callback(err, device); }); - }.bind(this)); - }.bind(this)); -}; - -/** - * Determines if the specified "device name" is an emulator or a device. - * @param {String} device - The name of the device returned from 'adb devices' - * @param {Object} [opts] - Detection options - * @param {String} [opts.type] - The type of emulator to load (avd); defaults to all - * @param {Function} callback - A function to call when the detection has completed - */ -EmulatorManager.prototype.isEmulator = function isEmulator(device, opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; + + socket.on('end', () => resolve(avdName)); + + socket.on('error', reject); + }); } - var files = opts && opts.type ? [ opts.type + '.js' ] : fs.readdirSync(path.join(__dirname, 'emulators')), - re = /\.js$/, - config = this.config; - - async.parallel(files.map(function (filename) { - return function (next) { - var file = path.join(__dirname, 'emulators', filename); - if (re.test(filename) && fs.existsSync(file)) { - var module = require(file); - if (typeof module.isEmulator === 'function') { - module.isEmulator(config, device, next); - return; - } - } - next(); - }; - }), function (err, results) { - if (err) { - callback(new Error(__('Unable to find device "%s"', device))); - } else { - callback(null, results.filter(n => n).shift()); - } - }); -}; - -function checkedBooted(config, opts, emulator) { - // we need to get the id of emulator - var adb = new ADB(config), - retryTimeout = 2000, // if an adb call fails, how long before we retry - bootTimeout = opts.bootTimeout || 240000, // 4 minutes to boot before timeout + checkedBooted(config, opts, emulator) { + // we need to get the id of emulator + const adb = new ADB(config); + const retryTimeout = 2000; // if an adb call fails, how long before we retry + const bootTimeout = opts.bootTimeout || 240000; // 4 minutes to boot before timeout + // if a timeout is set and the emulator doesn't boot quick enough, fire the timeout event, // however if the timeout is zero, still listen for the timeout to kill the whilst loop above - bootTimer = setTimeout(function () { - opts.logger && opts.logger.trace(__('Timed out while waiting for the emulator to boot; waited %s ms', bootTimeout)); - conn && conn.end(); - bootTimeout && emulator.emit('timeout', { type: 'emulator', waited: bootTimeout }); - }, bootTimeout), - sdcardTimeout = opts.sdcardTimeout || 60000, // 1 minute to boot before timeout - sdcardTimer, - conn, - deviceId, - emu = emulator.emulator, - emulib = require(path.join(__dirname, 'emulators', emu.type + '.js')); - - opts.logger && opts.logger.trace(__('Checking the boot state for the next %s ms', bootTimeout)); - opts.logger && opts.logger.trace(__('Waiting for emulator to register with ADB')); - - conn = adb.trackDevices(function (err, devices) { - if (err) { - opts.logger && opts.logger.trace(__('Error tracking devices: %s', err.message)); - return; - } else if (!devices.length) { - opts.logger && opts.logger.trace(__('No devices found, continuing to wait')); - return; - } + const bootTimer = setTimeout(() => { + opts.logger?.trace(`Timed out while waiting for the emulator to boot; waited ${bootTimeout} ms`); + conn?.end(); + if (bootTimeout) { + emulator.emit('timeout', { type: 'emulator', waited: bootTimeout }); + } + }, bootTimeout); - // just in case we get any extra events but we already have the deviceId, just return - if (deviceId) { - return; - } + const sdcardTimeout = opts.sdcardTimeout || 60000; // 1 minute to boot before timeout + let sdcardTimer = setTimeout(() => { + if (sdcardTimeout) { + emulator.emit('timeout', { type: 'sdcard', waited: sdcardTimeout }); + } + }, sdcardTimeout); - opts.logger && opts.logger.trace(__('Found %s devices, checking if any of them are the emulator...', devices.length)); + opts.logger?.trace(`Checking the boot state for the next ${bootTimeout} ms`); + opts.logger?.trace('Waiting for emulator to register with ADB'); - emulib.isRunning(config, emu, devices, function (err, running) { + conn = adb.trackDevices(async (err, devices) => { if (err) { + opts.logger?.trace(`Error tracking devices: ${err.message}`); + return; + } else if (!devices.length) { + opts.logger?.trace('No devices found, continuing to wait'); + return; + } + + // just in case we get any extra events but we already have the deviceId, just return + if (deviceId) { + return; + } + + opts.logger?.trace(`Found ${devices.length} devices, checking if any of them are the emulator...`); + + try { + const running = await emulib.isRunning(config, emu, devices); + if (!running) { + // try again + opts.logger?.trace('Emulator not running yet, continuing to wait'); + } else { + // running! + opts.logger?.trace('Emulator is running!'); + Object.assign(emulator, running); + deviceId = running.id; + conn.end(); // no need to track devices anymore + + // keep polling until the boot animation has finished + opts.logger?.trace('Checking if boot animation has finished...'); + + (function checkBootAnim() { + // emulator is running, now shell into it and check if it has booted + adb.shell(deviceId, 'getprop init.svc.bootanim', (err, output) => { + if (!err && output.toString().split('\n').shift().trim() === 'stopped') { + clearTimeout(bootTimer); + opts.logger?.trace('Emulator is booted, emitting booted event'); + emulator.emit('booted', emulator); + } else { + opts.logger?.trace(`Emulator is not booted yet; checking again in ${retryTimeout} ms`); + setTimeout(checkBootAnim, retryTimeout); + } + }); + }()); + } + } catch { // TODO: this could be bad... maybe we should emit an error event? - opts.logger && opts.logger.trace(__('Error checking if emulator is running: %s', err)); - } else if (!running) { - // try again - opts.logger && opts.logger.trace(__('Emulator not running yet, continuing to wait')); - } else { - // running! - opts.logger && opts.logger.trace(__('Emulator is running!')); - appc.util.mix(emulator, running); - deviceId = running.id; - conn.end(); // no need to track devices anymore - - // keep polling until the boot animation has finished - opts.logger && opts.logger.trace(__('Checking if boot animation has finished...')); - (function checkBootAnim() { - // emulator is running, now shell into it and check if it has booted - adb.shell(deviceId, 'getprop init.svc.bootanim', function (err, output) { - if (!err && output.toString().split('\n').shift().trim() === 'stopped') { - clearTimeout(bootTimer); - opts.logger && opts.logger.trace(__('Emulator is booted, emitting booted event')); - emulator.emit('booted', emulator); - } else { - opts.logger && opts.logger.trace(__('Emulator is not booted yet; checking again in %s ms', retryTimeout)); - setTimeout(checkBootAnim, retryTimeout); - } - }); - }()); + opts.logger?.trace(`Error checking if emulator is running: ${err}`); } }); - }); - emulator.on('booted', function () { - var done = false; + emulator.on('booted', async () => { + opts.logger?.info('Emulator is booted'); + + if (!opts.checkMounts || !emu.sdcard) { + // nothing to do, fire ready event + opts.logger?.info('SD card not required, skipping mount check'); + emulator.emit('ready', emulator); + return; + } + + opts.logger?.info('Checking if SD card is mounted'); + + // keep polling /sdcard until it's mounted + let retries = 32; + while (retries-- > 0) { + try { + const output = await adb.shell(deviceId, 'cd /sdcard && echo "SDCARD READY"'); + if (output.toString().split('\n').shift().trim() === 'SDCARD READY') { + break; + } + } catch { + await delay(retryTimeout); + } + } + + if (retries <= 0) { + opts.logger?.error('SD card timed out while waiting to be mounted'); + emulator.emit('timeout', { type: 'sdcard', waited: sdcardTimeout }); + return; + } + + let mounted = false; + const mountPoints = [ '/sdcard', '/mnt/sdcard' ]; + sdcardTimer = setTimeout(() => { + if (sdcardTimeout) { + emulator.emit('timeout', { type: 'sdcard', waited: sdcardTimeout }); + } + done = true; + }, sdcardTimeout || 30000); + + const output = await adb.shell(deviceId, 'ls -l /sdcard'); + const m = output.toString().trim().split('\n').shift().trim().match(/-> (\S+)/); + if (m && !mountPoints.includes(m[1])) { + mountPoints.unshift(m[1]); + } + + opts.logger?.debug(`Checking mount points: ${mountPoints.join(', ')}`); + + // wait for the sd card to be mounted + while (!mounted) { + const output = await adb.shell(deviceId, 'mount'); + const check = line => { + const parts = line.trim().split(' '); + return parts.length > 1 && mountPoints.includes(parts[1]); + }; + + if (!err && output.toString().trim().split('\n').some(check)) { + mounted = true; + clearTimeout(sdcardTimer); + opts.logger?.debug('SD card is mounted'); + break; + } else { + await delay(retryTimeout); + break; + } + } - opts.logger && opts.logger.info(__('Emulator is booted')); + // requery the devices since device state may have changed + const devices = await adb.devices(); + if (err) { + opts.logger?.trace(`Error checking if emulator is running: ${err}`); + return; + } - if (!opts.checkMounts || !emu.sdcard) { - // nothing to do, fire ready event - opts.logger && opts.logger.info(__('SD card not required, skipping mount check')); + try { + const running = await emulib.isRunning(config, emu, devices.filter(d => d.id = emulator.id)); + if (running) { + Object.assign(emulator, running); + } + } catch (err) { + opts.logger?.trace(`Error checking if emulator is running: ${err}`); + } emulator.emit('ready', emulator); - return; + }); + } + + /** + * Starts the specified emulator, if not already running. + * @param {String} id - The id of the emulator + * @param {Object} [opts] - Options for detection and launching the emulator + */ + async start(id, opts) { + opts.logger?.trace(`Checking if emulator ${id} is running...`); + + const running = await this.isRunning(id, opts); + if (running) { + // already running + const emulator = new Emulator(); + Object.assign(emulator, running); + opts.logger?.info('Emulator already running'); + this.checkedBooted(this.config, opts, emulator); + return emulator; } - opts.logger && opts.logger.info(__('Checking if SD card is mounted')); + opts.logger?.trace('Emulator not running, detecting emulator info'); - // keep polling /sdcard until it's mounted - async.whilst( - function () { return !done; }, + // not running, start the emulator + const emus = await this.detect(opts); + const emu = emus.find(e => e?.id === id); - function (cb) { - // emulator is running, now shell into it and check if it has booted - adb.shell(deviceId, 'cd /sdcard && echo "SDCARD READY"', function (err, output) { - if (!err && output.toString().split('\n').shift().trim() === 'SDCARD READY') { - done = true; - cb(); + // this should never happen because it would have happened already thanks to isRunning() + if (!emu) { + throw new Error(`Invalid emulator "${id}"`); + } + + const androidEnv = await detectAndroid(this.config, opts); + if (!androidEnv.sdk) { + throw new Error('No Android SDK found'); + } + + // check that 32-bit libs are good to go + if (androidEnv.linux64bit) { + if (androidEnv.linux64bit.ia32libs === false) { + throw new Error('32-bit libraries is not installed.\nTo install the required 32-bit libraries, run "sudo apt-get install ia32-libs".'); + } + } + + opts.logger?.trace('Starting the emulator...'); + + let { port } = opts; + let tryPort = 5554; // port must be between 5554 and 5584 + + opts.logger?.trace('Scanning ports to find a port for the emulator to listening on'); + + // we need to find a port to tell the emulator to listen on + while (!port) { + await new Promise((resolve, reject) => { + let socket = net.connect({ port: tryPort }, () => { + // port taken, try again + socket.end(); + tryPort++; + if (tryPort > 5584) { + reject(new Error('Unable to find a free port between 5554 and 5584')); } else { - setTimeout(cb, retryTimeout); + resolve(); } }); - }, - function () { - var mounted = false, - mountPoints = [ '/sdcard', '/mnt/sdcard' ]; - - adb.shell(deviceId, 'ls -l /sdcard', function (err, output) { - if (!err) { - var m = output.toString().trim().split('\n').shift().trim().match(/-> (\S+)/); - if (m && mountPoints.indexOf(m[1]) === -1) { - mountPoints.unshift(m[1]); - } + socket.on('end', (_err) => { + if (socket) { + socket.end(); + socket = null; } + }); - opts.logger && opts.logger.debug(__('Checking mount points: %s', mountPoints.join(', ').cyan)); - - // wait for the sd card to be mounted - async.whilst( - function () { return !mounted; }, - - function (cb) { - adb.shell(deviceId, 'mount', function (err, output) { - if (!err && output.toString().trim().split('\n').some(function (line) { - var parts = line.trim().split(' '); - return parts.length > 1 && mountPoints.indexOf(parts[1]) !== -1; - })) { - mounted = true; - clearTimeout(sdcardTimer); - opts.logger && opts.logger.debug(__('SD card is mounted')); - cb(); - } else { - setTimeout(cb, retryTimeout); - } - }); - }, - - function () { - // requery the devices since device state may have changed - adb.devices(function (err, devices) { - emulib.isRunning(config, emu, devices.filter(d => d.id = emulator.id), function (err, running) { - if (!err && running) { - appc.util.mix(emulator, running); - } - emulator.emit('ready', emulator); - }); - }); + socket.on('error', (err) => { + if (err.code === 'ECONNREFUSED') { + // port available! + if (socket) { + socket.end(); + socket = null; } - ); + port = tryPort; + resolve(); + } }); - } - ); + }); + } - sdcardTimer = setTimeout(function () { - sdcardTimeout && emulator.emit('timeout', { type: 'sdcard', waited: sdcardTimeout }); - done = true; - }, sdcardTimeout || 30000); - }); -} + opts.logger?.trace(`Emulator will listen on port ${port}`); -/** - * Starts the specified emulator, if not already running. - * @param {String} id - The id of the emulator - * @param {Object} [opts] - Options for detection and launching the emulator - * @param {Function} callback - A function to call when the emulator as launched - */ -EmulatorManager.prototype.start = function start(id, opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; - } + // default args + const args = [ + '-avd', emu.id, // use a specific android virtual device + '-port', port, // TCP port that will be used for the console + ]; - opts.logger && opts.logger.trace(__('Checking if emulator %s is running...', id.cyan)); + const addArg = (prop, option) => { + if (opts[prop]) { + args.push(option, opts[prop]); + } + }; - this.isRunning(id, opts, function (err, running) { - if (err) { - // something went boom - return callback(err); + if (opts.partitionSize !== undefined) { + args.push('-partition-size', opts.partitionSize); // system/data partition size in MBs } - if (running) { - // already running - var emulator = new Emulator(); - appc.util.mix(emulator, running); - opts.logger && opts.logger.info(__('Emulator already running')); - checkedBooted(this.config, opts, emulator); - callback(null, emulator); - return; + addArg('sdcard', '-sdcard'); // SD card image (default /sdcard.img) + + // add any other args + addArg('logcat', '-logcat'); // enable logcat output with given tags + addArg('sysdir', '-sysdir'); // search for system disk images in + addArg('system', '-system'); // read initial system image from + addArg('datadir', '-datadir'); // write user data into + addArg('kernel', '-kernel'); // use specific emulated kernel + addArg('ramdisk', '-ramdisk'); // ramdisk image (default /ramdisk.img + addArg('initdata', '-init-data'); // same as '-init-data ' + addArg('data', '-data'); // data image (default /userdata-qemu.img + addArg('cache', '-cache'); // cache partition image (default is temporary file) + addArg('cacheSize', '-cache-size'); // cache partition size in MBs + addArg('noCache', '-no-cache'); // disable the cache partition + addArg('snapStorage', '-snapstorage'); // file that contains all state snapshots (default /snapshots.img) + addArg('noSnapStorage', '-no-snapstorage'); // do not mount a snapshot storage file (this disables all snapshot functionality) + addArg('snapshot', '-snapshot'); // name of snapshot within storage file for auto-start and auto-save (default 'default-boot') + addArg('noSnapshot', '-no-snapshot'); // perform a full boot and do not do not auto-save, but qemu vmload and vmsave operate on snapstorage + addArg('noSnapshotSave', '-no-snapshot-save'); // do not auto-save to snapshot on exit: abandon changed state + addArg('noSnapshotLoad', '-no-snapshot-load'); // do not auto-start from snapshot: perform a full boot + addArg('snapshotList', '-snapshot-list'); // show a list of available snapshots + addArg('noSnapshotUpdateTime', '-no-snapshot-update-time'); // do not do try to correct snapshot time on restore + addArg('wipeData', '-wipe-data'); // reset the user data image (copy it from initdata) + addArg('skindir', '-skindir'); // search skins in (default /skins) + addArg('skin', '-skin'); // select a given skin + addArg('noSkin', '-no-skin'); // don't use any emulator skin + addArg('dynamicSkin', '-dynamic-skin'); // dynamically construct a skin of given size, requires -skin WxH option + addArg('memory', '-memory'); // physical RAM size in MBs + addArg('netspeed', '-netspeed'); // maximum network download/upload speeds + addArg('netdelay', '-netdelay'); // network latency emulation + addArg('netfast', '-netfast'); // disable network shaping + addArg('trace', '-trace'); // enable code profiling (F9 to start) + addArg('showKernel', '-show-kernel'); // display kernel messages + addArg('shell', '-shell'); // enable root shell on current terminal + addArg('noJNI', '-no-jni'); // disable JNI checks in the Dalvik runtime + addArg('noAudio', '-no-audio'); // disable audio support + addArg('audio', '-audio'); // use specific audio backend + addArg('rawKeys', '-raw-keys'); // disable Unicode keyboard reverse-mapping + addArg('radio', '-radio'); // redirect radio modem interface to character device + addArg('onion', '-onion'); // use overlay PNG image over screen + addArg('onionAlpha', '-onion-alpha'); // specify onion-skin translucency + addArg('onionRotation', '-onion-rotation'); // specify onion-skin rotation 0|1|2|3 + addArg('scale', '-scale'); // scale emulator window + addArg('dpiDevice', '-dpi-device'); // specify device's resolution in dpi (default 165) + addArg('httpProxy', '-http-proxy'); // make TCP connections through a HTTP/HTTPS proxy + addArg('timezone', '-timezone'); // use this timezone instead of the host's default + addArg('dnsServer', '-dns-server'); // use this DNS server(s) in the emulated system + addArg('cpuDelay', '-cpu-delay'); // throttle CPU emulation + addArg('noWindow', '-no-window'); // disable graphical window display + addArg('reportConsole', '-report-console'); // report console port to remote socket + addArg('gps', '-gps'); // redirect NMEA GPS to character device + addArg('keyset', '-keyset'); // specify keyset file name + addArg('shellSerial', '-shell-serial'); // specific character device for root shell + addArg('tcpdump', '-tcpdump'); // capture network packets to file + addArg('bootchart', '-bootchart'); // enable bootcharting + addArg('charmap', '-charmap'); // use specific key character map + addArg('sharedNetId', '-shared-net-id'); // join the shared network, using IP address 10.1.2. + addArg('nandLimits', '-nand-limits'); // enforce NAND/Flash read/write thresholds + addArg('memcheck', '-memcheck'); // enable memory access checking + addArg('gpu', '-gpu'); // set hardware OpenGLES emulation mode + addArg('cameraBack', '-camera-back'); // set emulation mode for a camera facing back + addArg('cameraFront', '-camera-front'); // set emulation mode for a camera facing front + addArg('screen', '-screen'); // set emulated screen mode + addArg('force32bit', '-force-32bit'); // always use 32-bit emulator + + // set system property on boot + if (opts.props && typeof opts.props === 'object') { + for (const prop of Object.keys(opts.props)) { + args.push('-prop', `${prop}=${opts.props[prop]}`); + } } - opts.logger && opts.logger.trace(__('Emulator not running, detecting emulator info')); + // pass arguments to qemu + if (Array.isArray(opts.qemu)) { + args.push('-qemu'); + args.push(...opts.qemu); + } - // not running, start the emulator - this.detect(opts, function (err, emus) { - if (err) { - return callback(err); - } + const emuopts = { + detached: Object.prototype.hasOwnProperty.call(opts, 'detached') ? !!opts.detached : true, + stdio: opts.stdio // || 'ignore' + }; + if (opts.cwd) { + emuopts.cwd = opts.cwd; + } + if (opts.env) { + emuopts.env = opts.env; + } + if (opts.uid) { + emuopts.uid = opts.uid; + } + if (opts.gid) { + emuopts.gid = opts.gid; + } - var emu = emus.filter(e => e && e.id == id).shift(); // eslint-disable-line eqeqeq + opts.logger?.info(`Running: ${(`${androidEnv.sdk.executables.emulator} "${args.join('" "')}"`)}`); + const device = new EmulatorManager.Emulator(); - // this should never happen because it would have happened already thanks to isRunning() - if (!emu) { - return callback(new Error(__('Invalid emulator "%s"', id)), null); - } + const child = spawn(androidEnv.sdk.executables.emulator, args, emuopts); - opts.logger && opts.logger.trace(__('Starting the emulator...')); + device.emulator = { + pid: child.pid + }; + Object.assign(device.emulator, emu); - var emulib = require(path.join(__dirname, 'emulators', emu.type + '.js')); - emulib.start(this.config, emu, opts, function (err, emulator) { - if (err) { - callback(err); - } else { - // give the emulator a second to get started before we start beating up adb - opts.logger && opts.logger.trace(__('Emulator is starting, monitoring boot state...')); - checkedBooted(this.config, opts, emulator); - callback(null, emulator); - } - }.bind(this)); - }.bind(this)); - }.bind(this)); -}; - -/** - * Stops the specified emulator, if running. - * @param {String} id - The id of the emulator - * @param {Object} [opts] - Options for detection and killing the emulator - * @param {Function} callback - A function to call when the emulator as been killed - */ -EmulatorManager.prototype.stop = function stop(id, opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; + child.stdout?.on('data', (data) => { + device.emit('stdout', data); + }); + child.stderr?.on('data', (data) => { + device.emit('stderr', data); + }); + + child.on('error', err => device.emit('error', err)); + child.on('close', (code, signal) => device.emit('exit', code, signal)); + + child.unref(); + + // give the emulator a second to get started before we start beating up adb + opts.logger?.trace('Emulator is starting, monitoring boot state...'); + this.checkedBooted(this.config, opts, device); + return device; } - this.isRunning(id, opts, function (err, running) { - if (err) { - // something went boom - callback(err); - } else if (!running) { + /** + * Stops the specified emulator, if running. + * @param {String} id - The id of the emulator + * @param {Object} [opts] - Options for detection and killing the emulator + */ + async stop(id, opts) { + const device = await this.isRunning(id, opts); + if (device) { + const androidEnv = await detectAndroid(this.config, opts); + if (!androidEnv.sdk) { + throw new Error('No Android SDK found'); + } + + // if they passed in the emulator name, get the emulator avd definition + const emu = androidEnv.avds.find(e => e && e.name === device.emulator.name); + if (!emu) { + throw new Error(`Invalid emulator "${device.emulator.name}"`); + } + + await new Promise((resolve, reject) => { + const child = spawn(results.sdk.executables.adb, [ '-s', device.id, 'emu', 'kill' ], { stdio: ['ignore', 'pipe', 'pipe']}); + let stdout = ''; + let stderr = ''; + child.stdout.on('data', (data) => { + stdout += data.toString(); + }); + child.stderr.on('data', (data) => { + stderr += data.toString(); + }); + child.on('close', (code) => { + if (code) { + reject(new Error(`Failed to stop emulator "${id}" (code ${code})`)); + } else { + resolve(); + } + }); + }); + } else { // already stopped - callback(new Error(__('Emulator "%s" not running', id))); - } else { - require(path.join(__dirname, 'emulators', running.emulator.type + '.js')).stop(this.config, running.emulator.name, running, opts, callback); + throw new Error(`Emulator "${id}" not running`); } - }.bind(this)); -}; + } +} diff --git a/lib/emulators/avd.js b/lib/emulators/avd.js deleted file mode 100644 index 03bab533..00000000 --- a/lib/emulators/avd.js +++ /dev/null @@ -1,386 +0,0 @@ -/** - * @overview - * Library for controlling an Android Emulator. - * - * @module lib/emulators/avd - * - * @copyright - * Copyright (c) 2009-2013 by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const appc = require('node-appc'), - __ = appc.i18n(__dirname).__, - async = require('async'), - android = require('../android'), - net = require('net'), - spawn = require('child_process').spawn, - EmulatorManager = require('../emulator'); - -/** - * Detects all existing Android Virtual Devices. - * @param {Object} config - The CLI config object - * @param {Object} opts - Detect options - * @param {Function} callback - A function to call when the detection has completed - */ -exports.detect = function detect(config, opts, callback) { - opts = opts || {}; - android.detect(config, opts, function (results) { - callback(null, results); - }); -}; - -function getAvdName(port, callback) { - let state = 'connecting', - avdName = null, - buffer = ''; - const responseRegExp = /(.*)\r\nOK\r\n/; - const socket = net.connect({ port: port }); - - socket.on('data', function (data) { - buffer += data.toString(); - const m = buffer.match(responseRegExp); - if (!m || state === 'done') { - // do nothing - } else if (state === 'connecting') { - state = 'sending command'; - buffer = ''; - socket.write('avd name\n'); - } else if (state === 'sending command') { - state = 'done'; - avdName = m[1].trim(); - socket.end('quit\n'); - } - }); - - socket.on('end', function () { - callback(null, avdName); - }); - - socket.on('error', callback); -} - -/** - * Detects if a specific Android Virtual Device is running and if so, returns - * the emulator AVD definition object and the device definition object. - * @param {Object} config - The CLI config object - * @param {Object} emu - The Android emulator avd definition - * @param {Array} devices - An array of device definition objects - * @param {Function} callback - A function to call when the detection has completed - * @returns {void} - */ -exports.isRunning = function isRunning(config, emu, devices, callback) { - if (emu.type !== 'avd') { - return callback(null, false); - } - - const emuRegExp = /^emulator-(\d+)$/; - const matchingDevice = devices.find(d => { - const m = d.id.match(emuRegExp); - return m && d.emulator.id === emu.id; - }); - // Don't filter by state of 'device' (which means running), because sometimes - // adb host:track-devices reports "offline' for an emulator just launched with a super fast boot via snapshots - // and really once it's listed, it's considered "running" (just maybe not fully booted) - return callback(null, matchingDevice); -}; - -/** - * Detects if a specific device name is an Android emulator. - * @param {Object} config - The CLI config object - * @param {Object} device - The device name - * @param {Function} callback - A function to call when the detection has completed - * @returns {void} - */ -exports.isEmulator = function isEmulator(config, device, callback) { - const port = device.match(/^emulator-(\d+)$/); - - if (!port) { - return callback(); - } - - appc.async.parallel(this, { - avdName: function (next) { - getAvdName(port[1], next); - }, - androidInfo: function (next) { - this.detect(config, null, next); - } - }, function (err, results) { - if (err) { - callback(true); - } else { - callback(null, results.androidInfo.avds.filter(e => e.id === results.avdName).shift()); - } - }); -}; - -/** - * Launches the specified Android emulator. - * @param {Object} config - The CLI config object - * @param {Object|String} emu - The Android emulator avd definition or the name of the emulator - * @param {Object} [opts] - Emulator start options - * @param {Boolean} [opts.bypassCache=false] - Bypasses the Android environment detection cache and re-queries the system - * @param {Number} [opts.port=5560] - The TCP port the emulator will use for the console - * @param {String} [opts.sdcard] - A path to the virtual SD card to use with the emulator - * @param {String} [opts.logcatFilter="*:d,*,TiAPI:V"] - The filter for logcat to use - * @param {Number} [opts.partitionSize=128] - The emulator's system/data partition size in MBs - * @param {String} [opts.cwd] - The current working directory to pass into spawn() - * @param {Array|String} [opts.stdio] - The stdio configuration to pass into spawn() - * @param {Object} [opts.env] - The environment variables to pass into spawn() - * @param {Boolean} [opts.detached] - The detached flag to pass into spawn() - * @param {Number} [opts.uid] - The user id to pass into spawn() - * @param {Number} [opts.gid] - The group id to pass into spawn() - * @param {Function} callback - A function to call when the emulator is started - */ -exports.start = function start(config, emu, opts, callback) { - opts = opts || {}; - - android.detect(config, { bypassCache: opts.bypassCache }, function (results) { - if (!results.sdk) { - return callback(new Error(__('No Android SDK found'))); - } - - // if they passed in the emulator name, get the emulator avd definition - if (emu && typeof emu === 'string') { - const name = emu; - emu = results.avds.filter(e => e && e.name === name).shift(); - if (!emu) { - return callback(new Error(__('Invalid emulator "%s"', name)), null); - } - } - - // check that 32-bit libs are good to go - if (results.linux64bit) { - if (results.linux64bit.ia32libs === false) { - return callback(new appc.exception( - __('32-bit libraries is not installed.'), - __('To install the required 32-bit libraries, run "%s".', 'sudo apt-get install ia32-libs') - )); - } - } - - var port = opts.port, - tryPort = 5554; // port must be between 5554 and 5584 - - opts.logger && opts.logger.trace(__('Scanning ports to find a port for the emulator to listening on')); - - // we need to find a port to tell the emulator to listen on - async.whilst( - function (cb) { cb(null, !port); }, - function (cb) { - var socket = net.connect({ port: tryPort }, function () { - // port taken, try again - socket.end(); - tryPort++; - cb(tryPort > 5584 ? new Error(__('Unable to find a free port between 5554 and 5584')) : null); - }); - - socket.on('end', function (_err) { - if (socket) { - socket.end(); - socket = null; - } - }); - - socket.on('error', function (err) { - if (err.code === 'ECONNREFUSED') { - // port available! - if (socket) { - socket.end(); - socket = null; - } - port = tryPort; - cb(); - } - }); - }, - function (err) { - if (err) { - return callback(err); - } - - opts.logger && opts.logger.trace(__('Emulator will listen on port %s', String(port).cyan)); - - // default args - var args = [ - '-avd', emu.id, // use a specific android virtual device - '-port', port, // TCP port that will be used for the console - ]; - - if (opts.partitionSize !== undefined) { - args.push('-partition-size', opts.partitionSize); // system/data partition size in MBs - } - - if (opts.sdcard) { - args.push('-sdcard', opts.sdcard); // SD card image (default /sdcard.img) - } - - // add any other args - opts.logcat && args.push('-logcat', opts.logcat); // enable logcat output with given tags - opts.sysdir && args.push('-sysdir', opts.sysdir); // search for system disk images in - opts.system && args.push('-system', opts.system); // read initial system image from - opts.datadir && args.push('-datadir', opts.datadir); // write user data into - opts.kernel && args.push('-kernel', opts.kernel); // use specific emulated kernel - opts.ramdisk && args.push('-ramdisk', opts.ramdisk); // ramdisk image (default /ramdisk.img - opts.initdata && args.push('-init-data', opts.initdata); // same as '-init-data ' - opts.data && args.push('-data', opts.data); // data image (default /userdata-qemu.img - opts.cache && args.push('-cache', opts.cache); // cache partition image (default is temporary file) - opts.cacheSize && args.push('-cache-size', opts.cacheSize); // cache partition size in MBs - opts.noCache && args.push('-no-cache'); // disable the cache partition - opts.snapStorage && args.push('-snapstorage', opts.snapStorage); // file that contains all state snapshots (default /snapshots.img) - opts.noSnapStorage && args.push('-no-snapstorage'); // do not mount a snapshot storage file (this disables all snapshot functionality) - opts.snapshot && args.push('-snapshot', opts.snapshot); // name of snapshot within storage file for auto-start and auto-save (default 'default-boot') - opts.noSnapshot && args.push('-no-snapshot'); // perform a full boot and do not do not auto-save, but qemu vmload and vmsave operate on snapstorage - opts.noSnapshotSave && args.push('-no-snapshot-save'); // do not auto-save to snapshot on exit: abandon changed state - opts.noSnapshotLoad && args.push('-no-snapshot-load'); // do not auto-start from snapshot: perform a full boot - opts.snapshotList && args.push('-snapshot-list'); // show a list of available snapshots - opts.noSnapshotUpdateTime && args.push('-no-snapshot-update-time'); // do not do try to correct snapshot time on restore - opts.wipeData && args.push('-wipe-data'); // reset the user data image (copy it from initdata) - opts.skindir && args.push('-skindir', opts.skindir); // search skins in (default /skins) - opts.skin && args.push('-skin', opts.skin); // select a given skin - opts.noSkin && args.push('-no-skin'); // don't use any emulator skin - opts.dynamicSkin && args.push('-dynamic-skin'); // dynamically construct a skin of given size, requires -skin WxH option - opts.memory && args.push('-memory', opts.memory); // physical RAM size in MBs - opts.netspeed && args.push('-netspeed', opts.netspeed); // maximum network download/upload speeds - opts.netdelay && args.push('-netdelay', opts.netdelay); // network latency emulation - opts.netfast && args.push('-netfast'); // disable network shaping - opts.trace && args.push('-trace', opts.trace); // enable code profiling (F9 to start) - opts.showKernel && args.push('-show-kernel'); // display kernel messages - opts.shell && args.push('-shell'); // enable root shell on current terminal - opts.noJNI && args.push('-no-jni'); // disable JNI checks in the Dalvik runtime - opts.noAudio && args.push('-no-audio'); // disable audio support - opts.audio && args.push('-audio', opts.audio); // use specific audio backend - opts.rawKeys && args.push('-raw-keys'); // disable Unicode keyboard reverse-mapping - opts.radio && args.push('-radio', opts.radio); // redirect radio modem interface to character device - opts.onion && args.push('-onion', opts.onion); // use overlay PNG image over screen - opts.onionAlpha && args.push('-onion-alpha', opts.onionAlpha); // specify onion-skin translucency - opts.onionRotation && args.push('-onion-rotation', opts.onionRotation); // specify onion-skin rotation 0|1|2|3 - opts.scale && args.push('-scale', opts.scale); // scale emulator window - opts.dpiDevice && args.push('-dpi-device', opts.dpiDevice); // specify device's resolution in dpi (default 165) - opts.httpProxy && args.push('-http-proxy', opts.httpProxy); // make TCP connections through a HTTP/HTTPS proxy - opts.timezone && args.push('-timezone', opts.timezone); // use this timezone instead of the host's default - opts.dnsServer && args.push('-dns-server', opts.dnsServer); // use this DNS server(s) in the emulated system - opts.cpuDelay && args.push('-cpu-delay', opts.cpuDelay); // throttle CPU emulation - opts.noWindow && args.push('-no-window'); // disable graphical window display - opts.reportConsole && args.push('-report-console', opts.reportConsole); // report console port to remote socket - opts.gps && args.push('-gps', opts.gps); // redirect NMEA GPS to character device - opts.keyset && args.push('-keyset', opts.keyset); // specify keyset file name - opts.shellSerial && args.push('-shell-serial', opts.shellSerial); // specific character device for root shell - opts.tcpdump && args.push('-tcpdump', opts.tcpdump); // capture network packets to file - opts.bootchart && args.push('-bootchart', opts.bootchart); // enable bootcharting - opts.charmap && args.push('-charmap', opts.charmap); // use specific key character map - opts.sharedNetId && args.push('-shared-net-id', opts.sharedNetId); // join the shared network, using IP address 10.1.2. - opts.nandLimits && args.push('-nand-limits', opts.nandLimits); // enforce NAND/Flash read/write thresholds - opts.memcheck && args.push('-memcheck', opts.memcheck); // enable memory access checking - opts.gpu && args.push('-gpu', opts.gpu); // set hardware OpenGLES emulation mode - opts.cameraBack && args.push('-camera-back', opts.cameraBack); // set emulation mode for a camera facing back - opts.cameraFront && args.push('-camera-front', opts.cameraFront); // set emulation mode for a camera facing front - opts.screen && args.push('-screen', opts.screen); // set emulated screen mode - opts.force32bit && args.push('-force-32bit'); // always use 32-bit emulator - - // set system property on boot - if (opts.props && typeof opts.props === 'object') { - Object.keys(opts.props).forEach(function (prop) { - args.push('-prop', prop + '=' + opts.props[prop]); - }); - } - - // pass arguments to qemu - if (Array.isArray(opts.qemu)) { - args.push('-qemu'); - args = args.concat(opts.qemu); - } - - var emuopts = { - detached: Object.prototype.hasOwnProperty.call(opts, 'detached') ? !!opts.detached : true, - stdio: opts.stdio// || 'ignore' - }; - opts.cwd && (emuopts.cwd = opts.cwd); - opts.env && (emuopts.env = opts.env); - opts.uid && (emuopts.uid = opts.uid); - opts.gid && (emuopts.gid = opts.gid); - - opts.logger && opts.logger.info(__('Running: %s', (results.sdk.executables.emulator + ' "' + args.join('" "') + '"').cyan)); - - var child = spawn(results.sdk.executables.emulator, args, emuopts), - device = new EmulatorManager.Emulator(); - - device.emulator = { - pid: child.pid - }; - appc.util.mix(device.emulator, emu); - - child.stdout && child.stdout.on('data', function (data) { - device.emit('stdout', data); - }); - - child.stderr && child.stderr.on('data', function (data) { - device.emit('stderr', data); - }); - - child.on('error', function (err) { - device.emit('error', err); - }); - - child.on('close', function (code, signal) { - device.emit('exit', code, signal); - }); - - child.unref(); - - callback(null, device); - } - ); - }); -}; - -/** - * Kills the specified Android emulator. - * @param {Object} config - The CLI config object - * @param {String} name - The name of the emulator - * @param {Object} device - Android device definition object - * @param {Object} opts - Emulator options object - * @param {String} [opts.titaniumHomeDir="~/.titanium"] - The Titanium home directory - * @param {Boolean} [opts.bypassCache=false] - Bypasses environment detection cache and re-queries the system - * @param {String} [opts.cwd] - The current working directory to pass into spawn() - * @param {Array|String} [opts.stdio="ignore"] - The stdio configuration to pass into spawn() - * @param {Object} [opts.env] - The environment variables to pass into spawn() - * @param {Boolean} [opts.detached=true] - The detached flag to pass into spawn() - * @param {Number} [opts.uid] - The user id to pass into spawn() - * @param {Number} [opts.gid] - The group id to pass into spawn() - * @param {Function} callback - A function to call when the emulator is stopped - */ -exports.stop = function stop(config, name, device, opts, callback) { - if (opts && typeof opts === 'function') { - callback = opts; - opts = {}; - } else { - opts = opts || {}; - } - - android.detect(config, { bypassCache: opts.bypassCache }, function (results) { - if (!results.sdk) { - return callback(new Error(__('No Android SDK found'))); - } - - // if they passed in the emulator name, get the emulator avd definition - const emu = results.avds.filter(e => e && e.name === name).shift(); - if (!emu) { - return callback(new Error(__('Invalid emulator "%s"', name)), null); - } - - exports.isRunning(config, emu, [ device ], function (err, running) { - if (err || !running) { - return callback(err); - } - appc.subprocess.run(results.sdk.executables.adb, [ '-s', device.id, 'emu', 'kill' ], function (code, out, err) { - callback(code, code ? err : out); - }); - }); - }); -}; diff --git a/lib/i18n.js b/lib/i18n.js deleted file mode 100644 index aa6d8909..00000000 --- a/lib/i18n.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Titanium SDK Library for Node.js - * Copyright (c) 2012-2013 by Appcelerator, Inc. All Rights Reserved. - * Please see the LICENSE file for information about licensing. - */ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const DOMParser = require('xmldom').DOMParser; - -const appc = require('node-appc'); -const __ = appc.i18n(__dirname).__; -const xml = appc.xml; - -const launchScreensCache = {}; - -exports.load = load; -exports.findLaunchScreens = findLaunchScreens; - -function load(projectDir, logger, opts) { - if (process.argv.indexOf('--i18n-dir') !== -1) { - // Enable developers to specify i18n directory location with build flag - const customI18n = process.argv[process.argv.indexOf('--i18n-dir') + 1]; - if (customI18n && fs.existsSync(path.join(path.resolve(projectDir), customI18n))) { - projectDir = path.join(projectDir, customI18n); - } - } - const i18nDir = path.join(projectDir, 'i18n'), - data = {}, - ignoreDirs = opts && opts.ignoreDirs, - ignoreFiles = opts && opts.ignoreFiles; - - // TODO: Process languages in parallel! - if (fs.existsSync(i18nDir)) { - logger && logger.debug(__('Compiling localization files')); - fs.readdirSync(i18nDir).forEach(function (lang) { - const langDir = path.join(i18nDir, lang), - isDir = fs.statSync(langDir).isDirectory(); - - if (fs.existsSync(langDir) && isDir && (!ignoreDirs || !ignoreDirs.test(lang))) { - const s = data[lang] = {}; - - fs.readdirSync(langDir).forEach(function (name) { - const file = path.join(langDir, name); - if (/.+\.xml$/.test(name) && (!ignoreFiles || !ignoreFiles.test(name)) && fs.existsSync(file) && fs.statSync(file).isFile()) { - logger && logger.debug(__('Processing i18n file: %s', (lang + '/' + name).cyan)); - - const dest = name === 'app.xml' ? 'app' : 'strings', - obj = s[dest] = s[dest] || {}, - dom = new DOMParser().parseFromString(fs.readFileSync(file).toString(), 'text/xml'); - - xml.forEachElement(dom.documentElement, function (elem) { - if (elem.nodeType == 1 && elem.tagName == 'string') { // eslint-disable-line eqeqeq - const name = xml.getAttr(elem, 'name'); - name && (obj[name] = elem && elem.firstChild && elem.firstChild.data || ''); - } - }); - } - }); - } - }); - } - - return data; -} - -function findLaunchScreens(projectDir, logger, opts) { - if (launchScreensCache[projectDir]) { - return launchScreensCache[projectDir]; - } - - var i18nDir = path.join(projectDir, 'i18n'), - data = []; - - opts || (opts = {}); - - if (fs.existsSync(i18nDir)) { - logger.debug(__('Checking for Splash Screen localization')); - fs.readdirSync(i18nDir).forEach(function (lang) { - var langDir = path.join(i18nDir, lang); - if (fs.existsSync(langDir) && fs.statSync(langDir).isDirectory() && (!opts.ignoreDirs || !opts.ignoreDirs.test(lang))) { - fs.readdirSync(langDir).forEach(function (name) { - if (/^(Default(-(Landscape|Portrait))?(-[0-9]+h)?(@[2-9]x)?)\.png$/.test(name)) { - data.push(path.join(langDir, name)); - } - }); - } - }); - } - - return launchScreensCache[projectDir] = data; -} diff --git a/lib/jsanalyze.js b/lib/jsanalyze.js deleted file mode 100644 index f6b8ea80..00000000 --- a/lib/jsanalyze.js +++ /dev/null @@ -1,376 +0,0 @@ -/** - * @overview - * Analyzes Titanium JavaScript files for symbols and optionally minifies the code. - * - * @module lib/jsanalyze - * - * @copyright - * Copyright (c) 2009-Present by Appcelerator, Inc. All Rights Reserved. - * - * @license - * Licensed under the terms of the Apache Public License - * Please see the LICENSE included with this distribution for details. - */ -'use strict'; - -const appc = require('node-appc'); -const fs = require('fs-extra'); -const DOMParser = require('xmldom').DOMParser; -const babel = require('@babel/core'); -const babylon = require('@babel/parser'); -const minify = require('babel-preset-minify'); -const env = require('@babel/preset-env'); -const apiTracker = require('./babel-plugins/ti-api'); -const path = require('path'); - -const SOURCE_MAPPING_URL_REGEXP = /\/\/#[ \t]+sourceMappingURL=([^\s'"`]+?)[ \t]*$/mg; -const __ = appc.i18n(__dirname).__; - -function sortObject(o) { - const sorted = {}; - for (const key of Object.keys(o).sort()) { - sorted[key] = o[key]; - } - return sorted; -} -exports.sortObject = sortObject; - -/** - * Returns an object with the Titanium API usage statistics. - * - * @returns {Object} The API usage stats - */ -exports.getAPIUsage = function getAPIUsage() { - return apiTracker.apiUsage; -}; - -/** - * Analyzes a Titanium JavaScript file for all Titanium API symbols. - * - * @param {String} file - The full path to the JavaScript file - * @param {Object} [opts] - Analyze options - * @param {Boolean} [opts.minify=false] - If true, minifies the JavaScript and returns it - * @param {String} [opts.dest] full filepath of the destination JavaScript file we'll write the contents to - * @param {Boolean} [opts.minify=false] - If true, minifies the JavaScript and returns it - * @param {Boolean} [opts.transpile=false] - If true, transpiles the JS code and retuns it - * @param {Array} [opts.plugins=[]] - An array of resolved Babel plugins - * @param {Function} [opts.logger] - Logger instance to use for logging warnings. - * @param {object} [opts.transform={}] - object holding static values about the app/platform/build for the babel titanium transform plugin - * @returns {Object} An object containing symbols and minified JavaScript - * @throws {Error} An error if unable to parse the JavaScript - */ -exports.analyzeJsFile = function analyzeJsFile(file, opts = {}) { - opts.filename = file; - return exports.analyzeJs(fs.readFileSync(file).toString(), opts); -}; - -/** - * Analyzes a string containing JavaScript for all Titanium API symbols. - * - * @param {String} contents - A string of JavaScript - * @param {Object} [opts] - Analyze options - * @param {String} [opts.filename] - The filename of the original JavaScript source - * @param {String} [opts.dest] full filepath of the destination JavaScript file we'll write the contents to - * @param {Boolean} [opts.minify=false] - If true, minifies the JavaScript and returns it - * @param {Boolean} [opts.transpile=false] - If true, transpiles the JS code and retuns it - * @param {Array} [opts.plugins=[]] - An array of resolved Babel plugins - * @param {Function} [opts.logger] - Logger instance to use for logging warnings. - * @param {object} [opts.transform={}] - object holding static values about the app/platform/build for the babel titanium transform plugin - * @returns {Object} An object containing symbols and minified JavaScript - * @throws {Error} An error if unable to parse the JavaScript - */ -exports.analyzeJs = function analyzeJs(contents, opts = {}) { - opts.plugins || (opts.plugins = []); - opts.transform || (opts.transform = {}); - - // parse the js file - let ast; - const parserOpts = { - sourceType: 'unambiguous', - filename: opts.filename - }; - try { - try { - ast = babylon.parse(contents, parserOpts); - } catch (err) { - // fall back to much looser parsing - parserOpts.allowReturnOutsideFunction = true; - ast = babylon.parse(contents, parserOpts); - } - } catch (ex) { - const errmsg = [ __('Failed to parse %s', opts.filename) ]; - if (ex.line) { - errmsg.push(__('%s [line %s, column %s]', ex.message, ex.line, ex.col)); - } else { - errmsg.push(ex.message); - } - try { - contents = contents.split('\n'); - if (ex.line && ex.line <= contents.length) { - errmsg.push(''); - errmsg.push(' ' + contents[ex.line - 1].replace(/\t/g, ' ')); - if (ex.col) { - var i = 0, - len = ex.col, - buffer = ' '; - for (; i < len; i++) { - buffer += '-'; - } - errmsg.push(buffer + '^'); - } - errmsg.push(''); - } - } catch (ex2) {} // eslint-disable-line no-empty - throw new Error(errmsg.join('\n')); - } - - const results = { - original: contents, - contents: contents, - symbols: [] // apiTracker plugin will gather these! - }; - - const options = { - filename: opts.filename, - retainLines: true, - presets: [], - plugins: [ - [ apiTracker, { skipStats: opts.skipStats } ] // track our API usage no matter what - ], - parserOpts - }; - - // transpile - if (opts.transpile) { - options.plugins.push(require.resolve('./babel-plugins/global-this')); - options.plugins.push([ require.resolve('babel-plugin-transform-titanium'), opts.transform ]); - options.presets.push([ env, { targets: opts.targets } ]); - } - - // minify - if (opts.minify) { - Object.assign(options, { - minified: true, - compact: true, - comments: false - }); - - options.presets.push([ minify, { - mangle: false, - deadcode: false - } ]); - - options.plugins.push(require.resolve('@babel/plugin-transform-property-literals')); - } - - if (opts.plugins.length) { - options.plugins.push.apply(options.plugins, opts.plugins); - } - - let sourceFileName = opts.filename; // used to point to correct original source in sources/sourceRoot of final source map - const sourceMap = (sourceFileName && sourceFileName.includes('/node_modules/')) ? false : opts.sourceMap; - - // generate a source map - if (sourceMap) { - // we manage the source maps ourselves rather than just choose 'inline' - // because we need to do some massaging - options.sourceMaps = true; - - // If the original file already has a source map, load it so we can pass it along to babel - const mapResults = findSourceMap(contents, opts.filename); - if (mapResults) { - const existingMap = mapResults.map; - // location we should try and resolve sources against (after sourceRoot) - // this may be a pointer to the external .map file, or point to the source file where the map was inlined - // Note that the spec is pretty ambiguous about this (relative to the SourceMap) and I think Safari may try relative to - // the original sourceURL too? - const mapFile = mapResults.filepath; - - // Choose last entry in 'sources' as the one we'll report as original sourceURL - sourceFileName = existingMap.sources[existingMap.sources.length - 1]; - - // If the existing source map has a source root, we need to combine it with source path to get full filepath - if (existingMap.sourceRoot) { - // source root may be a filepath, file URI or URL. We assume file URI/path here - if (existingMap.sourceRoot.startsWith('file://')) { - existingMap.sourceRoot = existingMap.sourceRoot.slice(7); - } - sourceFileName = path.resolve(existingMap.sourceRoot, sourceFileName); - } - // if sourceFilename is still not absolute, resolve relative to map file - sourceFileName = path.resolve(path.dirname(mapFile), sourceFileName); - - // ok, we've mangled the source map enough for babel to consume it - options.inputSourceMap = existingMap; - } - } - const transformed = babel.transformFromAstSync(ast, contents, options); - - // if the file is ignored by babel config, transformed will be null - if (transformed && transformed.code) { - - results.contents = transformed.code; - - if (sourceMap) { - // Drop the original sourceMappingURL comment (for alloy files) - results.contents = results.contents.replace(SOURCE_MAPPING_URL_REGEXP, ''); - - // Point the sourceRoot at the original dir (so the full filepath of the original source can be gleaned from sources/sourceRoot combo) - // we already have a sourceRoot in the case of an input source map - so don't override that - if (!transformed.map.sourceRoot) { - transformed.map.sourceRoot = path.dirname(sourceFileName); - } - // Android / Chrome DevTools is sane and can load the source from disk - // so we can ditch inlining the original source there (I'm looking at you Safari/WebInspector!) - if (opts.platform === 'android') { - // NOTE that this will drop some of the alloy template code too. If we want users to see the original source from that, don't delete this! - // Or alternatively, make alloy report the real template filename in it's source mapping - delete transformed.map.sourcesContent; - } else { - // if they didn't specify the final filepath, assume the js file's base name won't change from the source one (it shouldn't) - const generatedBasename = path.basename(opts.dest || opts.filename); - transformed.map.sources = transformed.map.sources.map(s => { - const sourceBasename = path.basename(s); - return sourceBasename === generatedBasename ? sourceBasename : s; - }); - // FIXME: on iOS/Safari - If there are multiple sources, any sources whose basename matches the generated file basename - // will get their parent path listed as a folder, but WILL NOT SHOW THE FILE! - // How in the world do we fix this? - // Well, if there's only one source with the same basename and we rename it to just the basename, that "fixes" the Web Inspector display - // IDEA: What if we fix iOS to report URIs like /app.js as Android does, will that make it behave more properly? - } - transformed.map = sortObject(transformed.map); - // Do our own inlined source map so we can have control over the map object that is written! - const base64Contents = Buffer.from(JSON.stringify(transformed.map)).toString('base64'); - // NOTE: We MUST append a \n or else iOS will break, because it injects a ';' after the - // original file contents when doing it's require() impl - // NOTE: Construction of the source-map url needs to be obfuscated to avoid unwanted - // detection of this line as an actual source-map by `source-map-support` package. - const sourceMapPrefix = 'sourceMappingURL=data:application/json;charset=utf-8;base64'; - results.contents += `\n//# ${sourceMapPrefix},${base64Contents}\n`; - } - } - results.symbols = Array.from(apiTracker.symbols.values()); // convert Set values to Array - - return results; -}; - -/** - * @param {string} contents source code to check - * @param {string} filepath original absolute path to JS file the contents came from - * @returns {object} - */ -function findSourceMap(contents, filepath) { - const m = SOURCE_MAPPING_URL_REGEXP.exec(contents); - if (!m) { - return null; - } - - let lastMatch = m.pop(); - // HANDLE inlined data: source maps! - if (lastMatch.startsWith('data:')) { - const parts = lastMatch.split(';'); - const contents = parts[2]; - if (contents.startsWith('base64,')) { - const map = JSON.parse(Buffer.from(contents.slice(7), 'base64').toString('utf-8')); - return { - map, - filepath - }; - } - // if starts with file://, drop that - } else if (lastMatch.startsWith('file://')) { - lastMatch = lastMatch.slice(7); - } - // resolve filepath relative to the original input JS file if we need to... - const mapFile = path.resolve(path.dirname(filepath), lastMatch); - - try { - const map = fs.readJSONSync(mapFile); - return { - map, - filepath: mapFile - }; - } catch (err) { - return null; - } -} - -/** - * Analyzes an HTML file for all app:// JavaScript files - * - * @param {String} file - The full path to the HTML file - * @param {String} [relPath] - A relative path to the HTML file with respect to the Resources directory - * @returns {Array} An array of app:// JavaScript files - */ -exports.analyzeHtmlFile = function analyzeHtmlFile(file, relPath) { - return exports.analyzeHtml(fs.readFileSync(file).toString(), relPath); -}; - -/** - * Analyzes a string containing JavaScript for all Titanium API symbols. - * - * @param {String} contents - A string of JavaScript - * @param {String} [relPath] - A relative path to the HTML file with respect to the Resources directory - * @returns {Array} An array of app:// JavaScript files - */ -exports.analyzeHtml = function analyzeHtml(contents, relPath) { - const files = []; - - function addFile(src) { - const m = src && src.match(/^(?:(.*):\/\/)?(.+)/); - let res = m && m[2]; - if (res) { - if (!m[1]) { - if (relPath && res.indexOf('/') !== 0) { - res = relPath.replace(/\/$/, '') + '/' + res; - } - - // compact the path - const p = res.split(/\/|\\/); - const r = []; - let q; - while (q = p.shift()) { - if (q === '..') { - r.pop(); - } else { - r.push(q); - } - } - - files.push(r.join('/')); - } else if (m[1] === 'app') { - files.push(res); - } - } - } - - try { - const dom = new DOMParser({ errorHandler: function () {} }).parseFromString('\n' + contents + '\n', 'text/html'), - doc = dom && dom.documentElement, - scripts = doc && doc.getElementsByTagName('script'), - len = scripts.length; - - if (scripts) { - for (let i = 0; i < len; i++) { - const src = scripts[i].getAttribute('src'); - src && addFile(src); - } - } - } catch (e) { - // bad html file, try to manually parse out the script tags - contents.split(''); - if (p !== -1) { - let m = chunk.substring(0, p).match(/src\s*=\s*['"]([^'"]+)/); - if (!m) { - // try again without the quotes - m = chunk.substring(0, p).match(/src\s*=\s*([^>\s]+)/); - } - m && addFile(m[1]); - } - }); - } - - return files; -}; diff --git a/lib/tiappxml.js b/lib/tiappxml.js deleted file mode 100644 index 9b281669..00000000 --- a/lib/tiappxml.js +++ /dev/null @@ -1,750 +0,0 @@ -/** - * Titanium SDK Library for Node.js - * Copyright (c) 2012-Present by Appcelerator, Inc. All Rights Reserved. - * Please see the LICENSE file for information about licensing. - */ -/* eslint no-loop-func: "off" */ -'use strict'; - -const appc = require('node-appc'); -const DOMParser = require('xmldom').DOMParser; -const fs = require('fs-extra'); -const path = require('path'); - -const plist = appc.plist; -const version = appc.version; -const xml = appc.xml; -const __ = appc.i18n(__dirname).__; - -const defaultDOMParserArgs = { errorHandler: function () {} }; -module.exports = tiapp; - -function toXml(dom, parent, name, value) { - // properties is a super special case - if (name === 'properties') { - Object.keys(value).forEach(function (v) { - dom.create('property', { - name: v, - type: value[v].type || 'string', - nodeValue: value[v].value - }, parent); - }); - return; - } - - var node = dom.create(name, null, parent); - - switch (name) { - case 'deployment-targets': - Object.keys(value).forEach(function (v) { - dom.create('target', { - device: v, - nodeValue: value[v] - }, node); - }); - break; - - case 'code-processor': - Object.keys(value).forEach(function (key) { - if (key === 'plugins') { - if (Array.isArray(value[key]) && value[key].length) { - dom.create('plugins', null, node, function (plugins) { - value[key].forEach(function (p) { - dom.create('plugin', { nodeValue: p }, plugins); - }); - }); - } - } else if (key === 'options') { - if (Object.prototype.toString.call(value[key]) === '[object Object]') { - dom.create('options', null, node, function (options) { - Object.keys(value[key]).forEach(function (opt) { - dom.create(opt, { nodeValue: value[key][opt] }, options); - }); - }); - } - } else { - dom.create(key, { nodeValue: value[key] }, node); - } - }); - break; - - case 'ios': - if (Object.prototype.hasOwnProperty.call(value, 'exclude-dir-from-asset-catalog')) { - dom.create('exclude-dir-from-asset-catalog', { nodeValue: !!value['exclude-dir-from-asset-catalog'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'enable-launch-screen-storyboard')) { - dom.create('enable-launch-screen-storyboard', { nodeValue: !!value['enable-launch-screen-storyboard'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'enablecoverage')) { - dom.create('enablecoverage', { nodeValue: !!value['enablecoverage'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'enablemdfind')) { - dom.create('enablemdfind', { nodeValue: !!value['enablemdfind'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'min-ios-ver')) { - dom.create('min-ios-ver', { nodeValue: version.format(value['min-ios-ver'], 2) }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'default-background-color')) { - dom.create('default-background-color', { nodeValue: value['default-background-color'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'team-id')) { - dom.create('team-id', { nodeValue: value['team-id'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'use-jscore-framework')) { - dom.create('use-jscore-framework', { nodeValue: !!value['use-jscore-framework'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'run-on-main-thread')) { - dom.create('run-on-main-thread', { nodeValue: !!value['run-on-main-thread'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'use-autolayout')) { - dom.create('use-autolayout', { nodeValue: !!value['use-autolayout'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'use-new-build-system')) { - dom.create('use-new-build-system', { nodeValue: !!value['use-new-build-system'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'use-app-thinning')) { - dom.create('use-app-thinning', { nodeValue: !!value['use-app-thinning'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'log-server-port')) { - dom.create('log-server-port', { nodeValue: value['log-server-port'] }, node); - } - - if (value.capabilities) { - var capNode = dom.create('capabilities', null, node); - Object.keys(value.capabilities).forEach(function (cap) { - if (cap === 'app-groups') { - var appGroupNode = dom.create(cap, null, capNode); - value.capabilities[cap].forEach(function (group) { - dom.create('group', { nodeValue: group }, appGroupNode); - }); - appGroupNode.appendChild(dom.createTextNode('\r\n\t\t\t')); - capNode.appendChild(dom.createTextNode('\r\n\t\t')); - } - }); - } - - if (value.entitlements) { - const enNode = dom.create('entitlements', null, node); - const pl = new plist(); - appc.util.mix(pl, value.entitlements); - const doc = pl.toXml(3); - enNode.appendChild(dom.createTextNode('\r\n\t\t\t')); - xml.forEachElement(doc, function (elem) { - enNode.appendChild(elem); - }); - enNode.appendChild(dom.createTextNode('\r\n\t\t')); - } - - if (value.plist) { - const plNode = dom.create('plist', null, node); - const pl = new plist(); - appc.util.mix(pl, value.plist); - const doc = pl.toXml(3); - plNode.appendChild(dom.createTextNode('\r\n\t\t\t')); - xml.forEachElement(doc, function (elem) { - plNode.appendChild(elem); - }); - plNode.appendChild(dom.createTextNode('\r\n\t\t')); - } - - if (Array.isArray(value.extensions)) { - var extsNode = dom.create('extentions', null, node); - value.extensions.forEach(function (ext) { - var extNode = dom.create('extention', { projectPath: ext.projectPath }, extsNode); - Array.isArray(ext.targets) && ext.targets.forEach(function (target) { - var targetNode = dom.create('target', { name: target.name }, extNode); - if (target.ppUUIDs && typeof target.ppUUIDs === 'object' && Object.keys(target.ppUUIDs).length) { - var ppUUIDsNode = dom.create('provisioning-profiles', null, targetNode); - Object.keys(target.ppUUIDs).forEach(function (type) { - dom.create(type, { nodeValue: target.ppUUIDs[type] }, ppUUIDsNode); - }); - ppUUIDsNode.appendChild(dom.createTextNode('\r\n\t\t\t\t\t')); - } - targetNode.appendChild(dom.createTextNode('\r\n\t\t\t\t')); - }); - extNode.appendChild(dom.createTextNode('\r\n\t\t\t')); - }); - extsNode.appendChild(dom.createTextNode('\r\n\t\t')); - } - break; - - case 'iphone': - value.orientations && Object.keys(value.orientations).forEach(function (o) { - dom.create('orientations', { device: o }, node, function (orientations) { - value.orientations[o].forEach(function (p) { - dom.create('orientation', { nodeValue: p }, orientations); - }); - }); - }); - - value.backgroundModes && dom.create('background', null, node, function (background) { - value.backgroundModes.forEach(function (mode) { - dom.create('mode', { nodeValue: mode }, background); - }); - }); - - value.requiredFeatures && dom.create('requires', null, node, function (requires) { - value.requiredFeatures.forEach(function (feature) { - dom.create('feature', { nodeValue: feature }, requires); - }); - }); - - value.types && dom.create('types', null, node, function (types) { - value.types.forEach(function (typeObj) { - dom.create('type', null, types, function (typeNode) { - dom.create('name', { nodeValue: typeObj.name }, typeNode); - dom.create('icon', { nodeValue: typeObj.icon }, typeNode); - dom.create('uti', { nodeValue: typeObj.uti.join(',') }, typeNode); - dom.create('owner', { nodeValue: !!typeObj.owner }, typeNode); - }); - }); - }); - break; - - case 'android': - node.setAttribute('xmlns:android', 'http://schemas.android.com/apk/res/android'); - - if (value.manifest) { - node.appendChild(dom.createTextNode('\r\n' + new Array(3).join('\t'))); - const opts = defaultDOMParserArgs; - opts.xmlns = { android: 'http://schemas.android.com/apk/res/android' }; - node.appendChild(new DOMParser(opts).parseFromString(value.manifest)); - } - - if (Object.prototype.hasOwnProperty.call(value, 'tool-api-level')) { - dom.create('tool-api-level', { nodeValue: value['tool-api-level'] }, node); - } - - if (Object.prototype.hasOwnProperty.call(value, 'abi')) { - dom.create('abi', { nodeValue: Array.isArray(value.abi) ? value.abi.join(',') : value.abi }, node); - } - - if (value.activities) { - dom.create('activities', null, node, function (node) { - Object.keys(value.activities).forEach(function (url) { - var attrs = {}; - Object.keys(value.activities[url]).forEach(function (attr) { - attr !== 'classname' && (attrs[attr] = value.activities[url][attr]); - }); - dom.create('activity', attrs, node); - }); - }); - } - - if (value.services) { - dom.create('services', null, node, function (node) { - Object.keys(value.services).forEach(function (url) { - var attrs = {}; - Object.keys(value.services[url]).forEach(function (attr) { - attr !== 'classname' && (attrs[attr] = value.services[url][attr]); - }); - dom.create('service', attrs, node); - }); - }); - } - break; - - case 'webpack': - if (value.type) { - dom.create('type', { nodeValue: value.type }, node); - } - if (Array.isArray(value.transpileDependencies)) { - dom.create('transpile-dependencies', null, node, depsNode => { - for (const dep of value.transpileDependencies) { - dom.create('dep', { nodeValue: dep }, depsNode); - } - }); - } - break; - - case 'modules': - value.forEach(function (mod) { - dom.create('module', { - platform: mod.platform, - version: mod.version ? version.format(mod.version, 2) : null, - 'deploy-type': mod.deployType || null, - nodeValue: mod.id - }, node); - }); - break; - - case 'plugins': - value.forEach(function (plugin) { - dom.create('plugin', { - version: version.format(plugin.version, 2), - nodeValue: plugin.id - }, node); - }); - break; - - default: - node.appendChild(dom.createTextNode(value)); - return; - } - - node.appendChild(dom.createTextNode('\r\n' + new Array(2).join('\t'))); -} - -function toJS(obj, doc, targetPlatform) { - var node = doc.firstChild; - while (node) { - if (node.nodeType === xml.ELEMENT_NODE) { - switch (node.tagName) { - case 'property': - var name = xml.getAttr(node, 'name'), - type = xml.getAttr(node, 'type') || 'string', - value = xml.getValue(node); - if (name) { - obj.properties || (obj.properties = {}); - obj.properties[name] = { - type: type, - value: type === 'bool' ? !!value - : type === 'int' ? (parseInt(value) || 0) - : type === 'double' ? (parseFloat(value) || 0) - : '' + value - }; - } - break; - - case 'deployment-targets': - var targets = obj['deployment-targets'] = {}; - xml.forEachElement(node, function (elem) { - var dev = xml.getAttr(elem, 'device'); - dev && (targets[dev] = xml.getValue(elem)); - }); - break; - - case 'code-processor': - var codeProcessor = obj['code-processor'] = {}; - xml.forEachElement(node, function (elem) { - switch (elem.tagName) { - case 'plugins': - codeProcessor.plugins = []; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'plugin') { - codeProcessor.plugins.push(xml.getValue(elem)); - } - }); - break; - case 'options': - codeProcessor.options = {}; - xml.forEachElement(elem, function (elem) { - codeProcessor.options[elem.tagName] = xml.getValue(elem); - }); - break; - default: - codeProcessor[elem.tagName] = xml.getValue(elem); - } - }); - break; - - case 'ios': - var ios = obj.ios = {}; - xml.forEachElement(node, function (elem) { - switch (elem.tagName) { - case 'exclude-dir-from-asset-catalog': - case 'enable-launch-screen-storyboard': - case 'enablecoverage': - case 'enablemdfind': - case 'default-background-color': - case 'team-id': - case 'use-jscore-framework': - case 'run-on-main-thread': - case 'use-autolayout': - case 'use-app-thinning': - case 'use-new-build-system': - case 'log-server-port': - ios[elem.tagName] = xml.getValue(elem); - break; - - case 'min-ios-ver': - if (elem.firstChild) { - ios['min-ios-ver'] = parseFloat(elem.firstChild.data) || 0; - } - break; - - case 'capabilities': - ios.capabilities = {}; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'app-groups') { - var appGroups = ios.capabilities[elem.tagName] = []; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'group') { - var group = xml.getValue(elem); - group && appGroups.push(group); - } - }); - } - }); - break; - - case 'entitlements': - ios.entitlements = {}; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'dict') { - const pl = new plist().parse('' + elem.toString() + ''); - Object.keys(pl).forEach(prop => ios.entitlements[prop] = pl[prop]); - } - }); - break; - - case 'plist': - ios.plist = {}; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'dict') { - var pl = new plist().parse('' + elem.toString() + ''); - Object.keys(pl).forEach(function (prop) { - if (!/^CFBundle(DisplayName|Executable|IconFile|Identifier|InfoDictionaryVersion|Name|PackageType|Signature)|LSRequiresIPhoneOS$/.test(prop)) { - ios.plist[prop] = pl[prop]; - } - }); - } - }); - break; - - case 'extensions': - var extensions = ios.extensions = []; - xml.forEachElement(elem, function (elem) { - if (elem.tagName !== 'extension') { - return; - } - - var ext = { - projectPath: elem.getAttribute('projectPath') || null, - targets: [] - }; - extensions.push(ext); - - xml.forEachElement(elem, function (elem) { - if (elem.tagName !== 'target') { - return; - } - - var target = { - name: elem.getAttribute('name'), - ppUUIDs: {} - }; - ext.targets.push(target); - - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'provisioning-profiles') { - xml.forEachElement(elem, function (elem) { - target.ppUUIDs[elem.tagName] = xml.getValue(elem); - }); - } - }); - }); - }); - break; - } - }); - break; - - case 'iphone': - var iphone = obj.iphone = {}, - dev; - xml.forEachElement(node, function (elem) { - switch (elem.tagName) { - case 'orientations': - iphone.orientations || (iphone.orientations = {}); - if (dev = xml.getAttr(elem, 'device')) { - iphone.orientations[dev] || (iphone.orientations[dev] = []); - xml.forEachElement(elem, function (elem) { - iphone.orientations[dev].push(xml.getValue(elem)); - }); - } - break; - - case 'background': - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'mode') { - iphone.backgroundModes || (iphone.backgroundModes = []); - iphone.backgroundModes.push(xml.getValue(elem)); - } - }); - break; - - case 'requires': - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'feature') { - iphone.requiredFeatures || (iphone.requiredFeatures = []); - iphone.requiredFeatures.push(xml.getValue(elem)); - } - }); - break; - - case 'types': - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'type') { - iphone.types || (iphone.types = []); - var type = { - name: '', - icon: '', - uti: [], - owner: false - }; - xml.forEachElement(elem, function (elem) { - var v = xml.getValue(elem); - type[elem.tagName] = elem.tagName === 'uti' ? v.split(',').map(s => s.trim()) : v; - }); - iphone.types.push(type); - } - }); - break; - } - }); - break; - - case 'android': - var android = obj.android = {}, - formatUrl = (url) => { - return appc.string.capitalize(url.replace(/^app:\/\//, '').replace(/\.js$/, '').replace(/\//g, '_')).replace(/[/ .$&@]/g, '_'); - }; - - xml.forEachElement(node, function (elem) { - switch (elem.tagName) { - case 'manifest': - // the tag is an XML document and we're just gonna - // defer the parsing to whoever wants its data - // Strip the 'android' XML namespace on the uses-sdk tag! It's already defined at tag level! - android.manifest = elem.toString().replace(/ xmlns:android="http:\/\/schemas\.android\.com\/apk\/res\/android"/, ''); - break; - - case 'abi': - android[elem.tagName] = xml.getValue(elem).split(',').map(s => s.trim()); - break; - - case 'tool-api-level': - android[elem.tagName] = xml.getValue(elem); - break; - - case 'activities': - case 'services': - var type = elem.tagName, - dest = android[type] = {}; - - xml.forEachElement(elem, function (elem) { - if ((type === 'activities' && elem.tagName === 'activity') || (type === 'services' && elem.tagName === 'service')) { - var url = xml.getAttr(elem, 'url') || xml.getValue(elem) || ''; - if (url) { - var a = dest[url] = {}; - xml.forEachAttr(elem, function (attr) { - a[attr.name] = xml.parse(attr.value); - }); - a['classname'] = formatUrl(url) + (type === 'activities' ? 'Activity' : 'Service'); - if (type === 'services') { - a['type'] = xml.getAttr(elem, 'type') || 'standard'; - } - a['url'] = url; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'intent-filter') { - var intentFilter = null; - xml.forEachElement(elem, function (elem) { - if (elem.tagName === 'action' || elem.tagName === 'category' || elem.tagName === 'data') { - intentFilter || (intentFilter = {}); - intentFilter[elem.tagName] || (intentFilter[elem.tagName] = []); - if (elem.tagName === 'data') { - var a = {}; - xml.forEachAttr(elem, function (attr) { - a[attr.name.replace(/^android:/, '')] = xml.parse(attr.value); - }); - intentFilter[elem.tagName].push(a); - } else { - intentFilter[elem.tagName].push(xml.getAttr(elem, 'android:name')); - } - } - }); - if (intentFilter) { - a['intent-filter'] || (a['intent-filter'] = []); - a['intent-filter'].push(intentFilter); - } - } else if (elem.tagName === 'meta-data') { - var obj = {}; - xml.forEachAttr(elem, function (attr) { - obj[attr.name.replace(/^android:/, '')] = xml.parse(attr.value); - }); - if (obj.name) { - a['meta-data'] || (a['meta-data'] = {}); - a['meta-data'][obj.name] = obj; - } - } - }); - } - } - }); - break; - } - }); - break; - - case 'modules': - var modules = obj.modules = []; - xml.forEachElement(node, function (elem) { - var opts = { - id: xml.getValue(elem), - platform: xml.getAttr(elem, 'platform') - }, - version = elem.getAttribute('version'), - deployType = xml.getAttr(elem, 'deploy-type'); - version && (opts.version = version); - deployType && (opts.deployType = deployType); - modules.push(opts); - }); - break; - - case 'plugins': - var plugins = obj.plugins = []; - xml.forEachElement(node, function (elem) { - var opts = { - id: xml.getValue(elem) - }, - version = elem.getAttribute('version'); - version && (opts.version = version); - plugins.push(opts); - }); - break; - - case 'version': - obj[node.tagName] = node.firstChild && node.firstChild.data.replace(/\n/g, '').trim() || ''; - break; - - case 'id': - if ((targetPlatform && xml.getAttr(node, 'platform') === targetPlatform) || obj[node.tagName] === undefined) { - obj[node.tagName] = '' + xml.getValue(node); - if (typeof obj[node.tagName] === 'string') { - obj[node.tagName] = obj[node.tagName].replace(/\n/g, ''); - } - } - break; - - case 'name': - case 'guid': - case 'icon': - // need to strip out line returns which shouldn't be there in the first place - obj[node.tagName] = '' + xml.getValue(node); - if (typeof obj[node.tagName] === 'string') { - obj[node.tagName] = obj[node.tagName].replace(/\n/g, ''); - } - break; - - case 'webpack': - const webpack = obj.webpack = {}; - xml.forEachElement(node, elem => { - switch (elem.tagName) { - case 'type': { - webpack[elem.tagName] = xml.getValue(elem); - break; - } - case 'transpile-dependencies': { - const transpileDependencies = webpack.transpileDependencies = []; - xml.forEachElement(elem, dep => { - transpileDependencies.push(xml.getValue(dep)); - }); - break; - } - } - }); - break; - - default: - obj[node.tagName] = xml.getValue(node); - } - } - node = node.nextSibling; - } -} - -function tiapp(filename, platform) { - - Object.defineProperty(this, 'load', { - value: function (file) { - if (!fs.existsSync(file)) { - throw new Error(__('tiapp.xml file does not exist')); - } - toJS(this, (new DOMParser(defaultDOMParserArgs).parseFromString(fs.readFileSync(file).toString(), 'text/xml')).documentElement, platform); - return this; - } - }); - - Object.defineProperty(this, 'parse', { - value: function (str) { - toJS(this, (new DOMParser(defaultDOMParserArgs).parseFromString(str, 'text/xml')).documentElement, platform); - return this; - } - }); - - Object.defineProperty(this, 'toString', { - value: function (fmt) { - if (fmt === 'xml') { - var dom = new DOMParser(defaultDOMParserArgs).parseFromString('', 'text/xml'); - - dom.create = function (tag, attrs, parent, callback) { - var node = dom.createElement(tag), - i = 0, - p = parent; - - attrs && Object.keys(attrs).forEach(function (attr) { - if (attr === 'nodeValue') { - node.appendChild(dom.createTextNode('' + attrs[attr])); - } else { - attrs[attr] != undefined && node.setAttribute(attr, '' + attrs[attr]); // eslint-disable-line eqeqeq - } - }); - - if (p) { - while (p.parentNode) { - i++; - p = p.parentNode; - } - parent.appendChild(dom.createTextNode('\r\n' + new Array(i + 1).join('\t'))); - } - - parent && parent.appendChild(node); - if (callback) { - callback(node); - node.appendChild(dom.createTextNode('\r\n' + new Array(i + 1).join('\t'))); - } - return node; - }; - - Object.keys(this).forEach(function (key) { - toXml(dom, dom.documentElement, key, this[key]); - }, this); - - dom.documentElement.appendChild(dom.createTextNode('\r\n')); - - var xml = dom.documentElement.toString(); - return '\n' + xml.replace(/uses-sdk xmlns:android="http:\/\/schemas\.android\.com\/apk\/res\/android"/, 'uses-sdk'); - } else if (fmt === 'pretty-json') { - return JSON.stringify(this, null, '\t'); - } else if (fmt === 'json') { - return JSON.stringify(this); - } - return Object.prototype.toString.call(this); - } - }); - - Object.defineProperty(this, 'save', { - value: function (file) { - if (file) { - fs.ensureDirSync(path.dirname(file)); - fs.writeFileSync(file, this.toString('xml')); - } - return this; - } - }); - - filename && this.load(filename); -} diff --git a/lib/titanium.js b/lib/titanium.js index 95179a58..cfc015f2 100644 --- a/lib/titanium.js +++ b/lib/titanium.js @@ -1,141 +1,116 @@ -/** - * Titanium SDK Library for Node.js - * Copyright (c) 2012-2013 by Appcelerator, Inc. All Rights Reserved. - * Please see the LICENSE file for information about licensing. - */ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const async = require('async'); -const spawn = require('child_process').spawn; // eslint-disable-line security/detect-child-process -const uuid = require('node-uuid'); -const appc = require('node-appc'); -const __ = appc.i18n(__dirname).__; -const afs = appc.fs; -const version = appc.version; -const manifest = appc.pkginfo.manifest(module); +import fs from 'node:fs'; +import path from 'node:path'; +import { spawn } from 'node:child_process'; +import { tiappxml } from './tiappxml'; +import { find as findTiPlugins } from './tiplugin.js'; +import * as version from './version.js'; +import { fileURLToPath } from 'node:url'; +import { loadManifestJson } from './util/load-manifest-json.js'; + +export const manifest = loadManifestJson(path.dirname(fileURLToPath(import.meta.url))); const platformAliases = { // add additional aliases here for new platforms ipad: 'iphone', ios: 'iphone' }; -exports.i18n = require('./i18n'); -exports.tiappxml = require('./tiappxml'); +import * as i18n from './i18n.js'; +import { suggest } from './util/suggest.js'; +export { i18n }; +export { tiappxml }; -exports.manifest = manifest; -exports.platforms = [].concat(manifest.platforms); -exports.targetPlatforms = (manifest.platforms || []).map(p => { +export const platforms = [...manifest.platforms]; +export const targetPlatforms = (manifest.platforms || []).map(p => { return p === 'iphone' ? 'ios' : p; }).sort(); -exports.availablePlatforms = (manifest.platforms || []).sort(); -exports.availablePlatformsNames = (function (platforms) { - Object.keys(platformAliases).forEach(function (alias) { - if (platforms.indexOf(platformAliases[alias]) !== -1) { +export const availablePlatforms = (manifest.platforms || []).sort(); + +export const availablePlatformsNames = (platforms => { + for (const alias of Object.keys(platformAliases)) { + if (platforms.includes(platformAliases[alias])) { platforms.push(alias); } - }); + } return platforms.sort(); -}(manifest.platforms || [])); -exports.allPlatformNames = [ 'android', 'ios', 'iphone', 'ipad' ]; +})(manifest.platforms || []); -exports.commonOptions = function (logger, config) { - return { - 'log-level': { - abbr: 'l', - callback: function (value) { - Object.prototype.hasOwnProperty.call(logger.levels, value) && logger.setLevel(value); - }, - desc: __('minimum logging level'), - default: config.cli.logLevel || 'trace', - hint: __('level'), - values: logger.getLevels() - } - }; -}; - -exports.platformOptions = function (logger, config, cli, commandName, finished) { - var result = {}, - targetPlatform = !cli.argv.help && (cli.argv.platform || cli.argv.p); +export async function platformOptions(logger, config, cli, commandName) { + const result = {}; + let targetPlatform = !cli.argv.help && (cli.argv.platform || cli.argv.p); if (!commandName) { - finished(result); - return; + return result; } function set(obj, title, platform) { // add the platform and title to the options and flags - [ 'options', 'flags' ].forEach(function (type) { + for (const type of [ 'options', 'flags' ]) { if (obj && obj[type]) { - result[platform] || (result[platform] = { - platform: platform, - title: title || platform - }); + if (!result[platform]) { + result[platform] = { + platform: platform, + title: title || platform + }; + } result[platform][type] = obj[type]; } - }); + } } // translate the platform name targetPlatform = platformAliases[targetPlatform] || targetPlatform; // for each platform, fetch their specific flags/options - async.parallel(manifest.platforms.map(function (platform) { - return function (callback) { - - // only configure target platform - if (targetPlatform && platform !== targetPlatform) { - return callback(); - } + return await Promise.all(manifest.platforms.map(async (platform) => { + // only configure target platform + if (targetPlatform && platform !== targetPlatform) { + return; + } - var platformDir = path.join(path.dirname(module.filename), '..', '..', '..', platform), - platformCommand = path.join(platformDir, 'cli', 'commands', '_' + commandName + '.js'), - command, - conf, - title; + const platformDir = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', platform); + const platformCommand = path.join(platformDir, 'cli', 'commands', `_${commandName}.js`); + let command, conf, title; - if (!fs.existsSync(platformCommand)) { - return callback(); - } + if (!fs.existsSync(platformCommand)) { + return; + } - command = require(platformCommand); - if (!command || !command.config) { - return callback(); - } + command = (await import(platformCommand)).default; + if (!command || !command.config) { + return; + } - // try to get the platform specific configuration - conf = command.config(logger, config, cli); + // try to get the platform specific configuration + conf = command.config(logger, config, cli); - try { - // try to read a title from the platform's package.json - title = JSON.parse(fs.readFileSync(path.join(platformDir, 'package.json'))).title; - } catch (e) {} + try { + // try to read a title from the platform's package.json + title = JSON.parse(fs.readFileSync(path.join(platformDir, 'package.json'))).title; + } catch {} + await new Promise((resolve) => { if (typeof conf === 'function') { // async callback - conf(function (obj) { + conf((obj) => { set(obj, title, platform); - callback(); + resolve(); }); return; } set(conf, title, platform); - callback(); - }; - }), function () { - finished(result); - }); -}; + resolve(); + }); + })); +} -exports.validateProjectDir = function (logger, cli, argv, name) { +export function validateProjectDir(logger, cli, argv, name) { const dir = argv[name] || (process.env.SOURCE_ROOT ? path.join(process.env.SOURCE_ROOT, '..', '..') : '.'); - let projectDir = argv[name] = appc.fs.resolvePath(dir); + let projectDir = argv[name] = expand(dir); if (!fs.existsSync(projectDir)) { logger.banner(); - logger.error(__('Project directory does not exist') + '\n'); + logger.error('Project directory does not exist\n'); process.exit(1); } @@ -147,204 +122,161 @@ exports.validateProjectDir = function (logger, cli, argv, name) { if (tiapp.split(path.sep).length === 2) { logger.banner(); - logger.error(__('Invalid project directory "%s"', dir) + '\n'); - dir === '.' && logger.log(__('Use the %s property to specify the project\'s directory', '--project-dir'.cyan) + '\n'); + logger.error(`Invalid project directory "${dir}"\n`); + if (dir === '.') { + logger.log('Use the --project-dir property to specify the project\'s directory\n'); + } process.exit(1); } // load the tiapp.xml cli.tiapp = new exports.tiappxml(path.join(projectDir, 'tiapp.xml')); -}; +} -exports.validateTiappXml = function (logger, config, tiapp) { +export function validateTiappXml(logger, config, tiapp) { if (!tiapp.id) { - logger.error(__('tiapp.xml is missing the element')); - logger.error(__('The app id must consist of letters, numbers, and underscores.')); - logger.error(__('Note: Android does not allow dashes and iOS does not allow underscores.')); - logger.error(__('The first character must be a letter or underscore.')); - logger.error(__('Usually the app id is your company\'s reversed Internet domain name. (i.e. com.example.myapp)') + '\n'); + logger.error('tiapp.xml is missing the element'); + logger.error('The app id must consist of letters, numbers, and underscores.'); + logger.error('Note: Android does not allow dashes and iOS does not allow underscores.'); + logger.error('The first character must be a letter or underscore.'); + logger.error('Usually the app id is your company\'s reversed Internet domain name. (i.e. com.example.myapp)\n'); process.exit(1); } if (!tiapp.name) { - logger.error(__('tiapp.xml is missing the element')); - logger.error(__('The project name must consist of letters, numbers, dashes, and underscores.')); - logger.error(__('The first character must be a letter.') + '\n'); + logger.error('tiapp.xml is missing the element'); + logger.error('The project name must consist of letters, numbers, dashes, and underscores.'); + logger.error('The first character must be a letter.\n'); process.exit(1); } if (!tiapp.guid) { - logger.error(__('tiapp.xml is missing the element')); - logger.error(__('The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.') + '\n'); - logger.log(__('If you need a new guid, below are 5 freshly generated new ones that you can choose from:')); + logger.error('tiapp.xml is missing the element'); + logger.error('The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.\n'); + logger.log('If you need a new guid, below are 5 freshly generated new ones that you can choose from:'); for (let i = 0; i < 5; i++) { - logger.log(' ' + uuid.v4().cyan); + logger.log(' ' + uuid.v4()); } logger.log(); process.exit(1); } if (!/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(tiapp.guid)) { - logger.error(__('tiapp.xml contains an invalid guid "%s"', tiapp.guid)); - logger.error(__('The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.') + '\n'); - logger.log(__('If you need a new guid, below are 5 freshly generated new ones that you can choose from:')); + logger.error(`tiapp.xml contains an invalid guid "${tiapp.guid}"`); + logger.error('The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.\n'); + logger.log('If you need a new guid, below are 5 freshly generated new ones that you can choose from:'); for (let i = 0; i < 5; i++) { - logger.log(' ' + uuid.v4().cyan); + logger.log(' ' + uuid.v4()); } logger.log(); process.exit(1); } - tiapp.version || (tiapp.version = '1.0'); + if (!tiapp.version) { + tiapp.version = '1.0'; + } if (!config.get('app.skipVersionValidation') && !tiapp.properties['ti.skipVersionValidation']) { if (!/^\d+(\.\d+(\.\d+(\..+)?)?)?$/.test(tiapp.version)) { - logger.error(__('tiapp.xml contains an invalid version "%s"', tiapp.version)); - logger.error(__('The version must consist of three positive integers in the format "X.Y.Z".') + '\n'); + logger.error(`tiapp.xml contains an invalid version "${tiapp.version}"`); + logger.error('The version must consist of three positive integers in the format "X.Y.Z".\n'); process.exit(1); } if (('' + tiapp.version).charAt(0) == '0') { // eslint-disable-line eqeqeq - logger.warn(__('tiapp.xml contains an invalid version "%s"', tiapp.version)); - logger.warn(__('The app version major number must be greater than zero.')); + logger.warn(`tiapp.xml contains an invalid version "${tiapp.version}"`); + logger.warn('The app version major number must be greater than zero.'); } } -}; +} -exports.validAppId = function (id) { - const words = { - abstract: 1, - assert: 1, - boolean: 1, - break: 1, - byte: 1, - case: 1, - catch: 1, - char: 1, - class: 1, - const: 1, - continue: 1, - default: 1, - do: 1, - double: 1, - else: 1, - enum: 1, - extends: 1, - false: 1, - final: 1, - finally: 1, - float: 1, - for: 1, - goto: 1, - if: 1, - implements: 1, - import: 1, - instanceof: 1, - int: 1, - interface: 1, - long: 1, - native: 1, - new: 1, - null: 1, - package: 1, - private: 1, - protected: 1, - public: 1, - return: 1, - short: 1, - static: 1, - strictfp: 1, - super: 1, - switch: 1, - synchronized: 1, - this: 1, - throw: 1, - throws: 1, - transient: 1, - true: 1, - try: 1, - void: 1, - volatile: 1, - while: 1 - }, - parts = id.split('.'), - l = parts.length; - - for (let i = 0; i < l; i++) { - if (words[parts[i]]) { - return false; - } - } - - return true; -}; - -exports.loadPlugins = function (logger, config, cli, projectDir, finished, silent, compact) { - var searchPaths = { - project: [ path.join(projectDir, 'plugins') ], - config: [], - global: [] - }, - confPaths = config.get('paths.plugins'), - defaultInstallLocation = cli.env.installPath, - sdkLocations = cli.env.os.sdkPaths.map(function (p) { return afs.resolvePath(p); }); +export function loadPlugins(logger, config, cli, projectDir, finished, silent, compact) { + const searchPaths = { + project: [ path.join(projectDir, 'plugins') ], + config: [], + global: [] + }; + let confPaths = config.get('paths.plugins'); + const defaultInstallLocation = cli.env.installPath; + const sdkLocations = cli.env.os.sdkPaths.map(p => expand(p)); // set our paths from the config file - Array.isArray(confPaths) || (confPaths = [ confPaths ]); - confPaths.forEach(function (p) { - p && fs.existsSync(p = afs.resolvePath(p)) && searchPaths.project.indexOf(p) === -1 && searchPaths.config.indexOf(p) === -1 && (searchPaths.config.push(p)); - }); + if (!Array.isArray(confPaths)) { + confPaths = [ confPaths ]; + } + for (let p of confPaths) { + if (p) { + p = expand(p); + if (fs.existsSync(p) && !searchPaths.project.includes(p) && !searchPaths.config.includes(p)) { + searchPaths.config.push(p); + } + } + } // add any plugins from various sdk locations - sdkLocations.indexOf(defaultInstallLocation) === -1 && sdkLocations.push(defaultInstallLocation); - cli.sdk && sdkLocations.push(afs.resolvePath(cli.sdk.path, '..', '..', '..')); - sdkLocations.forEach(function (p) { - fs.existsSync(p = afs.resolvePath(p, 'plugins')) && searchPaths.project.indexOf(p) === -1 && searchPaths.config.indexOf(p) === -1 && searchPaths.global.indexOf(p) === -1 && (searchPaths.global.push(p)); - }); + if (!sdkLocations.includes(defaultInstallLocation)) { + sdkLocations.push(defaultInstallLocation); + } + if (cli.sdk) { + sdkLocations.push(expand(cli.sdk.path, '..', '..', '..')); + } + for (let p of sdkLocations) { + p = expand(p, 'plugins'); + if (fs.existsSync(p) && !searchPaths.project.includes(p) && !searchPaths.config.includes(p) && !searchPaths.global.includes(p)) { + searchPaths.global.push(p); + } + } // find all hooks for active plugins - appc.tiplugin.find(cli.tiapp.plugins, searchPaths, config, logger, function (plugins) { + findTiPlugins(cli.tiapp.plugins, searchPaths, config, logger, (plugins) => { if (plugins.missing.length) { if (logger) { - logger.error(__('Could not find all required Titanium plugins:')); - plugins.missing.forEach(m => logger.error(' id: ' + m.id + '\t version: ' + m.version)); + logger.error('Could not find all required Titanium plugins:'); + for (const m of plugins.missing) { + logger.error(` id: ${m.id}\t version: ${m.version}`); + } logger.log(); } process.exit(1); } if (plugins.found.length) { - plugins.found.forEach(plugin => cli.scanHooks(afs.resolvePath(plugin.pluginPath, 'hooks'))); + for (const plugin of plugins.found) { + cli.scanHooks(expand(plugin.pluginPath, 'hooks')); + } } else { - logger && logger.debug(__('No project level plugins to load')); + logger?.debug('No project level plugins to load'); } - silent || cli.emit('cli:check-plugins', { compact: compact === undefined ? true : compact }); + if (!silent) { + cli.emit('cli:check-plugins', { compact: compact === undefined ? true : compact }); + } finished(); }); -}; +} -exports.loadModuleManifest = function (logger, manifestFile) { +export function loadModuleManifest(logger, manifestFile) { if (!fs.existsSync(manifestFile)) { - logger.error(__('Missing %s', manifestFile)); + logger.error(`Missing ${manifestFile}`); logger.log(); process.exit(1); } const re = /^(\S+)\s*:\s*(.*)$/; const manifest = {}; - fs.readFileSync(manifestFile).toString().split(/\r?\n/).forEach(function (line) { + const lines = fs.readFileSync(manifestFile).toString().split(/\r?\n/); + for (const line of lines) { const match = line.match(re); if (match) { manifest[match[1].trim()] = match[2].trim(); } - }); + } return manifest; -}; +} -exports.validateModuleManifest = function (logger, cli, manifest) { +export function validateModuleManifest(logger, cli, manifest) { const requiredModuleKeys = [ 'name', 'version', @@ -359,30 +291,29 @@ exports.validateModuleManifest = function (logger, cli, manifest) { ]; // check if all the required module keys are in the list - requiredModuleKeys.forEach(function (key) { + for (const key of requiredModuleKeys) { if (!manifest[key]) { - logger.error(__('Missing required manifest key "%s"', key)); + logger.error(`Missing required manifest key "${key}"`); logger.log(); process.exit(1); } - }); + } if (cli.argv.platform !== exports.resolvePlatform(manifest.platform)) { - logger.error(__('Unable to find "%s" module', cli.argv.platform)); + logger.error(`Unable to find "${cli.argv.platform}" module`); logger.log(); process.exit(1); } -}; +} -exports.validateCorrectSDK = function (logger, config, cli, commandName) { +export function validateCorrectSDK(logger, config, cli, commandName) { // tiapp.xml should exist by the time we get here - var argv = cli.argv, - tiapp = cli.tiapp, - sdkName = tiapp['sdk-version'], - selectedSdk = cli.sdk && cli.sdk.name || manifest.version; + const { argv, tiapp } = cli; + let sdkName = tiapp['sdk-version']; + const selectedSdk = cli.sdk?.name || manifest.version; if (!sdkName) { - sdkName = tiapp['sdk-version'] = cli.sdk && cli.sdk.name || Object.keys(cli.env.sdks).sort().pop(); + sdkName = tiapp['sdk-version'] = cli.sdk?.name || Object.keys(cli.env.sdks).sort().pop(); } if (argv.legacy !== true && (!sdkName || sdkName === selectedSdk)) { @@ -392,53 +323,45 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { // check the project's preferred sdk is even installed if (sdkName === '__global__' || !cli.env.sdks[sdkName]) { logger.banner(); - logger.error(__('Unable to compile project because the \'sdk-version\' in the tiapp.xml is not installed') + '\n'); - logger.log(__('The project\'s %s is currently set to %s, which is not installed.', 'sdk-version'.cyan, sdkName.cyan) + '\n'); - logger.log(__('Update the %s in the tiapp.xml to one of the installed Titaniums SDKs:', 'sdk-version'.cyan)); - Object.keys(cli.env.sdks).sort().forEach(function (ver) { + logger.error('Unable to compile project because the in the tiapp.xml is not installed\n'); + logger.log(`The project's is currently set to '${sdkName}', which is not installed.\n`); + logger.log(`Update the in the tiapp.xml to one of the installed Titaniums SDKs:`); + const sortedSdks = Object.keys(cli.env.sdks).sort(); + for (const ver of sortedSdks) { if (ver !== '__global__') { - logger.log(' ' + ver.cyan); + logger.log(' ' + ver); } - }); - logger.log(__('or run \'%s\' to download and install Titanium SDK %s', ('titanium sdk install ' + sdkName).cyan, sdkName) + '\n'); - process.exit(1); - } - - var sdkVersion = cli.env.sdks[sdkName].manifest && cli.env.sdks[sdkName].manifest.version || sdkName; - if (version.gte(sdkVersion, '3.0.0') && version.lte(sdkVersion, '3.0.2') && version.gte(process.version, '0.9.0')) { - logger.banner(); - logger.error(__('Unable to compile project using Titanium SDK %s with Node.js %s', sdkName, process.version) + '\n'); - logger.log(__('Titanium SDK %s requires Node.js v0.8. Node.js v0.10 and newer will not work.', sdkName.cyan) + '\n'); - logger.log(__('Either update your application to Titanium SDK %s or newer or download Node.js %s from %s.', '3.1.0.GA'.cyan, 'v0.8'.cyan, 'http://nodejs.org/dist/'.cyan) + '\n'); + } + logger.log(`or run 'titanium sdk install ${sdkName}' to download and install Titanium SDK ${sdkName}\n`); process.exit(1); } // fork or die if (config.cli.failOnWrongSDK) { logger.banner(); - logger.error(__('Unable to compile a %s project with Titanium SDK %s', sdkName, selectedSdk)); - logger.error(__('To build this application, set the in the tiapp.xml to the current Titaniums SDK: %s', selectedSdk) + '\n'); + logger.error(`Unable to compile a ${sdkName} project with Titanium SDK ${selectedSdk}`); + logger.error(`To build this application, set the in the tiapp.xml to the current Titaniums SDK: ${selectedSdk}\n`); process.exit(1); } - var args = argv.$_, - p = args.indexOf('--sdk'), - platform = exports.resolvePlatform(argv.platform), - cmd = [], - cmdSafe = [], - cmdRoot, - hideBanner = false, - delayCmd = false; - - function cmdAdd() { - for (var i = 0; i < arguments.length; i++) { + const args = argv.$_; + const p = args.indexOf('--sdk'); + const platform = exports.resolvePlatform(argv.platform); + const cmd = []; + const cmdSafe = []; + let cmdRoot; + let hideBanner = false; + let delayCmd = false; + + function cmdAdd(...args) { + for (let i = 0; i < args.length; i++) { cmd.push(arguments[i]); cmdSafe.push(arguments[i]); } } function cmdAddSecret(_param) { - for (var i = 0; i < arguments.length; i++) { + for (let i = 0; i < arguments.length; i++) { cmd.push(arguments[i]); cmdSafe.push('*******'); } @@ -449,9 +372,11 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { } if (!argv.legacy) { - logger.info(__('tiapp.xml set to %s, but current Titanium SDK set to %s', sdkName.cyan, selectedSdk.cyan)); + logger.info(`tiapp.xml set to ${sdkName}, but current Titanium SDK set to ${selectedSdk}`); } + const sdkVersion = cli.env.sdks[sdkName].manifest && cli.env.sdks[sdkName].manifest.version || sdkName; + if (argv.legacy || version.lt(sdkVersion, '2.2.0')) { // technically, there is no 2.2, it was released as 3.0 // in 3.2, we renamed --password to --store-password as to not conflict with the // authentication --password option @@ -461,7 +386,7 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { cmdRoot = 'python'; - var builderPy = path.join(path.resolve(cli.env.sdks[sdkName].path), platform, 'builder.py'); + const builderPy = path.join(expand(cli.env.sdks[sdkName].path), platform, 'builder.py'); cmdAdd(builderPy); switch (platform) { @@ -495,11 +420,11 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { } else { if (argv.target === 'emulator') { if (!argv['avd-id']) { - logger.error(__('Missing required option "%s"', '--avd-id') + '\n'); + logger.error(`Missing required option "${'--avd-id'}"\n`); process.exit(1); } if (!argv['avd-skin']) { - logger.error(__('Missing required option "%s"', '--avd-skin') + '\n'); + logger.error(`Missing required option "${'--avd-skin'}"\n`); process.exit(1); } } @@ -510,9 +435,11 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { delayCmd = true; // launch the emulator - var emuArgs = [ builderPy, 'emulator', tiapp.name, argv['android-sdk'], argv['project-dir'], tiapp.id, argv['avd-id'], argv['avd-skin'] ]; - argv['avd-abi'] && emuArgs.push(argv['avd-abi']); - logger.info(__('Launching Android emulator: %s', ('"' + cmdRoot + '" "' + emuArgs.join('" "') + '"').cyan)); + const emuArgs = [ builderPy, 'emulator', tiapp.name, argv['android-sdk'], argv['project-dir'], tiapp.id, argv['avd-id'], argv['avd-skin'] ]; + if (argv['avd-abi']) { + emuArgs.push(argv['avd-abi']); + } + logger.info(`Launching Android emulator: "${cmdRoot}" "${emuArgs.join('" "')}"`); spawn(cmdRoot, emuArgs, { detached: true, stdio: 'ignore' @@ -558,10 +485,10 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { hideBanner = true; // If the titanium path has spaces, then we are trying to combine the paths and verify after they were split. - var titaniumPath = (function getTitaniumPath (params) { - var paramsArray = params.split(' '), - pathSegment, - prevPath = ''; + const titaniumPath = (function getTitaniumPath(params) { + const paramsArray = params.split(' '); + let pathSegment; + let prevPath = ''; while ((pathSegment = paramsArray.pop())) { if (fs.existsSync(pathSegment + prevPath)) { return pathSegment + prevPath; @@ -575,41 +502,45 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { cmdAdd(titaniumPath); cmdAdd(commandName, '--sdk', sdkName); - var flags = {}, - options = {}; + const flags = {}; + const options = {}; // mix the command and platform specific options together - [ cli.globalContext, cli.command, cli.command.platform ].forEach(function (ctx) { + for (const ctx of [ cli.globalContext, cli.command, cli.command.platform ]) { if (ctx && ctx.conf) { - ctx.conf.flags && appc.util.mix(flags, ctx.conf.flags); - ctx.conf.options && appc.util.mix(options, ctx.conf.options); + if (ctx.conf.flags) { + Object.assign(flags, ctx.conf.flags); + } + if (ctx.conf.options) { + Object.assign(options, ctx.conf.options); + } } - }); + } - Object.keys(flags).forEach(function (name) { - var def = Object.prototype.hasOwnProperty.call(flags[name], 'default') ? flags[name].default : false; + for (const name of Object.keys(flags)) { + const def = Object.prototype.hasOwnProperty.call(flags[name], 'default') ? flags[name].default : false; if (argv[name] !== undefined && def !== argv[name]) { - cmdAdd('--' + (argv[name] ? '' : 'no-') + name); + cmdAdd(`--${(argv[name] ? '' : 'no-')}${name}`); } - }); + } - Object.keys(options).forEach(function (name) { + for (const name of Object.keys(options)) { if (name !== 'sdk' && argv[name] !== undefined) { // in 3.2, we renamed --password to --store-password as to not conflict with the // authentication --password option - var arg = name; + let arg = name; if (argv.platform === 'android' && arg === 'store-password' && version.lt(sdkVersion, '3.2.0')) { arg = 'password'; } - cmdAdd('--' + arg); + cmdAdd(`--${arg}`); if (options[name].secret) { cmdAddSecret(argv[name]); } else { cmdAdd(argv[name]); } } - }); + } } // trim off the empty trailing args @@ -619,29 +550,33 @@ exports.validateCorrectSDK = function (logger, config, cli, commandName) { } if (argv.legacy) { - logger.info(__('Forking legacy SDK command: %s', (cmdRoot + ' "' + cmdSafe.join('" "') + '"').cyan) + '\n'); + logger.info(`Forking legacy SDK command: ${cmdRoot} "${cmdSafe.join('" "')}"\n`); } else { - logger.info(__('Forking correct SDK command: %s', ('"' + cmdRoot + '" "' + cmdSafe.join('" "') + '"').cyan) + '\n'); + logger.info(`Forking correct SDK command: "${cmdRoot}" "${cmdSafe.join('" "')}"\n`); } - hideBanner && cmd.push('--no-banner'); + if (hideBanner) { + cmd.push('--no-banner'); + } // when doing a legacy Android build (1.X or 2.X), then we delay the build to // allow the emulator to start because there is a bug where the builder.py // doesn't like to be run concurrently - setTimeout(function () { + setTimeout(() => { spawn(cmdRoot, cmd, { stdio: 'inherit' - }).on('exit', function (code, _signal) { - code && process.exit(code); + }).on('close', (code, _signal) => { + if (code) { + process.exit(code); + } }); }, delayCmd ? 1000 : 0); -}; +} -exports.validateAppJsExists = function (projectDir, logger, platformDirs) { +export function validateAppJsExists(projectDir, logger, platformDirs) { if (!fs.existsSync(path.join(projectDir, 'Resources'))) { - logger.error(__('"Resources" directory not found')); - logger.error(__('Ensure the "Resources" directory exists and contains an "app.js" file.') + '\n'); + logger.error('"Resources" directory not found'); + logger.error('Ensure the "Resources" directory exists and contains an "app.js" file.\n'); process.exit(1); } @@ -649,71 +584,76 @@ exports.validateAppJsExists = function (projectDir, logger, platformDirs) { path.join(projectDir, 'Resources', 'app.js') ]; - Array.isArray(platformDirs) || (platformDirs = [ platformDirs ]); - platformDirs.forEach(function (platformDir) { + if (!Array.isArray(platformDirs)) { + platformDirs = [ platformDirs ]; + } + for (const platformDir of platformDirs) { files.push(path.join(projectDir, 'Resources', platformDir, 'app.js')); - }); + } if (!files.some(file => fs.existsSync(file))) { - logger.error(__('"app.js" not found')); - logger.error(__('Ensure the "app.js" file exists in your project\'s "Resources" directory.') + '\n'); + logger.error('"app.js" not found'); + logger.error('Ensure the "app.js" file exists in your project\'s "Resources" directory.\n'); process.exit(1); } -}; +} -exports.validatePlatformOptions = function (logger, config, cli, commandName) { - const platform = exports.resolvePlatform(cli.argv.platform), - platformCommand = path.join(path.dirname(module.filename), '..', '..', '..', manifest.platforms[manifest.platforms.indexOf(platform)], 'cli', 'commands', '_' + commandName + '.js'); +export async function validatePlatformOptions(logger, config, cli, commandName) { + const platform = resolvePlatform(cli.argv.platform); + const platformCommand = path.join(path.dirname(import.meta.url), '..', '..', '..', manifest.platforms[manifest.platforms.indexOf(platform)], 'cli', 'commands', `_${commandName}.js`); if (fs.existsSync(platformCommand)) { - const command = require(platformCommand); + const command = await import(platformCommand); return command && typeof command.validate === 'function' ? command.validate(logger, config, cli) : null; } -}; +} -exports.scrubPlatforms = function (platforms) { - const scrubbed = {}, // distinct list of un-aliased platforms - original = {}, - bad = {}; +export function scrubPlatforms(platforms) { + const scrubbed = {}; + const original = {}; + const bad = {}; - platforms.toLowerCase().split(',').forEach(function (platform) { + const platformArray = platforms.toLowerCase().split(','); + for (const platform of platformArray) { const name = platformAliases[platform] || platform; // if name is falsey, then it's invalid anyways if (name) { - if (manifest.platforms.indexOf(name) === -1) { + if (!manifest.platforms.includes(name)) { bad[platform] = 1; } else { scrubbed[name] = 1; original[platform] = 1; } } - }); + } return { scrubbed: Object.keys(scrubbed).sort(), // distinct list of un-aliased platforms original: Object.keys(original).sort(), bad: Object.keys(bad).sort() }; -}; +} -exports.resolvePlatform = function (platform) { +export function resolvePlatform(platform) { return platformAliases[platform] || platform; -}; +} -exports.filterPlatforms = function (platform) { +export function filterPlatforms(platform) { platform = platformAliases[platform] || platform; - return exports.availablePlatformsNames.filter(name => name != platform); // eslint-disable-line eqeqeq -}; + return availablePlatformsNames.filter(name => name != platform); +} -exports.validatePlatform = function (logger, cli, name) { - const platform = name ? cli.argv[name] : cli.argv, - p = cli.argv[name] = platformAliases[platform] || platform; - if (!p || manifest.platforms.indexOf(p) === -1) { +export function validatePlatform(logger, cli, name) { + const platform = name ? cli.argv[name] : cli.argv; + const p = cli.argv[name] = platformAliases[platform] || platform; + if (!p || !manifest.platforms.includes(p)) { logger.banner(); - logger.error(__('Invalid platform "%s"', platform) + '\n'); - appc.string.suggest(platform, exports.targetPlatforms, logger.log); - logger.log(__('Available platforms for SDK version %s:', cli.sdk && cli.sdk.name || manifest.version)); - exports.targetPlatforms.forEach(p => logger.log(' ' + p.cyan)); + logger.error(`Invalid platform "${platform}"\n`); + suggest(platform, targetPlatforms, logger.log); + logger.log(`Available platforms for SDK version ${cli.sdk?.name || manifest.version}:`); + for (const p of targetPlatforms) { + logger.log(` ${p}`); + } logger.log(); process.exit(1); } -}; +} diff --git a/lib/util/resize-image.js b/lib/util/resize-image.js new file mode 100644 index 00000000..4e59132c --- /dev/null +++ b/lib/util/resize-image.js @@ -0,0 +1,67 @@ +import fs from 'node:fs'; +import { spawnSync } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * Takes a source image and resizes it to one or more images. + * + * @param {String} src - The path to the source image being resized. + * @param {Array|Object} dest - One or more destination objects consisting of the dest `file`, `width`, and `height`. + * @param {Object} [logger] - A logger object containing a `trace()` function. + */ +export async function resizeImage(src, dest, logger) { + if (!src) { + throw new Error('Missing source'); + } + if (!fs.existsSync(src)) { + throw new Error('Source "' + src + '" does not exist'); + } + if (!dest) { + throw new Error('Missing dest'); + } + + if (!Array.isArray(dest)) { + dest = [ dest ]; + } + + const cmd = [ + `java -jar "${path.resolve(__dirname, '..', 'tools', 'resizer', 'resizer.jar')}"`, + `"${src}"` + ]; + + for (const d of dest) { + if (!d || typeof d !== 'object') { + throw new Error('Invalid destination'); + } + if (!d.file) { + throw new Error('Missing destination file'); + } + + let w = d.width | 0; + let h = d.height | 0; + + if (!w && !h) { + throw new Error('Missing destination width and height'); + } else if (w && !h) { + h = w; + } else if (!w && h) { + w = h; + } + + cmd.push(`"${d.file}"`); + cmd.push(w); + cmd.push(h); + } + + const cmdStr = cmd.join(' '); + logger?.trace(`Resizing images: ${cmdStr}`); + + const { status } = spawnSync(cmdStr); + if (status !== 0) { + throw new Error(`Failed to resize image: ${cmdStr}`); + } +} + diff --git a/locales/bn.js b/locales/bn.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/bn.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/de.js b/locales/de.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/de.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/el.js b/locales/el.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/el.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/en.js b/locales/en.js deleted file mode 100644 index 363c35e8..00000000 --- a/locales/en.js +++ /dev/null @@ -1,161 +0,0 @@ -{ - "Unknown adb result \"%s\"": "Unknown adb result \"%s\"", - "Unable to start Android Debug Bridge server (exit code %s)": "Unable to start Android Debug Bridge server (exit code %s)", - "Android SDK not found": "Android SDK not found", - "APK file \"%s\" does not exist": "APK file \"%s\" does not exist", - "device not found": "device not found", - "Executing: %s": "Executing: %s", - "Not enough free space on device": "Not enough free space on device", - "The app is already installed, but signed with a different certificate": "The app is already installed, but signed with a different certificate", - "You need to either manually uninstall the app or rebuild using the same certificate that was used to sign the installed app": "You need to either manually uninstall the app or rebuild using the same certificate that was used to sign the installed app", - "Application \"%s\" is not running": "Application \"%s\" is not running", - "Source file \"%s\" does not exist": "Source file \"%s\" does not exist", - "Failed to create destination directory \"%s\"": "Failed to create destination directory \"%s\"", - "JDK (Java Development Kit) not found.": "JDK (Java Development Kit) not found.", - "If you already have installed the JDK, verify your __JAVA_HOME__ environment variable is correctly set.": "If you already have installed the JDK, verify your __JAVA_HOME__ environment variable is correctly set.", - "The JDK can be downloaded and installed from %s.": "The JDK can be downloaded and installed from %s.", - "The JDK (Java Development Kit) path must not contain ampersands (&) on Windows.": "The JDK (Java Development Kit) path must not contain ampersands (&) on Windows.", - "Please move the JDK into a path without an ampersand and update the __JAVA_HOME__ environment variable.": "Please move the JDK into a path without an ampersand and update the __JAVA_HOME__ environment variable.", - "Unable to locate an /usr/lib/libGL.so.": "Unable to locate an /usr/lib/libGL.so.", - "Without the libGL library, the Android Emulator may not work properly.": "Without the libGL library, the Android Emulator may not work properly.", - "You may be able to fix it by reinstalling your graphics drivers and make sure it installs the 32-bit version.": "You may be able to fix it by reinstalling your graphics drivers and make sure it installs the 32-bit version.", - "i386 architecture is not configured.": "i386 architecture is not configured.", - "To ensure you install the required 32-bit libraries, you need to register the i386 architecture with dpkg.": "To ensure you install the required 32-bit libraries, you need to register the i386 architecture with dpkg.", - "To add the i386 architecture, run \"%s\".": "To add the i386 architecture, run \"%s\".", - "32-bit libraries is not installed.": "32-bit libraries is not installed.", - "Without the 32-bit libraries, the Android SDK will not work properly.": "Without the 32-bit libraries, the Android SDK will not work properly.", - "To install the required 32-bit libraries, run \"%s\".": "To install the required 32-bit libraries, run \"%s\".", - "32-bit glibc library is not installed.": "32-bit glibc library is not installed.", - "Without the 32-bit glibc library, the Android Emulator will not work properly.": "Without the 32-bit glibc library, the Android Emulator will not work properly.", - "To install the required 32-bit glibc library, run \"%s\".": "To install the required 32-bit glibc library, run \"%s\".", - "32-bit libstdc++ library is not installed.": "32-bit libstdc++ library is not installed.", - "Without the 32-bit libstdc++ library, the Android Emulator will not work properly.": "Without the 32-bit libstdc++ library, the Android Emulator will not work properly.", - "To install the required 32-bit libstdc++ library, run \"%s\".": "To install the required 32-bit libstdc++ library, run \"%s\".", - "Unable to locate an Android NDK.": "Unable to locate an Android NDK.", - "Without the NDK, you will not be able to build native Android Titanium modules.": "Without the NDK, you will not be able to build native Android Titanium modules.", - "If you have already downloaded and installed the Android NDK, you can tell Titanium where the Android NDK is located by running '%s', otherwise you can install it by running '%s' or manually downloading from %s.": "If you have already downloaded and installed the Android NDK, you can tell Titanium where the Android NDK is located by running '%s', otherwise you can install it by running '%s' or manually downloading from %s.", - "Unable to locate an Android SDK.": "Unable to locate an Android SDK.", - "If you have already downloaded and installed the Android SDK, you can tell Titanium where the Android SDK is located by running '%s', otherwise you can install it by running '%s' or manually downloading from %s.": "If you have already downloaded and installed the Android SDK, you can tell Titanium where the Android SDK is located by running '%s', otherwise you can install it by running '%s' or manually downloading from %s.", - "The Android SDK path must not contain ampersands (&) on Windows.": "The Android SDK path must not contain ampersands (&) on Windows.", - "Please move the Android SDK into a path without an ampersand and re-run __titanium setup android__.": "Please move the Android SDK into a path without an ampersand and re-run __titanium setup android__.", - "Missing required Android SDK tool: %%s": { - "one": "Missing required Android SDK tool: %%s", - "other": "Missing required Android SDK tools: %%s" - }, - "The Android SDK located at %s has incomplete or out-of-date packages.": "The Android SDK located at %s has incomplete or out-of-date packages.", - "Current installed Android SDK tools:": "Current installed Android SDK tools:", - "Make sure you have the latest Android SDK Tools, Platform Tools, and Build Tools installed.": "Make sure you have the latest Android SDK Tools, Platform Tools, and Build Tools installed.", - "You can also specify the exact location of these required tools by running:": "You can also specify the exact location of these required tools by running:", - "If you need to, run \"%s\" to reconfigure the Titanium Android settings.": "If you need to, run \"%s\" to reconfigure the Titanium Android settings.", - "Android API %s is too old and is no longer supported by Titanium SDK %s.": "Android API %s is too old and is no longer supported by Titanium SDK %s.", - "The minimum supported Android API level by Titanium SDK %s is API level %s.": "The minimum supported Android API level by Titanium SDK %s is API level %s.", - "Android API %s is too new and may or may not work with Titanium SDK %s.": "Android API %s is too new and may or may not work with Titanium SDK %s.", - "The maximum supported Android API level by Titanium SDK %s is API level %s.": "The maximum supported Android API level by Titanium SDK %s is API level %s.", - "No Android APIs found.": "No Android APIs found.", - "Run '%s' to install the latest Android APIs.": "Run '%s' to install the latest Android APIs.", - "No valid Android APIs found that are supported by Titanium SDK %s.": "No valid Android APIs found that are supported by Titanium SDK %s.", - "The Android emulator \"%s\" has a problem:": "The Android emulator \"%s\" has a problem:", - "Found %s emulators": "Found %s emulators", - "Detecting if %s exists...": "Detecting if %s exists...", - "Invalid emulator \"%s\"": "Invalid emulator \"%s\"", - "Emulator exists, detecting all running emulators and connected devices...": "Emulator exists, detecting all running emulators and connected devices...", - "Detected %s running emulators and connected devices": "Detected %s running emulators and connected devices", - "Checking %s devices to see if it's the emulator we want": "Checking %s devices to see if it's the emulator we want", - "Failed to check if the emulator was running: %s": "Failed to check if the emulator was running: %s", - "The emulator is running": "The emulator is running", - "The emulator is NOT running": "The emulator is NOT running", - "Unable to find device \"%s\"": "Unable to find device \"%s\"", - "Timed out while waiting for the emulator to boot; waited %s ms": "Timed out while waiting for the emulator to boot; waited %s ms", - "Checking the boot state for the next %s ms": "Checking the boot state for the next %s ms", - "Waiting for emulator to register with ADB": "Waiting for emulator to register with ADB", - "No devices found, continuing to wait": "No devices found, continuing to wait", - "Found %s devices, checking if any of them are the emulator...": "Found %s devices, checking if any of them are the emulator...", - "Error checking if emulator is running: %s": "Error checking if emulator is running: %s", - "Emulator not running yet, continuing to wait": "Emulator not running yet, continuing to wait", - "Emulator is running!": "Emulator is running!", - "Checking if boot animation has finished...": "Checking if boot animation has finished...", - "Emulator is booted, emitting booted event": "Emulator is booted, emitting booted event", - "Emulator is not booted yet; checking again in %s ms": "Emulator is not booted yet; checking again in %s ms", - "Emulator is booted": "Emulator is booted", - "SD card not required, skipping mount check": "SD card not required, skipping mount check", - "Checking if SD card is mounted": "Checking if SD card is mounted", - "Checking mount points: %s": "Checking mount points: %s", - "SD card is mounted": "SD card is mounted", - "Checking if emulator %s is running...": "Checking if emulator %s is running...", - "Emulator already running": "Emulator already running", - "Emulator not running, detecting running emulators": "Emulator not running, detecting running emulators", - "Starting the emulator...": "Starting the emulator...", - "Emulator is starting, monitoring boot state...": "Emulator is starting, monitoring boot state...", - "Emulator \"%s\" not running": "Emulator \"%s\" not running", - "Compiling localization files": "Compiling localization files", - "Processing i18n file: %s": "Processing i18n file: %s", - "Checking for Splash Screen localization": "Checking for Splash Screen localization", - "Failed to parse %s": "Failed to parse %s", - "%s [line %s, column %s]": "%s [line %s, column %s]", - "Parsing JSS file: %s": "Parsing JSS file: %s", - "Error parsing JSS file.": "Error parsing JSS file.", - "Couldn't find import file %s referenced from %s": "Couldn't find import file %s referenced from %s", - "Loading and parsing JSS files": "Loading and parsing JSS files", - "tiapp.xml file does not exist": "tiapp.xml file does not exist", - "minimum logging level": "minimum logging level", - "level": "level", - "Project directory does not exist": "Project directory does not exist", - "Invalid project directory \"%s\"": "Invalid project directory \"%s\"", - "Use the %s property to specify the project's directory": "Use the %s property to specify the project's directory", - "tiapp.xml is missing the element": "tiapp.xml is missing the element", - "The app id must consist of letters, numbers, and underscores.": "The app id must consist of letters, numbers, and underscores.", - "Note: Android does not allow dashes and iOS does not allow underscores.": "Note: Android does not allow dashes and iOS does not allow underscores.", - "The first character must be a letter or underscore.": "The first character must be a letter or underscore.", - "Usually the app id is your company's reversed Internet domain name. (i.e. com.example.myapp)": "Usually the app id is your company's reversed Internet domain name. (i.e. com.example.myapp)", - "tiapp.xml is missing the element": "tiapp.xml is missing the element", - "The project name must consist of letters, numbers, dashes, and underscores.": "The project name must consist of letters, numbers, dashes, and underscores.", - "The first character must be a letter.": "The first character must be a letter.", - "tiapp.xml is missing the element": "tiapp.xml is missing the element", - "The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.": "The guid must be in the format XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX and consist of letters and numbers.", - "If you need a new guid, below are 5 freshly generated new ones that you can choose from:": "If you need a new guid, below are 5 freshly generated new ones that you can choose from:", - "tiapp.xml contains an invalid guid \"%s\"": "tiapp.xml contains an invalid guid \"%s\"", - "tiapp.xml contains an invalid version \"%s\"": "tiapp.xml contains an invalid version \"%s\"", - "The version must consist of three positive integers in the format \"X.Y.Z\".": "The version must consist of three positive integers in the format \"X.Y.Z\".", - "The app version major number must be greater than zero.": "The app version major number must be greater than zero.", - "Could not find all required Titanium plugins:": "Could not find all required Titanium plugins:", - "No project level plugins to load": "No project level plugins to load", - "Unable to compile project because the 'sdk-version' in the tiapp.xml is not installed": "Unable to compile project because the 'sdk-version' in the tiapp.xml is not installed", - "The project's %s is currently set to %s, which is not installed.": "The project's %s is currently set to %s, which is not installed.", - "Update the %s in the tiapp.xml to one of the installed Titaniums SDKs:": "Update the %s in the tiapp.xml to one of the installed Titaniums SDKs:", - "or run '%s' to download and install Titanium SDK %s": "or run '%s' to download and install Titanium SDK %s", - "Unable to compile project using Titanium SDK %s with Node.js %s": "Unable to compile project using Titanium SDK %s with Node.js %s", - "Titanium SDK %s requires Node.js v0.8. Node.js v0.10 and newer will not work.": "Titanium SDK %s requires Node.js v0.8. Node.js v0.10 and newer will not work.", - "Either update your application to Titanium SDK %s or newer or download Node.js %s from %s.": "Either update your application to Titanium SDK %s or newer or download Node.js %s from %s.", - "Unable to compile a %s project with Titanium SDK %s": "Unable to compile a %s project with Titanium SDK %s", - "To build this application, set the in the tiapp.xml to the current Titaniums SDK: %s": "To build this application, set the in the tiapp.xml to the current Titaniums SDK: %s", - "tiapp.xml set to %s, but current Titanium SDK set to %s": "tiapp.xml set to %s, but current Titanium SDK set to %s", - "Missing required option \"%s\"": "Missing required option \"%s\"", - "Launching Android emulator: %s": "Launching Android emulator: %s", - "Forking legacy SDK command: %s": "Forking legacy SDK command: %s", - "Forking correct SDK command: %s": "Forking correct SDK command: %s", - "\"Resources\" directory not found": "\"Resources\" directory not found", - "Ensure the \"Resources\" directory exists and contains an \"app.js\" file.": "Ensure the \"Resources\" directory exists and contains an \"app.js\" file.", - "\"app.js\" not found": "\"app.js\" not found", - "Ensure the \"app.js\" file exists in your project's \"Resources\" directory.": "Ensure the \"app.js\" file exists in your project's \"Resources\" directory.", - "Invalid platform \"%s\"": "Invalid platform \"%s\"", - "Available platforms for SDK version %s:": "Available platforms for SDK version %s:", - "Microsoft Visual Studio not found.": "Microsoft Visual Studio not found.", - "You will be unable to build Windows Phone or Windows Store apps.": "You will be unable to build Windows Phone or Windows Store apps.", - "You can install it from %s.": "You can install it from %s.", - "Microsoft Windows Phone SDK not found.": "Microsoft Windows Phone SDK not found.", - "You will be unable to build Windows Phone apps.": "You will be unable to build Windows Phone apps.", - "Microsoft Windows Phone SDK is missing the deploy command.": "Microsoft Windows Phone SDK is missing the deploy command.", - "Failed to run MSBuild.": "Failed to run MSBuild.", - "This is most likely due to Visual Studio cannot find a suitable .NET framework.": "This is most likely due to Visual Studio cannot find a suitable .NET framework.", - "Please install the latest .NET framework.": "Please install the latest .NET framework.", - "The MSBuild version %s is too old.": "The MSBuild version %s is too old.", - "Titanium requires .NET MSBuild '%s'.": "Titanium requires .NET MSBuild '%s'.", - "Failed to enumerate Windows Phone devices.": "Failed to enumerate Windows Phone devices.", - "Ensure that the Windows Phone SDK is properly installed.": "Ensure that the Windows Phone SDK is properly installed.", - "Windows Phone Emulator is not installed.": "Windows Phone Emulator is not installed.", - "Ensure that the Windows Phone Emulator is properly installed.": "Ensure that the Windows Phone Emulator is properly installed.", - "You must be running 64-bit Windows 8.1 Pro with Hyper-V support enabled.": "You must be running 64-bit Windows 8.1 Pro with Hyper-V support enabled.", - "Executing PowerShell scripts is disabled.": "Executing PowerShell scripts is disabled.", - "In order to build Windows Hybrid apps for the Windows Store (winstore), you must change the execution policy to allow PowerShell scripts.": "In order to build Windows Hybrid apps for the Windows Store (winstore), you must change the execution policy to allow PowerShell scripts.", - "To enable PowerShell scripts, search __PowerShell__ in the __Start__ menu, right click the icon, select __Run as administrator__, then run:": "To enable PowerShell scripts, search __PowerShell__ in the __Start__ menu, right click the icon, select __Run as administrator__, then run:" -} \ No newline at end of file diff --git a/locales/es.js b/locales/es.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/es.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/fr.js b/locales/fr.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/fr.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/hi.js b/locales/hi.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/hi.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/it.js b/locales/it.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/it.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/ja.js b/locales/ja.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/ja.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/ko.js b/locales/ko.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/ko.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/ru.js b/locales/ru.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/ru.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/uk.js b/locales/uk.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/uk.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/locales/zh.js b/locales/zh.js deleted file mode 100644 index 9e26dfee..00000000 --- a/locales/zh.js +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index dbf44faa..00000000 --- a/package-lock.json +++ /dev/null @@ -1,18699 +0,0 @@ -{ - "name": "node-titanium-sdk", - "version": "6.0.1", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "node-titanium-sdk", - "version": "6.0.1", - "license": "Apache-2.0", - "dependencies": { - "@babel/core": "7.11.6", - "@babel/parser": "7.11.5", - "@babel/plugin-transform-property-literals": "7.10.1", - "@babel/preset-env": "7.10.2", - "async": "3.2.4", - "babel-plugin-transform-titanium": "0.1.1", - "babel-preset-minify": "0.5.2", - "colors": "1.4.0", - "fs-extra": "11.1.1", - "node-appc": "1.1.6", - "node-uuid": "1.4.8", - "stream-splitter": "0.3.2", - "unorm": "1.6.0", - "xmldom": "0.6.0" - }, - "devDependencies": { - "@commitlint/cli": "17.5.0", - "@commitlint/config-conventional": "17.4.4", - "@seadub/danger-plugin-dependencies": "1.0.0", - "@seadub/danger-plugin-eslint": "2.0.0", - "@seadub/danger-plugin-junit": "0.3.0", - "babel-plugin-tester": "10.1.0", - "danger": "11.2.4", - "eslint": "7.4.0", - "eslint-config-axway": "6.0.2", - "eslint-plugin-mocha": "9.0.0", - "husky": "8.0.3", - "lint-staged": "13.2.0", - "mocha": "8.1.1", - "mocha-jenkins-reporter": "0.4.8", - "nyc": "15.1.0", - "semver": "7.3.8", - "should": "13.2.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", - "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.6", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.5", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "dependencies": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", - "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", - "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", - "dependencies": { - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "dependencies": { - "@babel/types": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", - "dependencies": { - "@babel/types": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "dependencies": { - "@babel/types": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", - "dependencies": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "dependencies": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "dependencies": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", - "dependencies": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "dependencies": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz", - "integrity": "sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.1" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.2.tgz", - "integrity": "sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==", - "dependencies": { - "@babel/compat-data": "^7.10.1", - "@babel/helper-compilation-targets": "^7.10.2", - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-proposal-async-generator-functions": "^7.10.1", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-dynamic-import": "^7.10.1", - "@babel/plugin-proposal-json-strings": "^7.10.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1", - "@babel/plugin-proposal-numeric-separator": "^7.10.1", - "@babel/plugin-proposal-object-rest-spread": "^7.10.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.1", - "@babel/plugin-proposal-optional-chaining": "^7.10.1", - "@babel/plugin-proposal-private-methods": "^7.10.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.1", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.1", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.1", - "@babel/plugin-transform-arrow-functions": "^7.10.1", - "@babel/plugin-transform-async-to-generator": "^7.10.1", - "@babel/plugin-transform-block-scoped-functions": "^7.10.1", - "@babel/plugin-transform-block-scoping": "^7.10.1", - "@babel/plugin-transform-classes": "^7.10.1", - "@babel/plugin-transform-computed-properties": "^7.10.1", - "@babel/plugin-transform-destructuring": "^7.10.1", - "@babel/plugin-transform-dotall-regex": "^7.10.1", - "@babel/plugin-transform-duplicate-keys": "^7.10.1", - "@babel/plugin-transform-exponentiation-operator": "^7.10.1", - "@babel/plugin-transform-for-of": "^7.10.1", - "@babel/plugin-transform-function-name": "^7.10.1", - "@babel/plugin-transform-literals": "^7.10.1", - "@babel/plugin-transform-member-expression-literals": "^7.10.1", - "@babel/plugin-transform-modules-amd": "^7.10.1", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/plugin-transform-modules-systemjs": "^7.10.1", - "@babel/plugin-transform-modules-umd": "^7.10.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.10.1", - "@babel/plugin-transform-object-super": "^7.10.1", - "@babel/plugin-transform-parameters": "^7.10.1", - "@babel/plugin-transform-property-literals": "^7.10.1", - "@babel/plugin-transform-regenerator": "^7.10.1", - "@babel/plugin-transform-reserved-words": "^7.10.1", - "@babel/plugin-transform-shorthand-properties": "^7.10.1", - "@babel/plugin-transform-spread": "^7.10.1", - "@babel/plugin-transform-sticky-regex": "^7.10.1", - "@babel/plugin-transform-template-literals": "^7.10.1", - "@babel/plugin-transform-typeof-symbol": "^7.10.1", - "@babel/plugin-transform-unicode-escapes": "^7.10.1", - "@babel/plugin-transform-unicode-regex": "^7.10.1", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.10.2", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "dependencies": { - "regenerator-runtime": "^0.13.11" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@commitlint/cli": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.5.0.tgz", - "integrity": "sha512-yNW3+M7UM1ioK28LKTrryIVB5qGpXlEv8+rJQiWPMZNayy9/1XR5+lL8qBTNlgopYtZWWnIm5RETcAN29ZTL/A==", - "dev": true, - "dependencies": { - "@commitlint/format": "^17.4.4", - "@commitlint/lint": "^17.4.4", - "@commitlint/load": "^17.5.0", - "@commitlint/read": "^17.4.4", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - }, - "bin": { - "commitlint": "cli.js" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/config-conventional": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.4.4.tgz", - "integrity": "sha512-u6ztvxqzi6NuhrcEDR7a+z0yrh11elY66nRrQIpqsqW6sZmpxYkDLtpRH8jRML+mmxYQ8s4qqF06Q/IQx5aJeQ==", - "dev": true, - "dependencies": { - "conventional-changelog-conventionalcommits": "^5.0.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/config-validator": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.4.tgz", - "integrity": "sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==", - "dev": true, - "dependencies": { - "@commitlint/types": "^17.4.4", - "ajv": "^8.11.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/ensure": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.4.4.tgz", - "integrity": "sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g==", - "dev": true, - "dependencies": { - "@commitlint/types": "^17.4.4", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", - "dev": true, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/format": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", - "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", - "dev": true, - "dependencies": { - "@commitlint/types": "^17.4.4", - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/format/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/format/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/format/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/format/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/format/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/format/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/is-ignored": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.4.4.tgz", - "integrity": "sha512-Y3eo1SFJ2JQDik4rWkBC4tlRIxlXEFrRWxcyrzb1PUT2k3kZ/XGNuCDfk/u0bU2/yS0tOA/mTjFsV+C4qyACHw==", - "dev": true, - "dependencies": { - "@commitlint/types": "^17.4.4", - "semver": "7.3.8" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/lint": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.4.4.tgz", - "integrity": "sha512-qgkCRRFjyhbMDWsti/5jRYVJkgYZj4r+ZmweZObnbYqPUl5UKLWMf9a/ZZisOI4JfiPmRktYRZ2JmqlSvg+ccw==", - "dev": true, - "dependencies": { - "@commitlint/is-ignored": "^17.4.4", - "@commitlint/parse": "^17.4.4", - "@commitlint/rules": "^17.4.4", - "@commitlint/types": "^17.4.4" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/load": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.5.0.tgz", - "integrity": "sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.4.4", - "@commitlint/types": "^17.4.4", - "@types/node": "*", - "chalk": "^4.1.0", - "cosmiconfig": "^8.0.0", - "cosmiconfig-typescript-loader": "^4.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/load/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/load/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/load/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/load/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/message": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", - "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", - "dev": true, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/parse": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.4.4.tgz", - "integrity": "sha512-EKzz4f49d3/OU0Fplog7nwz/lAfXMaDxtriidyGF9PtR+SRbgv4FhsfF310tKxs6EPj8Y+aWWuX3beN5s+yqGg==", - "dev": true, - "dependencies": { - "@commitlint/types": "^17.4.4", - "conventional-changelog-angular": "^5.0.11", - "conventional-commits-parser": "^3.2.2" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/read": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.4.4.tgz", - "integrity": "sha512-B2TvUMJKK+Svzs6eji23WXsRJ8PAD+orI44lVuVNsm5zmI7O8RSGJMvdEZEikiA4Vohfb+HevaPoWZ7PiFZ3zA==", - "dev": true, - "dependencies": { - "@commitlint/top-level": "^17.4.0", - "@commitlint/types": "^17.4.4", - "fs-extra": "^11.0.0", - "git-raw-commits": "^2.0.0", - "minimist": "^1.2.6" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/resolve-extends": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz", - "integrity": "sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==", - "dev": true, - "dependencies": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/types": "^17.4.4", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/rules": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.4.4.tgz", - "integrity": "sha512-0tgvXnHi/mVcyR8Y8mjTFZIa/FEQXA4uEutXS/imH2v1UNkYDSEMsK/68wiXRpfW1euSgEdwRkvE1z23+yhNrQ==", - "dev": true, - "dependencies": { - "@commitlint/ensure": "^17.4.4", - "@commitlint/message": "^17.4.2", - "@commitlint/to-lines": "^17.4.0", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/to-lines": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", - "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", - "dev": true, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/top-level": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", - "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", - "dev": true, - "dependencies": { - "find-up": "^5.0.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0" - }, - "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@commitlint/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@commitlint/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - }, - "node_modules/@gitbeaker/core": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-21.7.0.tgz", - "integrity": "sha512-cw72rE7tA27wc6JJe1WqeAj9v/6w0S7XJcEji+bRNjTlUfE1zgfW0Gf1mbGUi7F37SOABGCosQLfg9Qe63aIqA==", - "dev": true, - "dependencies": { - "@gitbeaker/requester-utils": "^21.7.0", - "form-data": "^3.0.0", - "li": "^1.3.0", - "xcase": "^2.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@gitbeaker/node": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/node/-/node-21.7.0.tgz", - "integrity": "sha512-OdM3VcTKYYqboOsnbiPcO0XimXXpYK4gTjARBZ6BWc+1LQXKmqo+OH6oUbyxOoaFu9hHECafIt3WZU3NM4sZTg==", - "dev": true, - "dependencies": { - "@gitbeaker/core": "^21.7.0", - "@gitbeaker/requester-utils": "^21.7.0", - "form-data": "^3.0.0", - "got": "^11.1.4", - "xcase": "^2.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@gitbeaker/requester-utils": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-21.7.0.tgz", - "integrity": "sha512-eLTaVXlBnh8Qimj6QuMMA06mu/mLcJm3dy8nqhhn/Vm/D25sPrvpGwmbfFyvzj6QujPqtHvFfsCHtyZddL01qA==", - "dev": true, - "dependencies": { - "form-data": "^3.0.0", - "query-string": "^6.12.1", - "xcase": "^2.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/rest": { - "version": "18.12.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", - "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", - "dev": true, - "dependencies": { - "@octokit/core": "^3.5.1", - "@octokit/plugin-paginate-rest": "^2.16.8", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^5.12.0" - } - }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@seadub/danger-plugin-dependencies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-dependencies/-/danger-plugin-dependencies-1.0.0.tgz", - "integrity": "sha512-rk1OGopIHXf5/lfYZEIf6Kr9l1opRSSrhEF36CmXT2aoM3/VrLhB2w7g6nIxvl72ixDUSrXJrD02u/mKGLULxQ==", - "dev": true, - "dependencies": { - "date-fns": "^2.16.1", - "lodash.flatten": "^4.4.0", - "lodash.includes": "^4.3.0", - "node-fetch": "^2.6.1", - "semver": "^7.3.2" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@seadub/danger-plugin-eslint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-eslint/-/danger-plugin-eslint-2.0.0.tgz", - "integrity": "sha512-eOfolDJyWwP5vJQqKLVhr6FDayQfbqwmwPMslFWPMd9AhJfgU85Pz3R8MHfjfsdIzn/zNofnDa5k+GSZtMAZ5g==", - "dev": true, - "engines": { - "node": ">=6.0.0" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@seadub/danger-plugin-junit": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-junit/-/danger-plugin-junit-0.3.0.tgz", - "integrity": "sha512-x2PkV5Q7cR9UAhS2jsEgyqs4JP7yXGk2psQKdZFq4zuwRrzsMT0e4JpipSzb05zMaGLqtdwV6oW8XJwS3FpHIQ==", - "dev": true, - "dependencies": { - "@xmldom/xmldom": "^0.7.3", - "fs-extra": "^9.0.1", - "glob": "^7.1.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@seadub/danger-plugin-junit/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__core/node_modules/@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/babel-plugin-tester": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/babel-plugin-tester/-/babel-plugin-tester-9.0.5.tgz", - "integrity": "sha512-NRBPlhi5VkrTXMqDB1hSUnHs7vqLGRopeukC9u1zilOIFe9O1siwqeKZRiuJiVYakgpeDso/HE2Q5DU1aDqBog==", - "dev": true, - "dependencies": { - "@types/babel__core": "*", - "@types/prettier": "*" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "node_modules/@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "18.15.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.7.tgz", - "integrity": "sha512-LFmUbFunqmBn26wJZgZPYZPrDR1RwGOu2v79Mgcka1ndO6V0/cwjivPTc4yoK6n9kmw4/ls1r8cLrvh2iMibFA==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "node_modules/@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.9.tgz", - "integrity": "sha512-yceMpm/xd4W2a85iqZyO09gTnHvXF6pyiWjD2jcOJs7hRoZtNNOO1eJlhHj1ixA+xip2hOyGn+LgcvLCMo5zXA==", - "dev": true, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.map": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", - "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "node_modules/async-retry": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", - "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", - "dev": true, - "dependencies": { - "retry": "0.12.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/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==", - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "node_modules/babel-helper-evaluate-path": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", - "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==" - }, - "node_modules/babel-helper-flip-expressions": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", - "integrity": "sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA==" - }, - "node_modules/babel-helper-is-nodes-equiv": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw==" - }, - "node_modules/babel-helper-is-void-0": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", - "integrity": "sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg==" - }, - "node_modules/babel-helper-mark-eval-scopes": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", - "integrity": "sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA==" - }, - "node_modules/babel-helper-remove-or-void": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", - "integrity": "sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA==" - }, - "node_modules/babel-helper-to-multiple-sequence-expressions": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", - "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==" - }, - "node_modules/babel-plugin-minify-builtins": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", - "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==" - }, - "node_modules/babel-plugin-minify-constant-folding": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", - "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", - "dependencies": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "node_modules/babel-plugin-minify-dead-code-elimination": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz", - "integrity": "sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA==", - "dependencies": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-mark-eval-scopes": "^0.4.3", - "babel-helper-remove-or-void": "^0.4.3", - "lodash": "^4.17.11" - } - }, - "node_modules/babel-plugin-minify-flip-comparisons": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", - "integrity": "sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A==", - "dependencies": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "node_modules/babel-plugin-minify-guarded-expressions": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", - "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", - "dependencies": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3" - } - }, - "node_modules/babel-plugin-minify-infinity": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", - "integrity": "sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA==" - }, - "node_modules/babel-plugin-minify-mangle-names": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.1.tgz", - "integrity": "sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw==", - "dependencies": { - "babel-helper-mark-eval-scopes": "^0.4.3" - } - }, - "node_modules/babel-plugin-minify-numeric-literals": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", - "integrity": "sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A==" - }, - "node_modules/babel-plugin-minify-replace": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", - "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==" - }, - "node_modules/babel-plugin-minify-simplify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", - "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", - "dependencies": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3", - "babel-helper-is-nodes-equiv": "^0.0.1", - "babel-helper-to-multiple-sequence-expressions": "^0.5.0" - } - }, - "node_modules/babel-plugin-minify-type-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", - "integrity": "sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ==", - "dependencies": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "node_modules/babel-plugin-tester": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-tester/-/babel-plugin-tester-10.1.0.tgz", - "integrity": "sha512-4P2tNaM/Mtg6ytA9YAqmgONnMYqWvdbGDuwRTpIIC9yFZGQrEHoyvDPCx+X1QALAufVb5DKieOPGj5dffiEiNg==", - "dev": true, - "dependencies": { - "@types/babel-plugin-tester": "^9.0.0", - "lodash.mergewith": "^4.6.2", - "prettier": "^2.0.1", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=10.13", - "npm": ">=6" - }, - "peerDependencies": { - "@babel/core": "^7.11.6" - } - }, - "node_modules/babel-plugin-transform-inline-consecutive-adds": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", - "integrity": "sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q==" - }, - "node_modules/babel-plugin-transform-member-expression-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", - "integrity": "sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q==" - }, - "node_modules/babel-plugin-transform-merge-sibling-variables": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.5.tgz", - "integrity": "sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw==" - }, - "node_modules/babel-plugin-transform-minify-booleans": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", - "integrity": "sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA==" - }, - "node_modules/babel-plugin-transform-property-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", - "integrity": "sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA==", - "dependencies": { - "esutils": "^2.0.2" - } - }, - "node_modules/babel-plugin-transform-regexp-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", - "integrity": "sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g==" - }, - "node_modules/babel-plugin-transform-remove-console": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", - "integrity": "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==" - }, - "node_modules/babel-plugin-transform-remove-debugger": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", - "integrity": "sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw==" - }, - "node_modules/babel-plugin-transform-remove-undefined": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", - "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", - "dependencies": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "node_modules/babel-plugin-transform-simplify-comparison-operators": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", - "integrity": "sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A==" - }, - "node_modules/babel-plugin-transform-titanium": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-titanium/-/babel-plugin-transform-titanium-0.1.1.tgz", - "integrity": "sha512-N2ImhDNsfmT5Q68HeNJfg1xE8Z3NsVYWC+/TWLtckscXPjleDJRciIRzhUhI6876VXhxSjbw5s7ylv1NTa/xoA==" - }, - "node_modules/babel-plugin-transform-undefined-to-void": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", - "integrity": "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==" - }, - "node_modules/babel-preset-minify": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.2.tgz", - "integrity": "sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w==", - "dependencies": { - "babel-plugin-minify-builtins": "^0.5.0", - "babel-plugin-minify-constant-folding": "^0.5.0", - "babel-plugin-minify-dead-code-elimination": "^0.5.2", - "babel-plugin-minify-flip-comparisons": "^0.4.3", - "babel-plugin-minify-guarded-expressions": "^0.4.4", - "babel-plugin-minify-infinity": "^0.4.3", - "babel-plugin-minify-mangle-names": "^0.5.1", - "babel-plugin-minify-numeric-literals": "^0.4.3", - "babel-plugin-minify-replace": "^0.5.0", - "babel-plugin-minify-simplify": "^0.5.1", - "babel-plugin-minify-type-constructors": "^0.4.3", - "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", - "babel-plugin-transform-member-expression-literals": "^6.9.4", - "babel-plugin-transform-merge-sibling-variables": "^6.9.5", - "babel-plugin-transform-minify-booleans": "^6.9.4", - "babel-plugin-transform-property-literals": "^6.9.4", - "babel-plugin-transform-regexp-constructors": "^0.4.3", - "babel-plugin-transform-remove-console": "^6.9.4", - "babel-plugin-transform-remove-debugger": "^6.9.4", - "babel-plugin-transform-remove-undefined": "^0.5.0", - "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", - "babel-plugin-transform-undefined-to-void": "^6.9.4", - "lodash": "^4.17.11" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "engines": { - "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==", - "dev": true - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "engines": { - "node": ">=0.2.0" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase-keys/node_modules/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - } - ] - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.2" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "node_modules/compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "dependencies": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-changelog-conventionalcommits": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", - "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", - "dev": true, - "dependencies": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "dependencies": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "conventional-commits-parser": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "node_modules/core-js": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", - "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", - "dev": true, - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/core-js-compat": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.1.tgz", - "integrity": "sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==", - "dependencies": { - "browserslist": "^4.21.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "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==" - }, - "node_modules/cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, - "dependencies": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/d-fischer" - } - }, - "node_modules/cosmiconfig-typescript-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz", - "integrity": "sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==", - "dev": true, - "engines": { - "node": ">=12", - "npm": ">=6" - }, - "peerDependencies": { - "@types/node": "*", - "cosmiconfig": ">=7", - "ts-node": ">=10", - "typescript": ">=3" - } - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/danger": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/danger/-/danger-11.2.4.tgz", - "integrity": "sha512-9tSrDm79+vWijG3zLXp6DQFmUqFLXg8Fl3jZmPhymlfsmAX0NaAc4HbC81pTOsSgOdiJfJHWpDwKu7fsTktFOQ==", - "dev": true, - "dependencies": { - "@gitbeaker/node": "^21.3.0", - "@octokit/rest": "^18.12.0", - "async-retry": "1.2.3", - "chalk": "^2.3.0", - "commander": "^2.18.0", - "core-js": "^3.8.2", - "debug": "^4.1.1", - "fast-json-patch": "^3.0.0-1", - "get-stdin": "^6.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "hyperlinker": "^1.0.0", - "json5": "^2.1.0", - "jsonpointer": "^5.0.0", - "jsonwebtoken": "^9.0.0", - "lodash.find": "^4.6.0", - "lodash.includes": "^4.3.0", - "lodash.isobject": "^3.0.2", - "lodash.keys": "^4.0.8", - "lodash.mapvalues": "^4.6.0", - "lodash.memoize": "^4.1.2", - "memfs-or-file-map-to-github-branch": "^1.2.1", - "micromatch": "^4.0.4", - "node-cleanup": "^2.1.2", - "node-fetch": "^2.6.7", - "override-require": "^1.1.1", - "p-limit": "^2.1.0", - "parse-diff": "^0.7.0", - "parse-git-config": "^2.0.3", - "parse-github-url": "^1.0.2", - "parse-link-header": "^2.0.0", - "pinpoint": "^1.1.0", - "prettyjson": "^1.2.1", - "readline-sync": "^1.4.9", - "regenerator-runtime": "^0.13.9", - "require-from-string": "^2.0.2", - "supports-hyperlinks": "^1.0.1" - }, - "bin": { - "danger": "distribution/commands/danger.js", - "danger-ci": "distribution/commands/danger-ci.js", - "danger-init": "distribution/commands/danger-init.js", - "danger-js": "distribution/commands/danger.js", - "danger-local": "distribution/commands/danger-local.js", - "danger-pr": "distribution/commands/danger-pr.js", - "danger-process": "distribution/commands/danger-process.js", - "danger-reset-status": "distribution/commands/danger-reset-status.js", - "danger-runner": "distribution/commands/danger-runner.js" - }, - "engines": { - "node": ">=14.13.1" - } - }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "dev": true, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "dependencies": { - "is-obj": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "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==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.4.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.340.tgz", - "integrity": "sha512-zx8hqumOqltKsv/MF50yvdAlPF9S/4PXbyfzJS6ZGhbddGkRegdwImmfSVqCkEziYzrIGZ/TlrzBND4FysfkDg==" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - } - }, - "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/eslint": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", - "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-config-axway": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-axway/-/eslint-config-axway-6.0.2.tgz", - "integrity": "sha512-+O+kCrTycij3Vyk+hJtljZy/Xa/Xz0PdkJm4c4DRed6YT7JuSVpoH4UPCST/xCT9/Nonpy8VuyuZTa3kneHdjw==", - "dev": true, - "dependencies": { - "eslint-plugin-chai-expect": "^2.2.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^5.1.0", - "eslint-plugin-security": "^1.4.0", - "find-root": "^1.1.0", - "semver": "^7.3.4" - }, - "peerDependencies": { - "eslint": "7.x" - } - }, - "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - } - }, - "node_modules/eslint-import-resolver-node/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "dev": true, - "dependencies": { - "debug": "^3.2.7" - }, - "engines": { - "node": ">=4" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/eslint-module-utils/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-chai-expect": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-chai-expect/-/eslint-plugin-chai-expect-2.2.0.tgz", - "integrity": "sha512-ExTJKhgeYMfY8wDj3UiZmgpMKJOUHGNHmWMlxT49JUDB1vTnw0sSNfXJSxnX+LcebyBD/gudXzjzD136WqPJrQ==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - }, - "peerDependencies": { - "eslint": ">=2.0.0 <= 7.x" - } - }, - "node_modules/eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "dependencies": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=4.19.1" - } - }, - "node_modules/eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" - } - }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eslint-plugin-import/node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz", - "integrity": "sha512-d7knAcQj1jPCzZf3caeBIn3BnW6ikcvfz0kSqQpwPYcVGLoJV5sz0l0OJB2LR8I7dvTDbqq1oV6ylhSgzA10zg==", - "dev": true, - "dependencies": { - "eslint-utils": "^3.0.0", - "ramda": "^0.27.1" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-mocha/node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "dependencies": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "engines": { - "node": ">=8.10.0" - }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-plugin-node/node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/eslint-plugin-node/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-plugin-promise": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", - "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", - "dev": true, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "peerDependencies": { - "eslint": "^7.0.0" - } - }, - "node_modules/eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", - "dev": true, - "dependencies": { - "safe-regex": "^2.1.1" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/eslint/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "dependencies": { - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "dependencies": { - "homedir-polyfill": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "node_modules/extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "dependencies": { - "is-extendable": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", - "dev": true - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "dependencies": { - "flat-cache": "^2.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "dependencies": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "engines": { - "node": "*" - } - }, - "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==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/git-config-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", - "integrity": "sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "fs-exists-sync": "^0.1.0", - "homedir-polyfill": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "dependencies": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - }, - "bin": { - "git-raw-commits": "cli.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "dependencies": { - "ini": "^1.3.4" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/har-validator/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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/har-validator/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "engines": { - "node": ">=4" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hasha/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "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" - } - }, - "node_modules/homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "dependencies": { - "parse-passwd": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", - "dev": true, - "bin": { - "husky": "lib/bin.js" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/typicode" - } - }, - "node_modules/hyperlinker": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", - "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-fresh/node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dependencies": { - "loose-envify": "^1.0.0" - } - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "dependencies": { - "has-bigints": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "dependencies": { - "text-extensions": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-processinfo/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/iterate-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", - "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "dependencies": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "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-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "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==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ] - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "dependencies": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - }, - "bin": { - "JSONStream": "bin.js" - }, - "engines": { - "node": "*" - } - }, - "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "dev": true, - "dependencies": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dependencies": { - "leven": "^3.1.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/li": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/li/-/li-1.3.0.tgz", - "integrity": "sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw==", - "dev": true - }, - "node_modules/lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "node_modules/lint-staged": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.0.tgz", - "integrity": "sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==", - "dev": true, - "dependencies": { - "chalk": "5.2.0", - "cli-truncate": "^3.1.0", - "commander": "^10.0.0", - "debug": "^4.3.4", - "execa": "^7.0.0", - "lilconfig": "2.1.0", - "listr2": "^5.0.7", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.3", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.2.1" - }, - "bin": { - "lint-staged": "bin/lint-staged.js" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/lint-staged" - } - }, - "node_modules/lint-staged/node_modules/chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", - "dev": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/lint-staged/node_modules/execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - }, - "engines": { - "node": "^14.18.0 || ^16.14.0 || >=18.0.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/lint-staged/node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, - "engines": { - "node": ">=14.18.0" - } - }, - "node_modules/lint-staged/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "dependencies": { - "path-key": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "dependencies": { - "mimic-fn": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lint-staged/node_modules/strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/listr2/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/listr2/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/listr2/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "node_modules/lodash.find": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", - "dev": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "dev": true - }, - "node_modules/lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true - }, - "node_modules/lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", - "dev": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "node_modules/lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, - "node_modules/lodash.keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", - "integrity": "sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ==", - "dev": true - }, - "node_modules/lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", - "dev": true - }, - "node_modules/lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true - }, - "node_modules/lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "node_modules/lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "node_modules/lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "node_modules/lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-update/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/memfs-or-file-map-to-github-branch": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.1.tgz", - "integrity": "sha512-I/hQzJ2a/pCGR8fkSQ9l5Yx+FQ4e7X6blNHyWBm2ojeFLT3GVzGkTj7xnyWpdclrr7Nq4dmx3xrvu70m3ypzAQ==", - "dev": true, - "dependencies": { - "@octokit/rest": "^16.43.0 || ^17.11.0 || ^18.12.0" - } - }, - "node_modules/meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.1.tgz", - "integrity": "sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.3.1", - "debug": "3.2.6", - "diff": "4.0.2", - "escape-string-regexp": "1.0.5", - "find-up": "4.1.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.0", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha-jenkins-reporter": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/mocha-jenkins-reporter/-/mocha-jenkins-reporter-0.4.8.tgz", - "integrity": "sha512-1nz1Q+YgREUlh2kgFR+lrp+ufEFbdhCdtlEVEJR/5LhgqNLIg52+KG3X94hHpwWnf5SwYLS7udxgBbkWOUbyeQ==", - "dev": true, - "dependencies": { - "diff": "4.0.1", - "mkdirp": "^1.0.4", - "xml": "^1.0.1" - }, - "peerDependencies": { - "mocha": "^5.2.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0" - } - }, - "node_modules/mocha-jenkins-reporter/node_modules/diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/mocha/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/mocha/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/mocha/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/mocha/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/mocha/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/mocha/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/node-appc": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node-appc/-/node-appc-1.1.6.tgz", - "integrity": "sha512-ZfoHjoDLpNfXYBshztIq+aTjtlvCZF4XAE00ZYNk4u+/qAjQI+8BidCn957b69WzronQtyNw2NtnJEhsP3N7EQ==", - "dependencies": { - "@xmldom/xmldom": "^0.8.6", - "async": "^3.2.4", - "colors": "1.4.0", - "fs-extra": "~9.1.0", - "request": "~2.88.0", - "semver": "~7.3.8", - "sprintf": "^0.1.5", - "temp": "~0.9.4", - "uuid": "~9.0.0", - "yauzl": "^2.10.0" - }, - "engines": { - "node": ">=10.13" - } - }, - "node_modules/node-appc/node_modules/@xmldom/xmldom": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", - "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/node-appc/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" - }, - "node_modules/node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", - "deprecated": "Use uuid module instead", - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/nyc/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/nyc/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/nyc/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "engines": { - "node": "*" - } - }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/override-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", - "integrity": "sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==", - "dev": true - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate/node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-diff": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", - "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", - "dev": true - }, - "node_modules/parse-git-config": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", - "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", - "dev": true, - "dependencies": { - "expand-tilde": "^2.0.2", - "git-config-path": "^1.0.1", - "ini": "^1.3.5" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-github-url": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", - "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", - "dev": true, - "bin": { - "parse-github-url": "cli.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-link-header": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-2.0.0.tgz", - "integrity": "sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==", - "dev": true, - "dependencies": { - "xtend": "~4.0.1" - } - }, - "node_modules/parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" - }, - "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==" - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true, - "bin": { - "pidtree": "bin/pidtree.js" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/pinpoint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", - "integrity": "sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==", - "dev": true - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prettyjson": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz", - "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==", - "dev": true, - "dependencies": { - "colors": "1.4.0", - "minimist": "^1.2.0" - }, - "bin": { - "prettyjson": "bin/prettyjson" - } - }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "dependencies": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "dev": true, - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", - "dev": true, - "dependencies": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ramda": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", - "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==", - "dev": true - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.0.7" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/readline-sync": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", - "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "node_modules/regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", - "dev": true, - "bin": { - "regexp-tree": "bin/regexp-tree" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "bin": { - "jsesc": "bin/jsesc" - } - }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, - "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", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/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/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dependencies": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "dependencies": { - "global-dirs": "^0.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", - "dev": true, - "dependencies": { - "regexp-tree": "~0.1.1" - } - }, - "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "dependencies": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "node_modules/should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "dependencies": { - "should-type": "^1.4.0" - } - }, - "node_modules/should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "node_modules/should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", - "dev": true - }, - "node_modules/should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "dependencies": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "node_modules/should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", - "dev": true - }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "node_modules/split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "dependencies": { - "readable-stream": "^3.0.0" - } - }, - "node_modules/sprintf": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", - "integrity": "sha512-4X5KsuXFQ7f+d7Y+bi4qSb6eI+YoifDTGr0MQJXRoYO7BO7evfRCjds6kk3z7l5CiJYxgDN1x5Er4WiyCt+zTQ==", - "deprecated": "The sprintf package is deprecated in favor of sprintf-js.", - "engines": { - "node": ">=0.2.4" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "dependencies": { - "internal-slot": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stream-splitter": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/stream-splitter/-/stream-splitter-0.3.2.tgz", - "integrity": "sha512-9VAHJIhskQFJMbyKbf/5flSXV2HsP9MDFdCp3A8WDBWkZ8tP/SOfkI2c5lEHNNUNzbWdNkJEv6iNvQRJnSbYuA==", - "dependencies": { - "buffers": "~0.1.1" - } - }, - "node_modules/strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true, - "engines": { - "node": ">=0.6.19" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-hyperlinks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", - "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", - "dev": true, - "dependencies": { - "has-flag": "^2.0.0", - "supports-color": "^5.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/supports-hyperlinks/node_modules/has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "dependencies": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/table/node_modules/slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/table/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/temp": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "dependencies": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, - "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==", - "dev": true - }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } - }, - "node_modules/ts-node/node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/tsconfig-paths/node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "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==", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=12.20" - } - }, - "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "engines": { - "node": ">=4" - } - }, - "node_modules/universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist-lint": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "node_modules/write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "dependencies": { - "mkdirp": "^0.5.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/write/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/xcase": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz", - "integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==", - "dev": true - }, - "node_modules/xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true - }, - "node_modules/xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", - "dev": true, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/yargs-unparser/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs-unparser/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs-unparser/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yargs-unparser/node_modules/yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "node_modules/yargs-unparser/node_modules/yargs-parser": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", - "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "requires": { - "@babel/highlight": "^7.18.6" - } - }, - "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==" - }, - "@babel/core": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", - "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.6", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.5", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "@babel/generator": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", - "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", - "requires": { - "@babel/types": "^7.21.3", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", - "jsesc": "^2.5.1" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", - "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", - "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", - "browserslist": "^4.21.3", - "lru-cache": "^5.1.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.0.tgz", - "integrity": "sha512-Q8wNiMIdwsv5la5SPxNYzzkPnjgC0Sy0i7jLkVOCdllu/xcVNkr3TeZzbHBJrj+XXRqzX5uCyCoV9eu6xUG7KQ==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-member-expression-to-functions": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.0.tgz", - "integrity": "sha512-N+LaFW/auRSWdx7SHD/HiARwXQju1vXTW4fKr4u5SgBUTm51OKEjKgj+cs00ggW3kEvNqwErnlwuq7Y3xBe4eg==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.3.1" - } - }, - "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", - "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.0.tgz", - "integrity": "sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==", - "requires": { - "@babel/types": "^7.21.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", - "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==" - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", - "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-wrap-function": "^7.18.9", - "@babel/types": "^7.18.9" - } - }, - "@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" - } - }, - "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", - "requires": { - "@babel/types": "^7.20.2" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz", - "integrity": "sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==", - "requires": { - "@babel/types": "^7.20.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", - "requires": { - "@babel/types": "^7.18.6" - } - }, - "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" - }, - "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" - }, - "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==" - }, - "@babel/helper-wrap-function": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz", - "integrity": "sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==", - "requires": { - "@babel/helper-function-name": "^7.19.0", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" - } - }, - "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", - "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" - } - }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", - "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==" - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", - "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", - "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9", - "@babel/plugin-syntax-async-generators": "^7.8.4" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", - "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", - "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", - "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-json-strings": "^7.8.3" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", - "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", - "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", - "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", - "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.20.7" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", - "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", - "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", - "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", - "requires": { - "@babel/helper-create-class-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", - "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "requires": { - "@babel/helper-plugin-utils": "^7.14.5" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", - "integrity": "sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==", - "requires": { - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-remap-async-to-generator": "^7.18.9" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", - "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", - "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", - "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", - "requires": { - "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-replace-supers": "^7.20.7", - "@babel/helper-split-export-declaration": "^7.18.6", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/template": "^7.20.7" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", - "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", - "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", - "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", - "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.0.tgz", - "integrity": "sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", - "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", - "requires": { - "@babel/helper-compilation-targets": "^7.18.9", - "@babel/helper-function-name": "^7.18.9", - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", - "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", - "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz", - "integrity": "sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==", - "requires": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.2.tgz", - "integrity": "sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==", - "requires": { - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz", - "integrity": "sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==", - "requires": { - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-identifier": "^7.19.1" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", - "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", - "requires": { - "@babel/helper-module-transforms": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz", - "integrity": "sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.20.5", - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", - "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", - "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-replace-supers": "^7.18.6" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", - "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.1.tgz", - "integrity": "sha512-Kr6+mgag8auNrgEpbfIWzdXYOvqDHZOF0+Bx2xh4H2EDNwcbRb9lY6nkZg8oSjsX+DH9Ebxm9hOqtKW+gRDeNA==", - "requires": { - "@babel/helper-plugin-utils": "^7.10.1" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "regenerator-transform": "^0.15.1" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", - "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", - "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz", - "integrity": "sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==", - "requires": { - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", - "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", - "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", - "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.9" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", - "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "@babel/preset-env": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.10.2.tgz", - "integrity": "sha512-MjqhX0RZaEgK/KueRzh+3yPSk30oqDKJ5HP5tqTSB1e2gzGS3PLy7K0BIpnp78+0anFuSwOeuCf1zZO7RzRvEA==", - "requires": { - "@babel/compat-data": "^7.10.1", - "@babel/helper-compilation-targets": "^7.10.2", - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-plugin-utils": "^7.10.1", - "@babel/plugin-proposal-async-generator-functions": "^7.10.1", - "@babel/plugin-proposal-class-properties": "^7.10.1", - "@babel/plugin-proposal-dynamic-import": "^7.10.1", - "@babel/plugin-proposal-json-strings": "^7.10.1", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.1", - "@babel/plugin-proposal-numeric-separator": "^7.10.1", - "@babel/plugin-proposal-object-rest-spread": "^7.10.1", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.1", - "@babel/plugin-proposal-optional-chaining": "^7.10.1", - "@babel/plugin-proposal-private-methods": "^7.10.1", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.1", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.1", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.1", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.1", - "@babel/plugin-transform-arrow-functions": "^7.10.1", - "@babel/plugin-transform-async-to-generator": "^7.10.1", - "@babel/plugin-transform-block-scoped-functions": "^7.10.1", - "@babel/plugin-transform-block-scoping": "^7.10.1", - "@babel/plugin-transform-classes": "^7.10.1", - "@babel/plugin-transform-computed-properties": "^7.10.1", - "@babel/plugin-transform-destructuring": "^7.10.1", - "@babel/plugin-transform-dotall-regex": "^7.10.1", - "@babel/plugin-transform-duplicate-keys": "^7.10.1", - "@babel/plugin-transform-exponentiation-operator": "^7.10.1", - "@babel/plugin-transform-for-of": "^7.10.1", - "@babel/plugin-transform-function-name": "^7.10.1", - "@babel/plugin-transform-literals": "^7.10.1", - "@babel/plugin-transform-member-expression-literals": "^7.10.1", - "@babel/plugin-transform-modules-amd": "^7.10.1", - "@babel/plugin-transform-modules-commonjs": "^7.10.1", - "@babel/plugin-transform-modules-systemjs": "^7.10.1", - "@babel/plugin-transform-modules-umd": "^7.10.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", - "@babel/plugin-transform-new-target": "^7.10.1", - "@babel/plugin-transform-object-super": "^7.10.1", - "@babel/plugin-transform-parameters": "^7.10.1", - "@babel/plugin-transform-property-literals": "^7.10.1", - "@babel/plugin-transform-regenerator": "^7.10.1", - "@babel/plugin-transform-reserved-words": "^7.10.1", - "@babel/plugin-transform-shorthand-properties": "^7.10.1", - "@babel/plugin-transform-spread": "^7.10.1", - "@babel/plugin-transform-sticky-regex": "^7.10.1", - "@babel/plugin-transform-template-literals": "^7.10.1", - "@babel/plugin-transform-typeof-symbol": "^7.10.1", - "@babel/plugin-transform-unicode-escapes": "^7.10.1", - "@babel/plugin-transform-unicode-regex": "^7.10.1", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.10.2", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - }, - "dependencies": { - "@babel/plugin-transform-property-literals": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", - "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", - "requires": { - "@babel/helper-plugin-utils": "^7.18.6" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" - } - } - }, - "@babel/preset-modules": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", - "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==" - }, - "@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", - "requires": { - "regenerator-runtime": "^0.13.11" - } - }, - "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" - }, - "dependencies": { - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" - } - } - }, - "@babel/traverse": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", - "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.3", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.3", - "@babel/types": "^7.21.3", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==" - } - } - }, - "@babel/types": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", - "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", - "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", - "to-fast-properties": "^2.0.0" - } - }, - "@commitlint/cli": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.5.0.tgz", - "integrity": "sha512-yNW3+M7UM1ioK28LKTrryIVB5qGpXlEv8+rJQiWPMZNayy9/1XR5+lL8qBTNlgopYtZWWnIm5RETcAN29ZTL/A==", - "dev": true, - "requires": { - "@commitlint/format": "^17.4.4", - "@commitlint/lint": "^17.4.4", - "@commitlint/load": "^17.5.0", - "@commitlint/read": "^17.4.4", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0", - "lodash.isfunction": "^3.0.9", - "resolve-from": "5.0.0", - "resolve-global": "1.0.0", - "yargs": "^17.0.0" - } - }, - "@commitlint/config-conventional": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.4.4.tgz", - "integrity": "sha512-u6ztvxqzi6NuhrcEDR7a+z0yrh11elY66nRrQIpqsqW6sZmpxYkDLtpRH8jRML+mmxYQ8s4qqF06Q/IQx5aJeQ==", - "dev": true, - "requires": { - "conventional-changelog-conventionalcommits": "^5.0.0" - } - }, - "@commitlint/config-validator": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.4.4.tgz", - "integrity": "sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "ajv": "^8.11.0" - } - }, - "@commitlint/ensure": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.4.4.tgz", - "integrity": "sha512-AHsFCNh8hbhJiuZ2qHv/m59W/GRE9UeOXbkOqxYMNNg9pJ7qELnFcwj5oYpa6vzTSHtPGKf3C2yUFNy1GGHq6g==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "lodash.camelcase": "^4.3.0", - "lodash.kebabcase": "^4.1.1", - "lodash.snakecase": "^4.1.1", - "lodash.startcase": "^4.4.0", - "lodash.upperfirst": "^4.3.1" - } - }, - "@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", - "dev": true - }, - "@commitlint/format": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.4.4.tgz", - "integrity": "sha512-+IS7vpC4Gd/x+uyQPTAt3hXs5NxnkqAZ3aqrHd5Bx/R9skyCAWusNlNbw3InDbAK6j166D9asQM8fnmYIa+CXQ==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "chalk": "^4.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@commitlint/is-ignored": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.4.4.tgz", - "integrity": "sha512-Y3eo1SFJ2JQDik4rWkBC4tlRIxlXEFrRWxcyrzb1PUT2k3kZ/XGNuCDfk/u0bU2/yS0tOA/mTjFsV+C4qyACHw==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "semver": "7.3.8" - } - }, - "@commitlint/lint": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.4.4.tgz", - "integrity": "sha512-qgkCRRFjyhbMDWsti/5jRYVJkgYZj4r+ZmweZObnbYqPUl5UKLWMf9a/ZZisOI4JfiPmRktYRZ2JmqlSvg+ccw==", - "dev": true, - "requires": { - "@commitlint/is-ignored": "^17.4.4", - "@commitlint/parse": "^17.4.4", - "@commitlint/rules": "^17.4.4", - "@commitlint/types": "^17.4.4" - } - }, - "@commitlint/load": { - "version": "17.5.0", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.5.0.tgz", - "integrity": "sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.4.4", - "@commitlint/types": "^17.4.4", - "@types/node": "*", - "chalk": "^4.1.0", - "cosmiconfig": "^8.0.0", - "cosmiconfig-typescript-loader": "^4.0.0", - "lodash.isplainobject": "^4.0.6", - "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@commitlint/message": { - "version": "17.4.2", - "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.4.2.tgz", - "integrity": "sha512-3XMNbzB+3bhKA1hSAWPCQA3lNxR4zaeQAQcHj0Hx5sVdO6ryXtgUBGGv+1ZCLMgAPRixuc6en+iNAzZ4NzAa8Q==", - "dev": true - }, - "@commitlint/parse": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.4.4.tgz", - "integrity": "sha512-EKzz4f49d3/OU0Fplog7nwz/lAfXMaDxtriidyGF9PtR+SRbgv4FhsfF310tKxs6EPj8Y+aWWuX3beN5s+yqGg==", - "dev": true, - "requires": { - "@commitlint/types": "^17.4.4", - "conventional-changelog-angular": "^5.0.11", - "conventional-commits-parser": "^3.2.2" - } - }, - "@commitlint/read": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.4.4.tgz", - "integrity": "sha512-B2TvUMJKK+Svzs6eji23WXsRJ8PAD+orI44lVuVNsm5zmI7O8RSGJMvdEZEikiA4Vohfb+HevaPoWZ7PiFZ3zA==", - "dev": true, - "requires": { - "@commitlint/top-level": "^17.4.0", - "@commitlint/types": "^17.4.4", - "fs-extra": "^11.0.0", - "git-raw-commits": "^2.0.0", - "minimist": "^1.2.6" - } - }, - "@commitlint/resolve-extends": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz", - "integrity": "sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==", - "dev": true, - "requires": { - "@commitlint/config-validator": "^17.4.4", - "@commitlint/types": "^17.4.4", - "import-fresh": "^3.0.0", - "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" - } - }, - "@commitlint/rules": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.4.4.tgz", - "integrity": "sha512-0tgvXnHi/mVcyR8Y8mjTFZIa/FEQXA4uEutXS/imH2v1UNkYDSEMsK/68wiXRpfW1euSgEdwRkvE1z23+yhNrQ==", - "dev": true, - "requires": { - "@commitlint/ensure": "^17.4.4", - "@commitlint/message": "^17.4.2", - "@commitlint/to-lines": "^17.4.0", - "@commitlint/types": "^17.4.4", - "execa": "^5.0.0" - } - }, - "@commitlint/to-lines": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.4.0.tgz", - "integrity": "sha512-LcIy/6ZZolsfwDUWfN1mJ+co09soSuNASfKEU5sCmgFCvX5iHwRYLiIuoqXzOVDYOy7E7IcHilr/KS0e5T+0Hg==", - "dev": true - }, - "@commitlint/top-level": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.4.0.tgz", - "integrity": "sha512-/1loE/g+dTTQgHnjoCy0AexKAEFyHsR2zRB4NWrZ6lZSMIxAhBJnmCqwao7b4H8888PsfoTBCLBYIw8vGnej8g==", - "dev": true, - "requires": { - "find-up": "^5.0.0" - } - }, - "@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", - "dev": true, - "requires": { - "chalk": "^4.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "dependencies": { - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } - } - }, - "@gitbeaker/core": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/core/-/core-21.7.0.tgz", - "integrity": "sha512-cw72rE7tA27wc6JJe1WqeAj9v/6w0S7XJcEji+bRNjTlUfE1zgfW0Gf1mbGUi7F37SOABGCosQLfg9Qe63aIqA==", - "dev": true, - "requires": { - "@gitbeaker/requester-utils": "^21.7.0", - "form-data": "^3.0.0", - "li": "^1.3.0", - "xcase": "^2.0.1" - } - }, - "@gitbeaker/node": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/node/-/node-21.7.0.tgz", - "integrity": "sha512-OdM3VcTKYYqboOsnbiPcO0XimXXpYK4gTjARBZ6BWc+1LQXKmqo+OH6oUbyxOoaFu9hHECafIt3WZU3NM4sZTg==", - "dev": true, - "requires": { - "@gitbeaker/core": "^21.7.0", - "@gitbeaker/requester-utils": "^21.7.0", - "form-data": "^3.0.0", - "got": "^11.1.4", - "xcase": "^2.0.1" - } - }, - "@gitbeaker/requester-utils": { - "version": "21.7.0", - "resolved": "https://registry.npmjs.org/@gitbeaker/requester-utils/-/requester-utils-21.7.0.tgz", - "integrity": "sha512-eLTaVXlBnh8Qimj6QuMMA06mu/mLcJm3dy8nqhhn/Vm/D25sPrvpGwmbfFyvzj6QujPqtHvFfsCHtyZddL01qA==", - "dev": true, - "requires": { - "form-data": "^3.0.0", - "query-string": "^6.12.1", - "xcase": "^2.0.1" - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", - "requires": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3" - } - }, - "@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, - "requires": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, - "requires": { - "@octokit/types": "^6.40.0" - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", - "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", - "dev": true, - "requires": {} - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, - "requires": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - } - }, - "@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "requires": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "@octokit/rest": { - "version": "18.12.0", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", - "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", - "dev": true, - "requires": { - "@octokit/core": "^3.5.1", - "@octokit/plugin-paginate-rest": "^2.16.8", - "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^5.12.0" - } - }, - "@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, - "requires": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "@seadub/danger-plugin-dependencies": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-dependencies/-/danger-plugin-dependencies-1.0.0.tgz", - "integrity": "sha512-rk1OGopIHXf5/lfYZEIf6Kr9l1opRSSrhEF36CmXT2aoM3/VrLhB2w7g6nIxvl72ixDUSrXJrD02u/mKGLULxQ==", - "dev": true, - "requires": { - "date-fns": "^2.16.1", - "lodash.flatten": "^4.4.0", - "lodash.includes": "^4.3.0", - "node-fetch": "^2.6.1", - "semver": "^7.3.2" - } - }, - "@seadub/danger-plugin-eslint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-eslint/-/danger-plugin-eslint-2.0.0.tgz", - "integrity": "sha512-eOfolDJyWwP5vJQqKLVhr6FDayQfbqwmwPMslFWPMd9AhJfgU85Pz3R8MHfjfsdIzn/zNofnDa5k+GSZtMAZ5g==", - "dev": true, - "requires": {} - }, - "@seadub/danger-plugin-junit": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@seadub/danger-plugin-junit/-/danger-plugin-junit-0.3.0.tgz", - "integrity": "sha512-x2PkV5Q7cR9UAhS2jsEgyqs4JP7yXGk2psQKdZFq4zuwRrzsMT0e4JpipSzb05zMaGLqtdwV6oW8XJwS3FpHIQ==", - "dev": true, - "requires": { - "@xmldom/xmldom": "^0.7.3", - "fs-extra": "^9.0.1", - "glob": "^7.1.6" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } - } - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true - }, - "@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.0" - } - }, - "@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", - "dev": true - }, - "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", - "dev": true, - "requires": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - }, - "dependencies": { - "@babel/parser": { - "version": "7.21.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", - "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", - "dev": true - } - } - }, - "@types/babel__generator": { - "version": "7.6.4", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz", - "integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", - "dev": true, - "requires": { - "@babel/types": "^7.3.0" - } - }, - "@types/babel-plugin-tester": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@types/babel-plugin-tester/-/babel-plugin-tester-9.0.5.tgz", - "integrity": "sha512-NRBPlhi5VkrTXMqDB1hSUnHs7vqLGRopeukC9u1zilOIFe9O1siwqeKZRiuJiVYakgpeDso/HE2Q5DU1aDqBog==", - "dev": true, - "requires": { - "@types/babel__core": "*", - "@types/prettier": "*" - } - }, - "@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", - "integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "@types/node": { - "version": "18.15.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.7.tgz", - "integrity": "sha512-LFmUbFunqmBn26wJZgZPYZPrDR1RwGOu2v79Mgcka1ndO6V0/cwjivPTc4yoK6n9kmw4/ls1r8cLrvh2iMibFA==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/responselike": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz", - "integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@xmldom/xmldom": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.7.9.tgz", - "integrity": "sha512-yceMpm/xd4W2a85iqZyO09gTnHvXF6pyiWjD2jcOJs7hRoZtNNOO1eJlhHj1ixA+xip2hOyGn+LgcvLCMo5zXA==", - "dev": true - }, - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "requires": { - "type-fest": "^0.21.3" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "requires": { - "default-require-extensions": "^3.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==", - "dev": true - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" - } - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", - "dev": true - }, - "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" - } - }, - "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.map": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.5.tgz", - "integrity": "sha512-gfaKntvwqYIuC7mLLyv2wzZIJqrRhn5PZ9EfFejSx6a78sV7iDsGpG9P+3oUPtm1Rerqm6nrKS4FYuTIvWfo3g==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" - } - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", - "dev": true - }, - "asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" - }, - "async-retry": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.2.3.tgz", - "integrity": "sha512-tfDb02Th6CE6pJUF2gjW5ZVjsgwlucVXOEQMvEX9JgSJMs9gAX+Nz3xRuJBKuUYjTSYORqvDBORdAQ3LU59g7Q==", - "dev": true, - "requires": { - "retry": "0.12.0" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" - }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "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==" - }, - "aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==" - }, - "babel-helper-evaluate-path": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", - "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==" - }, - "babel-helper-flip-expressions": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", - "integrity": "sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA==" - }, - "babel-helper-is-nodes-equiv": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw==" - }, - "babel-helper-is-void-0": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", - "integrity": "sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg==" - }, - "babel-helper-mark-eval-scopes": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", - "integrity": "sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA==" - }, - "babel-helper-remove-or-void": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", - "integrity": "sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA==" - }, - "babel-helper-to-multiple-sequence-expressions": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", - "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==" - }, - "babel-plugin-minify-builtins": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", - "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==" - }, - "babel-plugin-minify-constant-folding": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", - "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-minify-dead-code-elimination": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz", - "integrity": "sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA==", - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-mark-eval-scopes": "^0.4.3", - "babel-helper-remove-or-void": "^0.4.3", - "lodash": "^4.17.11" - } - }, - "babel-plugin-minify-flip-comparisons": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", - "integrity": "sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A==", - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-minify-guarded-expressions": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", - "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3" - } - }, - "babel-plugin-minify-infinity": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", - "integrity": "sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA==" - }, - "babel-plugin-minify-mangle-names": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.1.tgz", - "integrity": "sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw==", - "requires": { - "babel-helper-mark-eval-scopes": "^0.4.3" - } - }, - "babel-plugin-minify-numeric-literals": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", - "integrity": "sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A==" - }, - "babel-plugin-minify-replace": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", - "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==" - }, - "babel-plugin-minify-simplify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", - "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3", - "babel-helper-is-nodes-equiv": "^0.0.1", - "babel-helper-to-multiple-sequence-expressions": "^0.5.0" - } - }, - "babel-plugin-minify-type-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", - "integrity": "sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ==", - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-tester": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-tester/-/babel-plugin-tester-10.1.0.tgz", - "integrity": "sha512-4P2tNaM/Mtg6ytA9YAqmgONnMYqWvdbGDuwRTpIIC9yFZGQrEHoyvDPCx+X1QALAufVb5DKieOPGj5dffiEiNg==", - "dev": true, - "requires": { - "@types/babel-plugin-tester": "^9.0.0", - "lodash.mergewith": "^4.6.2", - "prettier": "^2.0.1", - "strip-indent": "^3.0.0" - } - }, - "babel-plugin-transform-inline-consecutive-adds": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", - "integrity": "sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q==" - }, - "babel-plugin-transform-member-expression-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", - "integrity": "sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q==" - }, - "babel-plugin-transform-merge-sibling-variables": { - "version": "6.9.5", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.5.tgz", - "integrity": "sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw==" - }, - "babel-plugin-transform-minify-booleans": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", - "integrity": "sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA==" - }, - "babel-plugin-transform-property-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", - "integrity": "sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA==", - "requires": { - "esutils": "^2.0.2" - } - }, - "babel-plugin-transform-regexp-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", - "integrity": "sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g==" - }, - "babel-plugin-transform-remove-console": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", - "integrity": "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==" - }, - "babel-plugin-transform-remove-debugger": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", - "integrity": "sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw==" - }, - "babel-plugin-transform-remove-undefined": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", - "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-transform-simplify-comparison-operators": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", - "integrity": "sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A==" - }, - "babel-plugin-transform-titanium": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-titanium/-/babel-plugin-transform-titanium-0.1.1.tgz", - "integrity": "sha512-N2ImhDNsfmT5Q68HeNJfg1xE8Z3NsVYWC+/TWLtckscXPjleDJRciIRzhUhI6876VXhxSjbw5s7ylv1NTa/xoA==" - }, - "babel-plugin-transform-undefined-to-void": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", - "integrity": "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==" - }, - "babel-preset-minify": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.2.tgz", - "integrity": "sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w==", - "requires": { - "babel-plugin-minify-builtins": "^0.5.0", - "babel-plugin-minify-constant-folding": "^0.5.0", - "babel-plugin-minify-dead-code-elimination": "^0.5.2", - "babel-plugin-minify-flip-comparisons": "^0.4.3", - "babel-plugin-minify-guarded-expressions": "^0.4.4", - "babel-plugin-minify-infinity": "^0.4.3", - "babel-plugin-minify-mangle-names": "^0.5.1", - "babel-plugin-minify-numeric-literals": "^0.4.3", - "babel-plugin-minify-replace": "^0.5.0", - "babel-plugin-minify-simplify": "^0.5.1", - "babel-plugin-minify-type-constructors": "^0.4.3", - "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", - "babel-plugin-transform-member-expression-literals": "^6.9.4", - "babel-plugin-transform-merge-sibling-variables": "^6.9.5", - "babel-plugin-transform-minify-booleans": "^6.9.4", - "babel-plugin-transform-property-literals": "^6.9.4", - "babel-plugin-transform-regexp-constructors": "^0.4.3", - "babel-plugin-transform-remove-console": "^6.9.4", - "babel-plugin-transform-remove-debugger": "^6.9.4", - "babel-plugin-transform-remove-undefined": "^0.5.0", - "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", - "babel-plugin-transform-undefined-to-void": "^6.9.4", - "lodash": "^4.17.11" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", - "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "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==", - "dev": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==" - }, - "cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true - }, - "cacheable-request": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz", - "integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - } - } - }, - "caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - } - }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "dependencies": { - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - } - } - }, - "caniuse-lite": { - "version": "1.0.30001469", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", - "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==" - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==" - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - } - }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" - }, - "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "dev": true - }, - "colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true - }, - "compare-func": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", - "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^5.1.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "conventional-changelog-angular": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", - "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "q": "^1.5.1" - } - }, - "conventional-changelog-conventionalcommits": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz", - "integrity": "sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==", - "dev": true, - "requires": { - "compare-func": "^2.0.0", - "lodash": "^4.17.15", - "q": "^1.5.1" - } - }, - "conventional-commits-parser": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz", - "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==", - "dev": true, - "requires": { - "is-text-path": "^1.0.1", - "JSONStream": "^1.0.4", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" - }, - "core-js": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", - "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", - "dev": true - }, - "core-js-compat": { - "version": "3.29.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.29.1.tgz", - "integrity": "sha512-QmchCua884D8wWskMX8tW5ydINzd8oSJVx38lx/pVkFGqztxt73GYre3pm/hyYq8bPf+MW5In4I/uRShFDsbrA==", - "requires": { - "browserslist": "^4.21.5" - } - }, - "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==" - }, - "cosmiconfig": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", - "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", - "dev": true, - "requires": { - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0" - } - }, - "cosmiconfig-typescript-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz", - "integrity": "sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==", - "dev": true, - "requires": {} - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "danger": { - "version": "11.2.4", - "resolved": "https://registry.npmjs.org/danger/-/danger-11.2.4.tgz", - "integrity": "sha512-9tSrDm79+vWijG3zLXp6DQFmUqFLXg8Fl3jZmPhymlfsmAX0NaAc4HbC81pTOsSgOdiJfJHWpDwKu7fsTktFOQ==", - "dev": true, - "requires": { - "@gitbeaker/node": "^21.3.0", - "@octokit/rest": "^18.12.0", - "async-retry": "1.2.3", - "chalk": "^2.3.0", - "commander": "^2.18.0", - "core-js": "^3.8.2", - "debug": "^4.1.1", - "fast-json-patch": "^3.0.0-1", - "get-stdin": "^6.0.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.1", - "hyperlinker": "^1.0.0", - "json5": "^2.1.0", - "jsonpointer": "^5.0.0", - "jsonwebtoken": "^9.0.0", - "lodash.find": "^4.6.0", - "lodash.includes": "^4.3.0", - "lodash.isobject": "^3.0.2", - "lodash.keys": "^4.0.8", - "lodash.mapvalues": "^4.6.0", - "lodash.memoize": "^4.1.2", - "memfs-or-file-map-to-github-branch": "^1.2.1", - "micromatch": "^4.0.4", - "node-cleanup": "^2.1.2", - "node-fetch": "^2.6.7", - "override-require": "^1.1.1", - "p-limit": "^2.1.0", - "parse-diff": "^0.7.0", - "parse-git-config": "^2.0.3", - "parse-github-url": "^1.0.2", - "parse-link-header": "^2.0.0", - "pinpoint": "^1.1.0", - "prettyjson": "^1.2.1", - "readline-sync": "^1.4.9", - "regenerator-runtime": "^0.13.9", - "require-from-string": "^2.0.2", - "supports-hyperlinks": "^1.0.1" - } - }, - "dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", - "dev": true - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true - } - } - }, - "decode-uri-component": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", - "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", - "dev": true - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "default-require-extensions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz", - "integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==", - "dev": true, - "requires": { - "strip-bom": "^4.0.0" - } - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", - "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dot-prop": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", - "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", - "dev": true, - "requires": { - "is-obj": "^2.0.0" - } - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "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==", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "electron-to-chromium": { - "version": "1.4.340", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.340.tgz", - "integrity": "sha512-zx8hqumOqltKsv/MF50yvdAlPF9S/4PXbyfzJS6ZGhbddGkRegdwImmfSVqCkEziYzrIGZ/TlrzBND4FysfkDg==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", - "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" - } - }, - "es-array-method-boxes-properly": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true - }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - } - }, - "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" - } - }, - "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", - "dev": true, - "requires": { - "has": "^1.0.3" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" - }, - "eslint": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.4.0.tgz", - "integrity": "sha512-gU+lxhlPHu45H3JkEGgYhWhkR9wLHHEXC9FbWFnTlEkbKyZKWgWRLgf61E8zWmBuI6g5xKBph9ltg3NtZMVF8g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", - "esquery": "^1.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^5.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.0.0", - "globals": "^12.1.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash": "^4.17.14", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^5.2.3", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "globals": { - "version": "12.4.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", - "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", - "dev": true, - "requires": { - "type-fest": "^0.8.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "eslint-config-axway": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/eslint-config-axway/-/eslint-config-axway-6.0.2.tgz", - "integrity": "sha512-+O+kCrTycij3Vyk+hJtljZy/Xa/Xz0PdkJm4c4DRed6YT7JuSVpoH4UPCST/xCT9/Nonpy8VuyuZTa3kneHdjw==", - "dev": true, - "requires": { - "eslint-plugin-chai-expect": "^2.2.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^5.1.0", - "eslint-plugin-security": "^1.4.0", - "find-root": "^1.1.0", - "semver": "^7.3.4" - } - }, - "eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-chai-expect": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-chai-expect/-/eslint-plugin-chai-expect-2.2.0.tgz", - "integrity": "sha512-ExTJKhgeYMfY8wDj3UiZmgpMKJOUHGNHmWMlxT49JUDB1vTnw0sSNfXJSxnX+LcebyBD/gudXzjzD136WqPJrQ==", - "dev": true, - "requires": {} - }, - "eslint-plugin-es": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", - "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", - "dev": true, - "requires": { - "eslint-utils": "^2.0.0", - "regexpp": "^3.0.0" - } - }, - "eslint-plugin-import": { - "version": "2.27.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", - "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", - "dev": true, - "requires": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.7.4", - "has": "^1.0.3", - "is-core-module": "^2.11.0", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.values": "^1.1.6", - "resolve": "^1.22.1", - "semver": "^6.3.0", - "tsconfig-paths": "^3.14.1" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-plugin-mocha": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-9.0.0.tgz", - "integrity": "sha512-d7knAcQj1jPCzZf3caeBIn3BnW6ikcvfz0kSqQpwPYcVGLoJV5sz0l0OJB2LR8I7dvTDbqq1oV6ylhSgzA10zg==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "ramda": "^0.27.1" - }, - "dependencies": { - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - } - } - } - }, - "eslint-plugin-node": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", - "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", - "dev": true, - "requires": { - "eslint-plugin-es": "^3.0.0", - "eslint-utils": "^2.0.0", - "ignore": "^5.1.1", - "minimatch": "^3.0.4", - "resolve": "^1.10.1", - "semver": "^6.1.0" - }, - "dependencies": { - "ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", - "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", - "dev": true, - "requires": {} - }, - "eslint-plugin-security": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.7.1.tgz", - "integrity": "sha512-sMStceig8AFglhhT2LqlU5r+/fn9OwsA72O5bBuQVTssPCdQAOQzL+oMn/ZcpeUY6KcNfLJArgcrsSULNjYYdQ==", - "dev": true, - "requires": { - "safe-regex": "^2.1.1" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^1.1.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - }, - "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, - "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - } - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" - }, - "execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-patch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", - "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", - "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", - "dev": true, - "requires": { - "flat-cache": "^2.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "filter-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", - "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==", - "dev": true - }, - "find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - } - }, - "flat-cache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", - "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", - "dev": true, - "requires": { - "flatted": "^2.0.0", - "rimraf": "2.6.3", - "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==" - }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "fromentries": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", - "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", - "dev": true - }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha512-cR/vflFyPZtrN6b38ZyWxpWdhlXrzZEBawlpBQMq7033xVY7/kg0GDMBK5jg8lDYQckdJ5x/YC88lM3C7VMsLg==", - "dev": true - }, - "fs-extra": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", - "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" - } - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-stdin": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-6.0.0.tgz", - "integrity": "sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==", - "dev": true - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - } - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-config-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/git-config-path/-/git-config-path-1.0.1.tgz", - "integrity": "sha512-KcJ2dlrrP5DbBnYIZ2nlikALfRhKzNSX0stvv3ImJ+fvC4hXKoV+U+74SV0upg+jlQZbrtQzc0bu6/Zh+7aQbg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "fs-exists-sync": "^0.1.0", - "homedir-polyfill": "^1.0.0" - } - }, - "git-raw-commits": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", - "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", - "dev": true, - "requires": { - "dargs": "^7.0.0", - "lodash": "^4.17.15", - "meow": "^8.0.0", - "split2": "^3.0.0", - "through2": "^4.0.0" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" - }, - "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } - }, - "got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "requires": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==" - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "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" - } - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - } - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" - } - }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - } - } - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "requires": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true - }, - "husky": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", - "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", - "dev": true - }, - "hyperlinker": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/hyperlinker/-/hyperlinker-1.0.0.tgz", - "integrity": "sha512-Ty8UblRWFEcfSuIaajM34LdPXIhbs1ajEX/BBPv24J+enSVaEVY63xQ6lTO9VRYS5LAoghIG0IDJ+p+IPzKUQQ==", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - } - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", - "dev": true, - "requires": { - "has-bigints": "^1.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "dev": true - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "requires": { - "has": "^1.0.3" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true - }, - "is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true - }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } - }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true - }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.2" - } - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" - }, - "istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "requires": { - "append-transform": "^2.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-processinfo": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz", - "integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.3", - "istanbul-lib-coverage": "^3.2.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^8.3.2" - }, - "dependencies": { - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "iterate-iterator": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", - "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", - "dev": true - }, - "iterate-value": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", - "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", - "dev": true, - "requires": { - "es-get-iterator": "^1.0.2", - "iterate-iterator": "^1.0.1" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==" - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" - }, - "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-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "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==" - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true - }, - "jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "dev": true - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", - "dev": true, - "requires": { - "jws": "^3.2.2", - "lodash": "^4.17.21", - "ms": "^2.1.1", - "semver": "^7.3.8" - } - }, - "jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dev": true, - "requires": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dev": true, - "requires": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, - "keyv": { - "version": "4.5.2", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.2.tgz", - "integrity": "sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "requires": { - "leven": "^3.1.0" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "li": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/li/-/li-1.3.0.tgz", - "integrity": "sha512-z34TU6GlMram52Tss5mt1m//ifRIpKH5Dqm7yUVOdHI+BQCs9qGPHFaCUTIzsWX7edN30aa2WrPwR7IO10FHaw==", - "dev": true - }, - "lilconfig": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", - "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "lint-staged": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.0.tgz", - "integrity": "sha512-GbyK5iWinax5Dfw5obm2g2ccUiZXNGtAS4mCbJ0Lv4rq6iEtfBSjOYdcbOtAIFtM114t0vdpViDDetjVTSd8Vw==", - "dev": true, - "requires": { - "chalk": "5.2.0", - "cli-truncate": "^3.1.0", - "commander": "^10.0.0", - "debug": "^4.3.4", - "execa": "^7.0.0", - "lilconfig": "2.1.0", - "listr2": "^5.0.7", - "micromatch": "^4.0.5", - "normalize-path": "^3.0.0", - "object-inspect": "^1.12.3", - "pidtree": "^0.6.0", - "string-argv": "^0.3.1", - "yaml": "^2.2.1" - }, - "dependencies": { - "chalk": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz", - "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==", - "dev": true - }, - "commander": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.0.tgz", - "integrity": "sha512-zS5PnTI22FIRM6ylNW8G4Ap0IEOyk62fhLSD0+uHRT9McRCLGpkVNvao4bjimpK/GShynyQkFFxHhwMcETmduA==", - "dev": true - }, - "execa": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", - "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.1", - "human-signals": "^4.3.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^3.0.7", - "strip-final-newline": "^3.0.0" - } - }, - "human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "npm-run-path": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", - "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - } - } - }, - "listr2": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz", - "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==", - "dev": true, - "requires": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.19", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.8.0", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "requires": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "lodash.find": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha512-yaRZoAV3Xq28F1iafWN1+a0rflOej93l1DQUejs3SZ41h2O9UJBoS9aueGjPDgAl4B6tPC0NuuchLKaDQQ3Isg==", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", - "dev": true - }, - "lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "dev": true - }, - "lodash.isfunction": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", - "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", - "dev": true - }, - "lodash.isobject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz", - "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, - "lodash.kebabcase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", - "dev": true - }, - "lodash.keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-4.2.0.tgz", - "integrity": "sha512-J79MkJcp7Df5mizHiVNpjoHXLi4HLjh9VLS/M7lQSGoQ+0oQ+lWEigREkqKyizPB1IawvQLLKY8mzEcm1tkyxQ==", - "dev": true - }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==", - "dev": true - }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", - "dev": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.mergewith": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true - }, - "lodash.snakecase": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", - "dev": true - }, - "lodash.startcase": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", - "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", - "dev": true - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", - "dev": true - }, - "lodash.upperfirst": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - } - }, - "log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "requires": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - } - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true - }, - "memfs-or-file-map-to-github-branch": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/memfs-or-file-map-to-github-branch/-/memfs-or-file-map-to-github-branch-1.2.1.tgz", - "integrity": "sha512-I/hQzJ2a/pCGR8fkSQ9l5Yx+FQ4e7X6blNHyWBm2ojeFLT3GVzGkTj7xnyWpdclrr7Nq4dmx3xrvu70m3ypzAQ==", - "dev": true, - "requires": { - "@octokit/rest": "^16.43.0 || ^17.11.0 || ^18.12.0" - } - }, - "meow": { - "version": "8.1.2", - "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", - "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "dependencies": { - "type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true - } - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "mocha": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.1.tgz", - "integrity": "sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.3.1", - "debug": "3.2.6", - "diff": "4.0.2", - "escape-string-regexp": "1.0.5", - "find-up": "4.1.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "ms": "2.1.2", - "object.assign": "4.1.0", - "promise.allsettled": "1.0.2", - "serialize-javascript": "4.0.0", - "strip-json-comments": "3.0.1", - "supports-color": "7.1.0", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.0.0", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.1" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "mocha-jenkins-reporter": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/mocha-jenkins-reporter/-/mocha-jenkins-reporter-0.4.8.tgz", - "integrity": "sha512-1nz1Q+YgREUlh2kgFR+lrp+ufEFbdhCdtlEVEJR/5LhgqNLIg52+KG3X94hHpwWnf5SwYLS7udxgBbkWOUbyeQ==", - "dev": true, - "requires": { - "diff": "4.0.1", - "mkdirp": "^1.0.4", - "xml": "^1.0.1" - }, - "dependencies": { - "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", - "dev": true - } - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node-appc": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/node-appc/-/node-appc-1.1.6.tgz", - "integrity": "sha512-ZfoHjoDLpNfXYBshztIq+aTjtlvCZF4XAE00ZYNk4u+/qAjQI+8BidCn957b69WzronQtyNw2NtnJEhsP3N7EQ==", - "requires": { - "@xmldom/xmldom": "^0.8.6", - "async": "^3.2.4", - "colors": "1.4.0", - "fs-extra": "~9.1.0", - "request": "~2.88.0", - "semver": "~7.3.8", - "sprintf": "^0.1.5", - "temp": "~0.9.4", - "uuid": "~9.0.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "@xmldom/xmldom": { - "version": "0.8.6", - "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.6.tgz", - "integrity": "sha512-uRjjusqpoqfmRkTaNuLJ2VohVr67Q5YwDATW3VU7PfzTj6IRaihGrYI7zckGZjxQPBIp63nfvJbM+Yu5ICh0Bg==" - }, - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } - } - }, - "node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==", - "dev": true - }, - "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "requires": { - "process-on-spawn": "^1.0.0" - } - }, - "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" - }, - "node-uuid": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", - "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==" - }, - "normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "requires": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" - }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "requires": { - "mimic-fn": "^2.1.0" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "override-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/override-require/-/override-require-1.1.1.tgz", - "integrity": "sha512-eoJ9YWxFcXbrn2U8FKT6RV+/Kj7fiGAB1VvHzbYKt8xM5ZuKZgCGvnHzDxmreEjcBH28ejg5MiOH4iyY1mQnkg==", - "dev": true - }, - "p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - }, - "dependencies": { - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - } - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-diff": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/parse-diff/-/parse-diff-0.7.1.tgz", - "integrity": "sha512-1j3l8IKcy4yRK2W4o9EYvJLSzpAVwz4DXqCewYyx2vEwk2gcf3DBPqc8Fj4XV3K33OYJ08A8fWwyu/ykD/HUSg==", - "dev": true - }, - "parse-git-config": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/parse-git-config/-/parse-git-config-2.0.3.tgz", - "integrity": "sha512-Js7ueMZOVSZ3tP8C7E3KZiHv6QQl7lnJ+OkbxoaFazzSa2KyEHqApfGbU3XboUgUnq4ZuUmskUpYKTNx01fm5A==", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "git-config-path": "^1.0.1", - "ini": "^1.3.5" - } - }, - "parse-github-url": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-github-url/-/parse-github-url-1.0.2.tgz", - "integrity": "sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==", - "dev": true - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "parse-link-header": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-link-header/-/parse-link-header-2.0.0.tgz", - "integrity": "sha512-xjU87V0VyHZybn2RrCX5TIFGxTVZE6zqqZWMPlIKiSKuWh/X5WZdt+w1Ki1nXB+8L/KtL+nZ4iq+sfI6MrhhMw==", - "dev": true, - "requires": { - "xtend": "~4.0.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" - }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "pinpoint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pinpoint/-/pinpoint-1.1.0.tgz", - "integrity": "sha512-+04FTD9x7Cls2rihLlo57QDCcHoLBGn5Dk51SwtFBWkUWLxZaBXyNVpCw1S+atvE7GmnFjeaRZ0WLq3UYuqAdg==", - "dev": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - } - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.7.tgz", - "integrity": "sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==", - "dev": true - }, - "prettyjson": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/prettyjson/-/prettyjson-1.2.5.tgz", - "integrity": "sha512-rksPWtoZb2ZpT5OVgtmy0KHVM+Dca3iVwWY9ifwhcexfjebtgjg3wmrUt9PvJ59XIYBcknQeYHD8IAnVlh9lAw==", - "dev": true, - "requires": { - "colors": "1.4.0", - "minimist": "^1.2.0" - } - }, - "process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "requires": { - "fromentries": "^1.2.0" - } - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "promise.allsettled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/promise.allsettled/-/promise.allsettled-1.0.2.tgz", - "integrity": "sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg==", - "dev": true, - "requires": { - "array.prototype.map": "^1.0.1", - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "iterate-value": "^1.0.0" - } - }, - "psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==" - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", - "dev": true - }, - "qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==" - }, - "query-string": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", - "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", - "dev": true, - "requires": { - "decode-uri-component": "^0.2.0", - "filter-obj": "^1.1.0", - "split-on-first": "^1.0.0", - "strict-uri-encode": "^2.0.0" - } - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "ramda": { - "version": "0.27.2", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.2.tgz", - "integrity": "sha512-SbiLPU40JuJniHexQSAgad32hfwd+DRUdwF2PlVuI5RZD0/vahUco7R8vD86J/tcEKKF9vZrUVwgtmGCqlCKyA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.7" - } - }, - "readline-sync": { - "version": "1.4.10", - "resolved": "https://registry.npmjs.org/readline-sync/-/readline-sync-1.4.10.tgz", - "integrity": "sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==", - "dev": true - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" - }, - "regenerate-unicode-properties": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz", - "integrity": "sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==", - "requires": { - "regenerate": "^1.4.2" - } - }, - "regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" - }, - "regenerator-transform": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.1.tgz", - "integrity": "sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==", - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regexp-tree": { - "version": "0.1.24", - "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.24.tgz", - "integrity": "sha512-s2aEVuLhvnVJW6s/iPgEGK6R+/xngd2jNQ+xy4bXNDKxZKJH6jpPHY6kVeVv1IeLCHgswRj+Kl3ELaDjG6V1iw==", - "dev": true - }, - "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "requires": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - } - }, - "regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" - } - } - }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "requires": { - "is-core-module": "^2.9.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "requires": { - "global-dirs": "^0.1.1" - } - }, - "responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "requires": { - "lowercase-keys": "^2.0.0" - } - }, - "restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "requires": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - } - }, - "retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true - }, - "rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rxjs": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", - "dev": true, - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safe-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-2.1.1.tgz", - "integrity": "sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A==", - "dev": true, - "requires": { - "regexp-tree": "~0.1.1" - } - }, - "safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - } - } - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "should": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", - "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", - "dev": true, - "requires": { - "should-equal": "^2.0.0", - "should-format": "^3.0.3", - "should-type": "^1.4.0", - "should-type-adaptors": "^1.0.1", - "should-util": "^1.0.0" - } - }, - "should-equal": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", - "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", - "dev": true, - "requires": { - "should-type": "^1.4.0" - } - }, - "should-format": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", - "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-type-adaptors": "^1.0.1" - } - }, - "should-type": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", - "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==", - "dev": true - }, - "should-type-adaptors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", - "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", - "dev": true, - "requires": { - "should-type": "^1.3.0", - "should-util": "^1.0.0" - } - }, - "should-util": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", - "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", - "dev": true - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" - }, - "spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - } - }, - "spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, - "split-on-first": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", - "dev": true - }, - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dev": true, - "requires": { - "readable-stream": "^3.0.0" - } - }, - "sprintf": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/sprintf/-/sprintf-0.1.5.tgz", - "integrity": "sha512-4X5KsuXFQ7f+d7Y+bi4qSb6eI+YoifDTGr0MQJXRoYO7BO7evfRCjds6kk3z7l5CiJYxgDN1x5Er4WiyCt+zTQ==" - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", - "dev": true, - "requires": { - "internal-slot": "^1.0.4" - } - }, - "stream-splitter": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/stream-splitter/-/stream-splitter-0.3.2.tgz", - "integrity": "sha512-9VAHJIhskQFJMbyKbf/5flSXV2HsP9MDFdCp3A8WDBWkZ8tP/SOfkI2c5lEHNNUNzbWdNkJEv6iNvQRJnSbYuA==", - "requires": { - "buffers": "~0.1.1" - } - }, - "strict-uri-encode": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", - "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==", - "dev": true - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz", - "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true - }, - "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "requires": { - "has-flag": "^3.0.0" - } - }, - "supports-hyperlinks": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-1.0.1.tgz", - "integrity": "sha512-HHi5kVSefKaJkGYXbDuKbUGRVxqnWGn3J2e39CYcNJEfWciGq2zYtOhXLTlvrOZW1QU7VX67w7fMmWafHX9Pfw==", - "dev": true, - "requires": { - "has-flag": "^2.0.0", - "supports-color": "^5.0.0" - }, - "dependencies": { - "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==", - "dev": true - } - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" - }, - "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" - } - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "temp": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "requires": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "requires": { - "minimist": "^1.2.6" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "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==", - "dev": true - }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dev": true, - "requires": { - "readable-stream": "3" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "dev": true, - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "dependencies": { - "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", - "dev": true - } - } - }, - "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - } - } - }, - "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true - }, - "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" - } - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typescript": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.2.tgz", - "integrity": "sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw==", - "dev": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" - }, - "unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "requires": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==" - }, - "unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==" - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - }, - "unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==" - }, - "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", - "requires": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, - "uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", - "dev": true - }, - "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" - } - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "workerpool": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.0.tgz", - "integrity": "sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "write": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", - "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - }, - "dependencies": { - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - } - } - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xcase": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xcase/-/xcase-2.0.1.tgz", - "integrity": "sha512-UmFXIPU+9Eg3E9m/728Bii0lAIuoc+6nbrNUKaRPJOFp91ih44qqGlWtxMB6kXFrRD6po+86ksHM5XHCfk6iPw==", - "dev": true - }, - "xml": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", - "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", - "dev": true - }, - "xmldom": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.6.0.tgz", - "integrity": "sha512-iAcin401y58LckRZ0TkI4k0VSM1Qg0KGSc3i8rU+xrxe19A/BN1zHyVSJY7uoutVlaTSzYyk/v5AmkewAP7jtg==" - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, - "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", - "dev": true - }, - "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "dependencies": { - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } - } - }, - "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true - }, - "yargs-unparser": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", - "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "decamelize": "^1.2.0", - "flat": "^4.1.0", - "is-plain-obj": "^1.1.0", - "yargs": "^14.2.3" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - } - }, - "yargs-parser": { - "version": "15.0.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.3.tgz", - "integrity": "sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } - } -} diff --git a/package.json b/package.json index 45141682..0778a887 100644 --- a/package.json +++ b/package.json @@ -1,89 +1,96 @@ { "name": "node-titanium-sdk", - "description": "Appcelerator Titanium SDK Library", + "version": "7.0.0", + "description": "Titanium SDK Library", "keywords": [ - "appcelerator", + "mobile", + "tidev", "titanium", - "mobile" + "titanium-sdk" ], - "version": "6.1.0", - "author": "TiDev, Inc. ", + "homepage": "https://github.com/tidev/node-titanium-sdk", + "bugs": "https://github.com/tidev/node-titanium-sdk/issues", "license": "Apache-2.0", - "main": "./lib/titanium", - "directories": { - "lib": "./lib" + "author": "TiDev, Inc. ", + "repository": { + "type": "git", + "url": "https://github.com/tidev/node-titanium-sdk" + }, + "files": [ + "bin", + "dist" + ], + "type": "module", + "module": "./dist/index.mjs", + "exports": { + ".": { + "types": "./dist/index.d.js", + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" + }, + "./android": { + "types": "./dist/android/index.d.js", + "import": "./dist/android/index.mjs", + "require": "./dist/android/index.cjs" + }, + "./jdk": { + "types": "./dist/jdk/index.d.js", + "import": "./dist/jdk/index.mjs", + "require": "./dist/jdk/index.cjs" + }, + "./titanium": { + "types": "./dist/titanium/index.d.js", + "import": "./dist/titanium/index.mjs", + "require": "./dist/titanium/index.cjs" + }, + "./util": { + "types": "./dist/util/index.d.js", + "import": "./dist/util/index.mjs", + "require": "./dist/util/index.cjs" + } + }, + "scripts": { + "build": "rimraf dist && tsdown -c tsdown.config.ts", + "check": "pnpm type-check && pnpm lint && pnpm fmt:check", + "coverage": "vitest --coverage", + "fmt": "oxfmt", + "fmt:check": "oxfmt --check", + "lint": "oxlint", + "prepublishOnly": "pnpm run build", + "test": "cross-env CI=1 vitest", + "test:bun": "cross-env CI=1 bun --bun --config=bunfig.toml ./node_modules/vitest/vitest.mjs --reporter=verbose", + "test:deno": "cross-env CI=1 deno run --allow-all --sloppy-imports ./node_modules/vitest/vitest.mjs", + "type-check": "tsc --noEmit" }, "dependencies": { - "@babel/core": "7.11.6", - "@babel/parser": "7.11.5", - "@babel/plugin-transform-property-literals": "7.10.1", - "@babel/preset-env": "7.10.2", - "async": "3.2.4", + "@babel/core": "7.29.0", + "@babel/parser": "7.29.2", + "@babel/plugin-transform-property-literals": "7.27.1", + "@babel/preset-env": "7.29.2", + "@xmldom/xmldom": "0.8.11", "babel-plugin-transform-titanium": "0.1.1", "babel-preset-minify": "0.5.2", - "colors": "1.4.0", - "fs-extra": "11.1.1", - "node-appc": "1.1.6", - "node-uuid": "1.4.8", + "semver": "7.7.4", + "simple-plist": "1.3.1", + "snooplogg": "6.1.1", "stream-splitter": "0.3.2", - "unorm": "1.6.0", - "xmldom": "0.6.0" + "undici": "7.24.5", + "which": "6.0.1", + "yauzl": "3.2.1", + "zod": "4.3.6" }, "devDependencies": { - "@commitlint/cli": "17.5.0", - "@commitlint/config-conventional": "17.4.4", - "@seadub/danger-plugin-dependencies": "1.0.0", - "@seadub/danger-plugin-eslint": "2.0.0", - "@seadub/danger-plugin-junit": "0.3.0", - "babel-plugin-tester": "10.1.0", - "danger": "11.2.4", - "eslint": "7.4.0", - "eslint-config-axway": "6.0.2", - "eslint-plugin-mocha": "9.0.0", - "husky": "8.0.3", - "lint-staged": "13.2.0", - "mocha": "8.1.1", - "mocha-jenkins-reporter": "0.4.8", - "nyc": "15.1.0", - "semver": "7.3.8", - "should": "13.2.3" - }, - "homepage": "https://github.com/tidev/node-titanium-sdk", - "bugs": "https://github.com/tidev/node-titanium-sdk/issues", - "repository": "https://github.com/tidev/node-titanium-sdk", - "scripts": { - "lint": "eslint .", - "test": "npm run lint && npm run unit-test", - "unit-test": "nyc mocha tests/*_test.js --exit", - "prepare": "husky install" - }, - "mocha": { - "timeout": 30000, - "check-leaks": true, - "reporter": "mocha-jenkins-reporter", - "reporter-option": "junit_report_path=junit_report.xml" - }, - "nyc": { - "check-coverage": true, - "lines": 56, - "statements": 56, - "functions": 60, - "branches": 40, - "exclude": [ - "tests/**/*.js", - "locales/**/*.js" - ], - "reporter": [ - "cobertura", - "text" - ] - }, - "lint-staged": { - "*.js": "eslint" - }, - "commitlint": { - "extends": [ - "@commitlint/config-conventional" - ] + "@types/node": "25.5.0", + "@vitest/coverage-v8": "4.1.0", + "babel-plugin-tester": "12.0.0", + "cross-env": "10.1.0", + "lefthook": "2.1.4", + "oxfmt": "0.41.0", + "oxlint": "1.56.0", + "proxy": "3.0.0", + "rimraf": "6.1.3", + "tsdown": "0.21.4", + "typescript": "5.9.3", + "vitest": "4.1.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 00000000..19845cea --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4329 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@babel/core': + specifier: 7.29.0 + version: 7.29.0 + '@babel/parser': + specifier: 7.29.2 + version: 7.29.2 + '@babel/plugin-transform-property-literals': + specifier: 7.27.1 + version: 7.27.1(@babel/core@7.29.0) + '@babel/preset-env': + specifier: 7.29.2 + version: 7.29.2(@babel/core@7.29.0) + '@xmldom/xmldom': + specifier: 0.8.11 + version: 0.8.11 + babel-plugin-transform-titanium: + specifier: 0.1.1 + version: 0.1.1 + babel-preset-minify: + specifier: 0.5.2 + version: 0.5.2 + semver: + specifier: 7.7.4 + version: 7.7.4 + simple-plist: + specifier: 1.3.1 + version: 1.3.1 + snooplogg: + specifier: 6.1.1 + version: 6.1.1 + stream-splitter: + specifier: 0.3.2 + version: 0.3.2 + undici: + specifier: 7.24.5 + version: 7.24.5 + which: + specifier: 6.0.1 + version: 6.0.1 + yauzl: + specifier: 3.2.1 + version: 3.2.1 + zod: + specifier: 4.3.6 + version: 4.3.6 + devDependencies: + '@types/node': + specifier: 25.5.0 + version: 25.5.0 + '@vitest/coverage-v8': + specifier: 4.1.0 + version: 4.1.0(vitest@4.1.0(@types/node@25.5.0)(vite@7.1.12(@types/node@25.5.0))) + babel-plugin-tester: + specifier: 12.0.0 + version: 12.0.0(@babel/core@7.29.0) + cross-env: + specifier: 10.1.0 + version: 10.1.0 + lefthook: + specifier: 2.1.4 + version: 2.1.4 + oxfmt: + specifier: 0.41.0 + version: 0.41.0 + oxlint: + specifier: 1.56.0 + version: 1.56.0 + proxy: + specifier: 3.0.0 + version: 3.0.0 + rimraf: + specifier: 6.1.3 + version: 6.1.3 + tsdown: + specifier: 0.21.4 + version: 0.21.4(typescript@5.9.3) + typescript: + specifier: 5.9.3 + version: 5.9.3 + vitest: + specifier: 4.1.0 + version: 4.1.0(@types/node@25.5.0)(vite@7.1.12(@types/node@25.5.0)) + +packages: + + '@-xun/debug@2.0.2': + resolution: {integrity: sha512-qGaZ4bUZJuWc+YzndcaeOudFmHu4plOcjQGdod/8gafcZY+9oHkrsZNmA1tWrEpQwJV9AJ4QkYgfpreZp9W/Hg==} + engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} + + '@-xun/fs@2.0.0': + resolution: {integrity: sha512-252CZ4OJRszsbP0n+vQRrhdFyDyEzt4NqYvJ/P2Iha4dw/jtmQvAF0wYqARPDZe7uuUG6Og0uQxMUfXFO2BQ7g==} + engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.6': + resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/generator@8.0.0-rc.2': + resolution: {integrity: sha512-oCQ1IKPwkzCeJzAPb7Fv8rQ9k5+1sG8mf2uoHiMInPYvkRfrDJxbTIbH51U+jstlkghus0vAi3EBvkfvEsYNLQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.6': + resolution: {integrity: sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@8.0.0-rc.2': + resolution: {integrity: sha512-noLx87RwlBEMrTzncWd/FvTxoJ9+ycHNg0n8yyYydIoDsLZuxknKgWRJUqcrVkNrJ74uGyhWQzQaS3q8xfGAhQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@8.0.0-rc.2': + resolution: {integrity: sha512-xExUBkuXWJjVuIbO7z6q7/BA9bgfJDEhVL0ggrggLMbg0IzCUWGT1hZGE8qUH7Il7/RD/a6cZ3AAFrrlp1LF/A==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.28.3': + resolution: {integrity: sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.6': + resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/parser@8.0.0-rc.2': + resolution: {integrity: sha512-29AhEtcq4x8Dp3T72qvUMZHx0OMXCj4Jy/TEReQa+KWLln524Cj1fWb3QFi0l/xSpptQBR6y9RNEXuxpFvwiUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': + resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.28.6': + resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.28.6': + resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.6': + resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.28.6': + resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.28.6': + resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.6': + resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.28.6': + resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.28.6': + resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.6': + resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.28.6': + resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.28.6': + resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6': + resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.0': + resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': + resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.28.6': + resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.6': + resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.28.6': + resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.28.6': + resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.28.6': + resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.28.6': + resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.28.6': + resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.28.6': + resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.28.6': + resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6': + resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.29.2': + resolution: {integrity: sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@babel/types@8.0.0-rc.2': + resolution: {integrity: sha512-91gAaWRznDwSX4E2tZ1YjBuIfnQVOFDCQ2r0Toby0gu4XEbyF623kXLMA8d4ZbCu+fINcrudkmEcwSUHgDDkNw==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@epic-web/invariant@1.0.0': + resolution: {integrity: sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==} + + '@esbuild/aix-ppc64@0.25.11': + resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.11': + resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.11': + resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.11': + resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.11': + resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.11': + resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.11': + resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.11': + resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.11': + resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.11': + resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.11': + resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.11': + resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.11': + resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.11': + resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.11': + resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.11': + resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.11': + resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.11': + resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.11': + resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.11': + resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.11': + resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.11': + resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.11': + resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.11': + resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.11': + resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.11': + resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@jest/schemas@30.0.5': + resolution: {integrity: sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@napi-rs/wasm-runtime@1.1.1': + resolution: {integrity: sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==} + + '@oxc-project/types@0.115.0': + resolution: {integrity: sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==} + + '@oxfmt/binding-android-arm-eabi@0.41.0': + resolution: {integrity: sha512-REfrqeMKGkfMP+m/ScX4f5jJBSmVNYcpoDF8vP8f8eYPDuPGZmzp56NIUsYmx3h7f6NzC6cE3gqh8GDWrJHCKw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.41.0': + resolution: {integrity: sha512-s0b1dxNgb2KomspFV2LfogC2XtSJB42POXF4bMCLJyvQmAGos4ZtjGPfQreToQEaY0FQFjz3030ggI36rF1q5g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.41.0': + resolution: {integrity: sha512-EGXGualADbv/ZmamE7/2DbsrYmjoPlAmHEpTL4vapLF4EfVD6fr8/uQDFnPJkUBjiSWFJZtFNsGeN1B6V3owmA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.41.0': + resolution: {integrity: sha512-WxySJEvdQQYMmyvISH3qDpTvoS0ebnIP63IMxLLWowJyPp/AAH0hdWtlo+iGNK5y3eVfa5jZguwNaQkDKWpGSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.41.0': + resolution: {integrity: sha512-Y2kzMkv3U3oyuYaR4wTfGjOTYTXiFC/hXmG0yVASKkbh02BJkvD98Ij8bIevr45hNZ0DmZEgqiXF+9buD4yMYQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.41.0': + resolution: {integrity: sha512-ptazDjdUyhket01IjPTT6ULS1KFuBfTUU97osTP96X5y/0oso+AgAaJzuH81oP0+XXyrWIHbRzozSAuQm4p48g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.41.0': + resolution: {integrity: sha512-UkoL2OKxFD+56bPEBcdGn+4juTW4HRv/T6w1dIDLnvKKWr6DbarB/mtHXlADKlFiJubJz8pRkttOR7qjYR6lTA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.41.0': + resolution: {integrity: sha512-gofu0PuumSOHYczD8p62CPY4UF6ee+rSLZJdUXkpwxg6pILiwSDBIouPskjF/5nF3A7QZTz2O9KFNkNxxFN9tA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-arm64-musl@0.41.0': + resolution: {integrity: sha512-VfVZxL0+6RU86T8F8vKiDBa+iHsr8PAjQmKGBzSCAX70b6x+UOMFl+2dNihmKmUwqkCazCPfYjt6SuAPOeQJ3g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-ppc64-gnu@0.41.0': + resolution: {integrity: sha512-bwzokz2eGvdfJbc0i+zXMJ4BBjQPqg13jyWpEEZDOrBCQ91r8KeY2Mi2kUeuMTZNFXju+jcAbAbpyJxRGla0eg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-gnu@0.41.0': + resolution: {integrity: sha512-POLM//PCH9uqDeNDwWL3b3DkMmI3oI2cU6hwc2lnztD1o7dzrQs3R9nq555BZ6wI7t2lyhT9CS+CRaz5X0XqLA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-musl@0.41.0': + resolution: {integrity: sha512-NNK7PzhFqLUwx/G12Xtm6scGv7UITvyGdAR5Y+TlqsG+essnuRWR4jRNODWRjzLZod0T3SayRbnkSIWMBov33w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-s390x-gnu@0.41.0': + resolution: {integrity: sha512-qVf/zDC5cN9eKe4qI/O/m445er1IRl6swsSl7jHkqmOSVfknwCe5JXitYjZca+V/cNJSU/xPlC5EFMabMMFDpw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-gnu@0.41.0': + resolution: {integrity: sha512-ojxYWu7vUb6ysYqVCPHuAPVZHAI40gfZ0PDtZAMwVmh2f0V8ExpPIKoAKr7/8sNbAXJBBpZhs2coypIo2jJX4w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-musl@0.41.0': + resolution: {integrity: sha512-O2exZLBxoCMIv2vlvcbkdedazJPTdG0VSup+0QUCfYQtx751zCZNboX2ZUOiQ/gDTdhtXvSiot0h6GEGkOyalA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-openharmony-arm64@0.41.0': + resolution: {integrity: sha512-N+31/VoL+z+NNBt8viy3I4NaIdPbiYeOnB884LKqvXldaE2dRztdPv3q5ipfZYv0RwFp7JfqS4I27K/DSHCakg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.41.0': + resolution: {integrity: sha512-Z7NAtu/RN8kjCQ1y5oDD0nTAeRswh3GJ93qwcW51srmidP7XPBmZbLlwERu1W5veCevQJtPS9xmkpcDTYsGIwQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.41.0': + resolution: {integrity: sha512-uNxxP3l4bJ6VyzIeRqCmBU2Q0SkCFgIhvx9/9dJ9V8t/v+jP1IBsuaLwCXGR8JPHtkj4tFp+RHtUmU2ZYAUpMA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.41.0': + resolution: {integrity: sha512-49ZSpbZ1noozyPapE8SUOSm3IN0Ze4b5nkO+4+7fq6oEYQQJFhE0saj5k/Gg4oewVPdjn0L3ZFeWk2Vehjcw7A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxlint/binding-android-arm-eabi@1.56.0': + resolution: {integrity: sha512-IyfYPthZyiSKwAv/dLjeO18SaK8MxLI9Yss2JrRDyweQAkuL3LhEy7pwIwI7uA3KQc1Vdn20kdmj3q0oUIQL6A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.56.0': + resolution: {integrity: sha512-Ga5zYrzH6vc/VFxhn6MmyUnYEfy9vRpwTIks99mY3j6Nz30yYpIkWryI0QKPCgvGUtDSXVLEaMum5nA+WrNOSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.56.0': + resolution: {integrity: sha512-ogmbdJysnw/D4bDcpf1sPLpFThZ48lYp4aKYm10Z/6Nh1SON6NtnNhTNOlhEY296tDFItsZUz+2tgcSYqh8Eyw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.56.0': + resolution: {integrity: sha512-x8QE1h+RAtQ2g+3KPsP6Fk/tdz6zJQUv5c7fTrJxXV3GHOo+Ry5p/PsogU4U+iUZg0rj6hS+E4xi+mnwwlDCWQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.56.0': + resolution: {integrity: sha512-6G+WMZvwJpMvY7my+/SHEjb7BTk/PFbePqLpmVmUJRIsJMy/UlyYqjpuh0RCgYYkPLcnXm1rUM04kbTk8yS1Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.56.0': + resolution: {integrity: sha512-YYHBsk/sl7fYwQOok+6W5lBPeUEvisznV/HZD2IfZmF3Bns6cPC3Z0vCtSEOaAWTjYWN3jVsdu55jMxKlsdlhg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.56.0': + resolution: {integrity: sha512-+AZK8rOUr78y8WT6XkDb04IbMRqauNV+vgT6f8ZLOH8wnpQ9i7Nol0XLxAu+Cq7Sb+J9wC0j6Km5hG8rj47/yQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.56.0': + resolution: {integrity: sha512-urse2SnugwJRojUkGSSeH2LPMaje5Q50yQtvtL9HFckiyeqXzoFwOAZqD5TR29R2lq7UHidfFDM9EGcchcbb8A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.56.0': + resolution: {integrity: sha512-rkTZkBfJ4TYLjansjSzL6mgZOdN5IvUnSq3oNJSLwBcNvy3dlgQtpHPrRxrCEbbcp7oQ6If0tkNaqfOsphYZ9g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.56.0': + resolution: {integrity: sha512-uqL1kMH3u69/e1CH2EJhP3CP28jw2ExLsku4o8RVAZ7fySo9zOyI2fy9pVlTAp4voBLVgzndXi3SgtdyCTa2aA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.56.0': + resolution: {integrity: sha512-j0CcMBOgV6KsRaBdsebIeiy7hCjEvq2KdEsiULf2LZqAq0v1M1lWjelhCV57LxsqaIGChXFuFJ0RiFrSRHPhSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.56.0': + resolution: {integrity: sha512-7VDOiL8cDG3DQ/CY3yKjbV1c4YPvc4vH8qW09Vv+5ukq3l/Kcyr6XGCd5NvxUmxqDb2vjMpM+eW/4JrEEsUetA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.56.0': + resolution: {integrity: sha512-JGRpX0M+ikD3WpwJ7vKcHKV6Kg0dT52BW2Eu2BupXotYeqGXBrbY+QPkAyKO6MNgKozyTNaRh3r7g+VWgyAQYQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.56.0': + resolution: {integrity: sha512-dNaICPvtmuxFP/VbqdofrLqdS3bM/AKJN3LMJD52si44ea7Be1cBk6NpfIahaysG9Uo+L98QKddU9CD5L8UHnQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.56.0': + resolution: {integrity: sha512-pF1vOtM+GuXmbklM1hV8WMsn6tCNPvkUzklj/Ej98JhlanbmA2RB1BILgOpwSuCTRTIYx2MXssmEyQQ90QF5aA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.56.0': + resolution: {integrity: sha512-bp8NQ4RE6fDIFLa4bdBiOA+TAvkNkg+rslR+AvvjlLTYXLy9/uKAYLQudaQouWihLD/hgkrXIKKzXi5IXOewwg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.56.0': + resolution: {integrity: sha512-PxT4OJDfMOQBzo3OlzFb9gkoSD+n8qSBxyVq2wQSZIHFQYGEqIRTo9M0ZStvZm5fdhMqaVYpOnJvH2hUMEDk/g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.56.0': + resolution: {integrity: sha512-PTRy6sIEPqy2x8PTP1baBNReN/BNEFmde0L+mYeHmjXE1Vlcc9+I5nsqENsB2yAm5wLkzPoTNCMY/7AnabT4/A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.56.0': + resolution: {integrity: sha512-ZHa0clocjLmIDr+1LwoWtxRcoYniAvERotvwKUYKhH41NVfl0Y4LNbyQkwMZzwDvKklKGvGZ5+DAG58/Ik47tQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@quansync/fs@1.0.0': + resolution: {integrity: sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==} + + '@rolldown/binding-android-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-rc.9': + resolution: {integrity: sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-rc.9': + resolution: {integrity: sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9': + resolution: {integrity: sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': + resolution: {integrity: sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': + resolution: {integrity: sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': + resolution: {integrity: sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': + resolution: {integrity: sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.9': + resolution: {integrity: sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9': + resolution: {integrity: sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.9': + resolution: {integrity: sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-rc.9': + resolution: {integrity: sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw==} + + '@rollup/rollup-android-arm-eabi@4.52.5': + resolution: {integrity: sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.52.5': + resolution: {integrity: sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.52.5': + resolution: {integrity: sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.52.5': + resolution: {integrity: sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.52.5': + resolution: {integrity: sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.52.5': + resolution: {integrity: sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + resolution: {integrity: sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm-musleabihf@4.52.5': + resolution: {integrity: sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==} + cpu: [arm] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-arm64-gnu@4.52.5': + resolution: {integrity: sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-arm64-musl@4.52.5': + resolution: {integrity: sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-loong64-gnu@4.52.5': + resolution: {integrity: sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==} + cpu: [loong64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-ppc64-gnu@4.52.5': + resolution: {integrity: sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-gnu@4.52.5': + resolution: {integrity: sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-riscv64-musl@4.52.5': + resolution: {integrity: sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@rollup/rollup-linux-s390x-gnu@4.52.5': + resolution: {integrity: sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-gnu@4.52.5': + resolution: {integrity: sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.52.5': + resolution: {integrity: sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rollup/rollup-openharmony-arm64@4.52.5': + resolution: {integrity: sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.52.5': + resolution: {integrity: sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.52.5': + resolution: {integrity: sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.52.5': + resolution: {integrity: sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.52.5': + resolution: {integrity: sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.34.41': + resolution: {integrity: sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/jsesc@2.5.1': + resolution: {integrity: sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==} + + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + + '@vitest/coverage-v8@4.1.0': + resolution: {integrity: sha512-nDWulKeik2bL2Va/Wl4x7DLuTKAXa906iRFooIRPR+huHkcvp9QDkPQ2RJdmjOFrqOqvNfoSQLF68deE3xC3CQ==} + peerDependencies: + '@vitest/browser': 4.1.0 + vitest: 4.1.0 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@4.1.0': + resolution: {integrity: sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA==} + + '@vitest/mocker@4.1.0': + resolution: {integrity: sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@4.1.0': + resolution: {integrity: sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A==} + + '@vitest/runner@4.1.0': + resolution: {integrity: sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ==} + + '@vitest/snapshot@4.1.0': + resolution: {integrity: sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg==} + + '@vitest/spy@4.1.0': + resolution: {integrity: sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw==} + + '@vitest/utils@4.1.0': + resolution: {integrity: sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw==} + + '@xmldom/xmldom@0.8.11': + resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} + engines: {node: '>=10.0.0'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + args@5.0.3: + resolution: {integrity: sha512-h6k/zfFgusnv3i5TU08KQkVKuCPBtL/PWQbWkHUxvJrZ2nAyeaUupneemcrgn1xmqxPQsPIzwkUhOpoqPDRZuA==} + engines: {node: '>= 6.0.0'} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-kit@3.0.0-beta.1: + resolution: {integrity: sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw==} + engines: {node: '>=20.19.0'} + + ast-v8-to-istanbul@1.0.0: + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} + + babel-helper-evaluate-path@0.5.0: + resolution: {integrity: sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==} + + babel-helper-flip-expressions@0.4.3: + resolution: {integrity: sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA==} + + babel-helper-is-nodes-equiv@0.0.1: + resolution: {integrity: sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw==} + + babel-helper-is-void-0@0.4.3: + resolution: {integrity: sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg==} + + babel-helper-mark-eval-scopes@0.4.3: + resolution: {integrity: sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA==} + + babel-helper-remove-or-void@0.4.3: + resolution: {integrity: sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA==} + + babel-helper-to-multiple-sequence-expressions@0.5.0: + resolution: {integrity: sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==} + + babel-plugin-minify-builtins@0.5.0: + resolution: {integrity: sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==} + + babel-plugin-minify-constant-folding@0.5.0: + resolution: {integrity: sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==} + + babel-plugin-minify-dead-code-elimination@0.5.2: + resolution: {integrity: sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA==} + + babel-plugin-minify-flip-comparisons@0.4.3: + resolution: {integrity: sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A==} + + babel-plugin-minify-guarded-expressions@0.4.4: + resolution: {integrity: sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==} + + babel-plugin-minify-infinity@0.4.3: + resolution: {integrity: sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA==} + + babel-plugin-minify-mangle-names@0.5.1: + resolution: {integrity: sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw==} + + babel-plugin-minify-numeric-literals@0.4.3: + resolution: {integrity: sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A==} + + babel-plugin-minify-replace@0.5.0: + resolution: {integrity: sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==} + + babel-plugin-minify-simplify@0.5.1: + resolution: {integrity: sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==} + + babel-plugin-minify-type-constructors@0.4.3: + resolution: {integrity: sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ==} + + babel-plugin-polyfill-corejs2@0.4.15: + resolution: {integrity: sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.14.0: + resolution: {integrity: sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.6: + resolution: {integrity: sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-tester@12.0.0: + resolution: {integrity: sha512-V3ZFYmXPV9fm3ArpLHbvh0R5IfwnyFwlvdZ2FFQ49af4seC10U0JDWssjhXInuDDli6hyQsoOybGFSTCovrGyA==} + engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} + peerDependencies: + '@babel/core': '>=7.22.0' + + babel-plugin-transform-inline-consecutive-adds@0.4.3: + resolution: {integrity: sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q==} + + babel-plugin-transform-member-expression-literals@6.9.4: + resolution: {integrity: sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q==} + + babel-plugin-transform-merge-sibling-variables@6.9.5: + resolution: {integrity: sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw==} + + babel-plugin-transform-minify-booleans@6.9.4: + resolution: {integrity: sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA==} + + babel-plugin-transform-property-literals@6.9.4: + resolution: {integrity: sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA==} + + babel-plugin-transform-regexp-constructors@0.4.3: + resolution: {integrity: sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g==} + + babel-plugin-transform-remove-console@6.9.4: + resolution: {integrity: sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==} + + babel-plugin-transform-remove-debugger@6.9.4: + resolution: {integrity: sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw==} + + babel-plugin-transform-remove-undefined@0.5.0: + resolution: {integrity: sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==} + + babel-plugin-transform-simplify-comparison-operators@6.9.4: + resolution: {integrity: sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A==} + + babel-plugin-transform-titanium@0.1.1: + resolution: {integrity: sha512-N2ImhDNsfmT5Q68HeNJfg1xE8Z3NsVYWC+/TWLtckscXPjleDJRciIRzhUhI6876VXhxSjbw5s7ylv1NTa/xoA==} + + babel-plugin-transform-undefined-to-void@6.9.4: + resolution: {integrity: sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==} + + babel-preset-minify@0.5.2: + resolution: {integrity: sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w==} + + balanced-match@4.0.2: + resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==} + engines: {node: 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.8.20: + resolution: {integrity: sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==} + hasBin: true + + baseline-browser-mapping@2.9.19: + resolution: {integrity: sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==} + hasBin: true + + basic-auth-parser@0.0.2-1: + resolution: {integrity: sha512-GFj8iVxo9onSU6BnnQvVwqvxh60UcSHJEDnIk3z4B6iOjsKSmqe+ibW0Rsz7YO7IE1HG3D3tqCNIidP46SZVdQ==} + + big-integer@1.6.52: + resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} + engines: {node: '>=0.6'} + + birpc@4.0.0: + resolution: {integrity: sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==} + + bplist-creator@0.1.0: + resolution: {integrity: sha512-sXaHZicyEEmY86WyueLTQesbeoH/mquvarJaQNbjuOQO+7gbFcDEWqKmcWA4cOTLzFlfgvkiVxolk1k5bBIpmg==} + + bplist-parser@0.3.1: + resolution: {integrity: sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==} + engines: {node: '>= 5.10.0'} + + brace-expansion@5.0.2: + resolution: {integrity: sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw==} + engines: {node: 20 || >=22} + + browserslist@4.27.0: + resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffers@0.1.1: + resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} + engines: {node: '>=0.2.0'} + + cac@7.0.0: + resolution: {integrity: sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==} + engines: {node: '>=20.19.0'} + + camelcase@5.0.0: + resolution: {integrity: sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} + + caniuse-lite@1.0.30001769: + resolution: {integrity: sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + core-js-compat@3.48.0: + resolution: {integrity: sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==} + + core-js@3.46.0: + resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==} + + cross-env@10.1.0: + resolution: {integrity: sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==} + engines: {node: '>=20'} + hasBin: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + defu@6.1.4: + resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + + dts-resolver@2.1.3: + resolution: {integrity: sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw==} + engines: {node: '>=20.19.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + + electron-to-chromium@1.5.241: + resolution: {integrity: sha512-ILMvKX/ZV5WIJzzdtuHg8xquk2y0BOGlFOxBVwTpbiXqWIH0hamG45ddU4R3PQ0gYu+xgo0vdHXHli9sHIGb4w==} + + electron-to-chromium@1.5.286: + resolution: {integrity: sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==} + + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + + esbuild@0.25.11: + resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + exit-hook@4.0.0: + resolution: {integrity: sha512-Fqs7ChZm72y40wKjOFXBKg7nJZvQJmewP5/7LtePDdnah/+FH9Hp5sgMujSCMPXlxOAW2//1jrW9pnsY7o20vQ==} + engines: {node: '>=18'} + + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} + + glob@13.0.3: + resolution: {integrity: sha512-/g3B0mC+4x724v1TgtBlBtt2hPi/EWptsIAmXUx9Z2rvBYleQcsrmaOzd5LyL50jf/Soi83ZDJmw2+XqvH/EeA==} + engines: {node: 20 || >=22} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hookable@6.1.0: + resolution: {integrity: sha512-ZoKZSJgu8voGK2geJS+6YtYjvIzu9AOM/KZXsBxr83uhLL++e9pEv/dlgwgy3dvHg06kTz6JOh1hk3C8Ceiymw==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + import-without-cache@0.2.5: + resolution: {integrity: sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A==} + engines: {node: '>=20.19.0'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isexe@4.0.0: + resolution: {integrity: sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==} + engines: {node: '>=20'} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + js-tokens@10.0.0: + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + lefthook-darwin-arm64@2.1.4: + resolution: {integrity: sha512-BUAAE9+rUrjr39a+wH/1zHmGrDdwUQ2Yq/z6BQbM/yUb9qtXBRcQ5eOXxApqWW177VhGBpX31aqIlfAZ5Q7wzw==} + cpu: [arm64] + os: [darwin] + + lefthook-darwin-x64@2.1.4: + resolution: {integrity: sha512-K1ncIMEe84fe+ss1hQNO7rIvqiKy2TJvTFpkypvqFodT7mJXZn7GLKYTIXdIuyPAYthRa9DwFnx5uMoHwD2F1Q==} + cpu: [x64] + os: [darwin] + + lefthook-freebsd-arm64@2.1.4: + resolution: {integrity: sha512-PVUhjOhVN71YaYsVdQyNbFZ4a2jFB2Tg5hKrrn9kaWpx64aLz/XivLjwr8sEuTaP1GRlEWBpW6Bhrcsyo39qFw==} + cpu: [arm64] + os: [freebsd] + + lefthook-freebsd-x64@2.1.4: + resolution: {integrity: sha512-ZWV9o/LeyWNEBoVO+BhLqxH3rGTba05nkm5NvMjEFSj7LbUNUDbQmupZwtHl1OMGJO66eZP0CalzRfUH6GhBxQ==} + cpu: [x64] + os: [freebsd] + + lefthook-linux-arm64@2.1.4: + resolution: {integrity: sha512-iWN0pGnTjrIvNIcSI1vQBJXUbybTqJ5CLMniPA0olabMXQfPDrdMKVQe+mgdwHK+E3/Y0H0ZNL3lnOj6Sk6szA==} + cpu: [arm64] + os: [linux] + + lefthook-linux-x64@2.1.4: + resolution: {integrity: sha512-96bTBE/JdYgqWYAJDh+/e/0MaxJ25XTOAk7iy/fKoZ1ugf6S0W9bEFbnCFNooXOcxNVTan5xWKfcjJmPIKtsJA==} + cpu: [x64] + os: [linux] + + lefthook-openbsd-arm64@2.1.4: + resolution: {integrity: sha512-oYUoK6AIJNEr9lUSpIMj6g7sWzotvtc3ryw7yoOyQM6uqmEduw73URV/qGoUcm4nqqmR93ZalZwR2r3Gd61zvw==} + cpu: [arm64] + os: [openbsd] + + lefthook-openbsd-x64@2.1.4: + resolution: {integrity: sha512-i/Dv9Jcm68y9cggr1PhyUhOabBGP9+hzQPoiyOhKks7y9qrJl79A8XfG6LHekSuYc2VpiSu5wdnnrE1cj2nfTg==} + cpu: [x64] + os: [openbsd] + + lefthook-windows-arm64@2.1.4: + resolution: {integrity: sha512-hSww7z+QX4YMnw2lK7DMrs3+w7NtxksuMKOkCKGyxUAC/0m1LAICo0ZbtdDtZ7agxRQQQ/SEbzFRhU5ysNcbjA==} + cpu: [arm64] + os: [win32] + + lefthook-windows-x64@2.1.4: + resolution: {integrity: sha512-eE68LwnogxwcPgGsbVGPGxmghyMGmU9SdGwcc+uhGnUxPz1jL89oECMWJNc36zjVK24umNeDAzB5KA3lw1MuWw==} + cpu: [x64] + os: [win32] + + lefthook@2.1.4: + resolution: {integrity: sha512-JNfJ5gAn0KADvJ1I6/xMcx70+/6TL6U9gqGkKvPw5RNMfatC7jIg0Evl97HN846xmfz959BV70l8r3QsBJk30w==} + hasBin: true + + leven@2.1.0: + resolution: {integrity: sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==} + engines: {node: '>=0.10.0'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + magicast@0.5.2: + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.2.0: + resolution: {integrity: sha512-ugkC31VaVg9cF0DFVoADH12k6061zNZkZON+aX8AWsR9GhPcErkcMBceb6znR8wLERM2AkkOxy2nWRLpT9Jq5w==} + engines: {node: 20 || >=22} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mri@1.1.4: + resolution: {integrity: sha512-6y7IjGPm8AzlvoUrwAaw1tLnUBudaS3752vcd8JtrpGGQn+rXIe63LFVHm/YMwtqAuh+LJPCFdlLYPWM1nYn6w==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-releases@2.0.26: + resolution: {integrity: sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==} + + node-releases@2.0.27: + resolution: {integrity: sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + oxfmt@0.41.0: + resolution: {integrity: sha512-sKLdJZdQ3bw6x9qKiT7+eID4MNEXlDHf5ZacfIircrq6Qwjk0L6t2/JQlZZrVHTXJawK3KaMuBoJnEJPcqCEdg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + oxlint@1.56.0: + resolution: {integrity: sha512-Q+5Mj5PVaH/R6/fhMMFzw4dT+KPB+kQW4kaL8FOIq7tfhlnEVp6+3lcWqFruuTNlUo9srZUW3qH7Id4pskeR6g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.15.0' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@2.0.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + plist@3.1.0: + resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==} + engines: {node: '>=10.4.0'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@30.2.0: + resolution: {integrity: sha512-9uBdv/B4EefsuAL+pWqueZyZS2Ba+LxfFeQ9DN14HU4bN8bhaxKdkpjpB6fs9+pSjIBu+FXQHImEg8j/Lw0+vA==} + engines: {node: ^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0} + + proxy@3.0.0: + resolution: {integrity: sha512-3JQGizbKR8edoC+4EFkxCflh8toCZ3KbjYO10veRowcj+wHVJNIAavWo/BRUeez1kEHdvqad2ZZsCzSC2wOO+w==} + engines: {node: '>= 14'} + hasBin: true + + quansync@1.0.0: + resolution: {integrity: sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} + hasBin: true + + rejoinder@2.1.0: + resolution: {integrity: sha512-dLN0+SBPutC6bVFCH2+1o2VrHrvAj/PX6MzTemeaEKlCL10JKPMRlqszkitLQnHVgm90QQ94wxoBJRgfIEkstg==} + engines: {node: ^20.18.0 || ^22.12.0 || >=23.3.0} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + rimraf@6.1.3: + resolution: {integrity: sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA==} + engines: {node: 20 || >=22} + hasBin: true + + rolldown-plugin-dts@0.22.5: + resolution: {integrity: sha512-M/HXfM4cboo+jONx9Z0X+CUf3B5tCi7ni+kR5fUW50Fp9AlZk0oVLesibGWgCXDKFp5lpgQ9yhKoImUFjl3VZw==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@ts-macro/tsc': ^0.3.6 + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-rc.3 + typescript: ^5.0.0 || ^6.0.0-beta + vue-tsc: ~3.2.0 + peerDependenciesMeta: + '@ts-macro/tsc': + optional: true + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-rc.9: + resolution: {integrity: sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.52.5: + resolution: {integrity: sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + simple-plist@1.3.1: + resolution: {integrity: sha512-iMSw5i0XseMnrhtIzRb7XpQEXepa9xhWxGUojHBL43SIpQuDQkh3Wpy67ZbDzZVr6EKxvwVChnVpdl8hEVLDiw==} + + snooplogg@6.1.1: + resolution: {integrity: sha512-ERUf0zDe+4/wdzoTlz9aj45PCXRO/jckRY6BwlGLl4dZVr8hanHEW13MSYLSqOz9aDbRR8PGnb4arak+Nh4VqQ==} + engines: {node: '>=18.17'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@4.0.0: + resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} + + stream-buffers@2.2.0: + resolution: {integrity: sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==} + engines: {node: '>= 0.10.0'} + + stream-splitter@0.3.2: + resolution: {integrity: sha512-9VAHJIhskQFJMbyKbf/5flSXV2HsP9MDFdCp3A8WDBWkZ8tP/SOfkI2c5lEHNNUNzbWdNkJEv6iNvQRJnSbYuA==} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.2: + resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} + engines: {node: '>=18'} + + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + + tsdown@0.21.4: + resolution: {integrity: sha512-Q/kBi8SXkr4X6JI/NAZKZY1UuiEcbuXtIskL4tZCsgpDiEPM/2W6lC+OonNA31S+V3KsWedFvbFDBs23hvt+Aw==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@tsdown/css': 0.21.4 + '@tsdown/exe': 0.21.4 + '@vitejs/devtools': '*' + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@tsdown/css': + optional: true + '@tsdown/exe': + optional: true + '@vitejs/devtools': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-unused: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@4.41.0: + resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} + engines: {node: '>=16'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + unconfig-core@7.5.0: + resolution: {integrity: sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + undici@7.24.5: + resolution: {integrity: sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==} + engines: {node: '>=20.18.1'} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + unrun@0.2.32: + resolution: {integrity: sha512-opd3z6791rf281JdByf0RdRQrpcc7WyzqittqIXodM/5meNWdTwrVxeyzbaCp4/Rgls/um14oUaif1gomO8YGg==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + synckit: ^0.11.11 + peerDependenciesMeta: + synckit: + optional: true + + update-browserslist-db@1.1.4: + resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + vite@7.1.12: + resolution: {integrity: sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@4.1.0: + resolution: {integrity: sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.0 + '@vitest/browser-preview': 4.1.0 + '@vitest/browser-webdriverio': 4.1.0 + '@vitest/ui': 4.1.0 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + which@6.0.1: + resolution: {integrity: sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg==} + engines: {node: ^20.17.0 || >=22.9.0} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + xmlbuilder@15.1.1: + resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==} + engines: {node: '>=8.0'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yauzl@3.2.1: + resolution: {integrity: sha512-k1isifdbpNSFEHFJ1ZY4YDewv0IH9FR61lDetaRMD3j2ae3bIXGV+7c+LHCqtQGofSd8PIyV4X6+dHMAnSr60A==} + engines: {node: '>=12'} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + +snapshots: + + '@-xun/debug@2.0.2': + dependencies: + '@types/debug': 4.1.12 + debug: 4.4.3(supports-color@8.1.1) + supports-color: 8.1.1 + type-fest: 4.41.0 + + '@-xun/fs@2.0.0': + dependencies: + type-fest: 4.41.0 + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.6': {} + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/generator@8.0.0-rc.2': + dependencies: + '@babel/parser': 8.0.0-rc.2 + '@babel/types': 8.0.0-rc.2 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@types/jsesc': 2.5.1 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.27.0 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + debug: 4.4.3(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.3 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-string-parser@8.0.0-rc.2': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-identifier@8.0.0-rc.2': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.28.3': + dependencies: + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/parser@8.0.0-rc.2': + dependencies: + '@babel/types': 8.0.0-rc.2 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/preset-env@7.29.2(@babel/core@7.29.0)': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) + babel-plugin-polyfill-corejs2: 0.4.15(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.0 + esutils: 2.0.3 + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@babel/types@8.0.0-rc.2': + dependencies: + '@babel/helper-string-parser': 8.0.0-rc.2 + '@babel/helper-validator-identifier': 8.0.0-rc.2 + + '@bcoe/v8-coverage@1.0.2': {} + + '@emnapi/core@1.7.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.7.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@epic-web/invariant@1.0.0': {} + + '@esbuild/aix-ppc64@0.25.11': + optional: true + + '@esbuild/android-arm64@0.25.11': + optional: true + + '@esbuild/android-arm@0.25.11': + optional: true + + '@esbuild/android-x64@0.25.11': + optional: true + + '@esbuild/darwin-arm64@0.25.11': + optional: true + + '@esbuild/darwin-x64@0.25.11': + optional: true + + '@esbuild/freebsd-arm64@0.25.11': + optional: true + + '@esbuild/freebsd-x64@0.25.11': + optional: true + + '@esbuild/linux-arm64@0.25.11': + optional: true + + '@esbuild/linux-arm@0.25.11': + optional: true + + '@esbuild/linux-ia32@0.25.11': + optional: true + + '@esbuild/linux-loong64@0.25.11': + optional: true + + '@esbuild/linux-mips64el@0.25.11': + optional: true + + '@esbuild/linux-ppc64@0.25.11': + optional: true + + '@esbuild/linux-riscv64@0.25.11': + optional: true + + '@esbuild/linux-s390x@0.25.11': + optional: true + + '@esbuild/linux-x64@0.25.11': + optional: true + + '@esbuild/netbsd-arm64@0.25.11': + optional: true + + '@esbuild/netbsd-x64@0.25.11': + optional: true + + '@esbuild/openbsd-arm64@0.25.11': + optional: true + + '@esbuild/openbsd-x64@0.25.11': + optional: true + + '@esbuild/openharmony-arm64@0.25.11': + optional: true + + '@esbuild/sunos-x64@0.25.11': + optional: true + + '@esbuild/win32-arm64@0.25.11': + optional: true + + '@esbuild/win32-ia32@0.25.11': + optional: true + + '@esbuild/win32-x64@0.25.11': + optional: true + + '@isaacs/cliui@9.0.0': {} + + '@jest/schemas@30.0.5': + dependencies: + '@sinclair/typebox': 0.34.41 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@napi-rs/wasm-runtime@1.1.1': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@oxc-project/types@0.115.0': {} + + '@oxfmt/binding-android-arm-eabi@0.41.0': + optional: true + + '@oxfmt/binding-android-arm64@0.41.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.41.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.41.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.41.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.41.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.41.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.41.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.41.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.41.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.41.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.41.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.41.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.41.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.41.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.41.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.41.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.41.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.41.0': + optional: true + + '@oxlint/binding-android-arm-eabi@1.56.0': + optional: true + + '@oxlint/binding-android-arm64@1.56.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.56.0': + optional: true + + '@oxlint/binding-darwin-x64@1.56.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.56.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.56.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.56.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.56.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.56.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.56.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.56.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.56.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.56.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.56.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.56.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.56.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.56.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.56.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.56.0': + optional: true + + '@quansync/fs@1.0.0': + dependencies: + quansync: 1.0.0 + + '@rolldown/binding-android-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.9': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-rc.9': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-rc.9': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-rc.9': + dependencies: + '@napi-rs/wasm-runtime': 1.1.1 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.9': + optional: true + + '@rolldown/pluginutils@1.0.0-rc.9': {} + + '@rollup/rollup-android-arm-eabi@4.52.5': + optional: true + + '@rollup/rollup-android-arm64@4.52.5': + optional: true + + '@rollup/rollup-darwin-arm64@4.52.5': + optional: true + + '@rollup/rollup-darwin-x64@4.52.5': + optional: true + + '@rollup/rollup-freebsd-arm64@4.52.5': + optional: true + + '@rollup/rollup-freebsd-x64@4.52.5': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.52.5': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.52.5': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.52.5': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.52.5': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.52.5': + optional: true + + '@rollup/rollup-linux-x64-musl@4.52.5': + optional: true + + '@rollup/rollup-openharmony-arm64@4.52.5': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.52.5': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.52.5': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.52.5': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.52.5': + optional: true + + '@sinclair/typebox@0.34.41': {} + + '@standard-schema/spec@1.1.0': {} + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/deep-eql@4.0.2': {} + + '@types/estree@1.0.8': {} + + '@types/jsesc@2.5.1': {} + + '@types/ms@2.1.0': {} + + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + + '@vitest/coverage-v8@4.1.0(vitest@4.1.0(@types/node@25.5.0)(vite@7.1.12(@types/node@25.5.0)))': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.0 + ast-v8-to-istanbul: 1.0.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.2 + obug: 2.1.1 + std-env: 4.0.0 + tinyrainbow: 3.0.3 + vitest: 4.1.0(@types/node@25.5.0)(vite@7.1.12(@types/node@25.5.0)) + + '@vitest/expect@4.1.0': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.0 + '@vitest/utils': 4.1.0 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.1.0(vite@7.1.12(@types/node@25.5.0))': + dependencies: + '@vitest/spy': 4.1.0 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.1.12(@types/node@25.5.0) + + '@vitest/pretty-format@4.1.0': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.1.0': + dependencies: + '@vitest/utils': 4.1.0 + pathe: 2.0.3 + + '@vitest/snapshot@4.1.0': + dependencies: + '@vitest/pretty-format': 4.1.0 + '@vitest/utils': 4.1.0 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@4.1.0': {} + + '@vitest/utils@4.1.0': + dependencies: + '@vitest/pretty-format': 4.1.0 + convert-source-map: 2.0.0 + tinyrainbow: 3.0.3 + + '@xmldom/xmldom@0.8.11': {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@5.2.0: {} + + ansis@4.2.0: {} + + args@5.0.3: + dependencies: + camelcase: 5.0.0 + chalk: 2.4.2 + leven: 2.1.0 + mri: 1.1.4 + + assertion-error@2.0.1: {} + + ast-kit@3.0.0-beta.1: + dependencies: + '@babel/parser': 8.0.0-rc.2 + estree-walker: 3.0.3 + pathe: 2.0.3 + + ast-v8-to-istanbul@1.0.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + + babel-helper-evaluate-path@0.5.0: {} + + babel-helper-flip-expressions@0.4.3: {} + + babel-helper-is-nodes-equiv@0.0.1: {} + + babel-helper-is-void-0@0.4.3: {} + + babel-helper-mark-eval-scopes@0.4.3: {} + + babel-helper-remove-or-void@0.4.3: {} + + babel-helper-to-multiple-sequence-expressions@0.5.0: {} + + babel-plugin-minify-builtins@0.5.0: {} + + babel-plugin-minify-constant-folding@0.5.0: + dependencies: + babel-helper-evaluate-path: 0.5.0 + + babel-plugin-minify-dead-code-elimination@0.5.2: + dependencies: + babel-helper-evaluate-path: 0.5.0 + babel-helper-mark-eval-scopes: 0.4.3 + babel-helper-remove-or-void: 0.4.3 + lodash: 4.17.21 + + babel-plugin-minify-flip-comparisons@0.4.3: + dependencies: + babel-helper-is-void-0: 0.4.3 + + babel-plugin-minify-guarded-expressions@0.4.4: + dependencies: + babel-helper-evaluate-path: 0.5.0 + babel-helper-flip-expressions: 0.4.3 + + babel-plugin-minify-infinity@0.4.3: {} + + babel-plugin-minify-mangle-names@0.5.1: + dependencies: + babel-helper-mark-eval-scopes: 0.4.3 + + babel-plugin-minify-numeric-literals@0.4.3: {} + + babel-plugin-minify-replace@0.5.0: {} + + babel-plugin-minify-simplify@0.5.1: + dependencies: + babel-helper-evaluate-path: 0.5.0 + babel-helper-flip-expressions: 0.4.3 + babel-helper-is-nodes-equiv: 0.0.1 + babel-helper-to-multiple-sequence-expressions: 0.5.0 + + babel-plugin-minify-type-constructors@0.4.3: + dependencies: + babel-helper-is-void-0: 0.4.3 + + babel-plugin-polyfill-corejs2@0.4.15(@babel/core@7.29.0): + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.14.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + core-js-compat: 3.48.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.6(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + babel-plugin-tester@12.0.0(@babel/core@7.29.0): + dependencies: + '@-xun/fs': 2.0.0 + '@babel/core': 7.29.0 + core-js: 3.46.0 + lodash.mergewith: 4.6.2 + prettier: 3.6.2 + pretty-format: 30.2.0 + rejoinder: 2.1.0 + strip-indent~3: strip-indent@3.0.0 + type-fest: 4.41.0 + + babel-plugin-transform-inline-consecutive-adds@0.4.3: {} + + babel-plugin-transform-member-expression-literals@6.9.4: {} + + babel-plugin-transform-merge-sibling-variables@6.9.5: {} + + babel-plugin-transform-minify-booleans@6.9.4: {} + + babel-plugin-transform-property-literals@6.9.4: + dependencies: + esutils: 2.0.3 + + babel-plugin-transform-regexp-constructors@0.4.3: {} + + babel-plugin-transform-remove-console@6.9.4: {} + + babel-plugin-transform-remove-debugger@6.9.4: {} + + babel-plugin-transform-remove-undefined@0.5.0: + dependencies: + babel-helper-evaluate-path: 0.5.0 + + babel-plugin-transform-simplify-comparison-operators@6.9.4: {} + + babel-plugin-transform-titanium@0.1.1: {} + + babel-plugin-transform-undefined-to-void@6.9.4: {} + + babel-preset-minify@0.5.2: + dependencies: + babel-plugin-minify-builtins: 0.5.0 + babel-plugin-minify-constant-folding: 0.5.0 + babel-plugin-minify-dead-code-elimination: 0.5.2 + babel-plugin-minify-flip-comparisons: 0.4.3 + babel-plugin-minify-guarded-expressions: 0.4.4 + babel-plugin-minify-infinity: 0.4.3 + babel-plugin-minify-mangle-names: 0.5.1 + babel-plugin-minify-numeric-literals: 0.4.3 + babel-plugin-minify-replace: 0.5.0 + babel-plugin-minify-simplify: 0.5.1 + babel-plugin-minify-type-constructors: 0.4.3 + babel-plugin-transform-inline-consecutive-adds: 0.4.3 + babel-plugin-transform-member-expression-literals: 6.9.4 + babel-plugin-transform-merge-sibling-variables: 6.9.5 + babel-plugin-transform-minify-booleans: 6.9.4 + babel-plugin-transform-property-literals: 6.9.4 + babel-plugin-transform-regexp-constructors: 0.4.3 + babel-plugin-transform-remove-console: 6.9.4 + babel-plugin-transform-remove-debugger: 6.9.4 + babel-plugin-transform-remove-undefined: 0.5.0 + babel-plugin-transform-simplify-comparison-operators: 6.9.4 + babel-plugin-transform-undefined-to-void: 6.9.4 + lodash: 4.17.21 + + balanced-match@4.0.2: + dependencies: + jackspeak: 4.2.3 + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.8.20: {} + + baseline-browser-mapping@2.9.19: {} + + basic-auth-parser@0.0.2-1: {} + + big-integer@1.6.52: {} + + birpc@4.0.0: {} + + bplist-creator@0.1.0: + dependencies: + stream-buffers: 2.2.0 + + bplist-parser@0.3.1: + dependencies: + big-integer: 1.6.52 + + brace-expansion@5.0.2: + dependencies: + balanced-match: 4.0.2 + + browserslist@4.27.0: + dependencies: + baseline-browser-mapping: 2.8.20 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.241 + node-releases: 2.0.26 + update-browserslist-db: 1.1.4(browserslist@4.27.0) + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.9.19 + caniuse-lite: 1.0.30001769 + electron-to-chromium: 1.5.286 + node-releases: 2.0.27 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + buffer-crc32@0.2.13: {} + + buffers@0.1.1: {} + + cac@7.0.0: {} + + camelcase@5.0.0: {} + + caniuse-lite@1.0.30001751: {} + + caniuse-lite@1.0.30001769: {} + + chai@6.2.2: {} + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@5.6.2: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-name@1.1.3: {} + + convert-source-map@2.0.0: {} + + core-js-compat@3.48.0: + dependencies: + browserslist: 4.28.1 + + core-js@3.46.0: {} + + cross-env@10.1.0: + dependencies: + '@epic-web/invariant': 1.0.0 + cross-spawn: 7.0.6 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + debug@4.4.3(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + defu@6.1.4: {} + + dts-resolver@2.1.3: {} + + electron-to-chromium@1.5.241: {} + + electron-to-chromium@1.5.286: {} + + empathic@2.0.0: {} + + es-module-lexer@2.0.0: {} + + esbuild@0.25.11: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.11 + '@esbuild/android-arm': 0.25.11 + '@esbuild/android-arm64': 0.25.11 + '@esbuild/android-x64': 0.25.11 + '@esbuild/darwin-arm64': 0.25.11 + '@esbuild/darwin-x64': 0.25.11 + '@esbuild/freebsd-arm64': 0.25.11 + '@esbuild/freebsd-x64': 0.25.11 + '@esbuild/linux-arm': 0.25.11 + '@esbuild/linux-arm64': 0.25.11 + '@esbuild/linux-ia32': 0.25.11 + '@esbuild/linux-loong64': 0.25.11 + '@esbuild/linux-mips64el': 0.25.11 + '@esbuild/linux-ppc64': 0.25.11 + '@esbuild/linux-riscv64': 0.25.11 + '@esbuild/linux-s390x': 0.25.11 + '@esbuild/linux-x64': 0.25.11 + '@esbuild/netbsd-arm64': 0.25.11 + '@esbuild/netbsd-x64': 0.25.11 + '@esbuild/openbsd-arm64': 0.25.11 + '@esbuild/openbsd-x64': 0.25.11 + '@esbuild/openharmony-arm64': 0.25.11 + '@esbuild/sunos-x64': 0.25.11 + '@esbuild/win32-arm64': 0.25.11 + '@esbuild/win32-ia32': 0.25.11 + '@esbuild/win32-x64': 0.25.11 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + esutils@2.0.3: {} + + exit-hook@4.0.0: {} + + expect-type@1.3.0: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-tsconfig@4.13.6: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob@13.0.3: + dependencies: + minimatch: 10.2.0 + minipass: 7.1.2 + path-scurry: 2.0.1 + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hookable@6.1.0: {} + + html-escaper@2.0.2: {} + + import-without-cache@0.2.5: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + isexe@2.0.0: {} + + isexe@4.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + js-tokens@10.0.0: {} + + js-tokens@4.0.0: {} + + jsesc@3.1.0: {} + + json5@2.2.3: {} + + lefthook-darwin-arm64@2.1.4: + optional: true + + lefthook-darwin-x64@2.1.4: + optional: true + + lefthook-freebsd-arm64@2.1.4: + optional: true + + lefthook-freebsd-x64@2.1.4: + optional: true + + lefthook-linux-arm64@2.1.4: + optional: true + + lefthook-linux-x64@2.1.4: + optional: true + + lefthook-openbsd-arm64@2.1.4: + optional: true + + lefthook-openbsd-x64@2.1.4: + optional: true + + lefthook-windows-arm64@2.1.4: + optional: true + + lefthook-windows-x64@2.1.4: + optional: true + + lefthook@2.1.4: + optionalDependencies: + lefthook-darwin-arm64: 2.1.4 + lefthook-darwin-x64: 2.1.4 + lefthook-freebsd-arm64: 2.1.4 + lefthook-freebsd-x64: 2.1.4 + lefthook-linux-arm64: 2.1.4 + lefthook-linux-x64: 2.1.4 + lefthook-openbsd-arm64: 2.1.4 + lefthook-openbsd-x64: 2.1.4 + lefthook-windows-arm64: 2.1.4 + lefthook-windows-x64: 2.1.4 + + leven@2.1.0: {} + + lodash.debounce@4.0.8: {} + + lodash.mergewith@4.6.2: {} + + lodash@4.17.21: {} + + lru-cache@11.2.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + magicast@0.5.2: + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.4 + + min-indent@1.0.1: {} + + minimatch@10.2.0: + dependencies: + brace-expansion: 5.0.2 + + minipass@7.1.2: {} + + mri@1.1.4: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + node-releases@2.0.26: {} + + node-releases@2.0.27: {} + + obug@2.1.1: {} + + oxfmt@0.41.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.41.0 + '@oxfmt/binding-android-arm64': 0.41.0 + '@oxfmt/binding-darwin-arm64': 0.41.0 + '@oxfmt/binding-darwin-x64': 0.41.0 + '@oxfmt/binding-freebsd-x64': 0.41.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.41.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.41.0 + '@oxfmt/binding-linux-arm64-gnu': 0.41.0 + '@oxfmt/binding-linux-arm64-musl': 0.41.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.41.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.41.0 + '@oxfmt/binding-linux-riscv64-musl': 0.41.0 + '@oxfmt/binding-linux-s390x-gnu': 0.41.0 + '@oxfmt/binding-linux-x64-gnu': 0.41.0 + '@oxfmt/binding-linux-x64-musl': 0.41.0 + '@oxfmt/binding-openharmony-arm64': 0.41.0 + '@oxfmt/binding-win32-arm64-msvc': 0.41.0 + '@oxfmt/binding-win32-ia32-msvc': 0.41.0 + '@oxfmt/binding-win32-x64-msvc': 0.41.0 + + oxlint@1.56.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.56.0 + '@oxlint/binding-android-arm64': 1.56.0 + '@oxlint/binding-darwin-arm64': 1.56.0 + '@oxlint/binding-darwin-x64': 1.56.0 + '@oxlint/binding-freebsd-x64': 1.56.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.56.0 + '@oxlint/binding-linux-arm-musleabihf': 1.56.0 + '@oxlint/binding-linux-arm64-gnu': 1.56.0 + '@oxlint/binding-linux-arm64-musl': 1.56.0 + '@oxlint/binding-linux-ppc64-gnu': 1.56.0 + '@oxlint/binding-linux-riscv64-gnu': 1.56.0 + '@oxlint/binding-linux-riscv64-musl': 1.56.0 + '@oxlint/binding-linux-s390x-gnu': 1.56.0 + '@oxlint/binding-linux-x64-gnu': 1.56.0 + '@oxlint/binding-linux-x64-musl': 1.56.0 + '@oxlint/binding-openharmony-arm64': 1.56.0 + '@oxlint/binding-win32-arm64-msvc': 1.56.0 + '@oxlint/binding-win32-ia32-msvc': 1.56.0 + '@oxlint/binding-win32-x64-msvc': 1.56.0 + + package-json-from-dist@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.2 + minipass: 7.1.2 + + pathe@2.0.3: {} + + pend@1.2.0: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + plist@3.1.0: + dependencies: + '@xmldom/xmldom': 0.8.11 + base64-js: 1.5.1 + xmlbuilder: 15.1.1 + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.6.2: {} + + pretty-format@30.2.0: + dependencies: + '@jest/schemas': 30.0.5 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + proxy@3.0.0: + dependencies: + args: 5.0.3 + basic-auth-parser: 0.0.2-1 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + quansync@1.0.0: {} + + react-is@18.3.1: {} + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.0: + dependencies: + jsesc: 3.1.0 + + rejoinder@2.1.0: + dependencies: + '@-xun/debug': 2.0.2 + chalk: 5.6.2 + core-js: 3.46.0 + exit-hook: 4.0.0 + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + rimraf@6.1.3: + dependencies: + glob: 13.0.3 + package-json-from-dist: 1.0.1 + + rolldown-plugin-dts@0.22.5(rolldown@1.0.0-rc.9)(typescript@5.9.3): + dependencies: + '@babel/generator': 8.0.0-rc.2 + '@babel/helper-validator-identifier': 8.0.0-rc.2 + '@babel/parser': 8.0.0-rc.2 + '@babel/types': 8.0.0-rc.2 + ast-kit: 3.0.0-beta.1 + birpc: 4.0.0 + dts-resolver: 2.1.3 + get-tsconfig: 4.13.6 + obug: 2.1.1 + rolldown: 1.0.0-rc.9 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - oxc-resolver + + rolldown@1.0.0-rc.9: + dependencies: + '@oxc-project/types': 0.115.0 + '@rolldown/pluginutils': 1.0.0-rc.9 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-rc.9 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.9 + '@rolldown/binding-darwin-x64': 1.0.0-rc.9 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.9 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.9 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.9 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.9 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.9 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.9 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.9 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.9 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.9 + + rollup@4.52.5: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.52.5 + '@rollup/rollup-android-arm64': 4.52.5 + '@rollup/rollup-darwin-arm64': 4.52.5 + '@rollup/rollup-darwin-x64': 4.52.5 + '@rollup/rollup-freebsd-arm64': 4.52.5 + '@rollup/rollup-freebsd-x64': 4.52.5 + '@rollup/rollup-linux-arm-gnueabihf': 4.52.5 + '@rollup/rollup-linux-arm-musleabihf': 4.52.5 + '@rollup/rollup-linux-arm64-gnu': 4.52.5 + '@rollup/rollup-linux-arm64-musl': 4.52.5 + '@rollup/rollup-linux-loong64-gnu': 4.52.5 + '@rollup/rollup-linux-ppc64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-gnu': 4.52.5 + '@rollup/rollup-linux-riscv64-musl': 4.52.5 + '@rollup/rollup-linux-s390x-gnu': 4.52.5 + '@rollup/rollup-linux-x64-gnu': 4.52.5 + '@rollup/rollup-linux-x64-musl': 4.52.5 + '@rollup/rollup-openharmony-arm64': 4.52.5 + '@rollup/rollup-win32-arm64-msvc': 4.52.5 + '@rollup/rollup-win32-ia32-msvc': 4.52.5 + '@rollup/rollup-win32-x64-gnu': 4.52.5 + '@rollup/rollup-win32-x64-msvc': 4.52.5 + fsevents: 2.3.3 + + semver@6.3.1: {} + + semver@7.7.4: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + siginfo@2.0.0: {} + + simple-plist@1.3.1: + dependencies: + bplist-creator: 0.1.0 + bplist-parser: 0.3.1 + plist: 3.1.0 + + snooplogg@6.1.1: {} + + source-map-js@1.2.1: {} + + stackback@0.0.2: {} + + std-env@4.0.0: {} + + stream-buffers@2.2.0: {} + + stream-splitter@0.3.2: + dependencies: + buffers: 0.1.1 + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tinybench@2.9.0: {} + + tinyexec@1.0.2: {} + + tinyexec@1.0.4: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinypool@2.1.0: {} + + tinyrainbow@3.0.3: {} + + tree-kill@1.2.2: {} + + tsdown@0.21.4(typescript@5.9.3): + dependencies: + ansis: 4.2.0 + cac: 7.0.0 + defu: 6.1.4 + empathic: 2.0.0 + hookable: 6.1.0 + import-without-cache: 0.2.5 + obug: 2.1.1 + picomatch: 4.0.3 + rolldown: 1.0.0-rc.9 + rolldown-plugin-dts: 0.22.5(rolldown@1.0.0-rc.9)(typescript@5.9.3) + semver: 7.7.4 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig-core: 7.5.0 + unrun: 0.2.32 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@ts-macro/tsc' + - '@typescript/native-preview' + - oxc-resolver + - synckit + - vue-tsc + + tslib@2.8.1: + optional: true + + type-fest@4.41.0: {} + + typescript@5.9.3: {} + + unconfig-core@7.5.0: + dependencies: + '@quansync/fs': 1.0.0 + quansync: 1.0.0 + + undici-types@7.18.2: {} + + undici@7.24.5: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unrun@0.2.32: + dependencies: + rolldown: 1.0.0-rc.9 + + update-browserslist-db@1.1.4(browserslist@4.27.0): + dependencies: + browserslist: 4.27.0 + escalade: 3.2.0 + picocolors: 1.1.1 + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + vite@7.1.12(@types/node@25.5.0): + dependencies: + esbuild: 0.25.11 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.52.5 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.5.0 + fsevents: 2.3.3 + + vitest@4.1.0(@types/node@25.5.0)(vite@7.1.12(@types/node@25.5.0)): + dependencies: + '@vitest/expect': 4.1.0 + '@vitest/mocker': 4.1.0(vite@7.1.12(@types/node@25.5.0)) + '@vitest/pretty-format': 4.1.0 + '@vitest/runner': 4.1.0 + '@vitest/snapshot': 4.1.0 + '@vitest/spy': 4.1.0 + '@vitest/utils': 4.1.0 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.1.12(@types/node@25.5.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.5.0 + transitivePeerDependencies: + - msw + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + which@6.0.1: + dependencies: + isexe: 4.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + xmlbuilder@15.1.1: {} + + yallist@3.1.1: {} + + yauzl@3.2.1: + dependencies: + buffer-crc32: 0.2.13 + pend: 1.2.0 + + zod@4.3.6: {} diff --git a/src/android/android-ndk.ts b/src/android/android-ndk.ts new file mode 100644 index 00000000..5531fe18 --- /dev/null +++ b/src/android/android-ndk.ts @@ -0,0 +1,266 @@ +import { config } from '../config.js'; +import type { ErrorWithCode } from '../types/index.js'; +import { expand } from '../util/expand.js'; +import { isDir } from '../util/is-dir.js'; +import { isFile } from '../util/is-file.js'; +import { Issue } from '../util/issue.js'; +import { tailgate } from '../util/tailgate.js'; +import { readPropertiesFile } from './util/read-properties-file.js'; +import { readdir, readFile } from 'node:fs/promises'; +import { basename, join } from 'node:path'; +import snooplogg from 'snooplogg'; +import which from 'which'; + +const { log, warn } = snooplogg('android:ndk'); + +const cmd = process.platform === 'win32' ? '.cmd' : ''; + +/** + * A cached regex for matching the NDK architecture. + * @type {RegExp} + */ +const archRegExp = /\w-x86_64[/\\]/m; + +/** + * A cached regex for matching the NDK release version. + * @type {RegExp} + */ +const releaseRegExp = /^(r(\d+)([A-Za-z])?)(?:\s+\(([^)]+)\))?$/; + +/** + * A cached regex for matching the NDK version. + * @type {RegExp} + */ +const versionRegExp = /^(\d+)(?:\.(\d+))?/; + +type AndroidNDKOptions = { + arch: string; + executables: Record; + name: string; + path: string; + version: string | null; +}; + +/** + * Detects and organizes Android NDK information. + */ +export class AndroidNDK { + arch!: string; + executables!: Record; + name!: string; + path!: string; + version!: string | null; + + private constructor(options: AndroidNDKOptions) { + Object.assign(this, options); + } + + static async load(path: string): Promise { + log(`Loading: ${path}`); + if (typeof path !== 'string' || !path) { + throw new TypeError('Expected Android NDK path to be a valid string'); + } + if (!isDir(path)) { + throw new Error(`Android NDK path does not exist: ${path}`); + } + + let ndkWhich = join(path, `ndk-which${cmd}`); + + if (process.platform === 'win32' && !isFile(ndkWhich)) { + // For some reason, some releases of the Android NDK have a `ndk-which` + // executable without a `.cmd` extension + ndkWhich = join(path, 'ndk-which'); + } + + let name = basename(path); + let version: string | null = null; + let arch = '32-bit'; + let executables = { + 'ndk-build': join(path, `ndk-build${cmd}`), + 'ndk-which': ndkWhich, + }; + + for (const name of Object.keys(executables)) { + if (!isFile(executables[name])) { + const err = new Error( + `Directory does not contain the "${name}" executable` + ) as ErrorWithCode; + err.code = 'ANDROID_NDK_MISSING_EXECUTABLE'; + throw err; + } + } + + // get the archtecture + if (archRegExp.test(await readFile(executables['ndk-which'], 'utf8'))) { + arch = '64-bit'; + } + + // get the version + const sourceProps = await readPropertiesFile(join(path, 'source.properties')); + if (sourceProps) { + version = sourceProps['Pkg.Revision']; + if (version) { + const m = version.match(versionRegExp); + if (m) { + if (m[2] === undefined) { + version = `${m[1]}.0`; + } else if (Number.parseInt(m[2]) !== 0) { + name = `r${m[1]}${String.fromCharCode('a'.charCodeAt(0) + Number.parseInt(m[2]))}`; + } + } + } + } + + if (!version) { + // no version, try to find it in the release.txt file + for (const filename of await readdir(path)) { + if (filename.toLowerCase() === 'release.txt') { + const release = (await readFile(join(path, filename), 'utf8')) + .split(/\r?\n/) + .shift() + ?.trim(); + // release comes back in the format "r10e (64-bit)", so we + // need to extract a meaningful version number from that + const m = release?.match(releaseRegExp); + if (m) { + name = m[1]; + const minor = (m[3] ? m[3].toLowerCase() : 'a').charCodeAt(0) - 'a'.charCodeAt(0); + version = `${m[2]}.${minor}`; + if (m[4] && m[4].toLowerCase() === '64-bit') { + arch = '64-bit'; + } + } + break; + } + } + } + + log(`Found Android NDK: ${path} (version: ${version}, arch: ${arch})`); + return new AndroidNDK({ + arch, + executables, + name, + path, + version, + }); + } +} + +interface NDKs { + ndks: AndroidNDK[]; + issues: Issue[]; +} + +/** + * Detects installed Android NDKs. + * + * @param {Object} options - The options for the detection. + * @param {string[]} [options.searchPaths] - The paths to search for Android NDKs. + * @returns {Promise>} + */ +export async function detectAndroidNDKs( + options: { + searchPaths?: string[]; + } = {} +): Promise { + const searchPaths = await getSearchPaths(options); + + return tailgate('android:ndk:detect', async () => { + const ndks: AndroidNDK[] = []; + const ndkPaths = new Set(); + const issues: Issue[] = []; + + async function processPath( + path: string, + depth: number + ): Promise<{ ndk: AndroidNDK | null; subdirs: string[] }> { + try { + const ndk = await AndroidNDK.load(path); + return { ndk, subdirs: [] }; + } catch (err) { + if ( + err instanceof Error && + 'code' in err && + (err.code === 'ANDROID_NDK_MISSING_EXECUTABLE' || + err.code === 'ANDROID_NDK_MISSING_DIRECTORY') + ) { + if (depth === 0) { + const subdirs: string[] = []; + for (const name of await readdir(path)) { + const dir = join(path, name); + if (isDir(dir)) { + subdirs.push(dir); + } + } + return { ndk: null, subdirs }; + } + warn(err); + return { ndk: null, subdirs: [] }; + } + if (err instanceof Issue) { + warn(err.message); + issues.push(err); + return { ndk: null, subdirs: [] }; + } + warn(err); + return { ndk: null, subdirs: [] }; + } + } + + const level0Results = await Promise.all(searchPaths.map((path) => processPath(path, 0))); + const subdirs: string[] = []; + for (const { ndk, subdirs: s } of level0Results) { + if (ndk && !ndkPaths.has(ndk.path)) { + ndkPaths.add(ndk.path); + ndks.push(ndk); + } + subdirs.push(...s); + } + + const level1Results = await Promise.all(subdirs.map((path) => processPath(path, 1))); + for (const { ndk } of level1Results) { + if (ndk && !ndkPaths.has(ndk.path)) { + ndkPaths.add(ndk.path); + ndks.push(ndk); + } + } + + if (!ndks.length) { + issues.push( + new Issue('No Android NDKs found', { + id: 'ANDROID_NDK_NOT_FOUND', + type: 'warning', + details: 'No Android NDKs found. Please install the Android NDK and try again.', + }) + ); + } + + return { + ndks, + issues, + }; + }); +} + +async function getSearchPaths(options: { searchPaths?: string[] }) { + const searchPaths = new Set(); + if (Array.isArray(options?.searchPaths)) { + for (const path of options.searchPaths) { + searchPaths.add(expand(path)); + } + } + + const configPaths = config.android.ndk.searchPaths[process.platform]; + if (Array.isArray(configPaths)) { + for (const path of configPaths) { + searchPaths.add(expand(path)); + } + } + + const ndkBuildPath = await which(`ndk-build${cmd}`, { nothrow: true }); + if (ndkBuildPath) { + searchPaths.add(expand(ndkBuildPath, '..', '..')); + } + + return Array.from(searchPaths); +} diff --git a/src/android/android-sdk.ts b/src/android/android-sdk.ts new file mode 100644 index 00000000..7ba744ec --- /dev/null +++ b/src/android/android-sdk.ts @@ -0,0 +1,457 @@ +import { config } from '../config.js'; +import { expand } from '../util/expand.js'; +import { isDir } from '../util/is-dir.js'; +import { isFile } from '../util/is-file.js'; +import { Issue } from '../util/issue.js'; +import { tailgate } from '../util/tailgate.js'; +import { readPropertiesFile } from './util/read-properties-file.js'; +import { readdir } from 'node:fs/promises'; +import { join, relative } from 'node:path'; +import snooplogg from 'snooplogg'; + +const { log, warn } = snooplogg('android:sdk'); + +const exe = process.platform === 'win32' ? '.exe' : ''; + +interface AndroidSDKExecutables { + adb: string; + emulator: string; +} + +type SystemImage = { + abi: string; + sdk: string; + skins: string[]; + type: string; +}; + +type Platform = { + abis: Record; + androidJar: string | null; + apiLevel: number; + codename: string | null; + defaultSkin: string | null; + minToolsRev: number | null; + name: string; + path: string; + revision: number | null; + sdk: string; + skins: string[]; + version: string; +}; + +type Addon = { + abis: Record | null; + androidJar: string | null; + apiLevel: number; + basedOn: { version: string; apiLevel: number } | null; + codename: string | null; + defaultSkin: string | null; + description: string | null; + minToolsRev: number | null; + name: string; + path: string; + revision: number | null; + sdk: string; + skins: string[] | null; + vendor: string; + version: string | null; +}; + +interface AndroidSDKOptions extends AndroidSDKExecutables { + addons: Addon[]; + issues: Issue[]; + path: string; + platforms: Platform[]; + systemImages: Record; +} + +export class AndroidSDK { + adb!: string; + addons!: Addon[]; + emulator!: string; + issues!: Issue[]; + path!: string; + platforms!: Platform[]; + systemImages!: Record; + + constructor(options: AndroidSDKOptions) { + Object.assign(this, options); + } + + static async load(path: string): Promise { + log(`Loading: ${path}`); + if (typeof path !== 'string' || !path) { + throw new TypeError('Expected Android SDK path to be a valid string'); + } + if (!isDir(path)) { + throw new Error(`Android SDK path does not exist: ${path}`); + } + + const executables = { + adb: join(path, 'platform-tools', `adb${exe}`), + emulator: join(path, 'emulator', `emulator${exe}`), + }; + for (const [key, value] of Object.entries(executables)) { + if (!isFile(value)) { + throw new Error(`Invalid Android SDK: missing required executable "${key}"`); + } + } + + const issues: Issue[] = []; + + const systemImages = await AndroidSDK.detectSystemImages(path); + const platforms = await AndroidSDK.detectPlatforms(path, systemImages, issues); + const addons = await AndroidSDK.detectAddons(path, platforms); + + return new AndroidSDK({ + addons, + ...executables, + issues, + path, + platforms, + systemImages, + }); + } + + static async detectSystemImages(path: string): Promise> { + const systemImages: Record = {}; + const systemImagesDir = join(path, 'system-images'); + + if (isDir(systemImagesDir)) { + for (const platform of await readdir(systemImagesDir)) { + const platformDir = join(systemImagesDir, platform); + if (!isDir(platformDir)) { + continue; + } + + for (const tag of await readdir(platformDir)) { + const tagDir = join(platformDir, tag); + if (!isDir(tagDir)) { + continue; + } + + for (const abi of await readdir(tagDir)) { + const abiDir = join(tagDir, abi); + if (!isDir(abiDir)) { + continue; + } + + const props = await readPropertiesFile(join(abiDir, 'source.properties')); + if ( + props?.['AndroidVersion.ApiLevel'] && + props['SystemImage.TagId'] && + props['SystemImage.Abi'] + ) { + const imageDir = relative(systemImagesDir, abiDir).replace(/\\/g, '/'); + const skinsDir = join(abiDir, 'skins'); + const skins: string[] = []; + if (isDir(skinsDir)) { + for (const name of await readdir(skinsDir)) { + if (isFile(join(skinsDir, name, 'hardware.ini'))) { + skins.push(name); + } + } + } + systemImages[imageDir] = { + abi: props['SystemImage.Abi'], + sdk: `android-${props['AndroidVersion.CodeName'] || props['AndroidVersion.ApiLevel']}`, + skins, + type: props['SystemImage.TagId'], + }; + } + } + } + } + } + + return systemImages; + } + + static async detectPlatforms( + path: string, + systemImages: Record, + issues: Issue[] + ): Promise { + const platforms: Platform[] = []; + const platformsDir = join(path, 'platforms'); + + if (isDir(platformsDir)) { + for (const name of await readdir(platformsDir)) { + const dir = join(platformsDir, name); + if (!isFile(join(dir, 'build.prop'))) { + continue; + } + + const sourceProps = await readPropertiesFile(join(dir, 'source.properties')); + if (!sourceProps) { + continue; + } + + const apiLevel = sourceProps['AndroidVersion.ApiLevel'] + ? Number.parseInt(sourceProps['AndroidVersion.ApiLevel']) + : null; + if (!apiLevel) { + continue; + } + + // read in the sdk properties, if exists + const sdkProps = await readPropertiesFile(join(dir, 'sdk.properties')); + + // detect the available skins + const skinsDir = join(dir, 'skins'); + const skins: string[] = []; + if (isDir(skinsDir)) { + for (const name of await readdir(skinsDir)) { + if (isFile(join(skinsDir, name, 'hardware.ini'))) { + skins.push(name); + } + } + } + let defaultSkin: string | null = sdkProps?.['sdk.skin.default'] ?? 'WVGA800'; + if (defaultSkin && skins.includes(defaultSkin) && !skins.includes('WVGA800')) { + defaultSkin = skins[skins.length - 1] || null; + } + + const apiName = sourceProps?.['AndroidVersion.CodeName'] || apiLevel; + const sdk = `android-${apiName}`; + + const abis: Record = {}; + for (const image of Object.values(systemImages)) { + if (image.sdk === sdk) { + if (!abis[image.type]) { + abis[image.type] = []; + } + if (!abis[image.type].includes(image.abi)) { + abis[image.type].push(image.abi); + } + for (const skin of image.skins) { + if (!skins.includes(skin)) { + skins.push(skin); + } + } + } + } + + const androidJarFile = join(dir, 'android.jar'); + + platforms.push({ + abis: abis, + androidJar: isFile(androidJarFile) ? androidJarFile : null, + apiLevel, + codename: sourceProps['AndroidVersion.CodeName'] || null, + defaultSkin, + minToolsRev: sourceProps['Platform.MinToolsRev'] + ? Number.parseInt(sourceProps['Platform.MinToolsRev']) + : null, + name: `Android ${sourceProps['Platform.Version']}${sourceProps['AndroidVersion.CodeName'] ? ' (Preview)' : ''}`, + path: dir, + revision: sourceProps['Layoutlib.Revision'] + ? Number.parseInt(sourceProps['Layoutlib.Revision']) + : null, + sdk, + skins, + version: sourceProps['Platform.Version'], + }); + } + } + + if (Object.keys(platforms).length === 0) { + issues.push( + new Issue('No platforms found', { + id: 'ANDROID_SDK_NO_PLATFORMS', + type: 'error', + details: 'Unable to find any platforms.', + }) + ); + return []; + } + + return platforms.sort(sortPackages); + } + + static async detectAddons(path: string, platforms: Platform[]): Promise { + const addons: Addon[] = []; + const addonsDir = join(path, 'add-ons'); + if (!isDir(addonsDir)) { + return []; + } + + for (const name of await readdir(addonsDir)) { + const dir = join(addonsDir, name); + const props = + (await readPropertiesFile(join(dir, 'source.properties'))) || + (await readPropertiesFile(join(dir, 'manifest.ini'))); + if (!props) { + continue; + } + + const apiLevel = Number.parseInt(props['AndroidVersion.ApiLevel'] || props.api); + const vendorDisplay = props['Addon.VendorDisplay'] || props.vendor; + const nameDisplay = props['Addon.NameDisplay'] || props.name; + if (!apiLevel || isNaN(apiLevel) || !vendorDisplay || !nameDisplay) { + continue; + } + + let basedOn: Platform | null = null; + for (const platform of platforms) { + if (platform.codename === null && platform.apiLevel === apiLevel) { + basedOn = platform; + break; + } + } + + addons.push({ + abis: basedOn?.abis || null, + androidJar: basedOn?.androidJar || null, + apiLevel: apiLevel, + basedOn: basedOn ? { version: basedOn.version, apiLevel: basedOn.apiLevel } : null, + codename: props['AndroidVersion.CodeName'] || props.codename || null, + defaultSkin: (basedOn && basedOn.defaultSkin) || null, + description: props['Pkg.Desc'] || props.description || null, + minToolsRev: (basedOn && basedOn.minToolsRev) || null, + name: nameDisplay, + path: dir, + revision: Number.parseInt(props['Pkg.Revision'] || props.revision) || null, + sdk: `${vendorDisplay}:${nameDisplay}:${apiLevel}`, + skins: (basedOn && basedOn.skins) || null, + vendor: vendorDisplay, + version: (basedOn && basedOn.version) || null, + }); + } + + return addons.sort(sortPackages); + } +} + +interface SDKs { + sdks: AndroidSDK[]; + issues: Issue[]; +} + +/** + * Detects installed Android SDKs. + * + * @param options - The options for the detection. + * @param {string[]} [options.searchPaths] - The paths to search for Android SDKs. + * @returns {Promise} The detected Android SDKs. + */ +export async function detectAndroidSDKs( + options: { + searchPaths?: string[]; + } = {} +): Promise { + const searchPaths = await getSearchPaths(options); + + return tailgate('android:sdk:detect', async () => { + const sdks: AndroidSDK[] = []; + const sdkPaths = new Set(); + const issues: Issue[] = []; + + async function processPath( + path: string, + depth: number + ): Promise<{ sdk: AndroidSDK | null; subdirs: string[] }> { + try { + const sdk = await AndroidSDK.load(path); + return { sdk, subdirs: [] }; + } catch (err) { + if ( + err instanceof Error && + 'code' in err && + (err.code === 'ANDROID_SDK_MISSING_EXECUTABLE' || + err.code === 'ANDROID_SDK_MISSING_DIRECTORY') + ) { + if (depth === 0) { + const subdirs: string[] = []; + for (const name of await readdir(path)) { + const dir = join(path, name); + if (isDir(dir)) { + subdirs.push(dir); + } + } + return { sdk: null, subdirs }; + } + warn(err); + return { sdk: null, subdirs: [] }; + } + if (err instanceof Issue) { + warn(err.message); + issues.push(err); + return { sdk: null, subdirs: [] }; + } + warn(err); + return { sdk: null, subdirs: [] }; + } + } + + const level0Results = await Promise.all(searchPaths.map((path) => processPath(path, 0))); + const subdirs: string[] = []; + for (const { sdk, subdirs: s } of level0Results) { + if (sdk && !sdkPaths.has(sdk.path)) { + sdkPaths.add(sdk.path); + sdks.push(sdk); + } + subdirs.push(...s); + } + + const level1Results = await Promise.all(subdirs.map((path) => processPath(path, 1))); + for (const { sdk } of level1Results) { + if (sdk && !sdkPaths.has(sdk.path)) { + sdkPaths.add(sdk.path); + sdks.push(sdk); + } + } + + if (!sdks.length) { + issues.push( + new Issue('No Android SDKs found', { + id: 'ANDROID_SDK_NOT_FOUND', + type: 'warning', + details: 'No Android SDKs found. Please install the Android SDK and try again.', + }) + ); + } + + return { + sdks, + issues, + }; + }); +} + +async function getSearchPaths(options: { searchPaths?: string[] }) { + const searchPaths = new Set(); + if (Array.isArray(options?.searchPaths)) { + for (const path of options.searchPaths) { + searchPaths.add(expand(path)); + } + } + + const configPaths = config.android.sdk.searchPaths[process.platform]; + if (Array.isArray(configPaths)) { + for (const path of configPaths) { + searchPaths.add(expand(path)); + } + } + + return Array.from(searchPaths); +} + +type SortablePackage = { + apiLevel: number; + codename: string | null; +}; + +function sortPackages(a: T, b: T) { + if (a.codename === null) { + if (b.codename !== null && a.apiLevel === b.apiLevel) { + // sort GA releases before preview releases + return -1; + } + } else if (a.apiLevel === b.apiLevel) { + return b.codename === null ? 1 : a.codename.localeCompare(b.codename); + } + + return a.apiLevel - b.apiLevel; +} diff --git a/src/android/index.ts b/src/android/index.ts new file mode 100644 index 00000000..3e921b25 --- /dev/null +++ b/src/android/index.ts @@ -0,0 +1,2 @@ +export * from './android-ndk.js'; +export * from './android-sdk.js'; diff --git a/src/android/util/read-properties-file.ts b/src/android/util/read-properties-file.ts new file mode 100644 index 00000000..0480c0a1 --- /dev/null +++ b/src/android/util/read-properties-file.ts @@ -0,0 +1,29 @@ +import { isFile } from '../../util/is-file.js'; +import { readFile } from 'node:fs/promises'; + +/** + * Cached regex for matching key/values in properties files. + */ +const pkgPropRegExp = /^(?!\s*#)\s*([^=\s]+)\s*=\s*(.+?)\s*$/; + +/** + * Reads and parses the specified properties file into an object. + * + * @param file - The properties file to parse. + * @returns A record of key/values from the properties file, or `null` if the + * file does not exist. + */ +export async function readPropertiesFile(file: string): Promise | null> { + if (!isFile(file)) { + return null; + } + + const props: Record = {}; + for (const line of (await readFile(file, 'utf8')).split(/\r?\n/)) { + const m = line.match(pkgPropRegExp); + if (m) { + props[m[1]] = m[2]; + } + } + return props; +} diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 00000000..cc760c6c --- /dev/null +++ b/src/config.ts @@ -0,0 +1,276 @@ +import type { Config } from './types/index.js'; + +export const defaultConfig: Config = { + android: { + adb: { + install: { + /** + * The number of milliseconds to wait before installing an app times out. + * @type {Number} + */ + timeout: null, + }, + + /** + * The path to the ADB executable. + * @type {String} + */ + path: null, + + /** + * The port to connect to ADB. + * @type {Number} + */ + port: null, + + /** + * The options to start ADB. + * @type {Object} + */ + start: { + /** + * The number of milliseconds to wait before retrying to start ADB. + * @type {Number} + */ + retryInterval: null, + + /** + * The number of milliseconds to wait before starting ADB times out. + * @type {Number} + */ + timeout: null, + }, + }, + avd: { + /** + * The path to where AVDs are stored. + * @type {String} + */ + path: '~/.android/avd', + }, + emulator: { + start: { + /** + * The number of milliseconds to wait before starting the Android emulator times out. + * @type {Number} + */ + timeout: null, + }, + }, + ndk: { + /** + * A list of paths to search for Android NDKs. + * @type {String[]|Object} + */ + searchPaths: { + darwin: ['~/Library/Android/sdk/ndk', '~/Library/Android/sdk/ndk-bundle'], + linux: ['~/Android/sdk/ndk', '~/Android/sdk/ndk-bundle'], + win32: ['%LOCALAPPDATA%\\Android\\sdk\\ndk', '%LOCALAPPDATA%\\Android\\sdk\\ndk-bundle'], + }, + }, + sdk: { + /** + * A list of paths to search for Android SDKs. + * @type {String[]|Object} + */ + searchPaths: { + darwin: ['~/Library/Android/sdk', '/usr/local/share'], + linux: ['~/Android/sdk', '/usr/local/share'], + win32: ['%LOCALAPPDATA%\\Android\\sdk'], + }, + }, + }, + + env: { + /** + * An override for the `PATH` environment variable. + * @type {String} + */ + path: null, + }, + + ios: { + executables: { + /** + * Path to the `security` executable. + * @type {String} + */ + security: null, + + /** + * Path to the `sqlite` or `sqlite3` executable. Used to read the Xcode teams database. + * @type {String} + */ + sqlite: null, + + /** + * Path to the `xcode-select` executable. + * @type {String} + */ + xcodeSelect: null, + }, + + keychainMetaFile: '~/Library/Preferences/com.apple.security.plist', + + provisioning: { + /** + * A list of paths to search for provisioning profiles. + * @type {String[]} + */ + searchPaths: [ + '~/Library/Developer/Xcode/UserData/Provisioning Profiles', + '~/Library/MobileDevice/Provisioning Profiles', + ], + }, + + simulator: { + /** + * The path to the directory containing the simulator crash logs. + * @type {String} + */ + crashLogsDir: '~/Library/Logs/DiagnosticReports', + + /** + * The path to the directory containing the simulator device directories. + * @type {String} + */ + devicesDir: '~/Library/Developer/CoreSimulator/Devices', + + /** + * The path to the directory containing the simulator runtimes. + * @type {String} + */ + runtimesDir: '/Library/Developer/CoreSimulator/Profiles/Runtimes', + }, + + xcode: { + /** + * A list of paths to search for Xcode installations. + * @type {String[]} + */ + searchPaths: ['/Applications', '~/Applications'], + }, + }, + + jdk: { + javaHome: null, + + /** + * A list of paths to search for JDKs. + * @type {String[]|Object} + */ + searchPaths: { + darwin: ['/Library/Java/JavaVirtualMachines', '/System/Library/Java/JavaVirtualMachines'], + linux: ['/usr/lib/jvm/default', '/usr/lib/jvm', '~/opt/java'], + win32: ['%ProgramFiles%\\Java', '%ProgramFiles(x86)%\\Java', '~\\Java'], + }, + + windows: { + /** + * The registry keys to search for JDKs. + * @type {String[]} + */ + registryKeys: [ + 'HKLM\\SOFTWARE\\JavaSoft\\Java Development Kit', + 'HKLM\\SOFTWARE\\Wow6432Node\\JavaSoft\\Java Development Kit', + 'HKLM\\SOFTWARE\\JavaSoft\\JDK', + ], + }, + }, + + network: { + /** + * The options to pass to the `http.Agent` constructor. + * @type {Object} + */ + agentOptions: null, + + /** + * The path to the CA file. + * @type {String} + */ + caFile: null, + + /** + * The path to the certificate file. + * @type {String} + */ + certFile: null, + + /** + * The HTTP proxy to use. + * @type {String} + */ + httpProxy: null, + + /** + * The HTTPS proxy to use. + * @type {String} + */ + httpsProxy: null, + + /** + * The path to the key file. + * @type {String} + */ + keyFile: null, + + /** + * The passphrase to use. + * @type {String} + */ + passphrase: null, + + /** + * Whether to use strict SSL. + * @type {Boolean} + */ + strictSSL: true, + }, + + titanium: { + downloadsDir: '~/.titanium/downloads', + sdk: { + downloadURLs: { + branches: 'https://downloads.titaniumsdk.com/registry/branches.json', + branchBuilds: 'https://downloads.titaniumsdk.com/registry/${branch}.json', + releases: { + beta: 'https://downloads.titaniumsdk.com/registry/beta.json', + rc: 'https://downloads.titaniumsdk.com/registry/rc.json', + ga: 'https://downloads.titaniumsdk.com/registry/ga.json', + }, + }, + + installPath: { + darwin: '~/Library/Application Support/Titanium', + linux: '~/.titanium', + win32: '%ProgramData%\\Titanium', + }, + + /** + * A list of paths to search for Titanium SDKs. + * @type {String[]|Object} + */ + searchPaths: { + darwin: [ + '~/Library/Application Support/Titanium', + '/Library/Application Support/Titanium', // legacy + ], + linux: ['~/.titanium'], + win32: [ + '%ProgramData%\\Titanium', + '%APPDATA%\\Titanium', + '%ALLUSERSPROFILE%\\Application Data\\Titanium', + ], + }, + }, + }, +}; + +export let config: Config = { + ...defaultConfig, +}; + +export function resetConfig(): void { + config = { ...defaultConfig }; +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..dea29f97 --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export { config, defaultConfig } from './config.js'; diff --git a/src/jdk/detect-jdks.ts b/src/jdk/detect-jdks.ts new file mode 100644 index 00000000..5719e781 --- /dev/null +++ b/src/jdk/detect-jdks.ts @@ -0,0 +1,176 @@ +import { config } from '../config.js'; +import { exists, expand, isDir } from '../util/index.js'; +import { Issue } from '../util/issue.js'; +import { tailgate } from '../util/tailgate.js'; +import { JDK } from './jdk.js'; +import { readdir } from 'node:fs/promises'; +import { join } from 'node:path'; +import snooplogg from 'snooplogg'; +import which from 'which'; + +const { warn } = snooplogg('jdk:detect'); + +type JDKMap = Record; + +interface JDKs { + defaultVersion: string | undefined; + home: string | null; + jdks: JDKMap; + issues: Issue[]; +} + +export async function detectJDKs( + options: { + javaHome?: string; + searchPaths?: string[]; + } = {} +): Promise { + const { home, searchPaths } = await getSearchPaths(options); + + return tailgate('jdk:detect', async () => { + const jdks: JDKMap = {}; + const jdkPaths = new Set(); + const issues: Issue[] = []; + let defaultVersion: string | undefined = undefined; + + async function processPath( + path: string, + depth: number + ): Promise<{ jdk: JDK | null; subdirs: string[] }> { + try { + const jdk = await JDK.load(path); + return { jdk, subdirs: [] }; + } catch (err) { + if (err instanceof Error && 'code' in err && err.code === 'JDK_MISSING_REQUIRED_PROGRAM') { + if (depth === 0) { + const subdirs: string[] = []; + for (const name of await readdir(path)) { + const dir = join(path, name); + if (isDir(dir)) { + subdirs.push(dir); + } + } + return { jdk: null, subdirs }; + } + warn(err); + return { jdk: null, subdirs: [] }; + } + if (err instanceof Issue) { + warn(err.message); + issues.push(err); + return { jdk: null, subdirs: [] }; + } + warn(err); + return { jdk: null, subdirs: [] }; + } + } + + const level0Results = await Promise.all(searchPaths.map((path) => processPath(path, 0))); + const subdirs: string[] = []; + for (const { jdk, subdirs: s } of level0Results) { + if (jdk && !jdkPaths.has(jdk.path)) { + jdkPaths.add(jdk.path); + jdks[jdk.version] = jdk; + if (jdk.path === home) { + defaultVersion = jdk.version; + } + } + subdirs.push(...s); + } + + const level1Results = await Promise.all(subdirs.map((path) => processPath(path, 1))); + for (const { jdk } of level1Results) { + if (jdk && !jdkPaths.has(jdk.path)) { + jdkPaths.add(jdk.path); + jdks[jdk.version] = jdk; + if (jdk.path === home) { + defaultVersion = jdk.version; + } + } + } + + if (process.platform === 'win32') { + for (const jdk of Object.values(jdks)) { + if (jdk.path.includes('&')) { + issues.push( + new Issue(`JDK path contains ampersand: ${jdk.path}`, { + id: 'JDK_PATH_CONTAINS_AMPERSAND', + type: 'warning', + details: 'The JDK path contains an ampersand (&) and may cause issues.', + }) + ); + } + } + } + + if (Object.keys(jdks).length === 0) { + issues.push( + new Issue('No JDKs found', { + id: 'JDK_NOT_FOUND', + type: 'error', + details: `JDK (Java Development Kit) not found. The JDK is required for Titanium and must be manually downloaded and installed from __https://openjdk.org/__. If you already have installed the JDK, verify your __JAVA_HOME__ environment variable is correctly set.`, + }) + ); + } + + if (Object.keys(jdks).length > 1 && defaultVersion === undefined) { + issues.push( + new Issue('No default JDK set', { + id: 'JDK_DEFAULT_NOT_FOUND', + type: 'warning', + details: `Multiple JDKs found, but no default JDK set. To set a default JDK, set the +__JAVA_HOME__ environment variable to the preferred JDK's path.`, + }) + ); + } + + return { + defaultVersion, + home, + jdks, + issues, + }; + }); +} + +async function getSearchPaths(options: { javaHome?: string; searchPaths?: string[] }) { + const searchPaths = new Set(); + if (Array.isArray(options?.searchPaths)) { + for (const path of options.searchPaths) { + searchPaths.add(expand(path)); + } + } + + const configPaths = config.jdk.searchPaths[process.platform]; + if (Array.isArray(configPaths)) { + for (const path of configPaths) { + searchPaths.add(expand(path)); + } + } + + let home = options.javaHome ?? config.jdk.javaHome ?? process.env.JAVA_HOME ?? null; + if (home && typeof home === 'string') { + home = expand(home); + if (await exists(home)) { + searchPaths.add(home); + } else { + home = null; + } + } + + if (process.platform === 'win32') { + // TODO: check the Windows Registry + // config.jdk.windows.registryKeys + } + + const exe = process.platform === 'win32' ? '.exe' : ''; + const javacPath = await which(`javac${exe}`, { nothrow: true }); + if (javacPath) { + searchPaths.add(expand(javacPath, '..')); + } + + return { + home, + searchPaths: Array.from(searchPaths), + }; +} diff --git a/src/jdk/index.ts b/src/jdk/index.ts new file mode 100644 index 00000000..92aa036c --- /dev/null +++ b/src/jdk/index.ts @@ -0,0 +1,2 @@ +export * from './detect-jdks.js'; +export * from './jdk.js'; diff --git a/src/jdk/jdk.ts b/src/jdk/jdk.ts new file mode 100644 index 00000000..c565bd67 --- /dev/null +++ b/src/jdk/jdk.ts @@ -0,0 +1,123 @@ +import type { ErrorWithCode } from '../types/index.js'; +import { isDir } from '../util/is-dir.js'; +import { isFile } from '../util/is-file.js'; +import { execFile } from 'node:child_process'; +import { realpath } from 'node:fs/promises'; +import { join } from 'node:path'; +import { promisify } from 'node:util'; +import snooplogg from 'snooplogg'; + +const { log } = snooplogg('jdk'); + +const execFileAsync = promisify(execFile); + +/** + * Common search paths for the JVM library. This is used only for validating if + * a directory is a JDK. + * @type {Object} + */ +export const libjvmLocations: Record = { + linux: [ + 'lib/amd64/client/libjvm.so', + 'lib/amd64/server/libjvm.so', + 'lib/i386/client/libjvm.so', + 'lib/i386/server/libjvm.so', + 'jre/lib/amd64/client/libjvm.so', + 'jre/lib/amd64/server/libjvm.so', + 'jre/lib/i386/client/libjvm.so', + 'jre/lib/i386/server/libjvm.so', + 'lib/server/libjvm.so', + ], + darwin: ['jre/lib/server/libjvm.dylib', '../Libraries/libjvm.dylib', 'lib/server/libjvm.dylib'], + win32: ['jre/bin/server/jvm.dll', 'jre/bin/client/jvm.dll', 'bin/server/jvm.dll'], +}; + +const exe = process.platform === 'win32' ? '.exe' : ''; + +interface JDKExecutables { + java: string; + javac: string; + keytool: string; + jarsigner: string; +} + +interface JDKOptions extends JDKExecutables { + path: string; + version: string; +} + +/** + * Detects and organizes JDK information. + */ +export class JDK { + path!: string; + version!: string; + java!: string; + javac!: string; + keytool!: string; + jarsigner!: string; + + private constructor(options: JDKOptions) { + Object.assign(this, options); + } + + static async load(path: string): Promise { + log(`Loading: ${path}`); + if (typeof path !== 'string') { + throw new TypeError('Expected JDK path to be a valid string'); + } + if (!isDir(path)) { + throw new Error(`JDK path does not exist: ${path}`); + } + + // on macOS, the JDK lives in Contents/Home + if (process.platform === 'darwin') { + const macosPath = join(path, 'Contents', 'Home'); + if (isDir(macosPath)) { + path = macosPath; + } + } + + const executables: JDKExecutables = { + java: '', + javac: '', + keytool: '', + jarsigner: '', + }; + + await Promise.all( + Object.keys(executables).map(async (cmd) => { + const p = join(path, 'bin', `${cmd}${exe}`); + if (isFile(p)) { + executables[cmd] = await realpath(p); + } else { + const err = new Error(`Directory missing required program: ${p}`) as ErrorWithCode; + err.code = 'JDK_MISSING_REQUIRED_PROGRAM'; + throw err; + } + }) + ); + + let output = ''; + try { + const { stderr, stdout } = await execFileAsync(executables.javac, ['-version']); + output = stderr || stdout || ''; + } catch (error: any) { + // javac -version may exit with non-zero code but still provide output + output = error.stderr || ''; + } + + const result = output.trim().match(/javac (.+?)(?:_(.+))?$/); + const version = result?.[1] ?? ''; + if (!version) { + throw new Error(`Failed to determine JDK version: ${path}`); + } + log(`Found JDK: ${path} (version: ${version})`); + + return new JDK({ + path, + version, + ...executables, + }); + } +} diff --git a/src/titanium/detect-titanium-sdks.ts b/src/titanium/detect-titanium-sdks.ts new file mode 100644 index 00000000..e525d5cb --- /dev/null +++ b/src/titanium/detect-titanium-sdks.ts @@ -0,0 +1,185 @@ +import { config } from '../config.js'; +import { expand, isDir, tailgate, version } from '../util/index.js'; +import { Issue } from '../util/issue.js'; +import { readdir, readFile } from 'node:fs/promises'; +import { basename, dirname, join } from 'node:path'; + +const os = process.platform === 'darwin' ? 'osx' : process.platform; + +type TitaniumSDKOptions = { + manifest: Record; + name: string; + path: string; + platforms: Record; + type: string; + version: string; +}; + +type TitaniumSDKManifest = { + name: string; + version: string; + moduleAPIVersion: Record; + timestamp: string; + githash: string; + platforms: string[]; +}; + +class TitaniumSDK { + manifest!: TitaniumSDKManifest; + name!: string; + path!: string; + platforms!: Record; + type!: string; + version!: string; + + private constructor(options: TitaniumSDKOptions) { + Object.assign(this, options); + + if (typeof this.name !== 'string' || !this.name) { + throw new TypeError('Expected Titanium SDK name to be a valid string'); + } + } + + static async load(path: string): Promise { + const manifestFile = await readFile(join(path, 'manifest.json'), 'utf8'); + const manifest = JSON.parse(manifestFile); + + return new TitaniumSDK({ + name: manifest.name, + manifest, + path, + platforms: Array.isArray(manifest.platforms) + ? manifest.platforms.reduce((platforms, name) => { + platforms[name] = { + path: join(path, name), + }; + return platforms; + }, {}) + : {}, + type: getSDKType(manifest.name), + version: manifest.version, + }); + } +} + +type TitaniumSDKMap = Record; + +interface TiSDKs { + installPath: string; + latest: string | null; + sdkPaths: string[]; + sdks: TitaniumSDKMap; + issues: Issue[]; +} + +/** + * Detects installed Titanium SDKs. + * + * @param options - The options for the detection. + * @param options.searchPaths - The paths to search for Titanium SDKs. + * @returns The detected Titanium SDKs. + */ +export async function detectTitaniumSDKs( + options: { + searchPaths?: string[]; + } = {} +): Promise { + const searchPaths = await getSearchPaths(options); + + return tailgate('titanium:tisdk:detect', async () => { + const sdks: TitaniumSDKMap = {}; + + await Promise.all( + searchPaths.map(async (path) => { + // path could be an actual SDK or it could be a Titanium install + // directory with the mobilesdk/ subdir + try { + const sdk = await TitaniumSDK.load(path); + sdks[sdk.name] = sdk; + } catch { + // Not an SDK, check subdirectories + if (basename(path) !== os && basename(dirname(path)) !== 'mobilesdk') { + path = join(path, 'mobilesdk', os); + } + if (isDir(path)) { + for (const dir of await readdir(path)) { + try { + const sdk = await TitaniumSDK.load(join(path, dir)); + sdks[sdk.name] = sdk; + } catch { + // Not an SDK + } + } + } + } + }) + ); + + const issues: Issue[] = []; + + if (Object.keys(sdks).length === 0) { + issues.push( + new Issue('No Titanium SDKs found', { + id: 'TITANIUM_SDK_NOT_FOUND', + type: 'warning', + details: 'No Titanium SDKs found. Please install the Titanium SDK and try again.', + }) + ); + } + + const latest = + Object.keys(sdks) + .filter((s) => /.GA$/.test(s)) + .sort(version.compare) + .at(-1) || null; + + return { + installPath: config.titanium.sdk.installPath[process.platform], + latest, + sdkPaths: searchPaths, + sdks, + issues, + }; + }); +} + +function getSearchPaths(options: { searchPaths?: string[] }) { + const searchPaths = new Set(); + + if (Array.isArray(options?.searchPaths)) { + for (const path of options.searchPaths) { + if (typeof path === 'string') { + searchPaths.add(expand(path)); + } + } + } + + if (config.titanium.sdk.installPath[process.platform]) { + searchPaths.add(expand(config.titanium.sdk.installPath[process.platform])); + } + + const configPaths = config.titanium.sdk.searchPaths[process.platform]; + if (Array.isArray(configPaths)) { + for (const path of configPaths) { + searchPaths.add(expand(path)); + } + } + + return Array.from(searchPaths); +} + +function getSDKType(name) { + if (/\.ga$/i.test(name)) { + return 'ga'; + } + if (/\.rc$/i.test(name)) { + return 'rc'; + } + if (/\.beta$/i.test(name)) { + return 'beta'; + } + if (/\.v\d+$/i.test(name)) { + return 'nightly'; + } + return 'local'; +} diff --git a/src/titanium/downloads-path.ts b/src/titanium/downloads-path.ts new file mode 100644 index 00000000..9b916911 --- /dev/null +++ b/src/titanium/downloads-path.ts @@ -0,0 +1,10 @@ +import { config } from '../config.js'; +import { expand } from '../util/expand.js'; + +/** + * Returns the path to the downloads directory. + * @returns The path to the downloads directory. + */ +export function getDownloadsPath(): string { + return expand(config.titanium.downloadsDir); +} diff --git a/src/titanium/get-titanium-branch-builds.ts b/src/titanium/get-titanium-branch-builds.ts new file mode 100644 index 00000000..fc266ce3 --- /dev/null +++ b/src/titanium/get-titanium-branch-builds.ts @@ -0,0 +1,43 @@ +import { config } from '../config.js'; +import { request } from '../util/request.js'; + +type TitaniumBuild = { + name: string; + version: string; + date: string; + expires: string; + url: string; + assets: { + os: string; + url: string; + size: number; + }[]; +}; + +/** + * Retrieves the list of builds for a given branch. + * @param {String} branch - The name of the branch + * @param {String} os - The name of the current OS (osx, linux, win32) + * @returns {Promise} + */ +export async function getTitaniumBranchBuilds( + branch: string, + os: string +): Promise { + const res = await request( + config.titanium.sdk.downloadURLs.branchBuilds.replace('${branch}', branch), + { + responseType: 'json', + } + ); + const now = Date.now(); + const results = (await res.body.json()) as TitaniumBuild[]; + + if (os === 'darwin') { + os = 'osx'; + } + + return results.filter((b) => { + return (!b.expires || Date.parse(b.expires) > now) && b.assets.some((a) => a.os === os); + }); +} diff --git a/src/titanium/get-titanium-branches.ts b/src/titanium/get-titanium-branches.ts new file mode 100644 index 00000000..7d576e07 --- /dev/null +++ b/src/titanium/get-titanium-branches.ts @@ -0,0 +1,15 @@ +import { config } from '../config.js'; +import { request } from '../util/request.js'; + +/** + * Retrieves the list of branches. + * @returns {Promise} + */ +export async function getTitaniumBranches(): Promise { + const res = await request(config.titanium.sdk.downloadURLs.branches, { + responseType: 'json', + }); + return Object.entries((await res.body.json()) as Record) + .filter(([, count]) => count) + .map(([name]) => name); +} diff --git a/src/titanium/get-titanium-releases.ts b/src/titanium/get-titanium-releases.ts new file mode 100644 index 00000000..a79ff94b --- /dev/null +++ b/src/titanium/get-titanium-releases.ts @@ -0,0 +1,93 @@ +import { config } from '../config.js'; +import { request } from '../util/request.js'; + +const os = process.platform === 'darwin' ? 'osx' : process.platform; + +const sortTypes = ['local', 'nightly', 'beta', 'rc', 'ga']; + +type TitaniumRelease = { + name: string; + version: string; + date: string; + assets: { + os: string; + url: string; + size: number; + }[]; + type: string; +}; + +/** + * Retrieves the list of releases. + * @param unstable - When `true`, returns beta and rc releases along with ga releases. + * @returns {Promise} + */ +export async function getTitaniumReleases(unstable?: boolean): Promise { + const releaseRE = /^(\d+)\.(\d+)\.(\d+)\.(\w+)$/; + + const fetches = [ + unstable && + request(config.titanium.sdk.downloadURLs.releases.beta, { + responseType: 'json', + }).then(async (res) => ({ + type: 'beta', + releases: (await res.body.json()) as TitaniumRelease[], + })), + + unstable && + request(config.titanium.sdk.downloadURLs.releases.rc, { + responseType: 'json', + }).then(async (res) => ({ + type: 'rc', + releases: (await res.body.json()) as TitaniumRelease[], + })), + + request(config.titanium.sdk.downloadURLs.releases.ga, { + responseType: 'json', + }).then(async (res) => ({ + type: 'ga', + releases: (await res.body.json()) as TitaniumRelease[], + })), + ]; + + const results = await Promise.all(fetches); + + return results + .flatMap((value) => { + return value + ? value.releases.map((rel) => { + rel.type = value.type; + return rel; + }) + : []; + }) + .filter((r) => r.assets.some((a) => a.os === os)) + .sort((a, b) => { + const aMatch = a.name.toLowerCase().match(releaseRE); + const bMatch = b.name.toLowerCase().match(releaseRE); + + if (!aMatch || !bMatch) { + return 0; + } + + const [, amajor, aminor, apatch, atag] = aMatch; + const [, bmajor, bminor, bpatch, btag] = bMatch; + + let n = parseInt(bmajor) - parseInt(amajor); + if (n !== 0) { + return n; + } + + n = parseInt(bminor) - parseInt(aminor); + if (n !== 0) { + return n; + } + + n = parseInt(bpatch) - parseInt(apatch); + if (n !== 0) { + return n; + } + + return sortTypes.indexOf(btag) - sortTypes.indexOf(atag); + }); +} diff --git a/src/titanium/i18n.ts b/src/titanium/i18n.ts new file mode 100644 index 00000000..3659b53b --- /dev/null +++ b/src/titanium/i18n.ts @@ -0,0 +1,129 @@ +import { expand } from '../util/expand.js'; +import { isDir } from '../util/is-dir.js'; +import { isFile } from '../util/is-file.js'; +import * as xml from '../util/xml.js'; +import { DOMParser } from '@xmldom/xmldom'; +import { readdir, readFile } from 'node:fs/promises'; +import path from 'node:path'; +import snooplogg from 'snooplogg'; + +const { debug } = snooplogg('titanium')('i18n'); + +interface LoadOptions { + ignoreDirs?: RegExp; + ignoreFiles?: RegExp; +} + +interface LaunchScreensCache { + [projectDir: string]: string[]; +} + +interface I18NLangData { + app?: Record; + strings?: Record; +} + +interface I18NData { + [lang: string]: I18NLangData; +} + +const launchScreensCache: LaunchScreensCache = {}; + +/** + * Loads the i18n data from the project directory. + * + * @param projectDir - The project directory. + * @param opts - The options for the i18n data. + * @returns The i18n data. + */ +export async function load(projectDir: string, opts: LoadOptions = {}): Promise { + const i18nDir = expand(projectDir, 'i18n'); + const data: I18NData = {}; + const ignoreDirs = opts?.ignoreDirs; + const ignoreFiles = opts?.ignoreFiles; + + if (!isDir(i18nDir)) { + debug(`i18n directory not found in ${projectDir}`); + return data; + } + + debug(`Compiling localization files in ${i18nDir}`); + + for (const lang of await readdir(i18nDir)) { + const langDir = path.join(i18nDir, lang); + if (!isDir(langDir) || (ignoreDirs && !ignoreDirs.test(lang))) { + continue; + } + + const strings: I18NLangData = {}; + data[lang] = strings; + + for (const name of await readdir(langDir)) { + const file = path.join(langDir, name); + if (name.endsWith('.xml') && (!ignoreFiles || !ignoreFiles.test(name)) && isFile(file)) { + debug(`Processing i18n file: ${lang}/${name}`); + + const dest = name === 'app.xml' ? 'app' : 'strings'; + if (!strings[dest]) { + strings[dest] = {}; + } + const obj = strings[dest]; + const dom = new DOMParser().parseFromString(await readFile(file, 'utf8'), 'text/xml'); + + xml.forEachElement(dom.documentElement, (elem) => { + if (elem.nodeType === xml.ELEMENT_NODE && elem.tagName === 'string') { + const name = xml.getAttrString(elem, 'name'); + if (name !== null) { + obj[name] = xml.getValueString(elem); + } + } + }); + } + } + } + + return data; +} + +interface FindLaunchScreensOptions { + bypassCache?: boolean; + ignoreDirs?: RegExp; +} + +const launchScreensRegex = /^(Default(-(Landscape|Portrait))?(-[0-9]+h)?(@[2-9]x)?)\.png$/; + +/** + * Finds the launch screens in the i18n directory. + * + * @param projectDir - The project directory. + * @param opts - The options for the launch screens. + * @returns The launch screens. + */ +export async function findLaunchScreens( + projectDir: string, + opts: FindLaunchScreensOptions = {} +): Promise { + if (!opts.bypassCache && launchScreensCache[projectDir]) { + return launchScreensCache[projectDir]; + } + + const i18nDir = path.join(projectDir, 'i18n'); + const launchScreens: string[] = []; + + if (isDir(i18nDir)) { + debug('Checking for Splash Screen localization in %s', i18nDir); + for (const lang of await readdir(i18nDir)) { + const langDir = path.join(i18nDir, lang); + if (isDir(langDir) && (!opts.ignoreDirs || !opts.ignoreDirs.test(lang))) { + for (const name of await readdir(langDir)) { + if (launchScreensRegex.test(name)) { + launchScreens.push(path.join(langDir, name)); + } + } + } + } + } + + launchScreensCache[projectDir] = launchScreens; + return launchScreens; +} diff --git a/src/titanium/index.ts b/src/titanium/index.ts new file mode 100644 index 00000000..bf389626 --- /dev/null +++ b/src/titanium/index.ts @@ -0,0 +1,11 @@ +export * from './modules/index.js'; +export * from './detect-titanium-sdks.js'; +export * from './downloads-path.js'; +export * from './get-titanium-branch-builds.js'; +export * from './get-titanium-branches.js'; +export * from './get-titanium-releases.js'; +export * from './tiapp/tiapp-xml.js'; +export * from './valid-app-id.js'; + +import * as i18n from './i18n.js'; +export { i18n }; diff --git a/src/titanium/modules/detect-ti-modules.ts b/src/titanium/modules/detect-ti-modules.ts new file mode 100644 index 00000000..d84214e0 --- /dev/null +++ b/src/titanium/modules/detect-ti-modules.ts @@ -0,0 +1,353 @@ +import { config } from '../../config.js'; +import { exists, expand, extractZip, tailgate } from '../../util/index.js'; +import { TiModuleRegistry, platformAliases } from './ti-module-registry.js'; +import type { TiModuleManifest, TiModulePackageManifest } from './types.js'; +import { readdir, readFile, rm } from 'fs/promises'; +import { basename, dirname, join } from 'path'; +import snooplogg from 'snooplogg'; + +const { log, warn } = snooplogg('ti:modules'); + +/** + * Detects Titanium modules in the Titanium SDK install locations and user search paths, then + * returns a registry of found modules. + * + * @param options - The options for the function. + * @param options.searchPaths - An array of paths to search for Titanium modules. Search path can be + * a directory containing a `modules` subdirectory, an actual `modules` directory, a project + * directory containing a `node_modules` subdirectory, or a directory within a `modules` directory. + * @param options.skipInstall - When true, skips the installation of modules in the Titanium SDK + * install locations. + * @returns a registry of found modules. + */ +export async function detectTiModules( + options: { + searchPaths?: string[]; + skipInstall?: boolean; + } = {} +): Promise { + // init search paths with Titanium SDK install locations + const titaniumInstallDir = config.titanium.sdk.installPath[process.platform]; + const configPaths = config.titanium.sdk.searchPaths[process.platform]; + const modulesPaths = new Set(); + const nodeModulesPaths = new Set(); + + const sdkPaths = new Set(); + if (titaniumInstallDir) { + sdkPaths.add(expand(titaniumInstallDir)); + } + if (Array.isArray(configPaths)) { + for (const path of configPaths) { + sdkPaths.add(expand(path)); + } + } + + // before we add the user search paths, install any modules in the Titanium SDK install locations + if (!options.skipInstall) { + await Promise.all( + Array.from(sdkPaths).map(async (titaniumDir) => { + if (!(await exists(titaniumDir))) { + return; + } + const files = await readdir(titaniumDir); + await Promise.all( + files.map(async (file) => { + if (file.endsWith('.zip')) { + try { + const zipFile = join(titaniumDir, file); + log(`Installing Titanium module: ${zipFile}`); + await extractZip(zipFile, titaniumInstallDir || titaniumDir); + await rm(zipFile); + } catch (err) { + warn(`Error extracting zip file: ${(err as Error).message}`); + } + } + }) + ); + if (await exists(join(titaniumDir, 'modules'))) { + modulesPaths.add(join(titaniumDir, 'modules')); + } + }) + ); + } + + // add the user search paths + if (Array.isArray(options?.searchPaths)) { + for (let path of options.searchPaths) { + if (typeof path === 'string' && path !== '') { + path = expand(path); + if (await exists(join(path, 'node_modules'))) { + nodeModulesPaths.add(join(path, 'node_modules')); + } else if (basename(path) === 'modules' && (await exists(path))) { + modulesPaths.add(path); + } else if (await exists(join(path, 'modules'))) { + modulesPaths.add(join(path, 'modules')); + } else { + // we may be deep in the modules dir (like an actual module version directory) + while (path !== dirname(path)) { + path = dirname(path); + if (basename(path) === 'modules' && (await exists(path))) { + modulesPaths.add(path); + break; + } + } + } + } + } + } + + return tailgate('titanium:modules:detect', async () => { + const registry = new TiModuleRegistry(); + + await Promise.all([ + ...Array.from(modulesPaths).map((path) => scanPath(path, registry)), + ...Array.from(nodeModulesPaths).map((path) => scanNodeModules(path, registry)), + ]); + + return registry; + }); +} + +/** + * Scans a `modules` directory for Titanium modules. + * + * @param modulesDir - The path to the `modules` directory. + * @param registry - The registry to add the found modules to. + */ +async function scanPath(modulesDir: string, registry: TiModuleRegistry) { + log(`Detecting modules in path: ${modulesDir}`); + const platformDirs = await readdir(modulesDir); + for (const platformName of platformDirs) { + const moduleDirs = await readdir(join(modulesDir, platformName)).catch(() => []); + for (const moduleName of moduleDirs) { + const moduleDir = await readdir(join(modulesDir, platformName, moduleName)).catch(() => []); + for (const version of moduleDir) { + const path = join(modulesDir, platformName, moduleName, version); + if (!(await exists(join(path, 'manifest')))) { + continue; + } + + try { + const manifest = await readManifest(join(path, 'manifest')); + if (!manifest) { + continue; + } + log(`Found ${manifest.platform} module: ${manifest.moduleid}@${manifest.version}`); + registry.add(path, manifest); + } catch (err) { + warn(`Error reading module manifest: ${(err as Error).message}`); + } + } + } + } +} + +type TiPackageJson = { + author?: string | string[]; + copyright?: string; + description?: string; + license?: string; + name?: string; + titanium?: TiModulePackageManifest; + version?: string; +}; + +/** + * Scans a `node_modules` directory for Titanium modules. + * + * @param nodeModulesDir - The path to a `node_modules` directory. + * @param registry - The registry to add the found modules to. + */ +async function scanNodeModules(nodeModulesDir: string, registry: TiModuleRegistry) { + log(`Detecting modules in node_modules: ${nodeModulesDir}`); + const packageDirs = await readdir(nodeModulesDir).catch(() => []); + + for (const packageName of packageDirs) { + const packageDir = join(nodeModulesDir, packageName); + if (packageName.startsWith('@')) { + scanNodeModules(join(packageDir), registry); + return; + } + + if (!(await exists(join(packageDir, 'package.json')))) { + continue; + } + + log(`Scanning node package: ${packageDir}`); + + let pkgJson: TiPackageJson | undefined; + try { + const packageJsonContents = await readFile(join(packageDir, 'package.json'), 'utf8'); + pkgJson = JSON.parse(packageJsonContents) as TiPackageJson; + } catch (err) { + warn(`Error reading package.json: ${(err as Error).message}`); + continue; + } + + const pkgTiJson = pkgJson?.titanium as TiModulePackageManifest; + if (!pkgTiJson || typeof pkgTiJson !== 'object' || pkgTiJson.type !== 'native-module') { + continue; + } + + const platformNames: string[] = + typeof pkgTiJson.platform === 'string' + ? [pkgTiJson.platform] + : Array.isArray(pkgTiJson.platform) + ? pkgTiJson.platform + : typeof pkgTiJson.platform === 'object' && pkgTiJson.platform !== null + ? Object.keys(pkgTiJson.platform) + : []; + + const platformDirs: Record = {}; + for (const platformName of platformNames) { + platformDirs[platformName] = + platformAliases[platformName] && + (await exists(join(packageDir, platformAliases[platformName]))) + ? join(packageDir, platformAliases[platformName]) + : (await exists(join(packageDir, platformName))) + ? join(packageDir, platformName) + : null; + } + + if ( + platformNames.length === 1 && + platformDirs[platformNames[0]] === null && + (await exists(join(packageDir, 'manifest'))) + ) { + // the package dir is the module dir + platformDirs[platformNames[0]] = packageDir; + } + + const missingPlatformDirs = Object.entries(platformDirs) + .filter(([_platform, path]) => path === null) + .map(([platform]) => platform); + if (Object.keys(platformDirs).length > 1 && missingPlatformDirs.length) { + throw new Error( + `Multiple platform native modules require use of platform-specific subdirectories: ${missingPlatformDirs.join(', ')}` + ); + } + + for (const [platform, path] of Object.entries(platformDirs)) { + if (!path) { + continue; + } + + try { + const manifest = await readManifest(join(path, 'manifest')).catch(() => undefined); + const apiversion = + typeof pkgTiJson.apiversion === 'number' + ? pkgTiJson.apiversion + : typeof pkgTiJson.apiversion === 'string' + ? Number.parseInt(pkgTiJson.apiversion) + : manifest?.apiversion; + const author = + pkgTiJson.author || + (Array.isArray(pkgJson.author) && pkgJson.author[0]) || + (typeof pkgJson.author === 'string' && pkgJson.author) || + manifest?.author; + const moduleid = pkgTiJson.moduleid || manifest?.moduleid; + const name = + pkgTiJson.name || + (typeof pkgJson.name === 'string' && pkgJson.name.replace(/^@[^/]+\//, '')) || + manifest?.name; + const version = pkgJson.version || manifest?.version; + + if (!version) { + throw new Error(`Titanium module missing version: ${path}`); + } + + if (!moduleid) { + throw new Error(`Titanium module missing module id: ${path}`); + } + + log(`Found ${platform} module: ${moduleid}@${version}`); + + registry.add(path, { + architectures: Array.isArray(pkgTiJson.architectures) + ? pkgTiJson.architectures + : pkgTiJson.architectures?.split(' ') || manifest?.architectures, + apiversion: apiversion === undefined || isNaN(apiversion) ? undefined : apiversion, + author, + copyright: getPkgJsonProp('copyright', pkgJson, pkgTiJson, manifest), + description: getPkgJsonProp('description', pkgJson, pkgTiJson, manifest), + guid: pkgTiJson.guid || manifest?.guid, + license: getPkgJsonProp('license', pkgJson, pkgTiJson, manifest), + minsdk: getPkgJsonProp('minsdk', pkgJson, pkgTiJson, manifest), + moduleid, + name, + platform, + version, + }); + } catch (err) { + warn((err as Error).message); + } + } + } +} + +function getPkgJsonProp( + prop: string, + pkgJson: Record, + pkgTiJson: TiModulePackageManifest, + manifest?: TiModuleManifest +): string | undefined { + return ( + pkgTiJson[prop] || (typeof pkgJson[prop] === 'string' && pkgJson[prop]) || manifest?.[prop] + ); +} + +const versionRegExp = /^(\d+\.){0,2}(\d+)$/; + +/** + * Reads a module manifest file, validates it, and returns a TitaniumModuleManifest object or + * `undefined` if the manifest is invalid. + * @param manifestFile path to manifest file + * @returns TitaniumModuleManifest + */ +async function readManifest(manifestFile: string) { + const manifest: Record = {}; + const manifestContents = await readFile(manifestFile, 'utf8'); + + for (const line of manifestContents.split(/\r?\n/)) { + const p = line.indexOf(':'); + if (!line.startsWith('#') && p !== -1) { + const key = line.substring(0, p).trim(); + if (key) { + manifest[key] = line.substring(p + 1).trim(); + } + } + } + + if (!manifest.moduleid) { + throw new Error(`Module manifest is missing moduleid: ${manifestFile}`); + } + + if (!manifest.platform) { + throw new Error(`Module manifest is missing platform: ${manifestFile}`); + } + + if (!manifest.version) { + throw new Error(`Module manifest is missing version: ${manifestFile}`); + } + + if (!versionRegExp.test(manifest.version)) { + throw new Error(`Module manifest has invalid version: ${manifest.version}`); + } + + const platform = platformAliases[manifest.platform] || manifest.platform; + + return { + apiversion: manifest.apiversion ? Number.parseInt(manifest.apiversion) : undefined, + architectures: manifest.architectures ? manifest.architectures.split(' ') : undefined, + author: manifest.author, + copyright: manifest.copyright, + description: manifest.description, + guid: manifest.guid, + license: manifest.license, + moduleid: manifest.moduleid, + minsdk: manifest.minsdk, + name: manifest.name, + platform, + version: manifest.version, + } as TiModuleManifest; +} diff --git a/src/titanium/modules/index.ts b/src/titanium/modules/index.ts new file mode 100644 index 00000000..94f9227c --- /dev/null +++ b/src/titanium/modules/index.ts @@ -0,0 +1,2 @@ +export * from './detect-ti-modules.js'; +export * from './ti-module-registry.js'; diff --git a/src/titanium/modules/ti-module-registry.ts b/src/titanium/modules/ti-module-registry.ts new file mode 100644 index 00000000..ed669a7f --- /dev/null +++ b/src/titanium/modules/ti-module-registry.ts @@ -0,0 +1,233 @@ +import * as version from '../../util/version.js'; +import type { TiModule, TiModuleManifest } from './types.js'; +import snooplogg from 'snooplogg'; + +const { log } = snooplogg('ti:module-registry'); + +export const platformAliases = { + ipad: 'ios', + iphone: 'ios', +}; + +type TiModuleSearchResults = { + found: TiModule[]; + missing: TiappModule[]; + incompatible: TiModule[]; + conflict: TiModule[]; +}; + +type TiappModule = { + moduleid: string; + platform?: string; + version?: string; + deployType?: string; +}; + +export class TiModuleRegistry { + // moduleId > platform > version > module + modules: Record>> = {}; + + /** + * Registers a module from the tiapp.xml `` tag. + * @param path - The path to the module. + * @param manifest - The manifest of the module. + */ + add(path: string, manifest: TiModuleManifest) { + if (!this.modules[manifest.moduleid]) { + this.modules[manifest.moduleid] = {}; + } + + if (!this.modules[manifest.moduleid][manifest.platform]) { + this.modules[manifest.moduleid][manifest.platform] = {}; + } + log( + `Adding module "${manifest.moduleid}" on platform="${manifest.platform}" version="${manifest.version}" path="${path}"` + ); + + this.modules[manifest.moduleid][manifest.platform][manifest.version] = { + ...manifest, + path, + }; + } + + /** + * Search for installed Titanium modules. + * + * @param options - The options for the function. + * @param options.deployType - The deploy type to search for. + * @param options.moduleAPIVersion - The module API version to search for. + * @param options.modules - The found in the `tiapp.xml`. + * @param options.platform - The platform(s) to search for. Generally this + * is either `'android'` or `['ios', 'iphone']`. + * @param options.sdkVersion - The SDK version to search for. + * @returns Returns matching modules. + */ + async search(options: { + deployType?: string; + moduleAPIVersion?: string; + modules: TiappModule[]; + platform?: string | string[]; + sdkVersion?: string; + }): Promise { + const results: TiModuleSearchResults = { + found: [], + missing: [], + incompatible: [], + conflict: [], + }; + const foundByModuleId = new Map(); + + const tiappModules = options.modules; + if (tiappModules === undefined || !Array.isArray(tiappModules)) { + throw new Error('Expected modules to be an array'); + } + if (tiappModules.length === 0) { + return results; + } + + // clean up platforms + const platformsSet = new Set( + Array.isArray(options.platform) + ? options.platform + .map((p) => (platformAliases[p.trim()] || p.trim()).toLowerCase()) + .filter(Boolean) + : typeof options.platform === 'string' + ? options.platform + .split(/[, ]+/) + .map((p) => (platformAliases[p.trim()] || p.trim()).toLowerCase()) + .filter(Boolean) + : [] + ); + if (platformsSet.size > 0 && !platformsSet.has('commonjs')) { + platformsSet.add('commonjs'); + } + const wantedPlatforms = Array.from(platformsSet); + + for (const subject of tiappModules) { + const moduleid = subject.moduleid?.trim(); + if (!moduleid) { + // this should never happen + throw new Error('Module has no module id'); + } + const wantedVersion = + subject.version === undefined + ? 'latest' + : typeof subject.version !== 'string' || + !/^((\d+\.){0,2}(\d+))|latest$/i.test(subject.version.trim()) + ? null + : subject.version.trim().toLowerCase(); + if (wantedVersion === null) { + throw new Error(`Module "${moduleid}" has invalid version "${subject.version}"`); + } + + const byModuleId = this.modules[moduleid]; + if (!byModuleId) { + results.missing.push(subject); + continue; + } + + const deployTypes = + subject.deployType + ?.toLowerCase() + .split(/[, ]+/) + .map((p) => p.trim()) + .filter(Boolean) || []; + if (options.deployType && !deployTypes.includes(options.deployType.toLowerCase())) { + log(`Deploy type "${options.deployType}" not found for "${moduleid}"`); + continue; + } + + const platformsSet = new Set( + subject.platform + ? subject.platform + .split(/[, ]+/) + .map((p) => (platformAliases[p.trim()] || p.trim()).toLowerCase()) + .filter(Boolean) + : wantedPlatforms + ); + const modulePlatforms = platformsSet.size > 0 ? Array.from(platformsSet) : wantedPlatforms; + + const platformsToSearch = + wantedPlatforms.length > 0 + ? modulePlatforms.filter((p) => wantedPlatforms.includes(p)) + : modulePlatforms.length > 0 + ? modulePlatforms + : Object.keys(byModuleId); + + if (platformsToSearch.length === 0) { + log( + `No platforms found for "${moduleid}" wanted="${wantedPlatforms.join(',')}" available="${modulePlatforms.join(',')}"` + ); + continue; + } + + const isLatest = wantedVersion.toLowerCase() === 'latest'; + + for (const platform of platformsToSearch) { + const byVersion = byModuleId[platform]; + if (!byVersion || typeof byVersion !== 'object' || Object.keys(byVersion).length === 0) { + log(`Found "${moduleid}", but no versions found on platform="${platform}"`); + results.missing.push(subject); + continue; + } + + const ver = isLatest + ? (Object.keys(byVersion) + .sort((a, b) => version.compare(a, b)) + .at(-1) as string) + : wantedVersion; + + const candidate = byVersion[ver]; + + // moduleAPIVersion and sdkVersion vs TiModule.apiversion and TiModule.minsdk + if (options.moduleAPIVersion !== undefined && candidate.apiversion !== undefined) { + const wantApi = Number.parseInt(String(options.moduleAPIVersion), 10); + const moduleApi = Number(candidate.apiversion); + if (!Number.isNaN(wantApi) && wantApi !== moduleApi) { + log( + `Found "${moduleid}", but requires API version "${wantApi}" (current=${moduleApi})` + ); + results.incompatible.push(candidate); + continue; + } + } + + const minsdk = + typeof candidate.minsdk === 'string' + ? candidate.minsdk.replace(/^\.|[^\d.]|\.$/g, '') + : undefined; + if ( + options.sdkVersion !== undefined && + minsdk !== undefined && + version.isValid(minsdk) && + version.gte(minsdk, options.sdkVersion) + ) { + log( + `Found "${moduleid}", but requires SDK version "${minsdk}" (current=${options.sdkVersion})` + ); + results.incompatible.push(candidate); + continue; + } + + log(`Found "${moduleid}" platform="${platform}" version="${ver}"`); + results.found.push(candidate); + const list = foundByModuleId.get(candidate.moduleid) ?? []; + list.push(candidate); + foundByModuleId.set(candidate.moduleid, list); + } + } + + // detect conflicts: same moduleid with different platforms + const conflictingModuleIds = new Set(); + for (const [moduleid, mods] of foundByModuleId) { + const platforms = new Set(mods.map((m) => m.platform)); + if (platforms.size > 1) { + conflictingModuleIds.add(moduleid); + results.conflict.push(...mods); + } + } + results.found = results.found.filter((mod) => !conflictingModuleIds.has(mod.moduleid)); + + return results; + } +} diff --git a/src/titanium/modules/types.ts b/src/titanium/modules/types.ts new file mode 100644 index 00000000..f038fdbc --- /dev/null +++ b/src/titanium/modules/types.ts @@ -0,0 +1,48 @@ +export type TiModuleManifest = { + architectures?: string[]; + apiversion?: number; + author?: string; + copyright?: string; + description?: string; + guid?: string; + license?: string; + minsdk?: string; + moduleid: string; + name?: string; + platform: string; + version: string; +}; + +export type TiModulePackageManifest = { + architectures?: string | string[]; + apiversion?: number; + author?: string; + copyright?: string; + description?: string; + guid?: string; + license?: string; + minsdk?: string; + moduleid: string; + name?: string; + platform: string | string[] | Record; + type: string; + version: string; +}; + +export interface TiModule { + architectures?: string[]; + apiversion?: number; + author?: string; + copyright?: string; + description?: string; + guid?: string; + license?: string; + minsdk?: string; + moduleid: string; + name?: string; + path: string; + platform: string; + version: string; +} + +export type TiModuleVersion = Record; diff --git a/src/titanium/tiapp/README.md b/src/titanium/tiapp/README.md new file mode 100644 index 00000000..2b32f484 --- /dev/null +++ b/src/titanium/tiapp/README.md @@ -0,0 +1,58 @@ +# `tiapp.xml` + +Supported tags: + +- android + - abi + - activities + - manifest + - services + - tool-api-level +- copyright +- default-lang +- deployment-targets + - target +- description +- fullscreen +- guid +- icon +- id +- ios + - capabilities + - default-background-color + - enable-launch-screen-storyboard + - entitlements + - extensions + - log-server-port + - min-ios-ver + - plist + - team-id + - use-app-thinning + - use-autolayout + - use-jscore-framework + - use-new-build-system +- modules + - module +- name +- navbar-hidden +- override-permissions +- persistent-wifi +- prerendered-icon +- properties + - android.javac.maxMemory + - ti.android.compilejs + - ti.android.debug + - ti.android.loadfromsdcard + - ti.deployType + - ti.facebook.appid + - ti.skipAppIdValidation + - ti.skipVersionValidation + - ti.ui.defaultunit + - transpile +- publisher +- sdk-version +- source-maps +- statusbar-hidden +- statusbar-style +- url +- version diff --git a/src/titanium/tiapp/tiapp-schema.ts b/src/titanium/tiapp/tiapp-schema.ts new file mode 100644 index 00000000..f2805a4a --- /dev/null +++ b/src/titanium/tiapp/tiapp-schema.ts @@ -0,0 +1,204 @@ +import * as z from 'zod'; + +/** + * Coerce values to strings for XML text content + */ +const OptionalStringSchema = z + .union([z.string(), z.number()]) + .transform((val) => String(val)) + .optional(); + +/** + * Boolean schema that accepts boolean or string 'true'/'false' + */ +const BooleanSchema = z + .union([z.boolean(), z.literal('true'), z.literal('false'), z.string()]) + .transform((val) => { + if (typeof val === 'boolean') { + return val; + } + if (val === 'true') { + return true; + } + if (val === 'false') { + return false; + } + return Boolean(val); + }); + +/** + * Number schema that accepts numbers or numeric strings + */ +const NumberSchema = z.union([z.number(), z.string()]).transform((val) => { + if (typeof val === 'number') { + return val; + } + return Number.parseFloat(val); +}); + +/** + * Property value schema for tags + */ +export const PropertyValueSchema = z.object({ + type: z.enum(['string', 'bool', 'int', 'double']).default('string'), + value: z.any(), +}); + +/** + * Properties schema - record of property name to property value. + * Accepts both { type, value } format and flat primitive values. + */ +export const PropertiesSchema = z + .record(z.string(), z.union([PropertyValueSchema, z.string(), z.number(), z.boolean()])) + .optional(); + +/** + * Module schema for elements + */ +export const ModuleSchema = z.object({ + moduleid: z.string().min(1, { message: 'Module must have an id' }), + platform: z + .string() + .refine((val) => val === val.toLowerCase(), { message: 'Module "platform" must be lowercase' }) + .optional(), + version: z + .union([z.string(), z.number()]) + .transform((val) => String(val)) + .refine((val) => /^\d+(\.\d+)?(\.\d+)?$/.test(val), { + message: 'Module version is invalid', + }) + .optional(), + deployType: z.string().optional(), +}); + +/** + * Modules schema - array of modules + */ +export const ModulesSchema = z.array(ModuleSchema).optional(); + +/** + * Deployment target schema + */ +export const DeploymentTargetsSchema = z + .record(z.string(), z.union([z.boolean(), z.string()])) + .optional(); + +/** + * iOS capabilities schema + */ +export const IOSCapabilitiesSchema = z + .object({ + appGroups: z.array(z.string()).optional(), + }) + .optional(); + +/** + * iOS extension target schema + */ +const IOSExtensionTargetSchema = z.object({ + name: z.string(), + ppUUIDs: z.record(z.string(), z.string()).optional(), +}); + +/** + * iOS extension provisioning profile schema + */ +const IOSProvisioningProfileSchema = z.record(z.string(), z.any()); + +/** + * iOS extension schema - accepts target/targets and provisioningProfiles + */ +const IOSExtensionSchema = z.object({ + projectPath: z.string(), + target: z.string().optional(), + targets: z.array(IOSExtensionTargetSchema).optional(), + provisioningProfiles: z.array(IOSProvisioningProfileSchema).optional(), +}); + +/** + * iOS configuration schema + */ +export const IOSSchema = z + .object({ + capabilities: IOSCapabilitiesSchema, + defaultBackgroundColor: OptionalStringSchema, + enableLaunchScreenStoryboard: BooleanSchema.optional(), + entitlements: z.record(z.string(), z.any()).optional(), + extensions: z.array(IOSExtensionSchema).optional(), + logServerPort: z.number().optional(), + minIosVer: NumberSchema.optional(), + plist: z.record(z.string(), z.any()).optional(), + teamId: OptionalStringSchema, + useAppThinning: BooleanSchema.optional(), + useAutolayout: BooleanSchema.optional(), + useJscoreFramework: BooleanSchema.optional(), + useNewBuildSystem: BooleanSchema.optional(), + }) + .optional(); + +/** + * Android activity/service item (array element) + */ +const AndroidActivityServiceItemSchema = z.record(z.string(), z.any()); + +/** + * Android activity/service schema - accepts array or record format + */ +const AndroidActivityServiceSchema = z.union([ + z.array(AndroidActivityServiceItemSchema), + z.record(z.string(), z.any()), +]); + +/** + * Android configuration schema + */ +export const AndroidSchema = z + .object({ + manifest: OptionalStringSchema, + toolAPILevel: NumberSchema.optional(), + abi: z.union([z.array(z.string()), z.string()]).optional(), + activities: AndroidActivityServiceSchema.optional(), + services: AndroidActivityServiceSchema.optional(), + }) + .optional(); + +/** + * Main Tiapp schema + */ +export const TiappSchema = z + .object({ + id: z.string().optional(), + idPlatformAndroid: z.string().optional(), + idPlatformIos: z.string().optional(), + name: OptionalStringSchema, + version: OptionalStringSchema, + publisher: OptionalStringSchema, + url: OptionalStringSchema, + description: OptionalStringSchema, + copyright: OptionalStringSchema, + icon: OptionalStringSchema, + fullscreen: BooleanSchema.optional(), + navbarHidden: BooleanSchema.optional(), + analytics: BooleanSchema.optional(), + guid: OptionalStringSchema, + persistentWifi: BooleanSchema.optional(), + prerenderedIcon: BooleanSchema.optional(), + statusbarStyle: OptionalStringSchema, + statusbarHidden: BooleanSchema.optional(), + sdkVersion: OptionalStringSchema, + properties: PropertiesSchema, + deploymentTargets: DeploymentTargetsSchema, + modules: ModulesSchema, + ios: IOSSchema, + android: AndroidSchema, + }) + .partial(); + +/** + * Infer TypeScript types from schemas + */ +export type PropertyValue = z.infer; +export type Module = z.infer; +export type IOSConfig = z.infer; +export type AndroidConfig = z.infer; +export type Tiapp = z.infer; diff --git a/src/titanium/tiapp/tiapp-transform.ts b/src/titanium/tiapp/tiapp-transform.ts new file mode 100644 index 00000000..801ee0fc --- /dev/null +++ b/src/titanium/tiapp/tiapp-transform.ts @@ -0,0 +1,1240 @@ +import { parsePlist, stringifyPlist } from '../../util/plist.js'; +import * as xml from '../../util/xml.js'; +import { TiappSchema, type Tiapp } from './tiapp-schema.js'; +import { DOMParser } from '@xmldom/xmldom'; + +export type TiappData = Record; + +const ELEMENT_NODE = 1; + +/** + * Convert kebab-case to camelCase for JavaScript property names + */ +export function toCamelCase(xmlTag: string): string { + return xmlTag.replace(/-([a-z])/g, (_m, p1) => p1.toUpperCase()); +} + +/** + * Convert camelCase to kebab-case for XML tag names + */ +export function toXmlTag(camelCase: string): string { + return camelCase.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase()); +} + +/** + * Find an element by tag name and optional platform attribute + */ +export function findElement(doc: Document, tagName: string, platform?: string): Element | null { + const root = doc.documentElement; + let child = root.firstChild; + + while (child) { + if (child.nodeType === xml.ELEMENT_NODE) { + const elem = child as Element; + if (elem.tagName === tagName) { + const platformAttr = elem.getAttribute('platform'); + if (platform && platformAttr === platform) { + return elem; + } + if (!platform && !platformAttr) { + return elem; + } + } + } + child = child.nextSibling; + } + + return null; +} + +/** + * Find all elements by tag name + */ +export function findElements(doc: Document, tagName: string): Element[] { + const elements: Element[] = []; + const root = doc.documentElement; + let child = root.firstChild; + + while (child) { + if (child.nodeType === xml.ELEMENT_NODE) { + const elem = child as Element; + if (elem.tagName === tagName) { + elements.push(elem); + } + } + child = child.nextSibling; + } + + return elements; +} + +/** + * Detect indentation pattern from existing content + */ +export function detectIndentation(doc: Document): string { + const root = doc.documentElement; + let child = root.firstChild; + + while (child) { + if (child.nodeType === 3) { + // TEXT_NODE + const text = child.nodeValue || ''; + const match = text.match(/\n([\t ]+)/); + if (match) { + return match[1]; + } + } + child = child.nextSibling; + } + + // Default to tab + return '\t'; +} + +/** + * Remove an element and its surrounding whitespace + */ +export function removeElement(elem: Element): void { + const parent = elem.parentNode; + if (!parent) { + return; + } + + // Remove preceding whitespace text node if it exists + const prevSibling = elem.previousSibling; + if (prevSibling && prevSibling.nodeType === 3) { + const text = prevSibling.nodeValue || ''; + if (text.trim() === '') { + parent.removeChild(prevSibling); + } + } + + // Remove the element + parent.removeChild(elem); +} + +/** + * Create an element with proper whitespace + */ +export function createElement( + doc: Document, + tagName: string, + value: any, + platform?: string +): Element { + const root = doc.documentElement; + const indent = detectIndentation(doc); + + // Add whitespace before new element + root.appendChild(doc.createTextNode(`\n${indent}`)); + + // Create element + const elem = doc.createElement(tagName); + + // Add platform attribute if specified + if (platform) { + elem.setAttribute('platform', platform); + } + + // Set value + if (value !== undefined && value !== null) { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + elem.appendChild(doc.createTextNode(String(value))); + } + } + + root.appendChild(elem); + + return elem; +} + +/** + * Update an element's value + */ +export function updateElement(elem: Element, value: any): void { + // Clear existing content + while (elem.firstChild) { + elem.removeChild(elem.firstChild); + } + + // Set new value + if (value !== undefined && value !== null) { + if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { + elem.appendChild(elem.ownerDocument.createTextNode(String(value))); + } + } +} + +/** + * Parse a simple text value, coercing booleans where appropriate. + * Numbers are kept as strings to preserve XML format (e.g. version '1.0'). + */ +function parseSimpleValue(elem: Element, parseBool = true): string | boolean { + const raw = xml.getValueString(elem); + if (parseBool && raw === 'true') { + return true; + } + if (parseBool && raw === 'false') { + return false; + } + return raw; +} + +/** + * Parse property value with type attribute + */ +function parsePropertyValue(elem: Element): { type: string; value: unknown } { + const type = elem.getAttribute('type') || 'string'; + const raw = xml.getValueString(elem); + let value: unknown = raw; + if (type === 'bool') { + value = raw === 'true'; + } else if (type === 'int') { + value = Number.parseInt(raw) || 0; + } else if (type === 'double') { + value = Number.parseFloat(raw) || 0; + } + return { type, value }; +} + +/** + * Read deployment-targets structure + */ +function readDeploymentTargets(doc: Document): Record | undefined { + const container = findElement(doc, 'deployment-targets'); + if (!container) { + return undefined; + } + + const result: Record = {}; + let child = container.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + const elem = child as Element; + if (elem.tagName === 'target') { + const device = elem.getAttribute('device'); + if (device) { + const val = xml.getValueString(elem); + result[device] = val === 'true' ? true : val === 'false' ? false : val; + } + } + } + child = child.nextSibling; + } + return Object.keys(result).length > 0 ? result : undefined; +} + +/** + * Read properties structure (flat key -> value for JSON output) + */ +function readProperties(doc: Document): Record | undefined { + const elements = findElements(doc, 'property'); + if (elements.length === 0) { + return undefined; + } + + const result: Record = {}; + for (const elem of elements) { + const name = elem.getAttribute('name'); + if (name) { + const pv = parsePropertyValue(elem); + result[name] = pv.value; + } + } + return result; +} + +/** + * Read modules array + */ +function readModules( + doc: Document +): + | Array<{ moduleid: string; platform?: string; version?: string | number; deployType?: string }> + | undefined { + const container = findElement(doc, 'modules'); + if (!container) { + return undefined; + } + + const modules: Array<{ + moduleid: string; + platform?: string; + version?: string | number; + deployType?: string; + }> = []; + let child = container.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + const elem = child as Element; + if (elem.tagName === 'module') { + const moduleid = xml.getValueString(elem).trim() || ''; + modules.push({ + moduleid, + platform: elem.getAttribute('platform') || undefined, + version: elem.getAttribute('version') || undefined, + deployType: elem.getAttribute('deploy-type') || undefined, + }); + } + } + child = child.nextSibling; + } + return modules; +} + +/** + * Read plugins array (plugin elements may be inside plugins container) + */ +function readPlugins(doc: Document): Array<{ id: string; version?: string | number }> | undefined { + const elements = doc.getElementsByTagName ? doc.getElementsByTagName('plugin') : []; + const list = Array.from(elements); + if (list.length === 0) { + return undefined; + } + + return list.map((elem) => ({ + id: xml.getValueString(elem).trim(), + version: elem.getAttribute('version') || undefined, + })); +} + +/** + * Read iOS capabilities (app-groups etc.) + */ +function readIOSCapabilities(iosElem: Element): Record | undefined { + const capElem = iosElem.getElementsByTagName('capabilities')[0]; + if (!capElem) { + return undefined; + } + + const capabilities: Record = {}; + let child = capElem.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + const elem = child as Element; + if (elem.tagName === 'app-groups' || elem.tagName === 'appGroups') { + const groups: string[] = []; + let groupChild = elem.firstChild; + while (groupChild) { + if (groupChild.nodeType === ELEMENT_NODE) { + const g = groupChild as Element; + if (g.tagName === 'group') { + groups.push(xml.getValueString(g)); + } + } + groupChild = groupChild.nextSibling; + } + capabilities.appGroups = groups; + } + } + child = child.nextSibling; + } + return Object.keys(capabilities).length > 0 ? capabilities : undefined; +} + +/** + * Read iOS config + */ +function readIOS(doc: Document): Record | undefined { + const iosElem = findElement(doc, 'ios'); + if (!iosElem) { + return undefined; + } + + const result: Record = {}; + const simpleTags = [ + 'enable-launch-screen-storyboard', + 'default-background-color', + 'use-app-thinning', + 'min-ios-ver', + 'team-id', + 'log-server-port', + 'use-jscore-framework', + 'run-on-main-thread', + 'use-autolayout', + 'use-new-build-system', + 'use-app-thinning', + 'exclude-dir-from-asset-catalog', + ]; + for (const tag of simpleTags) { + const child = iosElem.getElementsByTagName(tag)[0]; + if (child) { + const key = toCamelCase(tag); + let val: unknown = parseSimpleValue(child); + if (tag === 'log-server-port' && typeof val === 'string') { + const n = Number.parseInt(val, 10); + val = Number.isNaN(n) ? val : n; + } + result[key] = val; + } + } + + const cap = readIOSCapabilities(iosElem); + if (cap) { + result.capabilities = cap; + } + + const entElem = iosElem.getElementsByTagName('entitlements')[0]; + if (entElem) { + const entRoot = entElem.firstElementChild ?? entElem.getElementsByTagName('dict')[0]; + if (entRoot) { + result.entitlements = parsePlist>( + `${entRoot.toString()}` + ); + } + } + + const plistElem = iosElem.getElementsByTagName('plist')[0]; + if (plistElem) { + const plistRoot = plistElem.firstElementChild ?? plistElem.getElementsByTagName('dict')[0]; + if (plistRoot) { + result.plist = parsePlist>( + `${plistRoot.toString()}` + ); + } + } + + const extElem = iosElem.getElementsByTagName('extensions')[0]; + if (extElem) { + const extensions: Array<{ + projectPath: string; + target?: string; + provisioningProfiles?: Array>; + }> = []; + const extList = extElem.getElementsByTagName('extension'); + for (let i = 0; i < extList.length; i++) { + const ext = extList[i]; + const projectPath = + ext.getAttribute('projectPath') || + ext.getAttribute('project-path') || + xml.getValueString(ext) || + ''; + const extObj: { + projectPath: string; + target?: string; + provisioningProfiles?: Array>; + } = { projectPath }; + const targets = ext.getElementsByTagName('target'); + if (targets.length > 0) { + const t = targets[0]; + extObj.target = t.getAttribute('name') || xml.getValueString(t) || ''; + const ppElem = t.getElementsByTagName('provisioning-profiles')[0]; + if (ppElem) { + const profiles: Array> = []; + const device = ppElem.getElementsByTagName('device')[0]; + const distAppstore = ppElem.getElementsByTagName('dist-appstore')[0]; + const distAdhoc = ppElem.getElementsByTagName('dist-adhoc')[0]; + if (device || distAppstore || distAdhoc) { + const prof: Record = {}; + if (device) { + prof.device = xml.getValueString(device); + } + if (distAppstore) { + prof.distAppstore = xml.getValueString(distAppstore); + } + if (distAdhoc) { + prof.distAdhoc = true; + } + profiles.push(prof); + } + extObj.provisioningProfiles = profiles; + } + } + extensions.push(extObj); + } + if (extensions.length > 0) { + result.extensions = extensions; + } + } + + return result; +} + +/** + * Read Android config + */ +function readAndroid(doc: Document): Record | undefined { + // findElement may miss 'android' in namespaced docs; try getElementsByTagName + let androidElem = findElement(doc, 'android'); + if (!androidElem && doc.getElementsByTagName) { + const list = doc.getElementsByTagName('android'); + androidElem = list.length ? list[0] : null; + } + if (!androidElem) { + return undefined; + } + + const result: Record = {}; + const manifestElem = androidElem.getElementsByTagName('manifest')[0]; + if (manifestElem) { + result.manifest = manifestElem + .toString() + .replace(/ xmlns:android="http:\/\/schemas\.android\.com\/apk\/res\/android"/g, ''); + } + + // tool-api-level: search within android + let toolApiVal: number | undefined; + const toolApiList = androidElem.getElementsByTagName('tool-api-level'); + if (toolApiList.length > 0) { + toolApiVal = Number.parseFloat(xml.getValueString(toolApiList[0])); + } + if (toolApiVal === undefined || Number.isNaN(toolApiVal)) { + // Fallback: walk direct children (getElementsByTagName can fail in namespaced docs) + xml.forEachElement(androidElem, (el) => { + const name = (el as Element & { localName?: string }).localName || el.tagName || ''; + if (name.toLowerCase().replace(/_/g, '-') === 'tool-api-level') { + const v = Number.parseFloat(xml.getValueString(el)); + if (!Number.isNaN(v)) { + toolApiVal = v; + } + } + }); + } + if (toolApiVal !== undefined && !Number.isNaN(toolApiVal)) { + result.toolAPILevel = toolApiVal; + } + + const abiElem = androidElem.getElementsByTagName('abi')[0]; + if (abiElem) { + const abiVal = xml.getValueString(abiElem); + result.abi = abiVal.includes(',') ? abiVal.split(',').map((s) => s.trim()) : abiVal; + } + + const activitiesElem = androidElem.getElementsByTagName('activities')[0]; + if (activitiesElem) { + const activities: Array> = []; + const acts = activitiesElem.getElementsByTagName('activity'); + for (let i = 0; i < acts.length; i++) { + const a = acts[i]; + const url = a.getAttribute('url') || xml.getValueString(a) || ''; + activities.push({ + url, + ...Object.fromEntries( + Array.from(a.attributes) + .filter((attr) => attr.name !== 'url') + .map((attr) => [toCamelCase(attr.name), attr.value]) + ), + }); + } + result.activities = activities; + } + + const servicesElem = androidElem.getElementsByTagName('services')[0]; + if (servicesElem) { + const services: Array> = []; + const svcs = servicesElem.getElementsByTagName('service'); + for (let i = 0; i < svcs.length; i++) { + const s = svcs[i]; + const url = s.getAttribute('url') || xml.getValueString(s) || ''; + services.push({ + url, + ...Object.fromEntries( + Array.from(s.attributes) + .filter((attr) => attr.name !== 'url') + .map((attr) => [toCamelCase(attr.name), attr.value]) + ), + }); + } + result.services = services; + } + + return result; +} + +/** + * Read webpack config + */ +function readWebpack(doc: Document): Record | undefined { + const webpackElem = findElement(doc, 'webpack'); + if (!webpackElem) { + return undefined; + } + + const result: Record = {}; + const typeElem = webpackElem.getElementsByTagName('type')[0]; + if (typeElem) { + result.type = xml.getValueString(typeElem); + } + + const depsElem = webpackElem.getElementsByTagName('transpile-dependencies')[0]; + if (depsElem) { + const deps: string[] = []; + const depList = depsElem.getElementsByTagName('dep'); + for (let i = 0; i < depList.length; i++) { + deps.push(xml.getValueString(depList[i])); + } + result.transpileDependencies = deps; + } + + return Object.keys(result).length > 0 ? result : undefined; +} + +/** + * Simple scalar tags at root level (with optional platform attribute) + */ +const SIMPLE_TAGS = [ + 'id', + 'name', + 'version', + 'publisher', + 'url', + 'description', + 'copyright', + 'icon', + 'fullscreen', + 'navbar-hidden', + 'analytics', + 'guid', + 'persistent-wifi', + 'prerendered-icon', + 'statusbar-style', + 'statusbar-hidden', + 'sdk-version', +]; + +/** + * Convert tiapp XML document to JSON object + */ +export function tiappXmlToJson(doc: Document): TiappData { + const result: TiappData = {}; + const root = doc.documentElement; + + // Track which tags have platform variants + const platformTags = new Set(); + let child = root.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + const elem = child as Element; + if (elem.getAttribute('platform')) { + platformTags.add(elem.tagName); + } + } + child = child.nextSibling; + } + + // Process each direct child + child = root.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + const elem = child as Element; + const tagName = elem.tagName; + const camelKey = toCamelCase(tagName); + + if (SIMPLE_TAGS.includes(tagName)) { + if (platformTags.has(tagName) && tagName === 'id') { + const platform = elem.getAttribute('platform'); + const val = xml.getValueString(elem); + if (platform) { + const platformKey = 'idPlatform' + platform.charAt(0).toUpperCase() + platform.slice(1); + result[platformKey] = val; + } else { + result.id = val; + } + } else if (!platformTags.has(tagName) && !result[camelKey]) { + const val = parseSimpleValue(elem); + result[camelKey] = val; + } + } else if (tagName === 'deployment-targets') { + result.deploymentTargets = readDeploymentTargets(doc); + } else if (tagName === 'property') { + // Handled in readProperties + if (!result.properties) { + result.properties = readProperties(doc); + } + } else if (tagName === 'modules') { + result.modules = readModules(doc); + } else if (tagName === 'plugins') { + if (!result.plugins) { + result.plugins = readPlugins(doc); + } + } else if (tagName === 'ios') { + result.ios = readIOS(doc); + } else if ( + tagName === 'android' || + (elem as Element & { localName?: string }).localName === 'android' + ) { + result.android = readAndroid(doc); + } else if (tagName === 'webpack') { + result.webpack = readWebpack(doc); + } + } + child = child.nextSibling; + } + + // Ensure plugins are read (container may have different tagName in namespaced docs) + if (!result.plugins) { + const plugins = readPlugins(doc); + if (plugins && plugins.length > 0) { + result.plugins = plugins; + } + } + + return result; +} + +/** + * Deep equality check + */ +function deepEqual(a: unknown, b: unknown): boolean { + if (a === b) { + return true; + } + if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') { + return false; + } + if (Array.isArray(a) !== Array.isArray(b)) { + return false; + } + if (Array.isArray(a) && Array.isArray(b)) { + if (a.length !== b.length) { + return false; + } + return a.every((v, i) => deepEqual(v, b[i])); + } + const keysA = Object.keys(a as object); + const keysB = Object.keys(b as object); + if (keysA.length !== keysB.length) { + return false; + } + return keysA.every( + (k) => + keysB.includes(k) && + deepEqual((a as Record)[k], (b as Record)[k]) + ); +} + +/** + * Write a simple scalar value to XML + */ +function writeSimpleValue(doc: Document, key: string, value: unknown, platform?: string): void { + const xmlTag = toXmlTag(key); + const strVal = value === true ? 'true' : value === false ? 'false' : String(value); + const elem = findElement(doc, xmlTag, platform); + if (elem) { + updateElement(elem, strVal); + } else { + createElement(doc, xmlTag, strVal, platform); + } +} + +/** + * Remove a simple element + */ +function removeSimpleElement(doc: Document, key: string, platform?: string): void { + const xmlTag = toXmlTag(key); + const elem = findElement(doc, xmlTag, platform); + if (elem) { + removeElement(elem); + } +} + +/** + * Normalize property value to { type, value } format + */ +function normalizePropertyValue(pv: unknown): { type: string; value: unknown } { + if (pv !== null && typeof pv === 'object' && 'value' in pv) { + return { + type: (pv as { type?: string }).type || 'string', + value: (pv as { value: unknown }).value, + }; + } + // Infer type from flat value + const type = typeof pv === 'boolean' ? 'bool' : typeof pv === 'number' ? 'double' : 'string'; + return { type, value: pv }; +} + +/** + * Write properties to XML + */ +function writeProperties(doc: Document, properties: Record): void { + const root = doc.documentElement; + const indent = detectIndentation(doc); + const existing = findElements(doc, 'property'); + const existingNames = new Set(existing.map((e) => e.getAttribute('name')).filter(Boolean)); + + for (const [name, pv] of Object.entries(properties)) { + const { type, value } = normalizePropertyValue(pv); + let val: string; + if (type === 'bool') { + val = value ? 'true' : 'false'; + } else if (type === 'int' || type === 'double') { + val = String(value); + } else { + val = String(value ?? ''); + } + + if (existingNames.has(name)) { + const elem = existing.find((e) => e.getAttribute('name') === name); + if (elem) { + elem.setAttribute('type', type); + updateElement(elem, val); + } + } else { + root.appendChild(doc.createTextNode(`\n${indent}`)); + const elem = doc.createElement('property'); + elem.setAttribute('name', name); + elem.setAttribute('type', type); + elem.appendChild(doc.createTextNode(val)); + root.appendChild(elem); + } + } + + // Remove properties that are no longer in the object + for (const elem of existing) { + const name = elem.getAttribute('name'); + if (name && !(name in properties)) { + removeElement(elem); + } + } +} + +/** + * Write deployment targets to XML + */ +function writeDeploymentTargets(doc: Document, targets: Record): void { + const indent = detectIndentation(doc); + const root = doc.documentElement; + let container = findElement(doc, 'deployment-targets'); + if (!container) { + root.appendChild(doc.createTextNode(`\n${indent}`)); + container = doc.createElement('deployment-targets'); + root.appendChild(container); + } + + // Clear and rebuild + while (container!.firstChild) { + container!.removeChild(container!.firstChild); + } + const innerIndent = indent + indent; + for (const [device, value] of Object.entries(targets)) { + container!.appendChild(doc.createTextNode(`\n${innerIndent}`)); + const target = doc.createElement('target'); + target.setAttribute('device', device); + target.appendChild(doc.createTextNode(String(value))); + container!.appendChild(target); + } + container!.appendChild(doc.createTextNode(`\n${indent}`)); +} + +/** + * Write modules to XML + */ +function writeModules( + doc: Document, + modules: Array<{ + moduleid: string; + platform?: string; + version?: string | number; + deployType?: string; + }> +): void { + const indent = detectIndentation(doc); + const root = doc.documentElement; + let container = findElement(doc, 'modules'); + if (!container) { + root.appendChild(doc.createTextNode(`\n${indent}`)); + container = doc.createElement('modules'); + root.appendChild(container); + } + + while (container!.firstChild) { + container!.removeChild(container!.firstChild); + } + const innerIndent = indent + indent; + for (const mod of modules) { + container!.appendChild(doc.createTextNode(`\n${innerIndent}`)); + const elem = doc.createElement('module'); + if (mod.platform) { + elem.setAttribute('platform', mod.platform); + } + if (mod.version !== undefined) { + elem.setAttribute('version', String(mod.version)); + } + if (mod.deployType) { + elem.setAttribute('deploy-type', mod.deployType); + } + elem.appendChild(doc.createTextNode(mod.moduleid)); + container!.appendChild(elem); + } + container!.appendChild(doc.createTextNode(`\n${indent}`)); +} + +/** + * Write plugins to XML + */ +function writePlugins( + doc: Document, + plugins: Array<{ id: string; version?: string | number }> +): void { + const existing = findElements(doc, 'plugin'); + const root = doc.documentElement; + const indent = detectIndentation(doc); + + for (const p of existing) { + removeElement(p); + } + + for (const p of plugins) { + root.appendChild(doc.createTextNode(`\n${indent}`)); + const elem = doc.createElement('plugin'); + if (p.version !== undefined) { + elem.setAttribute('version', String(p.version)); + } + elem.appendChild(doc.createTextNode(p.id)); + root.appendChild(elem); + } +} + +/** + * Normalize plist XML indentation to match tiapp.xml format. + * Plist/xmlbuilder uses 2 spaces per level; the root dict is at 2 spaces, subtract 1 so it aligns at baseIndent. + */ +function normalizePlistIndent(xml: string, baseIndent: string): string { + return xml.replace(/^([ \t]*)/gm, (match) => { + const tabCount = (match.match(/\t/g) || []).length; + if (tabCount > 0) { + return baseIndent + '\t'.repeat(Math.max(0, tabCount - 1)); + } + const spaces = match.replace(/\t/g, ' ').length; + const level = Math.max(0, Math.floor(spaces / 2) - 1); + return baseIndent + '\t'.repeat(level); + }); +} + +/** + * Extract the root dict or array from plist XML string (preserves original formatting). + */ +function extractPlistRoot(plistXml: string): string | null { + const dictStart = plistXml.indexOf(''); + const arrayStart = plistXml.indexOf(''); + let start: number; + let openTag: string; + let closeTag: string; + if (dictStart >= 0 && (arrayStart < 0 || dictStart < arrayStart)) { + start = dictStart; + openTag = ''; + closeTag = ''; + } else if (arrayStart >= 0) { + start = arrayStart; + openTag = ''; + closeTag = ''; + } else { + return null; + } + let depth = 0; + let pos = start; + while (pos < plistXml.length) { + const nextOpen = plistXml.indexOf(openTag, pos); + const nextClose = plistXml.indexOf(closeTag, pos); + if (nextClose < 0) break; + if (nextOpen >= 0 && nextOpen < nextClose) { + depth++; + pos = nextOpen + openTag.length; + } else { + depth--; + if (depth === 0) { + return plistXml.slice(start, nextClose + closeTag.length); + } + pos = nextClose + closeTag.length; + } + } + return null; +} + +/** + * Insert plist/entitlements object as XML into a parent element. + * Uses plist.stringify to produce valid plist XML, then extracts the root dict/array. + */ +function insertPlistAsXml( + doc: Document, + parent: Element, + obj: Record, + indent: string +): void { + const plistXml = stringifyPlist(obj); + const rawXml = extractPlistRoot(plistXml); + if (rawXml) { + const normalized = normalizePlistIndent(rawXml, indent); + const fragment = new DOMParser().parseFromString(`${normalized}`, 'text/xml'); + const dictElem = + fragment.getElementsByTagName('dict')[0] ?? fragment.getElementsByTagName('array')[0]; + if (dictElem) { + const imported = doc.importNode(dictElem, true); + parent.appendChild(doc.createTextNode(`\n${indent}`)); + parent.appendChild(imported); + parent.appendChild(doc.createTextNode(`\n${indent.replace(/\t$/, '')}`)); + } + } +} + +/** + * Write iOS config to XML + */ +function writeIOS(doc: Document, ios: Record): void { + const indent = detectIndentation(doc); + const root = doc.documentElement; + let iosElem = findElement(doc, 'ios'); + if (!iosElem) { + const last = root.lastChild; + if (last?.nodeType === 3 && /^\s*$/.test((last as Text).nodeValue ?? '')) { + root.removeChild(last); + } + root.appendChild(doc.createTextNode(`\n${indent}`)); + iosElem = doc.createElement('ios'); + root.appendChild(iosElem); + root.appendChild(doc.createTextNode('\n')); + } + + // Clear and rebuild + while (iosElem.firstChild) { + iosElem.removeChild(iosElem.firstChild); + } + + const innerIndent = indent + indent; + const plistIndent = innerIndent + indent; + + if ( + ios.plist && + typeof ios.plist === 'object' && + ios.plist !== null && + !Array.isArray(ios.plist) + ) { + iosElem.appendChild(doc.createTextNode(`\n${innerIndent}`)); + const plistElem = doc.createElement('plist'); + iosElem.appendChild(plistElem); + insertPlistAsXml(doc, plistElem, ios.plist as Record, plistIndent); + } + + if ( + ios.entitlements && + typeof ios.entitlements === 'object' && + ios.entitlements !== null && + !Array.isArray(ios.entitlements) + ) { + iosElem.appendChild(doc.createTextNode(`\n${innerIndent}`)); + const entElem = doc.createElement('entitlements'); + iosElem.appendChild(entElem); + insertPlistAsXml(doc, entElem, ios.entitlements as Record, plistIndent); + } + + // Write simple iOS tags + const simpleTags = [ + 'enable-launch-screen-storyboard', + 'use-app-thinning', + 'enablecoverage', + 'enablemdfind', + 'default-background-color', + 'min-ios-ver', + 'team-id', + 'log-server-port', + 'use-jscore-framework', + 'run-on-main-thread', + 'use-autolayout', + 'use-new-build-system', + 'exclude-dir-from-asset-catalog', + ]; + for (const tag of simpleTags) { + const key = toCamelCase(tag); + const val = ios[key]; + if (val !== undefined && val !== null) { + iosElem.appendChild(doc.createTextNode(`\n${innerIndent}`)); + const elem = doc.createElement(tag); + const strVal = val === true ? 'true' : val === false ? 'false' : String(val); + elem.appendChild(doc.createTextNode(strVal)); + iosElem.appendChild(elem); + } + } + + iosElem.appendChild(doc.createTextNode(`\n${indent}`)); +} + +/** + * Build full id value (string or platform object) from flat tiapp data + */ +function buildFullId(data: TiappData): string | Record | undefined { + const idVal = data.id; + const platformKeys = ['Ios', 'Android', 'Iphone', 'Ipad']; + const platformObj: Record = {}; + + if (typeof idVal === 'string') { + platformObj.default = idVal; + } else if (idVal && typeof idVal === 'object' && !Array.isArray(idVal)) { + Object.assign(platformObj, idVal as Record); + } + + for (const k of platformKeys) { + const key = 'idPlatform' + k; + const platform = k.toLowerCase(); + if (data[key] !== undefined && data[key] !== null) { + platformObj[platform] = String(data[key]); + } + } + + if (Object.keys(platformObj).length === 0) { + return undefined; + } + if (Object.keys(platformObj).length === 1 && platformObj.default !== undefined) { + return platformObj.default; + } + return platformObj; +} + +/** + * Write platform-specific id + */ +function writeId(doc: Document, id: string | Record): void { + if (typeof id === 'string') { + // Remove any platform-specific id elements, keep only default + const elems = findElements(doc, 'id'); + for (const e of elems) { + if (e.getAttribute('platform')) { + removeElement(e); + } + } + const defaultElem = findElement(doc, 'id'); + if (defaultElem) { + updateElement(defaultElem, id); + } else { + createElement(doc, 'id', id); + } + } else { + const obj = id as Record; + for (const [platform, value] of Object.entries(obj)) { + if (value === undefined) { + continue; + } + const key = platform === 'default' ? undefined : platform; + const elem = findElement(doc, 'id', key); + if (elem) { + updateElement(elem, value); + } else { + createElement(doc, 'id', value, key); + } + } + // Remove ids not in obj + const elems = findElements(doc, 'id'); + for (const e of elems) { + const platform = e.getAttribute('platform') || 'default'; + if (!(platform in obj)) { + removeElement(e); + } + } + } +} + +/** + * Apply diff from before to after, updating the XML document + */ +function applyDiff(doc: Document, before: TiappData, after: TiappData, key: string): void { + const beforeVal = before[key]; + const afterVal = after[key]; + + if (deepEqual(beforeVal, afterVal)) { + return; + } + + if (afterVal === undefined) { + // Remove + if (key === 'id') { + for (const e of findElements(doc, 'id')) { + removeElement(e); + } + } else if (key === 'properties') { + const elems = findElements(doc, 'property'); + for (const e of elems) removeElement(e); + } else if (key === 'deploymentTargets') { + const container = findElement(doc, 'deployment-targets'); + if (container) { + removeElement(container); + } + } else if (key === 'modules') { + const container = findElement(doc, 'modules'); + if (container) { + while (container.firstChild) { + container.removeChild(container.firstChild); + } + } + } else if (key === 'plugins') { + for (const e of findElements(doc, 'plugin')) { + removeElement(e); + } + } else if (key === 'ios') { + const ios = findElement(doc, 'ios'); + if (ios) { + removeElement(ios); + } + } else if (key === 'android') { + const android = findElement(doc, 'android'); + if (android) { + removeElement(android); + } + } else if (key === 'webpack') { + const webpack = findElement(doc, 'webpack'); + if (webpack) { + removeElement(webpack); + } + } else { + removeSimpleElement(doc, key); + } + return; + } + + // Add or update + if (key === 'id' || key.startsWith('idPlatform')) { + const fullId = buildFullId(after); + if (fullId !== undefined) { + writeId(doc, fullId); + } + } else if (key === 'properties' && typeof afterVal === 'object' && afterVal !== null) { + writeProperties(doc, afterVal as Record); + } else if (key === 'deploymentTargets' && typeof afterVal === 'object' && afterVal !== null) { + writeDeploymentTargets(doc, afterVal as Record); + } else if (key === 'modules' && Array.isArray(afterVal)) { + writeModules( + doc, + afterVal as Array<{ + moduleid: string; + platform?: string; + version?: string | number; + deployType?: string; + }> + ); + } else if (key === 'plugins' && Array.isArray(afterVal)) { + writePlugins(doc, afterVal as Array<{ id: string; version?: string | number }>); + } else if (key === 'ios' && typeof afterVal === 'object' && afterVal !== null) { + writeIOS(doc, afterVal as Record); + } else if ( + typeof afterVal === 'string' || + typeof afterVal === 'number' || + typeof afterVal === 'boolean' + ) { + writeSimpleValue(doc, key, afterVal); + } +} + +/** + * Validate tiapp data against schema + */ +export function validateTiappData(data: TiappData): Tiapp { + const result = TiappSchema.safeParse(data); + if (!result.success) { + const msg = result.error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('; '); + throw new Error(`Invalid tiapp data: ${msg}`); + } + return result.data; +} + +/** + * Apply JSON changes to XML document. Computes diff between before and after, + * updates the document accordingly, and validates the result. + */ +export function applyTiappJsonToXml(before: TiappData, after: TiappData, doc: Document): Document { + validateTiappData(after); + + const allKeys = new Set([...Object.keys(before), ...Object.keys(after)]); + for (const key of allKeys) { + applyDiff(doc, before, after, key); + } + + return doc; +} diff --git a/src/titanium/tiapp/tiapp-xml.ts b/src/titanium/tiapp/tiapp-xml.ts new file mode 100644 index 00000000..29a0c1da --- /dev/null +++ b/src/titanium/tiapp/tiapp-xml.ts @@ -0,0 +1,102 @@ +import { isFile } from '../../util/is-file.js'; +import { mergeDeep } from '../../util/merge-deep.js'; +import { tiappXmlToJson, applyTiappJsonToXml, validateTiappData } from './tiapp-transform.js'; +import { DOMParser, type Options } from '@xmldom/xmldom'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { dirname } from 'node:path'; + +declare module '@xmldom/xmldom' { + interface Options { + xmlns?: { [key: string]: string }; + } +} + +const defaultDOMParserArgs: Options = { + errorHandler: () => {}, +}; + +/** + * Factory function to create a TiappXML proxy + * + * @param file - Optional path to tiapp.xml file to load + * @returns A proxy object with Tiapp schema properties and methods + * + * @example + * ```ts + * const tiapp = new TiappXML(); + * const data = tiapp.data(); + * data.sdkVersion = '1.2.3'; + * tiapp.apply(data).save('/tmp/test-tiapp.xml'); + * ``` + */ +export class TiappXML { + dom!: Document; + file?: string; + + constructor(file?: string) { + // Load file if provided + if (file) { + this.load(file); + } else { + // Initialize with empty document + this.dom = new DOMParser(defaultDOMParserArgs).parseFromString( + '\n', + 'text/xml' + ); + } + } + + apply(data: Record) { + this.dom = applyTiappJsonToXml(this.data(), data, this.dom); + return this; + } + + data(): Record { + return tiappXmlToJson(this.dom); + } + + load(file: string) { + if (!isFile(file)) { + throw new Error('tiapp.xml file does not exist'); + } + this.file ??= file; + const content = readFileSync(file, 'utf8'); + return this.parse(content); + } + + merge(data: Record) { + this.apply(mergeDeep(this.data(), data)); + return this; + } + + parse(content: string) { + let errorMsg: string | undefined = undefined; + this.dom = new DOMParser({ + errorHandler(err) { + errorMsg = err; + }, + }).parseFromString(content, 'text/xml'); + if (errorMsg) { + throw new Error(`Invalid XML file: ${errorMsg}`); + } + validateTiappData(tiappXmlToJson(this.dom)); + return this; + } + + save(file: string) { + file = this.file ?? file; + if (file) { + mkdirSync(dirname(file), { recursive: true }); + writeFileSync(file, this.toString()); + } + return this; + } + + toString(): string { + const xmlStr = this.dom.toString(); + if (xmlStr.startsWith('\n${xmlStr}`; + } +} diff --git a/src/titanium/valid-app-id.ts b/src/titanium/valid-app-id.ts new file mode 100644 index 00000000..5c486b70 --- /dev/null +++ b/src/titanium/valid-app-id.ts @@ -0,0 +1,104 @@ +const words = new Set([ + 'abstract', + 'assert', + 'boolean', + 'break', + 'byte', + 'case', + 'catch', + 'char', + 'class', + 'const', + 'continue', + 'default', + 'do', + 'double', + 'else', + 'enum', + 'extends', + 'false', + 'final', + 'finally', + 'float', + 'for', + 'goto', + 'if', + 'implements', + 'import', + 'instanceof', + 'int', + 'interface', + 'long', + 'native', + 'new', + 'null', + 'package', + 'private', + 'protected', + 'public', + 'return', + 'short', + 'static', + 'strictfp', + 'super', + 'switch', + 'synchronized', + 'this', + 'throw', + 'throws', + 'transient', + 'true', + 'try', + 'void', + 'volatile', + 'while', +]); + +export function validAppId(id: string): boolean { + if (!id || typeof id !== 'string') { + return false; + } + + id = id.trim(); + + if (id.startsWith('.') || id.endsWith('.')) { + // must not start or end with a dash + return false; + } + + if (id.includes('..')) { + // must not contain consecutive periods + return false; + } + + if (!id.includes('.')) { + // must contain at least one period + return false; + } + + const segments = id.split('.'); + + for (const segment of segments) { + if (!/^[a-zA-Z0-9]/.test(segment)) { + // must start with a letter or number + return false; + } + + if (!/^[a-zA-Z0-9]*$/.test(segment)) { + // must contain only letters and numbers + return false; + } + + if (segment.length > 255) { + // must not be longer than 255 characters + return false; + } + + if (words.has(segment)) { + // must not contain a reserved word + return false; + } + } + + return true; +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 00000000..87cf5674 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,107 @@ +import type { AgentOptions } from 'node:http'; + +export type ConfigSearchPaths = + | string[] + | { + darwin?: string[]; + linux?: string[]; + win32?: string[]; + }; + +export interface Config { + android: { + adb: { + install: { + timeout: number | null; + }; + path: string | null; + port: number | null; + start: { + retryInterval: number | null; + timeout: number | null; + }; + }; + avd: { + path: string; + }; + emulator: { + start: { + timeout: number | null; + }; + }; + ndk: { + searchPaths: ConfigSearchPaths; + }; + sdk: { + searchPaths: ConfigSearchPaths; + }; + }; + + env: { + path: string | null; + }; + + ios: { + executables: { + security: string | null; + sqlite: string | null; + xcodeSelect: string | null; + }; + keychainMetaFile: string; + provisioning: { + searchPaths: ConfigSearchPaths; + }; + simulator: { + crashLogsDir: string; + devicesDir: string; + runtimesDir: string; + }; + xcode: { + searchPaths: ConfigSearchPaths; + }; + }; + + jdk: { + javaHome: string | null; + searchPaths: ConfigSearchPaths; + windows: { + registryKeys: string[]; + }; + }; + + network: { + agentOptions: AgentOptions | null; + caFile: string | null; + certFile: string | null; + httpProxy: string | null; + httpsProxy: string | null; + keyFile: string | null; + passphrase: string | null; + strictSSL: boolean; + }; + + titanium: { + downloadsDir: string; + sdk: { + downloadURLs: { + branches: string; + branchBuilds: string; + releases: { + beta: string; + rc: string; + ga: string; + }; + }; + installPath: { + darwin: string; + linux: string; + win32: string; + }; + searchPaths: ConfigSearchPaths; + }; + }; +} + +export interface ErrorWithCode extends Error { + code: string; +} diff --git a/src/types/simple-plist.d.ts b/src/types/simple-plist.d.ts new file mode 100644 index 00000000..43420399 --- /dev/null +++ b/src/types/simple-plist.d.ts @@ -0,0 +1,12 @@ +declare module 'simple-plist' { + type PlistJsObj = Record | any[]; + type StringOrBuffer = string | Buffer; + + interface SimplePlist { + stringify(anObject: PlistJsObj): string; + parse(aStringOrBuffer: StringOrBuffer): T; + } + + const plist: SimplePlist; + export = plist; +} diff --git a/src/util/capitalize.ts b/src/util/capitalize.ts new file mode 100644 index 00000000..ca5cb1bc --- /dev/null +++ b/src/util/capitalize.ts @@ -0,0 +1,3 @@ +export function capitalize(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} diff --git a/src/util/exists.ts b/src/util/exists.ts new file mode 100644 index 00000000..2703d528 --- /dev/null +++ b/src/util/exists.ts @@ -0,0 +1,27 @@ +import { lstatSync } from 'node:fs'; +import { lstat } from 'node:fs/promises'; + +/** + * Checks if a path exists using `lstat` instead of `fs.existsSync`. For some reason, on Windows + * `fs.existsSync` returns false for symlinks that exist. + * + * @param path The path to check if it exists. + * @returns True if the path exists, false otherwise. + */ +export async function exists(path: string): Promise { + try { + await lstat(path); + return true; + } catch { + return false; + } +} + +export function existsSync(path: string): boolean { + try { + lstatSync(path); + return true; + } catch { + return false; + } +} diff --git a/src/util/expand.ts b/src/util/expand.ts new file mode 100644 index 00000000..b5359866 --- /dev/null +++ b/src/util/expand.ts @@ -0,0 +1,21 @@ +import { join, resolve } from 'node:path'; + +const homeDirRegExp = /^~([\\|/].*)?$/; +const winRegExp = /^win/; +const winEnvVarRegExp = /(%([^%]*)%)/g; + +export function expand(...segments: string[]): string { + segments[0] = segments[0].replace( + homeDirRegExp, + (process.env.HOME || process.env.USERPROFILE) + '$1' + ); + /* v8 ignore next 6 */ + if (winRegExp.test(process.platform)) { + return resolve( + join(...segments).replace(winEnvVarRegExp, (_s, m, n) => { + return process.env[n] || m; + }) + ); + } + return resolve(...segments); +} diff --git a/src/util/extract-zip.ts b/src/util/extract-zip.ts new file mode 100644 index 00000000..ffffeac2 --- /dev/null +++ b/src/util/extract-zip.ts @@ -0,0 +1,162 @@ +import { exists } from './exists.js'; +import { expand } from './expand.js'; +import { isFile } from './is-file.js'; +import fs from 'node:fs'; +import { mkdir, rm, symlink } from 'node:fs/promises'; +import { dirname } from 'node:path'; +import snooplogg from 'snooplogg'; +import yauzl from 'yauzl'; + +const { error, log } = snooplogg('extract-zip'); + +type ExtractZipOptions = { + defaultPerm?: number; + onEntry?: ( + entry: yauzl.Entry, + index: number, + total: number + ) => void | Promise | boolean | Promise; +}; + +export async function extractZip(zipFile: string, dest: string, opts?: ExtractZipOptions) { + if (!zipFile || typeof zipFile !== 'string') { + throw new TypeError('Expected zip file to be a non-empty string'); + } + + if (!(await exists(zipFile))) { + throw new Error('The specified zip file does not exist'); + } + + if (!isFile(zipFile)) { + throw new Error('The specified zip file is not a file'); + } + + if (!dest || typeof dest !== 'string') { + throw new TypeError('Expected destination directory to be a non-empty string'); + } + + await new Promise((resolve, reject) => { + yauzl.open(zipFile, { lazyEntries: true }, (err, zipfile) => { + if (err) { + return reject(new Error(`Invalid zip file: ${err.message || err}`)); + } + + let idx = -1; + const total = zipfile.entryCount; + const abort = (err) => { + zipfile.removeListener('end', resolve); + zipfile.close(); + error(err); + reject(err); + }; + + log(`Extracting: "${zipFile}" to "${dest}"`); + + zipfile + .on('entry', async (entry) => { + try { + idx++; + + if (typeof opts?.onEntry === 'function') { + if ((await opts.onEntry(entry, idx, total)) === false) { + log(`Skipping: "${entry.fileName}" (onEntry callback returned false)`); + zipfile.readEntry(); + return; + } + } + + const destFile = expand(dest, entry.fileName); + const mode = (entry.externalFileAttributes >>> 16) & 0xffff || 0o644; + const isSymlink = (mode & fs.constants.S_IFMT) === fs.constants.S_IFLNK; + let isDir = (mode & fs.constants.S_IFMT) === fs.constants.S_IFDIR; + const madeBy = entry.versionMadeBy >> 8; + if (!isDir) { + isDir = madeBy === 0 && entry.externalFileAttributes === 16; + } + + if (isSymlink) { + if (!(await exists(dirname(destFile)))) { + log(`Creating directory: ${dirname(destFile)}`); + await mkdir(dirname(destFile), { recursive: true }); + } + + zipfile.openReadStream(entry, (err, readStream) => { + if (err) { + return abort(err); + } + + const chunks: Buffer[] = []; + const cleanupAndAbort = (err) => { + readStream.removeAllListeners(); + readStream.destroy(); + abort(err); + }; + + readStream.on('data', (chunk: Buffer) => chunks.push(chunk)); + readStream.on('error', cleanupAndAbort); + readStream.on('end', async () => { + const target = Buffer.concat(chunks) + .toString('utf8') + .replace(/[\\/]$/, ''); + + try { + log(`Symlinking: ${destFile} => ${target}`); + let destExists = await exists(destFile); + if (destExists) { + log(`Deleting existing symlink dest: ${destFile}`); + await rm(destFile, { force: true, recursive: true }); + } + await symlink(target, destFile); + zipfile.readEntry(); + } catch (err) { + cleanupAndAbort( + new Error(`Error symlinking ${destFile}: ${(err as Error).message || err}`) + ); + } + }); + }); + } else if (isDir) { + if (!(await exists(dirname(destFile)))) { + log(`Creating directory: ${dirname(destFile)}`); + await mkdir(dirname(destFile), { recursive: true }); + } + zipfile.readEntry(); + } else { + const dir = dirname(destFile); + if (!(await exists(dir))) { + log(`Creating directory: ${dir}`); + await mkdir(dir, { recursive: true }); + } + + zipfile.openReadStream(entry, (err, readStream) => { + if (err) { + return abort(err); + } + + log(`Extracting file: ${entry.fileName}`); + const writeStream = fs.createWriteStream(destFile, { mode }); + const cleanupAndAbort = (err) => { + readStream.removeAllListeners(); + readStream.unpipe(); + readStream.destroy(); + writeStream.removeAllListeners(); + writeStream.destroy(); + abort(err); + }; + + writeStream.on('close', () => zipfile.readEntry()); + writeStream.on('error', cleanupAndAbort); + readStream.on('error', cleanupAndAbort); + readStream.pipe(writeStream); + }); + } + } catch (err) { + return abort(err); + } + }) + .on('end', resolve) + .on('error', reject) + .readEntry(); + }); + }); +} diff --git a/src/util/index.ts b/src/util/index.ts new file mode 100644 index 00000000..6c9af1e1 --- /dev/null +++ b/src/util/index.ts @@ -0,0 +1,17 @@ +export * from './capitalize.js'; +export * from './exists.js'; +export * from './expand.js'; +export * from './extract-zip.js'; +export * from './is-dir.js'; +export * from './is-file.js'; +export * from './is-writable.js'; +export * from './merge-deep.js'; +export * as owner from './owner.js'; +export * from './plist.js'; +export * from './png-info.js'; +export * from './request.js'; +export * from './suggest.js'; +export * from './tailgate.js'; +export * from './time-diff.js'; +export * as version from './version.js'; +export * as xml from './xml.js'; diff --git a/src/util/is-dir.ts b/src/util/is-dir.ts new file mode 100644 index 00000000..261ddf71 --- /dev/null +++ b/src/util/is-dir.ts @@ -0,0 +1,9 @@ +import { statSync } from 'node:fs'; + +export function isDir(dir: string): boolean { + try { + return statSync(dir).isDirectory(); + } catch { + return false; + } +} diff --git a/src/util/is-file.ts b/src/util/is-file.ts new file mode 100644 index 00000000..4ac03e0d --- /dev/null +++ b/src/util/is-file.ts @@ -0,0 +1,9 @@ +import { statSync } from 'node:fs'; + +export function isFile(file: string): boolean { + try { + return statSync(file).isFile(); + } catch { + return false; + } +} diff --git a/src/util/is-writable.ts b/src/util/is-writable.ts new file mode 100644 index 00000000..d0a15e71 --- /dev/null +++ b/src/util/is-writable.ts @@ -0,0 +1,62 @@ +import { createTempName } from './temp.js'; +import { accessSync, constants, statSync, unlinkSync, writeFileSync, type Stats } from 'node:fs'; +import { access, unlink, writeFile } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; + +export async function isWritable(path: string): Promise { + let stat: Stats | undefined; + try { + stat = statSync(path); + } catch { + // path does not exist, check if parent is writable + return isWritable(dirname(path)); + } + + try { + if (stat.isFile()) { + await access(path, constants.W_OK); + return true; + } else if (stat.isDirectory()) { + // try writing a file + const tmpFile = join(path, createTempName({ prefix: 'tmp' })); + try { + await access(path, constants.W_OK); + await writeFile(tmpFile, '', 'utf-8'); + return true; + } finally { + await unlink(tmpFile); + } + } + } catch {} + + return false; +} + +export function isWritableSync(path: string): boolean { + let stat: Stats | undefined; + try { + stat = statSync(path); + } catch { + // path does not exist, check if parent is writable + return isWritableSync(dirname(path)); + } + + try { + if (stat.isFile()) { + accessSync(path, constants.W_OK); + return true; + } else if (stat.isDirectory()) { + // try writing a file + const tmpFile = join(path, createTempName({ prefix: 'tmp' })); + try { + accessSync(path, constants.W_OK); + writeFileSync(tmpFile, '', 'utf-8'); + return true; + } finally { + unlinkSync(tmpFile); + } + } + } catch {} + + return false; +} diff --git a/src/util/issue.ts b/src/util/issue.ts new file mode 100644 index 00000000..866a745d --- /dev/null +++ b/src/util/issue.ts @@ -0,0 +1,19 @@ +export class Issue extends Error { + id: string; + type: 'error' | 'warning'; + details: string; + + constructor( + message: string, + options: { + id: string; + type: 'error' | 'warning'; + details: string; + } + ) { + super(message); + this.id = options.id; + this.type = options.type; + this.details = options.details; + } +} diff --git a/src/util/merge-deep.ts b/src/util/merge-deep.ts new file mode 100644 index 00000000..15e3d91e --- /dev/null +++ b/src/util/merge-deep.ts @@ -0,0 +1,21 @@ +/** + * Merges two objects deeply. + * @param target - The target object. + * @param source - The source object. + * @returns The merged object. + */ +export function mergeDeep(target: any, source: any) { + for (const key in source) { + if (Array.isArray(source[key])) { + target[key] = source[key]; + } else if (source[key] instanceof Object) { + if (!target[key]) { + target[key] = {}; + } + mergeDeep(target[key], source[key]); + } else { + target[key] = source[key]; + } + } + return target; +} diff --git a/src/util/owner.ts b/src/util/owner.ts new file mode 100644 index 00000000..8e5b7e14 --- /dev/null +++ b/src/util/owner.ts @@ -0,0 +1,151 @@ +import { expand } from './expand.js'; +import { lchownSync, lstatSync } from 'node:fs'; +import { lchown, lstat } from 'node:fs/promises'; +import { dirname, parse } from 'node:path'; + +interface OwnerQuery { + origin: string; + root: string; + supported: boolean; + target: string; +} + +export interface OwnerSync { + apply(): void; + gid: number; + origin: string; + supported: boolean; + target: string; + uid: number; +} + +export interface Owner { + apply(): Promise; + gid: number; + origin: string; + supported: boolean; + target: string; + uid: number; +} + +function initOwnerQuery(path: string): OwnerQuery { + const target = expand(path); + const { root } = parse(target); + const origin = target; + const supported = process.platform !== 'win32' && typeof process.getuid === 'function'; + return { + origin, + root, + supported, + target, + }; +} + +/** + * Determines the owner of the nearest owner for the given path. + * + * @param path - The path to get nearest owner for + * @returns A promise that resolves an object containing the uid, gid, and + * target path + */ +export async function getOwner(path: string): Promise { + let { origin, root, supported, target } = initOwnerQuery(path); + + if (!supported) { + return { + async apply() {}, + gid: 0, + origin: dirname(origin), + supported, + target, + uid: 0, + }; + } + + // eslint-disable-next-line no-constant-condition + for (; true; origin = dirname(origin)) { + try { + const st = await lstat(origin); + if (st.isDirectory()) { + const { uid, gid } = st; + return { + async apply() { + let target2 = target; + let stat = await lstat(target2); + while (target2 !== origin && stat.uid !== uid) { + try { + await lchown(target2, uid, gid); + target2 = dirname(target2); + stat = await lstat(target2); + } catch { + break; + } + } + }, + gid, + origin, + supported, + target, + uid, + }; + } + } catch {} + if (origin === root) { + throw new Error(`Cannot determine owner of ${path}`); + } + } +} + +/** + * Determines the owner of the nearest owner for the given path. + * + * @param path - The path to get nearest owner for + * @returns An object containing the uid, gid, and target path + */ +export function getOwnerSync(path: string): OwnerSync { + let { origin, root, supported, target } = initOwnerQuery(path); + + if (!supported) { + return { + apply() {}, + gid: 0, + origin: dirname(origin), + supported, + target, + uid: 0, + }; + } + + // eslint-disable-next-line no-constant-condition + for (; true; origin = dirname(origin)) { + try { + const st = lstatSync(origin); + if (st.isDirectory()) { + const { uid, gid } = st; + return { + apply() { + let target2 = target; + let stat = lstatSync(target2); + while (target2 !== origin && stat.uid !== uid) { + try { + lchownSync(target2, uid, gid); + target2 = dirname(target2); + stat = lstatSync(target2); + } catch { + break; + } + } + }, + gid, + origin, + supported, + target, + uid, + }; + } + } catch {} + if (origin === root) { + throw new Error(`Cannot determine owner of ${path}`); + } + } +} diff --git a/src/util/plist.ts b/src/util/plist.ts new file mode 100644 index 00000000..ed423483 --- /dev/null +++ b/src/util/plist.ts @@ -0,0 +1,76 @@ +import { isFile } from './is-file.js'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; +import { mkdir, readFile, writeFile } from 'node:fs/promises'; +import { dirname } from 'node:path'; +import plist from 'simple-plist'; + +/** + * Convert a JavaScript object to a plist XML string. + * @param obj - The JavaScript object to convert. + * @returns The plist XML string. + */ +export function stringifyPlist(obj: Record): string { + return plist.stringify(obj); +} + +/** + * Parse a plist string or buffer into a JavaScript object. + * @param str - The plist string or buffer to parse. + * @returns The parsed JavaScript object. + * @throws An error if the plist is invalid. + */ +export function parsePlist(str: string | Buffer): T { + try { + return plist.parse(str); + } catch (err) { + throw new Error(`Invalid plist: ${err}`); + } +} + +/** + * Read a plist file synchronously and parse it into a JavaScript object. + * @param file - The path to the plist file. + * @returns The parsed JavaScript object. + * @throws An error if the plist file does not exist or is invalid. + */ +export function readPlistSync(file: string): T { + if (!isFile(file)) { + throw new Error('plist file does not exist'); + } + return parsePlist(readFileSync(file)); +} + +/** + * Read a plist file asynchronously and parse it into a JavaScript object. + * @param file - The path to the plist file. + * @returns The parsed JavaScript object. + * @throws An error if the plist file does not exist or is invalid. + */ +export async function readPlist(file: string): Promise { + if (!isFile(file)) { + throw new Error('plist file does not exist'); + } + return parsePlist(await readFile(file)); +} + +/** + * Write a JavaScript object to a plist file synchronously. + * @param file - The path to the plist file. + * @param data - The JavaScript object to write to the plist file. + * @throws An error if the plist file does not exist or is invalid. + */ +export function writePlistSync(file: string, data: Record): void { + mkdirSync(dirname(file), { recursive: true }); + writeFileSync(file, plist.stringify(data)); +} + +/** + * Write a JavaScript object to a plist file asynchronously. + * @param file - The path to the plist file. + * @param data - The JavaScript object to write to the plist file. + * @throws An error if the plist file does not exist or is invalid. + */ +export async function writePlist(file: string, data: Record): Promise { + await mkdir(dirname(file), { recursive: true }); + await writeFile(file, plist.stringify(data)); +} diff --git a/src/util/png-info.ts b/src/util/png-info.ts new file mode 100644 index 00000000..e1db8344 --- /dev/null +++ b/src/util/png-info.ts @@ -0,0 +1,18 @@ +/** + * Reads in a PNG file and returns the height, width, and color depth. + * + * @param {Buffer} buf - A buffer containing the contents of a PNG file. + * + * @returns {Object} An object containing the image's height, width, and color depth. + */ +export function pngInfo(buf: Buffer): { width: number; height: number; alpha: boolean } { + const u32 = (o: number): number => { + return (buf[o] << 24) | (buf[o + 1] << 16) | (buf[o + 2] << 8) | buf[o + 3]; + }; + + return { + width: u32(16), + height: u32(16 + 4), + alpha: !!(buf[25] & 4), + }; +} diff --git a/src/util/request.ts b/src/util/request.ts new file mode 100644 index 00000000..7f6ba2cf --- /dev/null +++ b/src/util/request.ts @@ -0,0 +1,62 @@ +import { config } from '../config.js'; +import { Agent, ProxyAgent, request as req } from 'undici'; +import type { Dispatcher } from 'undici'; + +const openDispatchers = new Set(); + +type RequestOptions = { dispatcher?: Dispatcher } & Omit< + Dispatcher.RequestOptions, + 'origin' | 'path' | 'method' +> & + Partial> & { responseType?: 'json' }; + +/** + * Makes a request to the given URL. + * @param url - The URL to request. + * @param opts - The options for the request. + * @returns The response data. + */ +export async function request( + url: string, + opts: RequestOptions = {} +): Promise> { + const proxyUrl = config.network.httpProxy; + const requestTls = { + rejectUnauthorized: config.network.strictSSL, + }; + + const dispatcher = proxyUrl + ? new ProxyAgent({ + uri: proxyUrl, + requestTls, + }) + : new Agent({ + connect: requestTls, + }); + + openDispatchers.add(dispatcher); + + const res = await req(url, { + dispatcher, + reset: true, + ...opts, + headers: { + Connection: 'close', + ...opts.headers, + }, + }); + + let closed = false; + const closeDispatcher = () => { + if (!closed) { + closed = true; + openDispatchers.delete(dispatcher); + dispatcher.close().catch(() => {}); + } + }; + res.body.once('end', closeDispatcher); + res.body.once('error', closeDispatcher); + res.body.once('close', closeDispatcher); + + return res; +} diff --git a/src/util/suggest.ts b/src/util/suggest.ts new file mode 100644 index 00000000..d6e3a7bb --- /dev/null +++ b/src/util/suggest.ts @@ -0,0 +1,35 @@ +export function suggest(subject: string, choices: string[]) { + const bestMatch = choices.reduce( + (best, choice) => { + const score = levenshtein(subject, choice); + return score < best.score ? { choice, score } : best; + }, + { choice: choices[0], score: Infinity } + ); + return bestMatch.choice; +} + +function levenshtein(a: string, b: string) { + if (a.length < b.length) { + [a, b] = [b, a]; // ensure 'b' is the shorter string to save memory + } + + const res = Array.from({ length: b.length + 1 }, (_, i) => i); + + for (let i = 1; i <= a.length; i++) { + let prevDiagonal = res[0]; // stores the (i-1, j-1) value + res[0] = i; + + for (let j = 1; j <= b.length; j++) { + const temp = res[j]; + res[j] = Math.min( + res[j] + 1, // deletion + res[j - 1] + 1, // insertion + prevDiagonal + (a[i - 1] === b[j - 1] ? 0 : 1) // substitution + ); + prevDiagonal = temp; + } + } + + return res[b.length]; +} diff --git a/src/util/tailgate.ts b/src/util/tailgate.ts new file mode 100644 index 00000000..6a822c70 --- /dev/null +++ b/src/util/tailgate.ts @@ -0,0 +1,50 @@ +type TailgateResolver = { + resolve: (value: T | PromiseLike) => void; + reject: (reason?: unknown) => void; +}; + +const tailgates: Record[]> = {}; + +/** + * Ensures that only a function is executed by a single task at a time. If a + * task is already running, then additional requests are queued. When the task + * completes, the result is immediately shared with the queued up callers. + * + * @param name - The tailgate name. + * @param callback - A function to call to get results. + * @returns Resolves whatever value `callback` returns/resolves. + */ +export function tailgate(name: string, callback: () => T): Promise { + return new Promise((resolve, reject) => { + if (Object.hasOwn(tailgates, name)) { + tailgates[name].push({ resolve, reject }); + return; + } + + tailgates[name] = [{ resolve, reject }]; + + const dispatchResolvers = (type: 'resolve' | 'reject', value: unknown) => { + const pending = tailgates[name]; + delete tailgates[name]; + for (const resolver of pending) { + resolver[type](value); + } + }; + + let result: unknown; + try { + result = callback(); + } catch (err: unknown) { + dispatchResolvers('reject', err); + return; + } + + if (result instanceof Promise) { + result + .then((result) => dispatchResolvers('resolve', result)) + .catch((err) => dispatchResolvers('reject', err)); + } else { + dispatchResolvers('resolve', result); + } + }); +} diff --git a/src/util/temp.ts b/src/util/temp.ts new file mode 100644 index 00000000..fc3432fe --- /dev/null +++ b/src/util/temp.ts @@ -0,0 +1,52 @@ +import { randomBytes } from 'node:crypto'; +import { mkdirSync } from 'node:fs'; +import { mkdir } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +interface TempNameOptions { + name?: string; + prefix?: string; + suffix?: string; +} + +/** + * Creates a temporary directory name. + * @param options - The options for the temporary directory name. + * @returns The name of the temporary directory. + */ +export function createTempName({ name, prefix, suffix }: TempNameOptions = {}): string { + name = name ?? randomBytes(16).toString('hex'); + return `${prefix ? `${prefix}-` : ''}${name}${suffix ? `-${suffix}` : ''}`; +} + +/** + * Creates a temporary directory path. + * @param options - The options for the temporary directory path. + * @returns The path to the temporary directory. + */ +export function createTempPath(options?: TempNameOptions): string { + return join(tmpdir(), createTempName(options)); +} + +/** + * Creates a temporary directory. + * @param options - The options for the temporary directory. + * @returns The path to the temporary directory. + */ +export async function createTempDir(options?: TempNameOptions): Promise { + const tmpDir = join(tmpdir(), createTempName(options)); + await mkdir(tmpDir, { recursive: true }); + return tmpDir; +} + +/** + * Creates a temporary directory synchronously. + * @param options - The options for the temporary directory. + * @returns The path to the temporary directory. + */ +export function createTempDirSync(options?: TempNameOptions): string { + const tmpDir = join(tmpdir(), createTempName(options)); + mkdirSync(tmpDir, { recursive: true }); + return tmpDir; +} diff --git a/src/util/time-diff.ts b/src/util/time-diff.ts new file mode 100644 index 00000000..118d6f81 --- /dev/null +++ b/src/util/time-diff.ts @@ -0,0 +1,29 @@ +/** + * Render the time difference between two dates in a human readable format + * broken down into days, hours, minutes, seconds, and milliseconds. + * Returns a string with one or more units, e.g. `1d 3h 5m 8s 13ms` + */ +export function timeDiff(start: Date, end: Date): string { + let delta = Math.abs(end.getTime() - start.getTime()); + + const ms = delta % 1000; + delta = Math.floor(delta / 1000); + const seconds = delta % 60; + delta = Math.floor(delta / 60); + const minutes = delta % 60; + delta = Math.floor(delta / 60); + const hours = delta % 24; + delta = Math.floor(delta / 24); + const days = delta; + + const parts: string[] = []; + if (days > 0) parts.push(`${days}d`); + if (hours > 0) parts.push(`${hours}h`); + if (minutes > 0) parts.push(`${minutes}m`); + if (seconds > 0) parts.push(`${seconds}s`); + if (ms > 0) parts.push(`${ms}ms`); + + if (parts.length === 0) parts.push('0ms'); + + return parts.join(' '); +} diff --git a/src/util/version.ts b/src/util/version.ts new file mode 100644 index 00000000..235b94a8 --- /dev/null +++ b/src/util/version.ts @@ -0,0 +1,254 @@ +import semver from 'semver'; + +const versionRegExp = /^(\d+)\.(\d+)\.(\d+)(?:-(.+))?/i; + +/** + * Compare function for sort(). + * @param {String} a - Version A + * @param {String} b - Version B + * @returns {Number} + */ +export function compare(a: string | number, b: string | number): number { + const matchA = format(a, 3).toLowerCase().match(versionRegExp); + const matchB = format(b, 3).toLowerCase().match(versionRegExp); + if (!matchA || !matchB) { + throw new Error('Invalid version format'); + } + const [, amajor, aminor, apatch, atag] = matchA; + const [, bmajor, bminor, bpatch, btag] = matchB; + + let n = Number.parseInt(amajor) - Number.parseInt(bmajor); + if (n !== 0) { + return n; + } + + n = Number.parseInt(aminor) - Number.parseInt(bminor); + if (n !== 0) { + return n; + } + + n = Number.parseInt(apatch) - Number.parseInt(bpatch); + if (n !== 0) { + return n; + } + + if (atag && btag) { + return atag.localeCompare(btag); + } + + return atag ? 1 : btag ? -1 : 0; +} + +/** + * Formats a version based on a minimum and maximum number of segments. + * @param {String} ver - The version + * @param {Number} [min] - The minimum number of segments + * @param {Number} [max] - The maximum number of segments + * @param {Boolean} [chopDash] - If true, chops off the dash and anything after it + * @returns {String} The formatted version + */ +export function format( + ver: string | number, + min?: number, + max?: number, + chopDash?: boolean +): string { + if (typeof ver !== 'string' && typeof ver !== 'number') { + throw new Error(`Invalid version "${ver}"`); + } + ver = String(ver || 0); + if (chopDash) { + ver = ver.replace(/(-.*)?$/, ''); + } + const parts = ver.split('.'); + if (min !== undefined) { + while (parts.length < min) { + parts.push('0'); + } + } + if (max !== undefined) { + return parts.slice(0, max).join('.'); + } + return parts.join('.'); +} + +/** + * Converts two versions into 3 segment format, then checks if they are equal to each other. + * @param {String} v1 - The first version to compare + * @param {String} v2 - The second version to compare + * @returns {Boolean} True if the versions are equal + */ +export function eq(v1: string | number, v2: string | number): boolean { + return semver.eq(format(v1, 3, 3), format(v2, 3, 3)); +} + +/** + * Converts two versions into 3 segment format, then checks if the first version is less than the + * second version. + * @param {String} v1 - The first version to compare + * @param {String} v2 - The second version to compare + * @returns {Boolean} True if the first version is less than the second version + */ +export function lt(v1: string | number, v2: string | number): boolean { + return semver.lt(format(v1, 3, 3), format(v2, 3, 3)); +} + +/** + * Converts two versions into 3 segment format, then checks if the first version is less than or + * equal to the second version. + * @param {String} v1 - The first version to compare + * @param {String} v2 - The second version to compare + * @returns {Boolean} True if the first version is less than or equal to the second version + */ +export function lte(v1: string | number, v2: string | number): boolean { + return semver.lte(format(v1, 3, 3), format(v2, 3, 3)); +} + +/** + * Converts two versions into 3 segment format, then checks if the first version is greater than the + * second version. + * @param {String} v1 - The first version to compare + * @param {String} v2 - The second version to compare + * @returns {Boolean} True if the first version is greater than the second version + */ +export function gt(v1: string | number, v2: string | number): boolean { + return semver.gt(format(v1, 3, 3), format(v2, 3, 3)); +} + +/** + * Converts two versions into 3 segment format, then checks if the first version is greater than or + * equal to the second version. + * @param {String} v1 - The first version to compare + * @param {String} v2 - The second version to compare + * @returns {Boolean} True if the first version is greater than or equal to the second version + */ +export function gte(v1: string | number, v2: string | number): boolean { + return semver.gte(format(v1, 3, 3), format(v2, 3, 3)); +} + +/** + * Checks if a version is valid. + * @param {String} v - The version to validate + * @returns {Boolean} `true` if the version is valid, `false` otherwise + */ +export function isValid(v: string | number): boolean { + try { + return semver.valid(format(v, 3, 3)) !== null; + } catch { + return false; + } +} + +/** + * Determines the most minimum value of the supplied range. + * @param {String} str - A string contain one or more versions or version ranges + * @returns {String} The minimum version found or undefined + */ +export function parseMin(str: string): string | undefined { + let min; + + for (const range of str.split(/\s*\|\|\s*/)) { + const x = range + .split(' ') + .shift() + ?.replace(/[^.\d]/g, ''); + if (x && (!min || lt(x, min))) { + min = x.replace(/\.$/, ''); + } + } + + return min; +} + +/** + * Determines the most maximum value of the supplied range. + * @param {String} str - A string contain one or more versions or version ranges + * @param {Boolean} [allowX=false] - When true, treats 'x' as apart of the version + * @returns {String} The maximum version found or undefined + */ +export function parseMax(str: string, allowX?: boolean): string | undefined { + let max: string | undefined; + let lt: boolean | undefined; + + for (const range of str.split(/\s*\|\|\s*/)) { + const segments = range.split(' '); + let x = segments.length === 1 ? segments.shift() : segments.slice(1).shift(); + if (x && !allowX) { + x = x.replace(/.x$/i, ''); + } + const y = x?.replace(allowX ? /[^.xX\d]/g : /[^.\d]/g, ''); + if (x && y && (!max || gt(y, max))) { + lt = /^<[^=]\d/.test(x); + max = y.replace(/\.$/, ''); + } + } + + return (lt ? '<' : '') + max; +} + +/** + * Checks if a version is in any of the supplied ranges. + * @param {String} ver - The version to check + * @param {String} str - The version ranges to validate against + * @param {Boolean} [maybe] - If true and the version is greater than at least + * one of the ranges, then it will return 'maybe'. + * @returns {Boolean|String} True if the version matches one of the ranges + */ +export function satisfies(ver: string, str: string, maybe?: boolean): boolean | string { + ver = format(ver, 3, 3, true); + + // if we get 1.x, we force it to 1.99999999 so that we should match + const replacedStr = str + .replace(/(<=?\d+(\.\d+)*?)\.x/g, '$1.99999999') + .replace(/(>=?\d+(\.\d+)*?)\.x/g, '$1.0'); + + try { + if (replacedStr === '*' || eq(ver, replacedStr)) { + return true; + } + } catch {} + + const r = replacedStr.split(/\s*\|\|\s*/).some((range) => { + // semver is picky with the '-' in comparisons and it just so happens when it + // parses versions in the range, it will add '-0' and cause '1.0.0' != '1.0.0-0', + // so we test our version with and without the '-9' + return ( + range === '*' || + semver.satisfies(ver, range) || + (!ver.includes('-') && semver.satisfies(ver + '-0', range)) + ); + }); + + // if true or we don't care if it maybe matches, then return now + if (r || !maybe) { + return r; + } + + // need to determine if the version is greater than any range + const range = new semver.Range(replacedStr); + for (let i = 0; i < range.set.length; i++) { + const set = range.set[i]; + for (let j = set.length - 1; j >= 0; j--) { + if (set[j].semver instanceof semver.SemVer) { + if ( + (set[j].operator === '<' || set[j].operator === '<=') && + !semver.cmp(ver, set[j].operator, set[j].semver, set[j].loose) + ) { + return 'maybe'; + } + break; + } + } + } + + return false; +} + +/** + * Sorts an array of version numbers in ascending order. + * @param {Array} arr - The array of version numbers to sort + * @returns {Array} The sorted versions + */ +export function sort(arr: string[]): string[] { + return arr.sort(compare); +} diff --git a/src/util/xml.ts b/src/util/xml.ts new file mode 100644 index 00000000..a8e4882f --- /dev/null +++ b/src/util/xml.ts @@ -0,0 +1,42 @@ +/** + * @constant {Number} Node type constant for an element node. + */ +export const ELEMENT_NODE = 1; + +/** + * Loops through all child element nodes for a given XML node skipping all + * non-element nodes (i.e. text, comment, etc) and calls the specified function + * for each element node found. + * @param node - An XML node + * @param fn - The function to call for each element node found + */ +export function forEachElement(node: Element, fn: (child: Element) => void): void { + let child = node.firstChild; + while (child) { + if (child.nodeType === ELEMENT_NODE) { + fn(child as Element); + } + child = child.nextSibling; + } +} + +/** + * Gets and parses an attribute of an XML node as a string. If attribute does + * not exist, it returns an empty string. + * @param node - An XML node + * @param attr - The name of the attribute to get + * @returns The value of the attribute or empty string if attribute does not exist + */ +export function getAttrString(node: Element, attr: string): string { + return node.getAttribute(attr) || ''; +} + +/** + * Determines if the specified XML node has a child data node and returns it as + * a string. + * @param node - An XML node + * @returns The value of the XML node + */ +export function getValueString(node: Element): string { + return node?.firstChild?.textContent || ''; +} diff --git a/test-old/adb.test.js b/test-old/adb.test.js new file mode 100644 index 00000000..71700ac3 --- /dev/null +++ b/test-old/adb.test.js @@ -0,0 +1,176 @@ +import fs from 'node:fs'; +import path from 'node:path'; +import { setTimeout as delay } from 'node:timers/promises'; +import { fileURLToPath } from 'node:url'; +import { rimraf } from 'rimraf'; +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { ADB } from '../lib/adb.js'; +import { setAndroidPackageJson } from '../lib/android.js'; +import { EmulatorManager } from '../lib/emulator.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +setAndroidPackageJson({ + vendorDependencies: { + 'android sdk': '>=23.x <=27.x', + 'android build tools': '>=25.x <=27.x', + 'android platform tools': '27.x', + 'android tools': '<=26.x', + 'android ndk': '>=r11c <=r16c', + node: '>=4.0 <=8.x', + java: '>=1.8.x', + }, +}); + +function MockConfig() { + this.get = (_s, d) => d; +} + +const config = new MockConfig(); +const adb = new ADB(config); +const emulator = new EmulatorManager(config); + +describe('adb', () => { + it('#version() returns a valid semver string', async () => { + const ver = await adb.version(); + expect(ver).toMatch(/^1\.0\.\d+/); + expect(semver.valid(ver)).not.toBeNull(); + }); + + // TODO: Add test where we start an emulator first, get it in listing, then stop it? + it('#devices() returns empty Array when no emulators running', async () => { + const devices = await adb.devices(); + expect(devices).toBeInstanceOf(Array); + }); + + // TODO: Start an emulator, make sure we get event? + it('#trackDevices()', () => + new Promise((resolve, reject) => { + const connection = adb.trackDevices((err, devices) => { + connection.end(); + if (err) { + return reject(err); + } + // console.log('trackDevicesCallback: ' + JSON.stringify(devices)); + expect(devices).toBeInstanceOf(Array); + resolve(); + }); + })); + + describe('with an emulator running', () => { + let avd; + let device; + + beforeAll(async () => { + const avds = await emulator.detect(); + if (avds.length === 0) { + throw new Error('Tests require at least one emulator defined!'); + } + avd = avds[0]; + + const emu = await emulator.start(avd.id); + await new Promise((resolve, reject) => { + emu.on('ready', (d) => { + device = d; + resolve(); + }); + + emu.on('timeout', () => reject(new Error('emulator.start() timed out'))); + }); + }, 30000); + + afterAll(async () => { + // Just call finished if there is no device, there may have been an issue when starting + // the emulator in the before + if (!device) { + return; + } + await emulator.stop(device.emulator.id); + await delay(5000); // let it wait 5 seconds or else adb will still report it as connected + }, 30000); + + it('#shell()', async () => { + const data = await adb.shell(device.id, 'cat /system/build.prop'); + // data is a Buffer! + expect(data).toBeTruthy(); + // (typeof data).should.eql('Buffer'); + }); + + it('#startApp(), #getPid() and #stopApp()', async () => { + const appId = 'com.android.settings'; + const data = await adb.startApp(device.id, appId, 'wifi.WifiStatusTest'); + + // data is a Buffer! + expect(data).toBeTruthy(); // TODO: Test data.toString() holds particular text? + + const pid = await adb.getPid(device.id, appId); + expect(err).toBeNull(); + + expect(pid).toBeInstanceOf(Number); + expect(pid).not.toEqual(0); + + await adb.stopApp(device.id, appId); + }, 30000); + + it('#pull()', async () => { + const dest = path.join(__dirname, 'hosts'); + expect(fs.existsSync(dest)).toBeFalsy(); + + await adb.pull(device.id, '/system/etc/hosts', __dirname); + + // verify build.prop exists in current dir now! + try { + expect(fs.existsSync(dest)).toBeTruthy(); + } finally { + try { + rimraf(dest); + } catch { + // squash + } + } + }); + + it('#push()', async () => { + const dest = '/mnt/sdcard/tmp/test-adb.js'; + + // Ensure dest file doesn't exist + await adb.shell(device.id, `rm -f '${dest}'`); + + // Then piush this file to dest + await adb.push(device.id, __filename, dest); + + // verify it now exists and matches + const data = await adb.shell(device.id, `cat '${dest}'`); + + // data is a Buffer! + expect(data).toBeTruthy(); + // normalize newlines, android uses \r\n + expect(data.toString().replace(/\r\n/g, '\n')).toEqual( + fs.readFileSync(__filename).toString() + ); + }); + }); // with running emulator + + // TODO: Install a pre-built test app! + // function testInstallApp() { + // adb.installApp('emulator-5554', '~/appc/workspace/testapp2/build/android/bin/app.apk', (err, data) => { + // if (err) { + // console.error('ERROR! ' + err + '\n'); + // } else { + // console.log('-----------------------------------------------------------------'); + // console.log(data); + // console.log(''); + // } + // }); + // } + // + // function testForward() { + // adb.forward('015d21d4ff181a17', 'tcp:5000', 'tcp:6000', (err, data) => { + // if (err) { + // console.error('ERROR! ' + err + '\n'); + // } else { + // console.log('result = ' + data + '\n'); + // } + // }); + // } +}); diff --git a/test-old/android.test.js b/test-old/android.test.js new file mode 100644 index 00000000..8fb2f9a8 --- /dev/null +++ b/test-old/android.test.js @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest'; +import { detect as detectAndroid, setAndroidPackageJson } from '../lib/android.js'; + +function MockConfig() { + this.get = (_s, d) => d; +} + +setAndroidPackageJson({ + vendorDependencies: { + 'android sdk': '>=23.x <=27.x', + 'android build tools': '>=25.x <=27.x', + 'android platform tools': '27.x', + 'android tools': '<=26.x', + 'android ndk': '>=r11c <=r16c', + node: '>=4.0 <=8.x', + java: '>=1.8.x', + }, +}); +const config = new MockConfig(); + +describe('android', () => { + it('should detect Android environment', async () => { + const info = await detectAndroid(config); + console.log(info); + }); +}); diff --git a/test-old/avd.test.js b/test-old/avd.test.js new file mode 100644 index 00000000..f1b08aa7 --- /dev/null +++ b/test-old/avd.test.js @@ -0,0 +1,75 @@ +import { beforeAll, describe, expect, it } from 'vitest'; +import { setAndroidPackageJson } from '../lib/android.js'; +import { EmulatorManager } from '../lib/emulator.js'; + +function MockConfig() { + this.get = (_s, d) => d; +} + +setAndroidPackageJson({ + vendorDependencies: { + 'android sdk': '>=23.x <=27.x', + 'android build tools': '>=25.x <=27.x', + 'android platform tools': '27.x', + 'android tools': '<=26.x', + 'android ndk': '>=r11c <=r16c', + node: '>=4.0 <=8.x', + java: '>=1.8.x', + }, +}); +const config = new MockConfig(); +const emulator = new EmulatorManager(config); + +describe('emulator', () => { + it('#detect() any', async () => { + const avds = await emulator.detect(); + expect(avds).toBeInstanceOf(Array); + }); + + it('#detect() type: avd', async () => { + const avds = await emulator.detect({ type: 'avd' }); + expect(avds).toBeInstanceOf(Array); + }); + + describe('lifecycle', () => { + let avd; + + beforeAll(async () => { + const avds = await emulator.detect(); + if (avds.length === 0) { + throw new Error('Tests require at least one emulator defined!'); + } + avd = avds[0]; + }); + + it('#isRunning() returns null object when not running', async () => { + const emu = await emulator.isRunning(avd.id); + expect(emu).toBeTruthy(); + }); + + // FIXME: This test isn't right. I think it will only pass when the emulator is running and we pass in the id (that has port in the value)? + // it('#isEmulator() returns matching emulator?', async () => { + // const emu = await emulator.isEmulator(avd.name); + // expect(emu).toBeTruthy(); + // }); + + it('#start(), #isRunning() and #stop()', async () => { + const emu = await emulator.start(avd.id); + expect(emu).toBeTruthy(); + + await new Promise((resolve, reject) => { + emu.on('ready', async (device) => { + expect(device).toBeTruthy(); + + const emu = await emulator.isRunning(device.emulator.id); + expect(emu).toBeTruthy(); + + await emulator.stop(device.emulator.id); + setTimeout(() => resolve(), 6000); // let it wait 5 seconds or else adb will still report it as connected + }); + + emu.on('timeout', () => reject(new Error('emulator.start() timed out'))); + }); + }, 30000); + }); +}); diff --git a/test/android/android-ndk.test.ts b/test/android/android-ndk.test.ts new file mode 100644 index 00000000..2d43b819 --- /dev/null +++ b/test/android/android-ndk.test.ts @@ -0,0 +1,177 @@ +import { detectAndroidNDKs, AndroidNDK } from '../../src/android/android-ndk.js'; +import { config, resetConfig } from '../../src/config.js'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const cmd = process.platform === 'win32' ? '.cmd' : ''; + +describe('Android NDK', () => { + afterEach(() => resetConfig()); + + describe('load()', () => { + it('should error if directory is invalid', async () => { + await expect(AndroidNDK.load(undefined as any)).rejects.toThrowError( + new TypeError('Expected Android NDK path to be a valid string') + ); + await expect(AndroidNDK.load(123 as any)).rejects.toThrowError( + new TypeError('Expected Android NDK path to be a valid string') + ); + await expect(AndroidNDK.load('')).rejects.toThrowError( + new TypeError('Expected Android NDK path to be a valid string') + ); + }); + + it('should error if directory does not exist', async () => { + const path = join(__dirname, 'doesnotexist'); + await expect(AndroidNDK.load(path)).rejects.toThrowError( + new Error(`Android NDK path does not exist: ${path}`) + ); + }); + + it('should error if directory is missing the "ndk-build" executable', async () => { + await expect( + AndroidNDK.load(join(__dirname, 'mocks', 'ndk', 'all', 'no-ndk-build')) + ).rejects.toThrow('Directory does not contain the "ndk-build" executable'); + }); + + it('should error if directory is missing the "ndk-which" executable', async () => { + await expect( + AndroidNDK.load(join(__dirname, 'mocks', 'ndk', process.platform, 'no-ndk-which')) + ).rejects.toThrow('Directory does not contain the "ndk-which" executable'); + }); + + it('should detect an NDK with no version', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'no-version'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'no-version', + version: null, + arch: '64-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + + it('should detect an NDK r9 64-bit release', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r9d-64bit'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'r9d', + version: '9.3', + arch: '64-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + + it('should detect an NDK r9d 32-bit release', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r9d-32bit'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'r9d', + version: '9.3', + arch: '32-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + + it('should detect an NDK r11b 64-bit release', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r11b-64bit'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'r11b', + version: '11.1.2683735', + arch: '64-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + + it('should detect an NDK r11b 32-bit release', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r11b-32bit'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'r11b', + version: '11.1.2683735', + arch: '32-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + + it('should detect an NDK r29', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r29'); + const ndk = await AndroidNDK.load(dir); + expect(ndk).toEqual({ + path: dir, + name: 'r29', + version: '29.0.14206865', + arch: '64-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + }); + }); + }); + + describe('detect()', () => { + it('should find Android NDKs', async () => { + const dir = join(__dirname, 'mocks', 'ndk', process.platform, 'r29'); + config.android.ndk.searchPaths[process.platform] = []; + const { ndks } = await detectAndroidNDKs({ + searchPaths: [dir], + }); + expect(ndks).toHaveLength(1); + expect(ndks[0]).toEqual({ + arch: '64-bit', + executables: { + 'ndk-build': join(dir, `ndk-build${cmd}`), + 'ndk-which': join(dir, `ndk-which${cmd}`), + }, + name: 'r29', + path: dir, + version: '29.0.14206865', + }); + }); + + it('should return issues if no Android NDKs are found', async () => { + config.android.ndk.searchPaths[process.platform] = ['does_not_exist']; + const { ndks, issues } = await detectAndroidNDKs(); + expect(ndks).toEqual([]); + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('ANDROID_NDK_NOT_FOUND'); + expect(issues[0].type).toBe('warning'); + }); + + it('should return issues if no valid Android NDKs are found', async () => { + delete process.env.JAVA_HOME; + config.android.ndk.searchPaths[process.platform] = [ + join(__dirname, 'mocks', 'ndk', process.platform, 'no-ndk-build'), + ]; + const { ndks, issues } = await detectAndroidNDKs(); + expect(ndks).toEqual([]); + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('ANDROID_NDK_NOT_FOUND'); + expect(issues[0].type).toBe('warning'); + }); + }); +}); diff --git a/test/android/android-sdk.test.ts b/test/android/android-sdk.test.ts new file mode 100644 index 00000000..8cb45957 --- /dev/null +++ b/test/android/android-sdk.test.ts @@ -0,0 +1,160 @@ +import { detectAndroidSDKs, AndroidSDK } from '../../src/android/android-sdk.js'; +import { config, resetConfig } from '../../src/config.js'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const exe = process.platform === 'win32' ? '.exe' : ''; +const testPlatform = process.platform === 'win32' ? 'win32' : 'posix'; + +describe('Android SDK', () => { + afterEach(() => resetConfig()); + + describe('load()', () => { + it('should error if directory is invalid', async () => { + await expect(AndroidSDK.load(undefined as any)).rejects.toThrowError( + new TypeError('Expected Android SDK path to be a valid string') + ); + await expect(AndroidSDK.load(123 as any)).rejects.toThrowError( + new TypeError('Expected Android SDK path to be a valid string') + ); + await expect(AndroidSDK.load('')).rejects.toThrowError( + new TypeError('Expected Android SDK path to be a valid string') + ); + }); + + it('should error if directory does not exist', async () => { + await expect(AndroidSDK.load(join(__dirname, 'doesnotexist'))).rejects.toThrowError( + new Error(`Android SDK path does not exist: ${join(__dirname, 'doesnotexist')}`) + ); + }); + + it('should error if missing adb executable', async () => { + await expect( + AndroidSDK.load(join(__dirname, 'mocks', 'sdk', testPlatform, 'missing-adb')) + ).rejects.toThrowError(new Error('Invalid Android SDK: missing required executable "adb"')); + }); + + it('should error if missing emulator executable', async () => { + await expect( + AndroidSDK.load(join(__dirname, 'mocks', 'sdk', testPlatform, 'missing-emulator')) + ).rejects.toThrowError( + new Error('Invalid Android SDK: missing required executable "emulator"') + ); + }); + + it('should detect minimal sdk', async () => { + const path = join(__dirname, 'mocks', 'sdk', testPlatform, 'minimal'); + const sdk = await AndroidSDK.load(path); + expect(sdk.addons).to.have.length(0); + expect(sdk.adb).to.equal(join(path, 'platform-tools', `adb${exe}`)); + expect(sdk.emulator).to.equal(join(path, 'emulator', `emulator${exe}`)); + expect(sdk.path).to.equal(path); + expect(sdk.platforms).to.deep.equal([]); + expect(sdk.systemImages).to.deep.equal({}); + + expect(sdk.issues).to.have.length(1); + expect(sdk.issues[0].id).to.equal('ANDROID_SDK_NO_PLATFORMS'); + }); + + it('should detect sdk with platforms and system images', async () => { + const path = join( + __dirname, + 'mocks', + 'sdk', + testPlatform, + 'with-platforms-and-system-images' + ); + const sdk = await AndroidSDK.load(path); + expect(sdk.addons).to.have.length(0); + expect(sdk.adb).to.equal(join(path, 'platform-tools', `adb${exe}`)); + expect(sdk.emulator).to.equal(join(path, 'emulator', `emulator${exe}`)); + expect(sdk.path).to.equal(path); + expect(sdk.platforms).to.deep.equal([ + { + abis: {}, + androidJar: null, + apiLevel: 36, + codename: null, + defaultSkin: 'WVGA800', + minToolsRev: 22, + name: 'Android 16', + path: join(path, 'platforms', 'android-36'), + revision: 1, + sdk: 'android-36', + skins: ['WVGA800'], + version: '16', + }, + ]); + expect(sdk.systemImages).to.deep.equal({ + 'android-36.1/example/x86_64': { + abi: 'x86_64', + sdk: 'android-36.1', + skins: [], + type: 'example', + }, + }); + + expect(sdk.issues).to.have.length(0); + }); + }); + + describe('detect()', () => { + it('should find Android SDKs', async () => { + const path = join( + __dirname, + 'mocks', + 'sdk', + testPlatform, + 'with-platforms-and-system-images' + ); + config.android.sdk.searchPaths[process.platform] = []; + const { sdks } = await detectAndroidSDKs({ + searchPaths: [path], + }); + expect(sdks).toEqual([ + { + addons: [], + adb: join(path, 'platform-tools', `adb${exe}`), + emulator: join(path, 'emulator', `emulator${exe}`), + issues: [], + path, + platforms: [ + { + abis: {}, + androidJar: null, + apiLevel: 36, + codename: null, + defaultSkin: 'WVGA800', + minToolsRev: 22, + name: 'Android 16', + path: join(path, 'platforms', 'android-36'), + revision: 1, + sdk: 'android-36', + skins: ['WVGA800'], + version: '16', + }, + ], + systemImages: { + 'android-36.1/example/x86_64': { + abi: 'x86_64', + sdk: 'android-36.1', + skins: [], + type: 'example', + }, + }, + }, + ]); + }); + + it('should return issues if no Android SDKs are found', async () => { + config.android.sdk.searchPaths[testPlatform] = ['does_not_exist']; + const { sdks, issues } = await detectAndroidSDKs(); + expect(sdks).toEqual([]); + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('ANDROID_SDK_NOT_FOUND'); + expect(issues[0].type).toBe('warning'); + }); + }); +}); diff --git a/test/android/mocks/adb-server.js b/test/android/mocks/adb-server.js new file mode 100644 index 00000000..459a15bf --- /dev/null +++ b/test/android/mocks/adb-server.js @@ -0,0 +1,86 @@ +import appcdLogger from 'appcd-logger'; + +const net = require('net'); +const { log } = appcdLogger('test:androidlib:adb-server'); + +class MockAdbServer { + constructor(port = 9999) { + this.server = null; + this.port = port; + } + + async start() { + let toClose = true; + + this.server = net.createServer(socket => { + socket.setNoDelay(true); + + log(`CONNECTED: ${socket.remoteAddress}:${socket.remotePort}`); + let timer; + + socket.on('data', data => { + log(`DATA ${socket.remoteAddress}: ${data}`); + + if (data.indexOf('host:fake') !== -1) { + socket.write('FAIL0014unknown host service'); + + } else if (data.indexOf('host:version') !== -1) { + socket.write('OKAY00040030'); + + } else if (data.indexOf('host:nodevices') !== -1) { + socket.write('OKAY00000'); + + } else if (data.indexOf('host:twodevices') !== -1) { + socket.write('OKAY002aemulator-5556\tdevice\nemulator-5554\tdevice\n'); + + } else if (data.indexOf('shell:ps') !== -1) { + toClose = false; + socket.write('OKAY'); + clearTimeout(timer); + timer = setTimeout(() => { + try { + socket.write('USER PID PPID VSIZE RSS WCHAN PC NAME\n'); + socket.write('root 1 0 8784 608 c00be88c 00026cbc S /init BYTES\n'); + socket.write('u0_a27 977 67 462792 24452 ffffffff b6e2cc9c S com.android.exchange'); + socket.end(); + } catch (e) { + // squelch + } + }, 10); + } else if (data.indexOf('host:transport:emulator-5554') !== -1) { + toClose = false; + clearTimeout(timer); + timer = setTimeout(() => { + socket.write('OKAY'); + }, 500); + } + + if (toClose) { + socket.end(); + } + }); + + socket.on('close', _data => { + log(`CLOSED: ${socket.remoteAddress}:${socket.remotePort}`); + clearTimeout(timer); + }); + }); + + await new Promise(resolve => { + this.server.listen(this.port, '127.0.0.1', () => { + log(`Server listening on 127.0.0.1:${this.port}`); + resolve(); + }); + }); + } + + async stop() { + if (this.server) { + return await new Promise(resolve => { + this.server.close(resolve); + }); + } + } +} + +module.exports = MockAdbServer; diff --git a/test/android/mocks/avd/test.avd/config.ini b/test/android/mocks/avd/test.avd/config.ini new file mode 100644 index 00000000..a360059b --- /dev/null +++ b/test/android/mocks/avd/test.avd/config.ini @@ -0,0 +1,41 @@ +AvdId=test_API_23 +abi.type=x86 +avd.ini.displayname=Test API 23 +avd.ini.encoding=UTF-8 +disk.dataPartition.size=800M +hw.accelerometer=yes +hw.audioInput=yes +hw.battery=yes +hw.camera.back=emulated +hw.camera.front=emulated +hw.cpu.arch=x86 +hw.cpu.ncore=4 +hw.dPad=no +hw.device.hash2=MD5:bc5032b2a871da511332401af3ac6bb0 +hw.device.manufacturer=Google +hw.device.name=Nexus 5X +hw.gps=yes +hw.gpu.enabled=yes +hw.gpu.mode=auto +hw.initialOrientation=Portrait +hw.keyboard=yes +hw.lcd.density=420 +hw.lcd.height=1920 +hw.lcd.width=1080 +hw.mainKeys=no +hw.ramSize=1536 +hw.sdCard=yes +hw.sensors.orientation=yes +hw.sensors.proximity=yes +hw.trackBall=no +image.sysdir.1=system-images/android-23/google_apis/x86/ +runtime.network.latency=none +runtime.network.speed=full +sdcard.path=/path/to/sdcard.img +showDeviceFrame=yes +skin.dynamic=yes +skin.name=nexus_5x +skin.path=/path/to/skins/nexus_5x +tag.display=Google APIs +tag.id=google_apis +vm.heapSize=256 diff --git a/test/android/mocks/avd/test.ini b/test/android/mocks/avd/test.ini new file mode 100644 index 00000000..db4690a1 --- /dev/null +++ b/test/android/mocks/avd/test.ini @@ -0,0 +1,3 @@ +avd.ini.encoding=UTF-8 +path.rel=avd/test.avd +target=android-23 diff --git a/test/android/mocks/avd2/config.ini b/test/android/mocks/avd2/config.ini new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/empty/.gitignore b/test/android/mocks/empty/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/all/no-build-dir/.gitignore b/test/android/mocks/ndk/all/no-build-dir/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/all/no-ndk-build/build/.gitignore b/test/android/mocks/ndk/all/no-ndk-build/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/all/no-ndk-build/platforms/.gitignore b/test/android/mocks/ndk/all/no-ndk-build/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/all/no-platforms-dir/build/.gitignore b/test/android/mocks/ndk/all/no-platforms-dir/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/darwin/no-ndk-build/.gitignore b/test/android/mocks/ndk/darwin/no-ndk-build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/darwin/no-ndk-which/ndk-build b/test/android/mocks/ndk/darwin/no-ndk-which/ndk-build new file mode 100755 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/no-ndk-which/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/no-version/RELEASE.TXT b/test/android/mocks/ndk/darwin/no-version/RELEASE.TXT new file mode 100644 index 00000000..facd29e7 --- /dev/null +++ b/test/android/mocks/ndk/darwin/no-version/RELEASE.TXT @@ -0,0 +1 @@ +wtf diff --git a/test/android/mocks/ndk/darwin/no-version/ndk-build b/test/android/mocks/ndk/darwin/no-version/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/no-version/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/no-version/ndk-which b/test/android/mocks/ndk/darwin/no-version/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/darwin/no-version/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/darwin/r11b-32bit/ndk-build b/test/android/mocks/ndk/darwin/r11b-32bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-32bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/r11b-32bit/ndk-which b/test/android/mocks/ndk/darwin/r11b-32bit/ndk-which new file mode 100644 index 00000000..d2a267f0 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-32bit/ndk-which @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-which" diff --git a/test/android/mocks/ndk/darwin/r11b-32bit/source.properties b/test/android/mocks/ndk/darwin/r11b-32bit/source.properties new file mode 100644 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-32bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/darwin/r11b-64bit/ndk-build b/test/android/mocks/ndk/darwin/r11b-64bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-64bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/r11b-64bit/ndk-which b/test/android/mocks/ndk/darwin/r11b-64bit/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-64bit/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/darwin/r11b-64bit/source.properties b/test/android/mocks/ndk/darwin/r11b-64bit/source.properties new file mode 100644 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r11b-64bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/darwin/r29/ndk-build b/test/android/mocks/ndk/darwin/r29/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r29/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/r29/ndk-which b/test/android/mocks/ndk/darwin/r29/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/darwin/r29/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/darwin/r29/source.properties b/test/android/mocks/ndk/darwin/r29/source.properties new file mode 100644 index 00000000..5eb143b8 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r29/source.properties @@ -0,0 +1,4 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 29.0.14206865 +Pkg.BaseRevision = 29.0.14206865 +Pkg.ReleaseName = r29 diff --git a/test/android/mocks/ndk/darwin/r9d-32bit/RELEASE.TXT b/test/android/mocks/ndk/darwin/r9d-32bit/RELEASE.TXT new file mode 100644 index 00000000..1c18d2bc --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-32bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (32-bit) diff --git a/test/android/mocks/ndk/darwin/r9d-32bit/ndk-build b/test/android/mocks/ndk/darwin/r9d-32bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-32bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/r9d-32bit/ndk-which b/test/android/mocks/ndk/darwin/r9d-32bit/ndk-which new file mode 100644 index 00000000..d2a267f0 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-32bit/ndk-which @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-which" diff --git a/test/android/mocks/ndk/darwin/r9d-64bit/RELEASE.TXT b/test/android/mocks/ndk/darwin/r9d-64bit/RELEASE.TXT new file mode 100644 index 00000000..4472de7e --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-64bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (64-bit) diff --git a/test/android/mocks/ndk/darwin/r9d-64bit/ndk-build b/test/android/mocks/ndk/darwin/r9d-64bit/ndk-build new file mode 100755 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-64bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/darwin/r9d-64bit/ndk-which b/test/android/mocks/ndk/darwin/r9d-64bit/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/darwin/r9d-64bit/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/linux/no-ndk-build/.gitignore b/test/android/mocks/ndk/linux/no-ndk-build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/linux/no-ndk-which/ndk-build b/test/android/mocks/ndk/linux/no-ndk-which/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/no-ndk-which/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/no-version/RELEASE.TXT b/test/android/mocks/ndk/linux/no-version/RELEASE.TXT new file mode 100644 index 00000000..facd29e7 --- /dev/null +++ b/test/android/mocks/ndk/linux/no-version/RELEASE.TXT @@ -0,0 +1 @@ +wtf diff --git a/test/android/mocks/ndk/linux/no-version/ndk-build b/test/android/mocks/ndk/linux/no-version/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/no-version/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/no-version/ndk-which b/test/android/mocks/ndk/linux/no-version/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/linux/no-version/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/linux/platforms/.gitignore b/test/android/mocks/ndk/linux/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/linux/r11b-32bit/ndk-build b/test/android/mocks/ndk/linux/r11b-32bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-32bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/r11b-32bit/ndk-which b/test/android/mocks/ndk/linux/r11b-32bit/ndk-which new file mode 100644 index 00000000..d2a267f0 --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-32bit/ndk-which @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-which" diff --git a/test/android/mocks/ndk/linux/r11b-32bit/source.properties b/test/android/mocks/ndk/linux/r11b-32bit/source.properties new file mode 100644 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-32bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/linux/r11b-64bit/ndk-build b/test/android/mocks/ndk/linux/r11b-64bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-64bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/r11b-64bit/ndk-which b/test/android/mocks/ndk/linux/r11b-64bit/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-64bit/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/linux/r11b-64bit/source.properties b/test/android/mocks/ndk/linux/r11b-64bit/source.properties new file mode 100644 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/linux/r11b-64bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/linux/r29/ndk-build b/test/android/mocks/ndk/linux/r29/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/r29/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/r29/ndk-which b/test/android/mocks/ndk/linux/r29/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/linux/r29/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/linux/r29/source.properties b/test/android/mocks/ndk/linux/r29/source.properties new file mode 100644 index 00000000..5eb143b8 --- /dev/null +++ b/test/android/mocks/ndk/linux/r29/source.properties @@ -0,0 +1,4 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 29.0.14206865 +Pkg.BaseRevision = 29.0.14206865 +Pkg.ReleaseName = r29 diff --git a/test/android/mocks/ndk/linux/r9d-32bit/RELEASE.TXT b/test/android/mocks/ndk/linux/r9d-32bit/RELEASE.TXT new file mode 100644 index 00000000..1c18d2bc --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-32bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (32-bit) diff --git a/test/android/mocks/ndk/linux/r9d-32bit/ndk-build b/test/android/mocks/ndk/linux/r9d-32bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-32bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/r9d-32bit/ndk-which b/test/android/mocks/ndk/linux/r9d-32bit/ndk-which new file mode 100644 index 00000000..d2a267f0 --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-32bit/ndk-which @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-which" diff --git a/test/android/mocks/ndk/linux/r9d-64bit/RELEASE.TXT b/test/android/mocks/ndk/linux/r9d-64bit/RELEASE.TXT new file mode 100644 index 00000000..4472de7e --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-64bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (64-bit) diff --git a/test/android/mocks/ndk/linux/r9d-64bit/ndk-build b/test/android/mocks/ndk/linux/r9d-64bit/ndk-build new file mode 100644 index 00000000..b821d6d4 --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-64bit/ndk-build @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock ndk-build" diff --git a/test/android/mocks/ndk/linux/r9d-64bit/ndk-which b/test/android/mocks/ndk/linux/r9d-64bit/ndk-which new file mode 100644 index 00000000..24c5bc0d --- /dev/null +++ b/test/android/mocks/ndk/linux/r9d-64bit/ndk-which @@ -0,0 +1,4 @@ +#!/bin/sh +echo "mock ndk-which" + +# dummy-x86_64/ diff --git a/test/android/mocks/ndk/win32/no-ndk-which/build/.gitignore b/test/android/mocks/ndk/win32/no-ndk-which/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/no-ndk-which/ndk-build.cmd b/test/android/mocks/ndk/win32/no-ndk-which/ndk-build.cmd new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/no-ndk-which/platforms/.gitignore b/test/android/mocks/ndk/win32/no-ndk-which/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/no-version/RELEASE.TXT b/test/android/mocks/ndk/win32/no-version/RELEASE.TXT new file mode 100644 index 00000000..facd29e7 --- /dev/null +++ b/test/android/mocks/ndk/win32/no-version/RELEASE.TXT @@ -0,0 +1 @@ +wtf diff --git a/test/android/mocks/ndk/win32/no-version/build/.gitignore b/test/android/mocks/ndk/win32/no-version/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/no-version/ndk-build.cmd b/test/android/mocks/ndk/win32/no-version/ndk-build.cmd new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/no-version/ndk-which.cmd b/test/android/mocks/ndk/win32/no-version/ndk-which.cmd new file mode 100644 index 00000000..ed7509a5 --- /dev/null +++ b/test/android/mocks/ndk/win32/no-version/ndk-which.cmd @@ -0,0 +1 @@ +dummy-x86_64/ diff --git a/test/android/mocks/ndk/win32/no-version/platforms/.gitignore b/test/android/mocks/ndk/win32/no-version/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-32bit/build/.gitignore b/test/android/mocks/ndk/win32/r11b-32bit/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-32bit/ndk-build.cmd b/test/android/mocks/ndk/win32/r11b-32bit/ndk-build.cmd new file mode 100755 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-32bit/ndk-which.cmd b/test/android/mocks/ndk/win32/r11b-32bit/ndk-which.cmd new file mode 100644 index 00000000..3f1b426b --- /dev/null +++ b/test/android/mocks/ndk/win32/r11b-32bit/ndk-which.cmd @@ -0,0 +1 @@ +dummy/ diff --git a/test/android/mocks/ndk/win32/r11b-32bit/platforms/.gitignore b/test/android/mocks/ndk/win32/r11b-32bit/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-32bit/source.properties b/test/android/mocks/ndk/win32/r11b-32bit/source.properties new file mode 100755 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/win32/r11b-32bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/win32/r11b-64bit/build/.gitignore b/test/android/mocks/ndk/win32/r11b-64bit/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-64bit/ndk-build.cmd b/test/android/mocks/ndk/win32/r11b-64bit/ndk-build.cmd new file mode 100755 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-64bit/ndk-which.cmd b/test/android/mocks/ndk/win32/r11b-64bit/ndk-which.cmd new file mode 100644 index 00000000..ed7509a5 --- /dev/null +++ b/test/android/mocks/ndk/win32/r11b-64bit/ndk-which.cmd @@ -0,0 +1 @@ +dummy-x86_64/ diff --git a/test/android/mocks/ndk/win32/r11b-64bit/platforms/.gitignore b/test/android/mocks/ndk/win32/r11b-64bit/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r11b-64bit/source.properties b/test/android/mocks/ndk/win32/r11b-64bit/source.properties new file mode 100755 index 00000000..97322096 --- /dev/null +++ b/test/android/mocks/ndk/win32/r11b-64bit/source.properties @@ -0,0 +1,2 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 11.1.2683735 diff --git a/test/android/mocks/ndk/win32/r29/build/.gitignore b/test/android/mocks/ndk/win32/r29/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r29/ndk-build.cmd b/test/android/mocks/ndk/win32/r29/ndk-build.cmd new file mode 100755 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r29/ndk-which.cmd b/test/android/mocks/ndk/win32/r29/ndk-which.cmd new file mode 100644 index 00000000..ed7509a5 --- /dev/null +++ b/test/android/mocks/ndk/win32/r29/ndk-which.cmd @@ -0,0 +1 @@ +dummy-x86_64/ diff --git a/test/android/mocks/ndk/win32/r29/platforms/.gitignore b/test/android/mocks/ndk/win32/r29/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r29/source.properties b/test/android/mocks/ndk/win32/r29/source.properties new file mode 100644 index 00000000..5eb143b8 --- /dev/null +++ b/test/android/mocks/ndk/win32/r29/source.properties @@ -0,0 +1,4 @@ +Pkg.Desc = Android NDK +Pkg.Revision = 29.0.14206865 +Pkg.BaseRevision = 29.0.14206865 +Pkg.ReleaseName = r29 diff --git a/test/android/mocks/ndk/win32/r9d-32bit/RELEASE.TXT b/test/android/mocks/ndk/win32/r9d-32bit/RELEASE.TXT new file mode 100755 index 00000000..1c18d2bc --- /dev/null +++ b/test/android/mocks/ndk/win32/r9d-32bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (32-bit) diff --git a/test/android/mocks/ndk/win32/r9d-32bit/build/.gitignore b/test/android/mocks/ndk/win32/r9d-32bit/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r9d-32bit/ndk-build.cmd b/test/android/mocks/ndk/win32/r9d-32bit/ndk-build.cmd new file mode 100755 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r9d-32bit/ndk-which.cmd b/test/android/mocks/ndk/win32/r9d-32bit/ndk-which.cmd new file mode 100644 index 00000000..3f1b426b --- /dev/null +++ b/test/android/mocks/ndk/win32/r9d-32bit/ndk-which.cmd @@ -0,0 +1 @@ +dummy/ diff --git a/test/android/mocks/ndk/win32/r9d-32bit/platforms/.gitignore b/test/android/mocks/ndk/win32/r9d-32bit/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r9d-64bit/RELEASE.TXT b/test/android/mocks/ndk/win32/r9d-64bit/RELEASE.TXT new file mode 100755 index 00000000..4472de7e --- /dev/null +++ b/test/android/mocks/ndk/win32/r9d-64bit/RELEASE.TXT @@ -0,0 +1 @@ +r9d (64-bit) diff --git a/test/android/mocks/ndk/win32/r9d-64bit/build/.gitignore b/test/android/mocks/ndk/win32/r9d-64bit/build/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r9d-64bit/ndk-build.cmd b/test/android/mocks/ndk/win32/r9d-64bit/ndk-build.cmd new file mode 100755 index 00000000..e69de29b diff --git a/test/android/mocks/ndk/win32/r9d-64bit/ndk-which.cmd b/test/android/mocks/ndk/win32/r9d-64bit/ndk-which.cmd new file mode 100644 index 00000000..ed7509a5 --- /dev/null +++ b/test/android/mocks/ndk/win32/r9d-64bit/ndk-which.cmd @@ -0,0 +1 @@ +dummy-x86_64/ diff --git a/test/android/mocks/ndk/win32/r9d-64bit/platforms/.gitignore b/test/android/mocks/ndk/win32/r9d-64bit/platforms/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/sdk/all/invalid-tools-source-props/tools/source.properties b/test/android/mocks/sdk/all/invalid-tools-source-props/tools/source.properties new file mode 100644 index 00000000..74d0a43f --- /dev/null +++ b/test/android/mocks/sdk/all/invalid-tools-source-props/tools/source.properties @@ -0,0 +1 @@ +foo=bar diff --git a/test/android/mocks/sdk/all/missing-emulator/tools/source.properties b/test/android/mocks/sdk/all/missing-emulator/tools/source.properties new file mode 100644 index 00000000..806c0c98 --- /dev/null +++ b/test/android/mocks/sdk/all/missing-emulator/tools/source.properties @@ -0,0 +1,3 @@ +Pkg.UserSrc=false +Pkg.Revision=24.4.1 +Platform.MinPlatformToolsRev=20 diff --git a/test/android/mocks/sdk/posix/minimal/emulator/emulator b/test/android/mocks/sdk/posix/minimal/emulator/emulator new file mode 100644 index 00000000..1b29b65a --- /dev/null +++ b/test/android/mocks/sdk/posix/minimal/emulator/emulator @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock emulator" diff --git a/test/android/mocks/sdk/posix/minimal/platform-tools/adb b/test/android/mocks/sdk/posix/minimal/platform-tools/adb new file mode 100644 index 00000000..4c1c4ba9 --- /dev/null +++ b/test/android/mocks/sdk/posix/minimal/platform-tools/adb @@ -0,0 +1,2 @@ +#!/bin/sh +echo 'mock adb' diff --git a/test/android/mocks/sdk/posix/missing-adb/platform-tools/.gitkeep b/test/android/mocks/sdk/posix/missing-adb/platform-tools/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/sdk/posix/missing-emulator/platform-tools/adb b/test/android/mocks/sdk/posix/missing-emulator/platform-tools/adb new file mode 100644 index 00000000..4c1c4ba9 --- /dev/null +++ b/test/android/mocks/sdk/posix/missing-emulator/platform-tools/adb @@ -0,0 +1,2 @@ +#!/bin/sh +echo 'mock adb' diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/emulator/emulator b/test/android/mocks/sdk/posix/with-platforms-and-system-images/emulator/emulator new file mode 100644 index 00000000..1b29b65a --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/emulator/emulator @@ -0,0 +1,2 @@ +#!/bin/sh +echo "mock emulator" diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/platform-tools/adb b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platform-tools/adb new file mode 100644 index 00000000..4c1c4ba9 --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platform-tools/adb @@ -0,0 +1,2 @@ +#!/bin/sh +echo 'mock adb' diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/build.prop b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/build.prop new file mode 100644 index 00000000..539d917f --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/build.prop @@ -0,0 +1,104 @@ +#################################### +# from generate-common-build-props +# These properties identify this partition image. +#################################### +ro.product.system.brand=Android +ro.product.system.device=mainline_x86 +ro.product.system.manufacturer=unknown +ro.product.system.model=sdk +ro.product.system.name=sdk +ro.system.product.cpu.abilist=x86 +ro.system.product.cpu.abilist32=x86 +ro.system.product.cpu.abilist64= +ro.system.build.date=Mon Apr 14 08:51:49 UTC 2025 +ro.system.build.date.utc=1744620709 +ro.system.build.fingerprint=Android/sdk/mainline_x86:16/BP22.250325.007/13352765:userdebug/test-keys +ro.system.build.id=BP22.250325.007 +ro.system.build.tags=test-keys +ro.system.build.type=userdebug +ro.system.build.version.incremental=13352765 +ro.system.build.version.release=16 +ro.system.build.version.release_or_codename=16 +ro.system.build.version.sdk=36 +ro.system.build.version.sdk_full=36.0 +#################################### +# from gen_build_prop.py:generate_build_info +#################################### +# begin build properties +ro.build.id=BP22.250325.007 +ro.build.display.id=sdk-userdebug 16 BP22.250325.007 13352765 test-keys +ro.build.version.incremental=13352765 +ro.build.version.sdk=36 +ro.build.version.sdk_full=36.0 +ro.build.version.preview_sdk=0 +ro.build.version.preview_sdk_fingerprint=REL +ro.build.version.codename=REL +ro.build.version.all_codenames=REL +ro.build.version.known_codenames=Base,Base11,Cupcake,Donut,Eclair,Eclair01,EclairMr1,Froyo,Gingerbread,GingerbreadMr1,Honeycomb,HoneycombMr1,HoneycombMr2,IceCreamSandwich,IceCreamSandwichMr1,JellyBean,JellyBeanMr1,JellyBeanMr2,Kitkat,KitkatWatch,Lollipop,LollipopMr1,M,N,NMr1,O,OMr1,P,Q,R,S,Sv2,Tiramisu,UpsideDownCake,VanillaIceCream,Baklava +ro.build.version.release=16 +ro.build.version.release_or_codename=16 +ro.build.version.release_or_preview_display=16 +ro.build.version.security_patch=2025-04-05 +ro.build.version.base_os= +ro.build.version.min_supported_target_sdk=28 +ro.build.date=Mon Apr 14 08:51:49 UTC 2025 +ro.build.date.utc=1744620709 +ro.build.type=userdebug +ro.build.user=android-build +ro.build.host=7580da790f81 +ro.build.tags=test-keys +ro.build.flavor=sdk-userdebug +# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete, +# use ro.product.cpu.abilist instead. +ro.product.cpu.abi=x86 +ro.product.locale=en-US +ro.wifi.channels= +# ro.build.product is obsolete; use ro.product.device +ro.build.product=mainline_x86 +# Do not try to parse description or thumbprint +ro.build.description=sdk-userdebug 16 BP22.250325.007 13352765 test-keys +# end build properties +#################################### +# from variable ADDITIONAL_SYSTEM_PROPERTIES +#################################### +ro.treble.enabled=true +ro.llndk.api_level=202504 +ro.actionable_compatible_property.enabled=true +persist.debug.dalvik.vm.core_platform_api_policy=just-warn +ro.postinstall.fstab.prefix=/system +ro.secure=1 +security.perf_harden=1 +ro.allow.mock.location=0 +dalvik.vm.lockprof.threshold=500 +ro.debuggable=1 +xmpp.auto-presence=true +ro.config.nocheckin=yes +net.bt.name=Android +ro.force.debuggable=0 +#################################### +# from variable PRODUCT_SYSTEM_PROPERTIES +#################################### +dalvik.vm.image-dex2oat-Xms=64m +dalvik.vm.image-dex2oat-Xmx=64m +dalvik.vm.dex2oat-Xms=64m +dalvik.vm.dex2oat-Xmx=512m +#################################### +# from variable PRODUCT_SYSTEM_DEFAULT_PROPERTIES +#################################### +# Auto-added by post_process_props.py +persist.sys.usb.config=adb +#################################### +# Adding footer from :applied_backported_fixes +# with path out/soong/.intermediates/build/make/backported_fixes/applied_backported_fixes/gen/applied_backported_fixes.prop +#################################### +# The following backported fixes have been applied +# https://issuetracker.google.com/issues/350037023 with alias 1 +# https://issuetracker.google.com/issues/385124056 with alias 4 +ro.build.backported_fixes.alias_bitset.long_list=18 +# end of file +ro.build.user=generic +ro.build.host=generic +ro.product.brand=generic +ro.product.manufacturer=generic +ro.product.device=generic +ro.build.product=generic diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/sdk.properties b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/sdk.properties new file mode 100644 index 00000000..4f5ca6fe --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/sdk.properties @@ -0,0 +1,5 @@ +# SDK properties +# This file is copied in the root folder of each platform component. +# If it used by various tools to figure out what the platform can do. +sdk.ant.templates.revision=1 +sdk.skin.default=WVGA800 diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini new file mode 100644 index 00000000..fd2a6d56 --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini @@ -0,0 +1,4 @@ +# skin-specific hardware values +hw.lcd.density=240 +vm.heapSize=48 +hw.ramSize=512 diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/source.properties b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/source.properties new file mode 100644 index 00000000..bbd397db --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/platforms/android-36/source.properties @@ -0,0 +1,11 @@ +Pkg.Desc=Android SDK Platform 16 +Pkg.UserSrc=false +Platform.Version=16 +Platform.CodeName= +Pkg.Revision=2 +AndroidVersion.ApiLevel=36 +AndroidVersion.ExtensionLevel=17 +AndroidVersion.IsBaseSdk=true +Layoutlib.Api=15 +Layoutlib.Revision=1 +Platform.MinToolsRev=22 diff --git a/test/android/mocks/sdk/posix/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties b/test/android/mocks/sdk/posix/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties new file mode 100644 index 00000000..6de71b9b --- /dev/null +++ b/test/android/mocks/sdk/posix/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties @@ -0,0 +1,12 @@ +Pkg.Desc=System Image x86_64 +Pkg.Revision=3 +Pkg.Dependencies=emulator#35.4.9 +AndroidVersion.ApiLevel=36.1 +AndroidVersion.ExtensionLevel=20 +AndroidVersion.IsBaseSdk=true +SystemImage.Abi=x86_64 +SystemImage.TagId=example +SystemImage.TagDisplay=Example +SystemImage.GpuSupport=true +Addon.VendorId=tidev +Addon.VendorDisplay=TiDev Inc. diff --git a/test/android/mocks/sdk/win32/minimal/emulator/emulator.exe b/test/android/mocks/sdk/win32/minimal/emulator/emulator.exe new file mode 100644 index 00000000..24671fd0 Binary files /dev/null and b/test/android/mocks/sdk/win32/minimal/emulator/emulator.exe differ diff --git a/test/android/mocks/sdk/win32/minimal/platform-tools/adb.exe b/test/android/mocks/sdk/win32/minimal/platform-tools/adb.exe new file mode 100644 index 00000000..9169ce74 Binary files /dev/null and b/test/android/mocks/sdk/win32/minimal/platform-tools/adb.exe differ diff --git a/test/android/mocks/sdk/win32/missing-adb/platform-tools/.gitkeep b/test/android/mocks/sdk/win32/missing-adb/platform-tools/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/android/mocks/sdk/win32/missing-emulator/platform-tools/adb.exe b/test/android/mocks/sdk/win32/missing-emulator/platform-tools/adb.exe new file mode 100644 index 00000000..9169ce74 Binary files /dev/null and b/test/android/mocks/sdk/win32/missing-emulator/platform-tools/adb.exe differ diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/emulator/emulator.exe b/test/android/mocks/sdk/win32/with-platforms-and-system-images/emulator/emulator.exe new file mode 100644 index 00000000..24671fd0 Binary files /dev/null and b/test/android/mocks/sdk/win32/with-platforms-and-system-images/emulator/emulator.exe differ diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/platform-tools/adb.exe b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platform-tools/adb.exe new file mode 100644 index 00000000..9169ce74 Binary files /dev/null and b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platform-tools/adb.exe differ diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/build.prop b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/build.prop new file mode 100644 index 00000000..539d917f --- /dev/null +++ b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/build.prop @@ -0,0 +1,104 @@ +#################################### +# from generate-common-build-props +# These properties identify this partition image. +#################################### +ro.product.system.brand=Android +ro.product.system.device=mainline_x86 +ro.product.system.manufacturer=unknown +ro.product.system.model=sdk +ro.product.system.name=sdk +ro.system.product.cpu.abilist=x86 +ro.system.product.cpu.abilist32=x86 +ro.system.product.cpu.abilist64= +ro.system.build.date=Mon Apr 14 08:51:49 UTC 2025 +ro.system.build.date.utc=1744620709 +ro.system.build.fingerprint=Android/sdk/mainline_x86:16/BP22.250325.007/13352765:userdebug/test-keys +ro.system.build.id=BP22.250325.007 +ro.system.build.tags=test-keys +ro.system.build.type=userdebug +ro.system.build.version.incremental=13352765 +ro.system.build.version.release=16 +ro.system.build.version.release_or_codename=16 +ro.system.build.version.sdk=36 +ro.system.build.version.sdk_full=36.0 +#################################### +# from gen_build_prop.py:generate_build_info +#################################### +# begin build properties +ro.build.id=BP22.250325.007 +ro.build.display.id=sdk-userdebug 16 BP22.250325.007 13352765 test-keys +ro.build.version.incremental=13352765 +ro.build.version.sdk=36 +ro.build.version.sdk_full=36.0 +ro.build.version.preview_sdk=0 +ro.build.version.preview_sdk_fingerprint=REL +ro.build.version.codename=REL +ro.build.version.all_codenames=REL +ro.build.version.known_codenames=Base,Base11,Cupcake,Donut,Eclair,Eclair01,EclairMr1,Froyo,Gingerbread,GingerbreadMr1,Honeycomb,HoneycombMr1,HoneycombMr2,IceCreamSandwich,IceCreamSandwichMr1,JellyBean,JellyBeanMr1,JellyBeanMr2,Kitkat,KitkatWatch,Lollipop,LollipopMr1,M,N,NMr1,O,OMr1,P,Q,R,S,Sv2,Tiramisu,UpsideDownCake,VanillaIceCream,Baklava +ro.build.version.release=16 +ro.build.version.release_or_codename=16 +ro.build.version.release_or_preview_display=16 +ro.build.version.security_patch=2025-04-05 +ro.build.version.base_os= +ro.build.version.min_supported_target_sdk=28 +ro.build.date=Mon Apr 14 08:51:49 UTC 2025 +ro.build.date.utc=1744620709 +ro.build.type=userdebug +ro.build.user=android-build +ro.build.host=7580da790f81 +ro.build.tags=test-keys +ro.build.flavor=sdk-userdebug +# ro.product.cpu.abi and ro.product.cpu.abi2 are obsolete, +# use ro.product.cpu.abilist instead. +ro.product.cpu.abi=x86 +ro.product.locale=en-US +ro.wifi.channels= +# ro.build.product is obsolete; use ro.product.device +ro.build.product=mainline_x86 +# Do not try to parse description or thumbprint +ro.build.description=sdk-userdebug 16 BP22.250325.007 13352765 test-keys +# end build properties +#################################### +# from variable ADDITIONAL_SYSTEM_PROPERTIES +#################################### +ro.treble.enabled=true +ro.llndk.api_level=202504 +ro.actionable_compatible_property.enabled=true +persist.debug.dalvik.vm.core_platform_api_policy=just-warn +ro.postinstall.fstab.prefix=/system +ro.secure=1 +security.perf_harden=1 +ro.allow.mock.location=0 +dalvik.vm.lockprof.threshold=500 +ro.debuggable=1 +xmpp.auto-presence=true +ro.config.nocheckin=yes +net.bt.name=Android +ro.force.debuggable=0 +#################################### +# from variable PRODUCT_SYSTEM_PROPERTIES +#################################### +dalvik.vm.image-dex2oat-Xms=64m +dalvik.vm.image-dex2oat-Xmx=64m +dalvik.vm.dex2oat-Xms=64m +dalvik.vm.dex2oat-Xmx=512m +#################################### +# from variable PRODUCT_SYSTEM_DEFAULT_PROPERTIES +#################################### +# Auto-added by post_process_props.py +persist.sys.usb.config=adb +#################################### +# Adding footer from :applied_backported_fixes +# with path out/soong/.intermediates/build/make/backported_fixes/applied_backported_fixes/gen/applied_backported_fixes.prop +#################################### +# The following backported fixes have been applied +# https://issuetracker.google.com/issues/350037023 with alias 1 +# https://issuetracker.google.com/issues/385124056 with alias 4 +ro.build.backported_fixes.alias_bitset.long_list=18 +# end of file +ro.build.user=generic +ro.build.host=generic +ro.product.brand=generic +ro.product.manufacturer=generic +ro.product.device=generic +ro.build.product=generic diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/sdk.properties b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/sdk.properties new file mode 100644 index 00000000..4f5ca6fe --- /dev/null +++ b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/sdk.properties @@ -0,0 +1,5 @@ +# SDK properties +# This file is copied in the root folder of each platform component. +# If it used by various tools to figure out what the platform can do. +sdk.ant.templates.revision=1 +sdk.skin.default=WVGA800 diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini new file mode 100644 index 00000000..fd2a6d56 --- /dev/null +++ b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/skins/WVGA800/hardware.ini @@ -0,0 +1,4 @@ +# skin-specific hardware values +hw.lcd.density=240 +vm.heapSize=48 +hw.ramSize=512 diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/source.properties b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/source.properties new file mode 100644 index 00000000..bbd397db --- /dev/null +++ b/test/android/mocks/sdk/win32/with-platforms-and-system-images/platforms/android-36/source.properties @@ -0,0 +1,11 @@ +Pkg.Desc=Android SDK Platform 16 +Pkg.UserSrc=false +Platform.Version=16 +Platform.CodeName= +Pkg.Revision=2 +AndroidVersion.ApiLevel=36 +AndroidVersion.ExtensionLevel=17 +AndroidVersion.IsBaseSdk=true +Layoutlib.Api=15 +Layoutlib.Revision=1 +Platform.MinToolsRev=22 diff --git a/test/android/mocks/sdk/win32/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties b/test/android/mocks/sdk/win32/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties new file mode 100644 index 00000000..6de71b9b --- /dev/null +++ b/test/android/mocks/sdk/win32/with-platforms-and-system-images/system-images/android-36.1/example/x86_64/source.properties @@ -0,0 +1,12 @@ +Pkg.Desc=System Image x86_64 +Pkg.Revision=3 +Pkg.Dependencies=emulator#35.4.9 +AndroidVersion.ApiLevel=36.1 +AndroidVersion.ExtensionLevel=20 +AndroidVersion.IsBaseSdk=true +SystemImage.Abi=x86_64 +SystemImage.TagId=example +SystemImage.TagDisplay=Example +SystemImage.GpuSupport=true +Addon.VendorId=tidev +Addon.VendorDisplay=TiDev Inc. diff --git a/test/jdk/jdk.test.ts b/test/jdk/jdk.test.ts new file mode 100644 index 00000000..2aad228f --- /dev/null +++ b/test/jdk/jdk.test.ts @@ -0,0 +1,249 @@ +import { config, resetConfig } from '../../src/config.js'; +import { detectJDKs, JDK } from '../../src/jdk/index.js'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, beforeAll, describe, expect, it } from 'vitest'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const exe = process.platform === 'win32' ? '.exe' : ''; + +describe('JDK', function () { + let javaHome: string | undefined; + + beforeAll(() => { + javaHome = process.env.JAVA_HOME; + }); + + afterEach(() => { + delete process.env.MOCK_STDOUT; + delete process.env.MOCK_STDERR; + delete process.env.MOCK_EXITCODE; + resetConfig(); + + if (javaHome) { + process.env.JAVA_HOME = javaHome; + } else { + delete process.env.JAVA_HOME; + } + }); + + describe('load()', () => { + it('should throw error if dir is not a string', async () => { + await expect(JDK.load(undefined as any)).rejects.toThrowError( + new TypeError('Expected JDK path to be a valid string') + ); + await expect(JDK.load(123 as any)).rejects.toThrowError( + new TypeError('Expected JDK path to be a valid string') + ); + }); + + it('should throw error if dir does not exist', async () => { + await expect(JDK.load('doesnotexist')).rejects.toThrow('JDK path does not exist'); + }); + + it('should error if dir is missing essential jdk tools', async () => { + await expect(JDK.load(path.join(__dirname, 'mocks', 'incomplete-jdk'))).rejects.toThrow( + 'Directory missing required program' + ); + }); + + it('should detect JDK 1.6', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDERR = 'javac 1.6.0_45'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('1.6.0'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it('should detect JDK 1.7', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDERR = 'javac 1.7.0_80'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('1.7.0'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it('should detect JDK 1.8', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDERR = 'javac 1.8.0_92'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('1.8.0'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it.skipIf(process.platform !== 'darwin')( + 'should detect JDK 1.8 with macOS pathing', + async () => { + process.env.MOCK_STDERR = 'javac 1.8.0_92'; + const dir = path.join(__dirname, 'mocks', 'mock-jdk-darwin'); + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(path.join(dir, 'Contents', 'Home')); + expect(jdk.version).toBe('1.8.0'); + expect(jdk.java).toBe(path.join(dir, 'Contents', 'Home', 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'Contents', 'Home', 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'Contents', 'Home', 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'Contents', 'Home', 'bin', `jarsigner${exe}`)); + } + ); + + it('should detect JDK 9', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDOUT = 'javac 9'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('9'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it.skipIf(process.platform !== 'darwin')('should detect JDK 9 with macOS pathing', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk-darwin'); + process.env.MOCK_STDOUT = 'javac 9.0.1'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(path.join(dir, 'Contents', 'Home')); + expect(jdk.version).toBe('9.0.1'); + expect(jdk.java).toBe(path.join(dir, 'Contents', 'Home', 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'Contents', 'Home', 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'Contents', 'Home', 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'Contents', 'Home', 'bin', `jarsigner${exe}`)); + }); + + it('should detect JDK 20.0.1', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDOUT = 'javac 20.0.1'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('20.0.1'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it('should detect JDK 25', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDOUT = 'javac 25'; + const jdk = await JDK.load(dir); + + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('25'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + }); + + it('should not detect version if javac is bad', async () => { + const dir = path.join(__dirname, 'mocks', 'bad-bin-jdk'); + await expect(JDK.load(dir)).rejects.toThrow('Failed to determine JDK version'); + }); + }); + + describe('detectJDKs()', () => { + it('should find JDKs', async () => { + try { + const dir = path.join(__dirname, 'mocks', 'mock-jdk'); + process.env.MOCK_STDOUT = 'javac 9'; + process.env.JAVA_HOME = dir; + const { defaultVersion, home, jdks } = await detectJDKs(); + expect(home).toBe(dir); + expect(defaultVersion).toBe('9'); + + const jdk = jdks['9']; + expect(jdk).toBeDefined(); + expect(jdk!.path).toBe(dir); + expect(jdk!.version).toBe('9'); + expect(jdk!.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk!.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk!.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk!.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + } finally { + delete process.env.JAVA_HOME; + } + }, 60_000); + + it('should find JDKs without JAVA_HOME', async () => { + const javaHome = process.env.JAVA_HOME; + try { + process.env.MOCK_STDOUT = 'javac 9'; + process.env.JAVA_HOME = 'does_not_exist'; + const { home } = await detectJDKs(); + expect(home).toBeNull(); + } finally { + if (javaHome) { + process.env.JAVA_HOME = javaHome; + } else { + delete process.env.JAVA_HOME; + } + } + }); + + it('should return issues if no JDKs are found', async () => { + delete process.env.JAVA_HOME; + config.jdk.searchPaths[process.platform] = ['does_not_exist']; + const { jdks, issues } = await detectJDKs(); + expect(jdks).toEqual({}); + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('JDK_NOT_FOUND'); + expect(issues[0].type).toBe('error'); + }); + + it('should return issues if no valid JDKs are found', async () => { + delete process.env.JAVA_HOME; + config.jdk.searchPaths[process.platform] = []; + const { jdks, issues } = await detectJDKs({ + searchPaths: [path.join(__dirname, 'mocks', 'incomplete-jdk')], + }); + expect(jdks).toEqual({}); + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('JDK_NOT_FOUND'); + expect(issues[0].type).toBe('error'); + }); + + it('should return issues if JDK path contains ampersand', async () => { + const dir = path.join(__dirname, 'mocks', 'mock-jdk-&ersand'); + config.jdk.searchPaths[process.platform] = [dir]; + process.env.MOCK_STDOUT = 'javac 25'; + delete process.env.JAVA_HOME; + const { jdks, issues } = await detectJDKs(); + + const jdk = jdks['25']; + expect(jdk).toBeDefined(); + expect(jdk.path).toBe(dir); + expect(jdk.version).toBe('25'); + expect(jdk.java).toBe(path.join(dir, 'bin', `java${exe}`)); + expect(jdk.javac).toBe(path.join(dir, 'bin', `javac${exe}`)); + expect(jdk.keytool).toBe(path.join(dir, 'bin', `keytool${exe}`)); + expect(jdk.jarsigner).toBe(path.join(dir, 'bin', `jarsigner${exe}`)); + + if (process.platform === 'win32') { + expect(issues.length).toBe(1); + expect(issues[0].id).toBe('JDK_PATH_CONTAINS_AMPERSAND'); + expect(issues[0].type).toBe('warning'); + } else { + expect(issues).toEqual([]); + } + }); + }); +}); diff --git a/test/jdk/mocks/bad-bin-jdk/bin/jarsigner b/test/jdk/mocks/bad-bin-jdk/bin/jarsigner new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/bad-bin-jdk/bin/jarsigner.exe b/test/jdk/mocks/bad-bin-jdk/bin/jarsigner.exe new file mode 100644 index 00000000..09561313 Binary files /dev/null and b/test/jdk/mocks/bad-bin-jdk/bin/jarsigner.exe differ diff --git a/test/jdk/mocks/bad-bin-jdk/bin/java b/test/jdk/mocks/bad-bin-jdk/bin/java new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/bad-bin-jdk/bin/java.exe b/test/jdk/mocks/bad-bin-jdk/bin/java.exe new file mode 100644 index 00000000..234196cd Binary files /dev/null and b/test/jdk/mocks/bad-bin-jdk/bin/java.exe differ diff --git a/test/jdk/mocks/bad-bin-jdk/bin/javac b/test/jdk/mocks/bad-bin-jdk/bin/javac new file mode 100644 index 00000000..ecdbef95 --- /dev/null +++ b/test/jdk/mocks/bad-bin-jdk/bin/javac @@ -0,0 +1,2 @@ +#!/bin/sh +exit 1 diff --git a/test/jdk/mocks/bad-bin-jdk/bin/javac.exe b/test/jdk/mocks/bad-bin-jdk/bin/javac.exe new file mode 100644 index 00000000..de19a80a Binary files /dev/null and b/test/jdk/mocks/bad-bin-jdk/bin/javac.exe differ diff --git a/test/jdk/mocks/bad-bin-jdk/bin/keytool b/test/jdk/mocks/bad-bin-jdk/bin/keytool new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/bad-bin-jdk/bin/keytool.exe b/test/jdk/mocks/bad-bin-jdk/bin/keytool.exe new file mode 100644 index 00000000..7f6d8fd7 Binary files /dev/null and b/test/jdk/mocks/bad-bin-jdk/bin/keytool.exe differ diff --git a/test/jdk/mocks/bad-bin-jdk/jre/bin/server/jvm.dll b/test/jdk/mocks/bad-bin-jdk/jre/bin/server/jvm.dll new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/bad-bin-jdk/jre/lib/amd64/server/libjvm.so b/test/jdk/mocks/bad-bin-jdk/jre/lib/amd64/server/libjvm.so new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/bad-bin-jdk/jre/lib/server/libjvm.dylib b/test/jdk/mocks/bad-bin-jdk/jre/lib/server/libjvm.dylib new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/empty/.gitignore b/test/jdk/mocks/empty/.gitignore new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/incomplete-jdk/bin/javac b/test/jdk/mocks/incomplete-jdk/bin/javac new file mode 100755 index 00000000..95b23273 --- /dev/null +++ b/test/jdk/mocks/incomplete-jdk/bin/javac @@ -0,0 +1,26 @@ +#!/bin/bash + +out="${MOCK_STDOUT}" +err="${MOCK_STDERR}" +exitCode="${MOCK_EXITCODE}" + +code=0 +if [ -n "$exitCode" ]; then + # Validate that exitCode is a valid integer + if [ "$exitCode" -eq "$exitCode" ] 2>/dev/null && [ "$exitCode" -ge -2147483648 ] && [ "$exitCode" -le 2147483647 ]; then + code=$exitCode + fi +fi + +if [ -n "$out" ]; then + echo "$out" +fi +if [ -n "$err" ]; then + echo "$err" +fi +if [ -z "$out" ] && [ -z "$err" ]; then + echo "This is a mock executable" + echo "Set MOCK_STDOUT, MOCK_STDERR, and MOCK_EXITCODE to simulate executables" +fi + +exit $code diff --git a/test/jdk/mocks/incomplete-jdk/bin/javac.exe b/test/jdk/mocks/incomplete-jdk/bin/javac.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/incomplete-jdk/bin/javac.exe differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/jarsigner b/test/jdk/mocks/mock-jdk-&ersand/bin/jarsigner new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/jarsigner.exe b/test/jdk/mocks/mock-jdk-&ersand/bin/jarsigner.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-&ersand/bin/jarsigner.exe differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/java b/test/jdk/mocks/mock-jdk-&ersand/bin/java new file mode 100644 index 00000000..297dc2f7 --- /dev/null +++ b/test/jdk/mocks/mock-jdk-&ersand/bin/java @@ -0,0 +1,4 @@ +#!/bin/sh +>&2 echo "java version \"9\"" +>&2 echo "Java(TM) SE Runtime Environment (build 9+181)" +>&2 echo "Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)" diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/java.exe b/test/jdk/mocks/mock-jdk-&ersand/bin/java.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-&ersand/bin/java.exe differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/javac b/test/jdk/mocks/mock-jdk-&ersand/bin/javac new file mode 100755 index 00000000..95b23273 --- /dev/null +++ b/test/jdk/mocks/mock-jdk-&ersand/bin/javac @@ -0,0 +1,26 @@ +#!/bin/bash + +out="${MOCK_STDOUT}" +err="${MOCK_STDERR}" +exitCode="${MOCK_EXITCODE}" + +code=0 +if [ -n "$exitCode" ]; then + # Validate that exitCode is a valid integer + if [ "$exitCode" -eq "$exitCode" ] 2>/dev/null && [ "$exitCode" -ge -2147483648 ] && [ "$exitCode" -le 2147483647 ]; then + code=$exitCode + fi +fi + +if [ -n "$out" ]; then + echo "$out" +fi +if [ -n "$err" ]; then + echo "$err" +fi +if [ -z "$out" ] && [ -z "$err" ]; then + echo "This is a mock executable" + echo "Set MOCK_STDOUT, MOCK_STDERR, and MOCK_EXITCODE to simulate executables" +fi + +exit $code diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/javac.exe b/test/jdk/mocks/mock-jdk-&ersand/bin/javac.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-&ersand/bin/javac.exe differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/keytool b/test/jdk/mocks/mock-jdk-&ersand/bin/keytool new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/keytool.exe b/test/jdk/mocks/mock-jdk-&ersand/bin/keytool.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-&ersand/bin/keytool.exe differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/bin/server/jvm.dll b/test/jdk/mocks/mock-jdk-&ersand/bin/server/jvm.dll new file mode 100644 index 00000000..3dea9b24 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-&ersand/bin/server/jvm.dll differ diff --git a/test/jdk/mocks/mock-jdk-&ersand/lib/server/libjvm.dylib b/test/jdk/mocks/mock-jdk-&ersand/lib/server/libjvm.dylib new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-&ersand/lib/server/libjvm.so b/test/jdk/mocks/mock-jdk-&ersand/lib/server/libjvm.so new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/jarsigner b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/jarsigner new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/jarsigner.exe b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/jarsigner.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/jarsigner.exe differ diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java new file mode 100644 index 00000000..297dc2f7 --- /dev/null +++ b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java @@ -0,0 +1,4 @@ +#!/bin/sh +>&2 echo "java version \"9\"" +>&2 echo "Java(TM) SE Runtime Environment (build 9+181)" +>&2 echo "Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)" diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java.exe b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/java.exe differ diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac new file mode 100755 index 00000000..95b23273 --- /dev/null +++ b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac @@ -0,0 +1,26 @@ +#!/bin/bash + +out="${MOCK_STDOUT}" +err="${MOCK_STDERR}" +exitCode="${MOCK_EXITCODE}" + +code=0 +if [ -n "$exitCode" ]; then + # Validate that exitCode is a valid integer + if [ "$exitCode" -eq "$exitCode" ] 2>/dev/null && [ "$exitCode" -ge -2147483648 ] && [ "$exitCode" -le 2147483647 ]; then + code=$exitCode + fi +fi + +if [ -n "$out" ]; then + echo "$out" +fi +if [ -n "$err" ]; then + echo "$err" +fi +if [ -z "$out" ] && [ -z "$err" ]; then + echo "This is a mock executable" + echo "Set MOCK_STDOUT, MOCK_STDERR, and MOCK_EXITCODE to simulate executables" +fi + +exit $code diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac.exe b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/javac.exe differ diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/keytool b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/keytool new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/keytool.exe b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/keytool.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/keytool.exe differ diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/server/jvm.dll b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/server/jvm.dll new file mode 100644 index 00000000..3dea9b24 Binary files /dev/null and b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/bin/server/jvm.dll differ diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/lib/server/libjvm.dylib b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/lib/server/libjvm.dylib new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk-darwin/Contents/Home/lib/server/libjvm.so b/test/jdk/mocks/mock-jdk-darwin/Contents/Home/lib/server/libjvm.so new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk/bin/jarsigner b/test/jdk/mocks/mock-jdk/bin/jarsigner new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk/bin/jarsigner.exe b/test/jdk/mocks/mock-jdk/bin/jarsigner.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk/bin/jarsigner.exe differ diff --git a/test/jdk/mocks/mock-jdk/bin/java b/test/jdk/mocks/mock-jdk/bin/java new file mode 100644 index 00000000..297dc2f7 --- /dev/null +++ b/test/jdk/mocks/mock-jdk/bin/java @@ -0,0 +1,4 @@ +#!/bin/sh +>&2 echo "java version \"9\"" +>&2 echo "Java(TM) SE Runtime Environment (build 9+181)" +>&2 echo "Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)" diff --git a/test/jdk/mocks/mock-jdk/bin/java.exe b/test/jdk/mocks/mock-jdk/bin/java.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk/bin/java.exe differ diff --git a/test/jdk/mocks/mock-jdk/bin/javac b/test/jdk/mocks/mock-jdk/bin/javac new file mode 100755 index 00000000..95b23273 --- /dev/null +++ b/test/jdk/mocks/mock-jdk/bin/javac @@ -0,0 +1,26 @@ +#!/bin/bash + +out="${MOCK_STDOUT}" +err="${MOCK_STDERR}" +exitCode="${MOCK_EXITCODE}" + +code=0 +if [ -n "$exitCode" ]; then + # Validate that exitCode is a valid integer + if [ "$exitCode" -eq "$exitCode" ] 2>/dev/null && [ "$exitCode" -ge -2147483648 ] && [ "$exitCode" -le 2147483647 ]; then + code=$exitCode + fi +fi + +if [ -n "$out" ]; then + echo "$out" +fi +if [ -n "$err" ]; then + echo "$err" +fi +if [ -z "$out" ] && [ -z "$err" ]; then + echo "This is a mock executable" + echo "Set MOCK_STDOUT, MOCK_STDERR, and MOCK_EXITCODE to simulate executables" +fi + +exit $code diff --git a/test/jdk/mocks/mock-jdk/bin/javac.exe b/test/jdk/mocks/mock-jdk/bin/javac.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk/bin/javac.exe differ diff --git a/test/jdk/mocks/mock-jdk/bin/keytool b/test/jdk/mocks/mock-jdk/bin/keytool new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk/bin/keytool.exe b/test/jdk/mocks/mock-jdk/bin/keytool.exe new file mode 100644 index 00000000..720af670 Binary files /dev/null and b/test/jdk/mocks/mock-jdk/bin/keytool.exe differ diff --git a/test/jdk/mocks/mock-jdk/bin/server/jvm.dll b/test/jdk/mocks/mock-jdk/bin/server/jvm.dll new file mode 100644 index 00000000..3dea9b24 Binary files /dev/null and b/test/jdk/mocks/mock-jdk/bin/server/jvm.dll differ diff --git a/test/jdk/mocks/mock-jdk/lib/server/libjvm.dylib b/test/jdk/mocks/mock-jdk/lib/server/libjvm.dylib new file mode 100644 index 00000000..e69de29b diff --git a/test/jdk/mocks/mock-jdk/lib/server/libjvm.so b/test/jdk/mocks/mock-jdk/lib/server/libjvm.so new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/get-titanium-branch-builds.test.ts b/test/titanium/get-titanium-branch-builds.test.ts new file mode 100644 index 00000000..696b6c74 --- /dev/null +++ b/test/titanium/get-titanium-branch-builds.test.ts @@ -0,0 +1,52 @@ +import { getTitaniumBranchBuilds } from '../../src/titanium/index.js'; +import { describe, expect, it } from 'vitest'; + +describe('getTitaniumBranchBuilds()', () => { + it('should return the list of builds for Linux', async () => { + const builds = await getTitaniumBranchBuilds('13_1_X', 'linux'); + expect(builds).toBeDefined(); + const build = builds[0]; + expect(build.name).toMatch(/^13\.1./); + expect(build.version).toMatch(/^13\.1./); + expect(build.date).toBeDefined(); + expect(build.expires).toBeDefined(); + expect(build.url.startsWith('https://github.com/tidev/titanium-sdk/actions/runs/')).toBe(true); + expect(build.assets).toBeDefined(); + expect(build.assets.length).toBeGreaterThan(0); + expect(build.assets.map((asset) => asset.os).sort()).toEqual(['linux', 'osx', 'win32']); + expect(build.assets.every((asset) => asset.url !== undefined)).toBe(true); + expect(build.assets.every((asset) => asset.size > 0)).toBe(true); + }); + + it('should return the list of builds for macOS', async () => { + const builds = await getTitaniumBranchBuilds('13_1_X', 'osx'); + expect(builds).toBeDefined(); + const build = builds[0]; + expect(build.name).toMatch(/^13\.1./); + expect(build.version).toMatch(/^13\.1./); + expect(build.date).toBeDefined(); + expect(build.expires).toBeDefined(); + expect(build.url.startsWith('https://github.com/tidev/titanium-sdk/actions/runs/')).toBe(true); + expect(build.assets).toBeDefined(); + expect(build.assets.length).toBeGreaterThan(0); + expect(build.assets.map((asset) => asset.os).sort()).toEqual(['linux', 'osx', 'win32']); + expect(build.assets.every((asset) => asset.url !== undefined)).toBe(true); + expect(build.assets.every((asset) => asset.size > 0)).toBe(true); + }); + + it('should return the list of builds for Windows', async () => { + const builds = await getTitaniumBranchBuilds('13_1_X', 'win32'); + expect(builds).toBeDefined(); + const build = builds[0]; + expect(build.name).toMatch(/^13\.1./); + expect(build.version).toMatch(/^13\.1./); + expect(build.date).toBeDefined(); + expect(build.expires).toBeDefined(); + expect(build.url.startsWith('https://github.com/tidev/titanium-sdk/actions/runs/')).toBe(true); + expect(build.assets).toBeDefined(); + expect(build.assets.length).toBeGreaterThan(0); + expect(build.assets.map((asset) => asset.os).sort()).toEqual(['linux', 'osx', 'win32']); + expect(build.assets.every((asset) => asset.url !== undefined)).toBe(true); + expect(build.assets.every((asset) => asset.size > 0)).toBe(true); + }); +}); diff --git a/test/titanium/get-titanium-branches.test.ts b/test/titanium/get-titanium-branches.test.ts new file mode 100644 index 00000000..4877942f --- /dev/null +++ b/test/titanium/get-titanium-branches.test.ts @@ -0,0 +1,11 @@ +import { getTitaniumBranches } from '../../src/titanium/index.js'; +import { describe, expect, it } from 'vitest'; + +describe('getTitaniumBranches()', () => { + it('should return the list of branches', async () => { + const branches = await getTitaniumBranches(); + expect(branches).toBeDefined(); + expect(branches.includes('main')).toBe(true); + expect(branches.includes('13_1_X')).toBe(true); + }); +}); diff --git a/test/titanium/get-titanium-releases.test.ts b/test/titanium/get-titanium-releases.test.ts new file mode 100644 index 00000000..4baa8796 --- /dev/null +++ b/test/titanium/get-titanium-releases.test.ts @@ -0,0 +1,46 @@ +import { getTitaniumReleases } from '../../src/titanium/index.js'; +import { describe, expect, it } from 'vitest'; + +describe('getTitaniumReleases()', () => { + it('should return the list of releases', async () => { + const releases = await getTitaniumReleases(); + expect(releases).toBeDefined(); + const release = releases.find((release) => release.name === '13.1.1.GA'); + expect(release).toEqual({ + name: '13.1.1.GA', + version: '13.1.1', + date: '2026-01-29T13:36:18Z', + url: 'https://github.com/tidev/titanium-sdk/releases/tag/13_1_1_GA', + assets: [ + { + os: 'linux', + size: 100889320, + url: 'https://github.com/tidev/titanium-sdk/releases/download/13_1_1_GA/mobilesdk-13.1.1.GA-linux.zip', + }, + { + os: 'osx', + size: 170457154, + url: 'https://github.com/tidev/titanium-sdk/releases/download/13_1_1_GA/mobilesdk-13.1.1.GA-osx.zip', + }, + { + os: 'win32', + size: 100889320, + url: 'https://github.com/tidev/titanium-sdk/releases/download/13_1_1_GA/mobilesdk-13.1.1.GA-win32.zip', + }, + ], + type: 'ga', + }); + }); + + it('should return the list of releases including unstable builds', async () => { + const releases = await getTitaniumReleases(true); + expect(releases).toBeDefined(); + const unstableReleases = releases.filter((release) => release.type !== 'ga'); + for (const unstableRelease of unstableReleases) { + expect(unstableRelease.type).toBeOneOf(['beta', 'rc', 'nightly']); + expect(unstableRelease.assets.some((asset) => asset.os === 'linux')).toBe(true); + expect(unstableRelease.assets.some((asset) => asset.os === 'osx')).toBe(true); + expect(unstableRelease.assets.some((asset) => asset.os === 'win32')).toBe(true); + } + }); +}); diff --git a/test/titanium/i18n/i18n.test.ts b/test/titanium/i18n/i18n.test.ts new file mode 100644 index 00000000..115a052e --- /dev/null +++ b/test/titanium/i18n/i18n.test.ts @@ -0,0 +1,72 @@ +import { i18n } from '../../../src/titanium/index.js'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('i18n', () => { + describe('load()', () => { + it('should load the i18n data', async () => { + const result = await i18n.load(join(__dirname, 'mocks', 'good')); + expect(result).toEqual({ + en: { + strings: { + whatever: 'value', + }, + }, + es: { + app: { + whatever: 'my spanish value', + }, + }, + }); + }); + + it('should return no data if the directory does not exist', async () => { + const result = await i18n.load(join(__dirname, 'mocks', 'does-not-exist')); + expect(result).toEqual({}); + }); + + it('should return no data if directory is empty', async () => { + let result = await i18n.load(join(__dirname, 'mocks', 'empty')); + expect(result).toEqual({}); + + result = await i18n.load(join(__dirname, 'mocks', 'empty2')); + expect(result).toEqual({}); + }); + }); + + describe('findLaunchScreens()', () => { + it('should find the launch screens', async () => { + const result = await i18n.findLaunchScreens(join(__dirname, 'mocks', 'good'), { + bypassCache: true, + }); + expect(result).toEqual([ + join(__dirname, 'mocks', 'good', 'i18n', 'en', 'Default-568h@2x.png'), + ]); + + const result2 = await i18n.findLaunchScreens(join(__dirname, 'mocks', 'good')); + expect(result2).toBe(result); + }); + + it('should return no launch screens if the directory does not exist', async () => { + const result = await i18n.findLaunchScreens(join(__dirname, 'mocks', 'does-not-exist'), { + bypassCache: true, + }); + expect(result).toEqual([]); + }); + + it('should return no launch screens if the directory is empty', async () => { + let result = await i18n.findLaunchScreens(join(__dirname, 'mocks', 'empty'), { + bypassCache: true, + }); + expect(result).toEqual([]); + + result = await i18n.findLaunchScreens(join(__dirname, 'mocks', 'empty2'), { + bypassCache: true, + }); + expect(result).toEqual([]); + }); + }); +}); diff --git a/test/titanium/i18n/mocks/empty/.gitkeep b/test/titanium/i18n/mocks/empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/i18n/mocks/empty2/i18n/.gitkeep b/test/titanium/i18n/mocks/empty2/i18n/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/tests/i18n/en/Default-568h@2x.png b/test/titanium/i18n/mocks/good/i18n/en/Default-568h@2x.png similarity index 100% rename from tests/i18n/en/Default-568h@2x.png rename to test/titanium/i18n/mocks/good/i18n/en/Default-568h@2x.png diff --git a/test/titanium/i18n/mocks/good/i18n/en/en.xml b/test/titanium/i18n/mocks/good/i18n/en/en.xml new file mode 100644 index 00000000..f19244c1 --- /dev/null +++ b/test/titanium/i18n/mocks/good/i18n/en/en.xml @@ -0,0 +1,3 @@ + + value + diff --git a/test/titanium/i18n/mocks/good/i18n/es/app.xml b/test/titanium/i18n/mocks/good/i18n/es/app.xml new file mode 100644 index 00000000..1a8ed566 --- /dev/null +++ b/test/titanium/i18n/mocks/good/i18n/es/app.xml @@ -0,0 +1,3 @@ + + my spanish value + diff --git a/test/titanium/modules/mocks/android-only/modules/android/ti.map/3.1.0/manifest b/test/titanium/modules/mocks/android-only/modules/android/ti.map/3.1.0/manifest new file mode 100644 index 00000000..acf6635d --- /dev/null +++ b/test/titanium/modules/mocks/android-only/modules/android/ti.map/3.1.0/manifest @@ -0,0 +1,18 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 3.1.0 +apiversion: 2 +architectures: arm64-v8a armeabi-v7a x86 +description: External version of Map module +author: Tester +license: Apache Public License v2 +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +name: map +moduleid: ti.map +guid: fee93b77-8eb3-418c-8f04-013664c4af83 +platform: android +minsdk: 6.2.2.GA diff --git a/test/titanium/modules/mocks/commonjs-ios/modules/commonjs/ambiguous/1.0/manifest b/test/titanium/modules/mocks/commonjs-ios/modules/commonjs/ambiguous/1.0/manifest new file mode 100644 index 00000000..21a58ec3 --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-ios/modules/commonjs/ambiguous/1.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is an ambiguous module that will conflict with a native module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: ambiguous +moduleid: ti.ambiguous +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: commonjs +minsdk: 3.0 diff --git a/test/titanium/modules/mocks/commonjs-ios/modules/ios/ambiguous/1.0/manifest b/test/titanium/modules/mocks/commonjs-ios/modules/ios/ambiguous/1.0/manifest new file mode 100644 index 00000000..fad6ecfb --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-ios/modules/ios/ambiguous/1.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is an ambiguous module that will conflict with a commonjs module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: ambiguous +moduleid: ti.ambiguous +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: iphone +minsdk: 3.0 diff --git a/test/titanium/modules/mocks/commonjs-ios/modules/ios/baz/2.0.1/manifest b/test/titanium/modules/mocks/commonjs-ios/modules/ios/baz/2.0.1/manifest new file mode 100644 index 00000000..c847930b --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-ios/modules/ios/baz/2.0.1/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is an ambiguous module that will conflict with a commonjs module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: baz +moduleid: baz +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: iphone +minsdk: 3.0 diff --git a/test/titanium/modules/mocks/commonjs-ios/modules/ios/toonew/1.0/manifest b/test/titanium/modules/mocks/commonjs-ios/modules/ios/toonew/1.0/manifest new file mode 100644 index 00000000..4e2b5912 --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-ios/modules/ios/toonew/1.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is a dummy module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: toonew +moduleid: ti.toonew +guid: 8d99922e-7727-4f64-90b9-325992eddb1b +platform: iphone +minsdk: 999.0 diff --git a/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.0/manifest b/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.0/manifest new file mode 100644 index 00000000..a21d2c1a --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is an ambiguous module that will conflict with a native module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: latestvalid +moduleid: ti.latestvalid +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: commonjs +minsdk: 3.0 diff --git a/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.1/manifest b/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.1/manifest new file mode 100644 index 00000000..c550b9f3 --- /dev/null +++ b/test/titanium/modules/mocks/commonjs-only/modules/commonjs/latestvalid/1.1/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.1 +description: This is an ambiguous module that will conflict with a native module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: latestvalid +moduleid: ti.latestvalid +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: commonjs +minsdk: 3.6 diff --git a/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/android/manifest b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/android/manifest new file mode 100644 index 00000000..e29fbdd4 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/android/manifest @@ -0,0 +1,13 @@ +version: 1.2.3 +apiversion: 6 +architectures: armeabi-v7a x86 +description: Cross Platform Native Module with Manifest +author: Tester +license: Apache +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +guid: ccb89061-0fdb-4ff1-95a8-02876f5601f9 +moduleid: cross-platform-with-manifest-android +platform: android +minsdk: 4.0.0 diff --git a/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/ios/manifest b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/ios/manifest new file mode 100644 index 00000000..db2cbf89 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/ios/manifest @@ -0,0 +1,13 @@ +version: 1.2.3 +apiversion: 1 +architectures: armv7 i386 +description: Cross Platform Native Module with Manifest +author: Tester +license: Apache +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +guid: ccb89061-0fdb-4ff1-95a8-02876f5601f9 +moduleid: cross-platform-with-manifest-ios +platform: iphone +minsdk: 3.0.0 diff --git a/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/package.json b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/package.json new file mode 100644 index 00000000..1c768679 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-specific-package-json/node_modules/cross-platform/package.json @@ -0,0 +1,27 @@ +{ + "name": "@seadub/cross-platform-npm-package", + "version": "2.0.1", + "description": "Pretend Cross Platform Native Module for Titanium SDK", + "author": "Tester", + "license": "Apache", + "copyright": "Copyright (c) 2026 by Your Company", + "titanium": { + "type": "native-module", + "guid": "bba89061-0fdb-4ff1-95a8-02876f5601f9", + "moduleid": "cross-platform", + "platform": { + "ios": { + "version": "4.3.1", + "apiversion": 2, + "architectures": [ "armv7", "arm64", "i386", "x86_64" ], + "minsdk": "5.0.0" + }, + "android": { + "version": "6.0.1", + "architectures": [ "arm64-v8a", "armeabi-v7a", "x86" ], + "minsdk": "7.0.0", + "apiversion": 4 + } + } + } +} diff --git a/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/android/manifest b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/android/manifest new file mode 100644 index 00000000..d6bd7789 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/android/manifest @@ -0,0 +1,13 @@ +version: 1.2.3 +apiversion: 6 +architectures: armeabi-v7a x86 +description: Cross Platform Native Module with Manifest +author: Tester +license: Apache +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +guid: ccb89061-0fdb-4ff1-95a8-02876f5601f9 +moduleid: cross-platform-with-manifest +platform: android +minsdk: 4.0.0 diff --git a/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/ios/manifest b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/ios/manifest new file mode 100644 index 00000000..4a648ed9 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/ios/manifest @@ -0,0 +1,14 @@ +version: 1.2.3 +apiversion: 1 +architectures: armv7 i386 +description: Cross Platform Native Module with Manifest +author: Tester +license: Apache +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +guid: ccb89061-0fdb-4ff1-95a8-02876f5601f9 +name: Cross Platform Native Module +moduleid: cross-platform-with-manifest +platform: iphone +minsdk: 3.0.0 diff --git a/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/package.json b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/package.json new file mode 100644 index 00000000..3eb29981 --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module-with-manifest/node_modules/cross-platform/package.json @@ -0,0 +1,12 @@ +{ + "name": "@titianimsdk/cross-platform", + "version": "2.0.1", + "description": "Pretend Cross Platform Native Module for Titanium SDK", + "author": "Tester", + "license": "Apache", + "copyright": "Copyright (c) 2026 by Your Company", + "titanium": { + "type": "native-module", + "platform": [ "ios", "android" ] + } +} diff --git a/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/android/.gitkeep b/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/android/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/ios/.gitkeep b/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/ios/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/package.json b/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/package.json new file mode 100644 index 00000000..5bbbde9f --- /dev/null +++ b/test/titanium/modules/mocks/cross-platform-native-module/node_modules/cross-platform/package.json @@ -0,0 +1,26 @@ +{ + "name": "@titianimsdk/cross-platform", + "version": "2.0.1", + "description": "Pretend Cross Platform Native Module for Titanium SDK", + "author": "Tester", + "license": "Apache", + "copyright": "Copyright (c) 2026 by Your Company", + "titanium": { + "type": "native-module", + "guid": "bba89061-0fdb-4ff1-95a8-02876f5601f9", + "name": "Cross Platform Native Module", + "moduleid": "cross-platform", + "platform": { + "ios": { + "apiversion": 2, + "architectures": [ "armv7", "arm64", "i386", "x86_64" ], + "minsdk": "5.0.0" + }, + "android": { + "architectures": [ "arm64-v8a", "armeabi-v7a", "x86" ], + "minsdk": "7.0.0", + "apiversion": 4 + } + } + } +} diff --git a/test/titanium/modules/mocks/empty/.gitkeep b/test/titanium/modules/mocks/empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/modules/mocks/good/modules/android/test-module/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/android/test-module/1.0.0/manifest new file mode 100644 index 00000000..468a3954 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/android/test-module/1.0.0/manifest @@ -0,0 +1,18 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +apiversion: 4 +architectures: arm64-v8a armeabi-v7a x86 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: android +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/commonjs/invalid-platform/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/commonjs/invalid-platform/1.0.0/manifest new file mode 100644 index 00000000..e302b418 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/commonjs/invalid-platform/1.0.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.0/manifest new file mode 100644 index 00000000..cdda1f36 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: foo +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: commonjs +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.1/manifest b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.1/manifest new file mode 100644 index 00000000..77efc2bc --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.1/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: commonjs +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.2/manifest b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.2/manifest new file mode 100644 index 00000000..77597586 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/commonjs/invalid-version/1.0.2/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: NaN +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: commonjs +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/commonjs/test-module/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/commonjs/test-module/1.0.0/manifest new file mode 100644 index 00000000..94abfcdd --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/commonjs/test-module/1.0.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: commonjs +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/ios/test-module/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/ios/test-module/1.0.0/manifest new file mode 100644 index 00000000..3d93f694 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/ios/test-module/1.0.0/manifest @@ -0,0 +1,18 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +apiversion: 2 +architectures: armv7 arm64 i386 x86_64 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: ios +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/good/modules/iphone/test-module/1.0.0/manifest b/test/titanium/modules/mocks/good/modules/iphone/test-module/1.0.0/manifest new file mode 100644 index 00000000..cbed62a4 --- /dev/null +++ b/test/titanium/modules/mocks/good/modules/iphone/test-module/1.0.0/manifest @@ -0,0 +1,18 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +apiversion: 2 +architectures: armv7 arm64 i386 x86_64 +description: testModule +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: testModule +moduleid: com.test.module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: iphone +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/install-modules/android-only.zip b/test/titanium/modules/mocks/install-modules/android-only.zip new file mode 100644 index 00000000..244c058d Binary files /dev/null and b/test/titanium/modules/mocks/install-modules/android-only.zip differ diff --git a/test/titanium/modules/mocks/install-modules/badzip-ios-1.0.0.zip b/test/titanium/modules/mocks/install-modules/badzip-ios-1.0.0.zip new file mode 100644 index 00000000..b0ca6162 --- /dev/null +++ b/test/titanium/modules/mocks/install-modules/badzip-ios-1.0.0.zip @@ -0,0 +1 @@ +Not a zip file diff --git a/test/titanium/modules/mocks/install-modules/dummy-ios-1.2.3.zip b/test/titanium/modules/mocks/install-modules/dummy-ios-1.2.3.zip new file mode 100644 index 00000000..c6ac7f28 Binary files /dev/null and b/test/titanium/modules/mocks/install-modules/dummy-ios-1.2.3.zip differ diff --git a/test/titanium/modules/mocks/install-modules/ios-only.zip b/test/titanium/modules/mocks/install-modules/ios-only.zip new file mode 100644 index 00000000..5db7ed7a Binary files /dev/null and b/test/titanium/modules/mocks/install-modules/ios-only.zip differ diff --git a/test/titanium/modules/mocks/ios-only/modules/ios/baz/2.0.1/manifest b/test/titanium/modules/mocks/ios-only/modules/ios/baz/2.0.1/manifest new file mode 100644 index 00000000..fad6ecfb --- /dev/null +++ b/test/titanium/modules/mocks/ios-only/modules/ios/baz/2.0.1/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0 +description: This is an ambiguous module that will conflict with a commonjs module +author: Tester +license: Apache Public License +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: ambiguous +moduleid: ti.ambiguous +guid: 8d99922e-7727-4f64-90b9-325992eddb1c +platform: iphone +minsdk: 3.0 diff --git a/test/titanium/modules/mocks/iphone-only/modules/iphone/ti.map/3.1.0/manifest b/test/titanium/modules/mocks/iphone-only/modules/iphone/ti.map/3.1.0/manifest new file mode 100644 index 00000000..9331e78a --- /dev/null +++ b/test/titanium/modules/mocks/iphone-only/modules/iphone/ti.map/3.1.0/manifest @@ -0,0 +1,18 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 3.1.0 +apiversion: 2 +architectures: armv7 arm64 i386 x86_64 +description: External version of Map module +author: Tester +license: Apache Public License v2 +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: map +moduleid: ti.map +guid: fee93b77-8eb3-418c-8f04-013664c4af83 +platform: iphone +minsdk: 6.2.2.GA diff --git a/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/manifest b/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/manifest new file mode 100644 index 00000000..2018e610 --- /dev/null +++ b/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/manifest @@ -0,0 +1,14 @@ +version: 4.0.2 +apiversion: 2 +architectures: armv7 arm64 i386 x86_64 +description: hyperloop +author: Tester +license: Apache +copyright: Copyright (c) 2026 by Your Company + +# these should not be edited +guid: bba89061-0fdb-4ff1-95a8-02876f5601f9 +name: Native Module w/ Manifest +moduleid: native-module-with-manifest +platform: iphone +minsdk: 5.0.0 diff --git a/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/package.json b/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/package.json new file mode 100644 index 00000000..ff587087 --- /dev/null +++ b/test/titanium/modules/mocks/native-module-with-manifest/node_modules/native-module-with-manifest/package.json @@ -0,0 +1,12 @@ +{ + "name": "@seadub/native-module-with-manifest", + "version": "2.0.1", + "description": "Pretend Native Module with manifest file for Titanium SDK", + "author": "Tester", + "license": "Apache", + "copyright": "Copyright (c) 2026 by Your Company", + "titanium": { + "type": "native-module", + "platform": "ios" + } +} diff --git a/test/titanium/modules/mocks/native-module-with-platform-subdir/node_modules/native-module/ios/.gitkeep b/test/titanium/modules/mocks/native-module-with-platform-subdir/node_modules/native-module/ios/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/modules/mocks/native-module-with-platform-subdir/node_modules/native-module/package.json b/test/titanium/modules/mocks/native-module-with-platform-subdir/node_modules/native-module/package.json new file mode 100644 index 00000000..37e263a7 --- /dev/null +++ b/test/titanium/modules/mocks/native-module-with-platform-subdir/node_modules/native-module/package.json @@ -0,0 +1,21 @@ +{ + "name": "@seadub/native-module", + "version": "2.0.1", + "description": "Pretend Native Module for Titanium SDK", + "author": "Tester", + "license": "Apache", + "copyright": "Copyright (c) 2026 by Your Company", + "titanium": { + "type": "native-module", + "guid": "bba89061-0fdb-4ff1-95a8-02876f5601f9", + "name": "Native Module", + "moduleid": "native-module", + "platform": { + "ios": { + "apiversion": 2, + "architectures": [ "armv7", "arm64", "i386", "x86_64" ], + "minsdk": "5.0.0" + } + } + } +} diff --git a/test/titanium/modules/mocks/npm-native-module/node_modules/fake-module/package.json b/test/titanium/modules/mocks/npm-native-module/node_modules/fake-module/package.json new file mode 100644 index 00000000..e059a848 --- /dev/null +++ b/test/titanium/modules/mocks/npm-native-module/node_modules/fake-module/package.json @@ -0,0 +1,8 @@ +{ + "name": "@seadub/fake-module", + "version": "2.0.1", + "description": "Run of the mill node module", + "author": "Chris Williams", + "license": "Apache", + "copyright": "Copyright (c) 2015 by Appcelerator Inc." +} diff --git a/test/titanium/modules/mocks/npm-native-module/node_modules/native-module/package.json b/test/titanium/modules/mocks/npm-native-module/node_modules/native-module/package.json new file mode 100644 index 00000000..7aa3b152 --- /dev/null +++ b/test/titanium/modules/mocks/npm-native-module/node_modules/native-module/package.json @@ -0,0 +1,21 @@ +{ + "name": "@seadub/native-module", + "version": "2.0.1", + "description": "Pretend Native Module for Titanium SDK", + "author": "Chris Williams", + "license": "Apache", + "copyright": "Copyright (c) 2015 by Appcelerator Inc.", + "titanium": { + "type": "native-module", + "guid": "bba89061-0fdb-4ff1-95a8-02876f5601f9", + "name": "Native Module", + "moduleid": "native-module", + "platform": { + "ios": { + "apiversion": 2, + "architectures": [ "armv7", "arm64", "i386", "x86_64" ], + "minsdk": "5.0.0" + } + } + } +} diff --git a/test/titanium/modules/mocks/npm-native-module/node_modules/no-package-json/.gitkeep b/test/titanium/modules/mocks/npm-native-module/node_modules/no-package-json/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/modules/mocks/search-test/modules/android/ti.map/5.7.0/manifest b/test/titanium/modules/mocks/search-test/modules/android/ti.map/5.7.0/manifest new file mode 100644 index 00000000..e4ab9265 --- /dev/null +++ b/test/titanium/modules/mocks/search-test/modules/android/ti.map/5.7.0/manifest @@ -0,0 +1,19 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 5.7.0 +apiversion: 4 +architectures: arm64-v8a armeabi-v7a x86 x86_64 +description: External version of Map module using native Google Maps library +author: Your Name +license: Apache Public License v2 +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: map +moduleid: ti.map +guid: f0d8fd44-86d2-4730-b67d-bd454577aeee +platform: android +minsdk: 12.7.0 +respackage: com.google.android.gms diff --git a/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/1.0.0/manifest b/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/1.0.0/manifest new file mode 100644 index 00000000..17668d7e --- /dev/null +++ b/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/1.0.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 1.0.0 +description: CommonJS Module +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: CJS Module +moduleid: cjs-module +guid: dcaea77e-2860-42c1-a57b-319f81da10e0 +platform: commonjs +minsdk: 7.2.0 diff --git a/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/2.0.0/manifest b/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/2.0.0/manifest new file mode 100644 index 00000000..db3e3819 --- /dev/null +++ b/test/titanium/modules/mocks/search-test/modules/commonjs/cjs-module/2.0.0/manifest @@ -0,0 +1,16 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# +version: 2.0.0 +description: CommonJS Module +author: Your Name +license: Specify your license +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: CJS Module +moduleid: cjs-module +guid: dcaea77e-2860-42c1-a57b-319f81da10e1 +platform: commonjs +minsdk: 10.0.0 diff --git a/test/titanium/modules/mocks/search-test/modules/iphone/ti.map/7.3.1/manifest b/test/titanium/modules/mocks/search-test/modules/iphone/ti.map/7.3.1/manifest new file mode 100644 index 00000000..d409e3ea --- /dev/null +++ b/test/titanium/modules/mocks/search-test/modules/iphone/ti.map/7.3.1/manifest @@ -0,0 +1,20 @@ +# +# this is your module manifest and used by Titanium +# during compilation, packaging, distribution, etc. +# + +version: 7.3.1 +apiversion: 2 +architectures: arm64 x86_64 +description: External version of Map module +author: Your name +license: Apache Public License v2 +copyright: Copyright (c) 2022 by Your Company + +# these should not be edited +name: map +mac: true +moduleid: ti.map +guid: f0d8fd44-86d2-4730-b67d-bd454577aeee +platform: iphone +minsdk: 10.0.0 diff --git a/test/titanium/modules/search-modules.ts b/test/titanium/modules/search-modules.ts new file mode 100644 index 00000000..00d3d7f5 --- /dev/null +++ b/test/titanium/modules/search-modules.ts @@ -0,0 +1,132 @@ +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +export const TestModuleAndroid = { + apiversion: 4, + architectures: ['arm64-v8a', 'armeabi-v7a', 'x86'], + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'testModule', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e0', + license: 'Specify your license', + minsdk: '7.2.0', + moduleid: 'com.test.module', + name: 'testModule', + path: join(__dirname, 'mocks', 'good', 'modules', 'android', 'test-module', '1.0.0'), + platform: 'android', + version: '1.0.0', +}; + +export const TestModuleCommonjs = { + apiversion: undefined, + architectures: undefined, + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'testModule', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e0', + license: 'Specify your license', + minsdk: '7.2.0', + moduleid: 'com.test.module', + name: 'testModule', + path: join(__dirname, 'mocks', 'good', 'modules', 'commonjs', 'test-module', '1.0.0'), + platform: 'commonjs', + version: '1.0.0', +}; + +export const TestModuleCommonjs10 = { + apiversion: undefined, + architectures: undefined, + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'testModule', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e0', + license: 'Specify your license', + minsdk: '7.2.0', + moduleid: 'com.test.module', + name: 'testModule', + path: join(__dirname, 'mocks', 'good', 'modules', 'commonjs', 'invalid-version', '1.0.1'), + platform: 'commonjs', + version: '1.0', +}; + +export const TestModuleIos = { + apiversion: 2, + architectures: ['armv7', 'arm64', 'i386', 'x86_64'], + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'testModule', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e0', + license: 'Specify your license', + minsdk: '7.2.0', + moduleid: 'com.test.module', + name: 'testModule', + path: join(__dirname, 'mocks', 'good', 'modules', 'iphone', 'test-module', '1.0.0'), + platform: 'ios', + version: '1.0.0', +}; + +export const CJSModule1 = { + apiversion: undefined, + architectures: undefined, + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'CommonJS Module', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e0', + license: 'Specify your license', + minsdk: '7.2.0', + moduleid: 'cjs-module', + name: 'CJS Module', + path: join(__dirname, 'mocks', 'search-test', 'modules', 'commonjs', 'cjs-module', '1.0.0'), + platform: 'commonjs', + version: '1.0.0', +}; + +export const CJSModule2 = { + apiversion: undefined, + architectures: undefined, + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'CommonJS Module', + guid: 'dcaea77e-2860-42c1-a57b-319f81da10e1', + license: 'Specify your license', + minsdk: '10.0.0', + moduleid: 'cjs-module', + name: 'CJS Module', + path: join(__dirname, 'mocks', 'search-test', 'modules', 'commonjs', 'cjs-module', '2.0.0'), + platform: 'commonjs', + version: '2.0.0', +}; + +export const TiMapAndroid = { + apiversion: 4, + architectures: ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'], + author: 'Your Name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'External version of Map module using native Google Maps library', + guid: 'f0d8fd44-86d2-4730-b67d-bd454577aeee', + license: 'Apache Public License v2', + minsdk: '12.7.0', + moduleid: 'ti.map', + name: 'map', + path: join(__dirname, 'mocks', 'search-test', 'modules', 'android', 'ti.map', '5.7.0'), + platform: 'android', + version: '5.7.0', +}; + +export const TiMapIos = { + apiversion: 2, + architectures: ['arm64', 'x86_64'], + author: 'Your name', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'External version of Map module', + guid: 'f0d8fd44-86d2-4730-b67d-bd454577aeee', + license: 'Apache Public License v2', + minsdk: '10.0.0', + moduleid: 'ti.map', + name: 'map', + path: join(__dirname, 'mocks', 'search-test', 'modules', 'iphone', 'ti.map', '7.3.1'), + platform: 'ios', + version: '7.3.1', +}; diff --git a/test/titanium/modules/ti-modules.test.ts b/test/titanium/modules/ti-modules.test.ts new file mode 100644 index 00000000..54cd3172 --- /dev/null +++ b/test/titanium/modules/ti-modules.test.ts @@ -0,0 +1,1066 @@ +import { config, resetConfig } from '../../../src/config.js'; +import { detectTiModules, TiappXML, TiModuleRegistry } from '../../../src/titanium/index.js'; +import { + TestModuleAndroid, + TestModuleCommonjs, + TestModuleCommonjs10, + TestModuleIos, + CJSModule1, + CJSModule2, + TiMapAndroid, + TiMapIos, +} from './search-modules.js'; +import { randomBytes } from 'node:crypto'; +import { copyFile, mkdir, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('detectTitaniumModules', () => { + afterEach(() => resetConfig()); + + describe('detect', () => { + it('should detect Titanium modules', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'good'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'com.test.module': { + android: { + '1.0.0': TestModuleAndroid, + }, + commonjs: { + '1.0': TestModuleCommonjs10, + '1.0.0': TestModuleCommonjs, + }, + ios: { + '1.0.0': TestModuleIos, + }, + }, + }); + }); + + it('should detect modules with Android only', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'android-only'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.map': { + android: { + '3.1.0': { + apiversion: 2, + architectures: ['arm64-v8a', 'armeabi-v7a', 'x86'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'External version of Map module', + guid: 'fee93b77-8eb3-418c-8f04-013664c4af83', + license: 'Apache Public License v2', + minsdk: '6.2.2.GA', + moduleid: 'ti.map', + name: 'map', + path: join( + __dirname, + 'mocks', + 'android-only', + 'modules', + 'android', + 'ti.map', + '3.1.0' + ), + platform: 'android', + version: '3.1.0', + }, + }, + }, + }); + }); + + it('should detect modules with CommonJS and iOS', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'commonjs-ios'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.ambiguous': { + commonjs: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a native module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'ti.ambiguous', + name: 'ambiguous', + path: join( + __dirname, + 'mocks', + 'commonjs-ios', + 'modules', + 'commonjs', + 'ambiguous', + '1.0' + ), + platform: 'commonjs', + version: '1.0', + }, + }, + ios: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a commonjs module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'ti.ambiguous', + name: 'ambiguous', + path: join(__dirname, 'mocks', 'commonjs-ios', 'modules', 'ios', 'ambiguous', '1.0'), + platform: 'ios', + version: '1.0', + }, + }, + }, + baz: { + ios: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a commonjs module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'baz', + name: 'baz', + path: join(__dirname, 'mocks', 'commonjs-ios', 'modules', 'ios', 'baz', '2.0.1'), + platform: 'ios', + version: '1.0', + }, + }, + }, + 'ti.toonew': { + ios: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is a dummy module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1b', + license: 'Apache Public License', + minsdk: '999.0', + moduleid: 'ti.toonew', + name: 'toonew', + path: join(__dirname, 'mocks', 'commonjs-ios', 'modules', 'ios', 'toonew', '1.0'), + platform: 'ios', + version: '1.0', + }, + }, + }, + }); + }); + + it('should detect modules with CommonJS only', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'commonjs-only'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.latestvalid': { + commonjs: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a native module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'ti.latestvalid', + name: 'latestvalid', + path: join( + __dirname, + 'mocks', + 'commonjs-only', + 'modules', + 'commonjs', + 'latestvalid', + '1.0' + ), + platform: 'commonjs', + version: '1.0', + }, + '1.1': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a native module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.6', + moduleid: 'ti.latestvalid', + name: 'latestvalid', + path: join( + __dirname, + 'mocks', + 'commonjs-only', + 'modules', + 'commonjs', + 'latestvalid', + '1.1' + ), + platform: 'commonjs', + version: '1.1', + }, + }, + }, + }); + }); + + it('should detect modules with iOS only', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'ios-only'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.ambiguous': { + ios: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'This is an ambiguous module that will conflict with a commonjs module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'ti.ambiguous', + name: 'ambiguous', + path: join(__dirname, 'mocks', 'ios-only', 'modules', 'ios', 'baz', '2.0.1'), + platform: 'ios', + version: '1.0', + }, + }, + }, + }); + }); + + it('should detect modules with iPhone only', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'iphone-only'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.map': { + ios: { + '3.1.0': { + apiversion: 2, + architectures: ['armv7', 'arm64', 'i386', 'x86_64'], + author: 'Tester', + copyright: 'Copyright (c) 2022 by Your Company', + description: 'External version of Map module', + guid: 'fee93b77-8eb3-418c-8f04-013664c4af83', + license: 'Apache Public License v2', + minsdk: '6.2.2.GA', + moduleid: 'ti.map', + name: 'map', + path: join(__dirname, 'mocks', 'iphone-only', 'modules', 'iphone', 'ti.map', '3.1.0'), + platform: 'ios', + version: '3.1.0', + }, + }, + }, + }); + }); + + it('should detect nothing in empty directory', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'empty'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({}); + }); + + it('should detect nothing in non-existent directory', async () => { + config.titanium.sdk.installPath[process.platform] = join( + __dirname, + 'mocks', + 'does-not-exist' + ); + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({}); + }); + + it('should detect cross-platform Android and iOS in node_modules', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [join(__dirname, 'mocks', 'cross-platform-native-module')], + }); + expect(modules).toEqual({ + 'cross-platform': { + android: { + '2.0.1': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: undefined, + moduleid: 'cross-platform', + name: 'Cross Platform Native Module', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module', + 'node_modules', + 'cross-platform', + 'android' + ), + platform: 'android', + version: '2.0.1', + }, + }, + ios: { + '2.0.1': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: undefined, + moduleid: 'cross-platform', + name: 'Cross Platform Native Module', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module', + 'node_modules', + 'cross-platform', + 'ios' + ), + platform: 'ios', + version: '2.0.1', + }, + }, + }, + }); + }); + + it('should detect cross-platform Android and iOS in node_modules with specific package.json', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [ + join(__dirname, 'mocks', 'cross-platform-native-module-specific-package-json'), + ], + }); + expect(modules).toEqual({ + 'cross-platform': { + android: { + '2.0.1': { + apiversion: 6, + architectures: ['armeabi-v7a', 'x86'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: '4.0.0', + moduleid: 'cross-platform', + name: 'cross-platform-npm-package', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module-specific-package-json', + 'node_modules', + 'cross-platform', + 'android' + ), + platform: 'android', + version: '2.0.1', + }, + }, + ios: { + '2.0.1': { + apiversion: 1, + architectures: ['armv7', 'i386'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: '3.0.0', + moduleid: 'cross-platform', + name: 'cross-platform-npm-package', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module-specific-package-json', + 'node_modules', + 'cross-platform', + 'ios' + ), + platform: 'ios', + version: '2.0.1', + }, + }, + }, + }); + }); + + it('should detect cross-platform Android and iOS in node_modules with manifests', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [join(__dirname, 'mocks', 'cross-platform-native-module-with-manifest')], + }); + expect(modules).toEqual({ + 'cross-platform-with-manifest': { + android: { + '2.0.1': { + apiversion: 6, + architectures: ['armeabi-v7a', 'x86'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'ccb89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: '4.0.0', + moduleid: 'cross-platform-with-manifest', + name: 'cross-platform', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module-with-manifest', + 'node_modules', + 'cross-platform', + 'android' + ), + platform: 'android', + version: '2.0.1', + }, + }, + ios: { + '2.0.1': { + apiversion: 1, + architectures: ['armv7', 'i386'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Cross Platform Native Module for Titanium SDK', + guid: 'ccb89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: '3.0.0', + moduleid: 'cross-platform-with-manifest', + name: 'cross-platform', + path: join( + __dirname, + 'mocks', + 'cross-platform-native-module-with-manifest', + 'node_modules', + 'cross-platform', + 'ios' + ), + platform: 'ios', + version: '2.0.1', + }, + }, + }, + }); + }); + + it('should detect native module with manifest', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [join(__dirname, 'mocks', 'native-module-with-manifest')], + }); + expect(modules).toEqual({ + 'native-module-with-manifest': { + ios: { + '2.0.1': { + apiversion: 2, + architectures: ['armv7', 'arm64', 'i386', 'x86_64'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Native Module with manifest file for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: '5.0.0', + moduleid: 'native-module-with-manifest', + name: 'native-module-with-manifest', + path: join( + __dirname, + 'mocks', + 'native-module-with-manifest', + 'node_modules', + 'native-module-with-manifest' + ), + platform: 'ios', + version: '2.0.1', + }, + }, + }, + }); + }); + + it('should detect native module with platform subdirectories', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [join(__dirname, 'mocks', 'native-module-with-platform-subdir')], + }); + expect(modules).toEqual({ + 'native-module': { + ios: { + '2.0.1': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'Pretend Native Module for Titanium SDK', + guid: 'bba89061-0fdb-4ff1-95a8-02876f5601f9', + license: 'Apache', + minsdk: undefined, + moduleid: 'native-module', + name: 'Native Module', + path: join( + __dirname, + 'mocks', + 'native-module-with-platform-subdir', + 'node_modules', + 'native-module', + 'ios' + ), + platform: 'ios', + version: '2.0.1', + }, + }, + }, + }); + }); + + it('should detect npm native module', async () => { + config.titanium.sdk.installPath[process.platform] = undefined; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules({ + searchPaths: [join(__dirname, 'mocks', 'npm-native-module')], + }); + expect(modules).toEqual({}); + }); + + it('should install modules in a Titanium SDK install location', async () => { + const tmpDir = join( + tmpdir(), + 'node-titanium-sdk', + `module-install-test-${randomBytes(8).toString('hex')}` + ); + try { + await mkdir(tmpDir, { recursive: true }); + await copyFile( + join(__dirname, 'mocks', 'install-modules', 'android-only.zip'), + join(tmpDir, 'android-only.zip') + ); + await copyFile( + join(__dirname, 'mocks', 'install-modules', 'badzip-ios-1.0.0.zip'), + join(tmpDir, 'badzip-ios-1.0.0.zip') + ); + await copyFile( + join(__dirname, 'mocks', 'install-modules', 'dummy-ios-1.2.3.zip'), + join(tmpDir, 'dummy-ios-1.2.3.zip') + ); + await copyFile( + join(__dirname, 'mocks', 'install-modules', 'ios-only.zip'), + join(tmpDir, 'ios-only.zip') + ); + + config.titanium.sdk.installPath[process.platform] = tmpDir; + config.titanium.sdk.searchPaths[process.platform] = []; + + const { modules } = await detectTiModules(); + expect(modules).toEqual({ + 'ti.map': { + android: { + '3.1.0': { + apiversion: 2, + architectures: ['arm64-v8a', 'armeabi-v7a', 'x86'], + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'External version of Map module', + guid: 'fee93b77-8eb3-418c-8f04-013664c4af83', + license: 'Apache Public License v2', + minsdk: '6.2.2.GA', + moduleid: 'ti.map', + name: 'map', + path: join(tmpDir, 'modules', 'android', 'ti.map', '3.1.0'), + platform: 'android', + version: '3.1.0', + }, + }, + }, + 'ti.ambiguous': { + ios: { + '1.0': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2018 by Your Company', + description: + 'This is an ambiguous module that will conflict with a commonjs module', + guid: '8d99922e-7727-4f64-90b9-325992eddb1c', + license: 'Apache Public License', + minsdk: '3.0', + moduleid: 'ti.ambiguous', + name: 'ambiguous', + path: join(tmpDir, 'modules', 'ios', 'baz', '2.0.1'), + platform: 'ios', + version: '1.0', + }, + }, + }, + 'ti.dummy': { + ios: { + '1.2.3': { + apiversion: undefined, + architectures: undefined, + author: 'Tester', + copyright: 'Copyright (c) 2026 by Your Company', + description: 'This is a dummy module', + guid: 'ae19fb34-df25-4978-e70f-a8c1c3d3779d', + license: 'Apache Public License', + minsdk: '2.0', + moduleid: 'ti.dummy', + name: 'dummy', + path: join(tmpDir, 'modules', 'ios', 'dummy', '1.2.3'), + platform: 'ios', + version: '1.2.3', + }, + }, + }, + }); + } finally { + await rm(tmpDir, { recursive: true, force: true }); + } + }); + }); + + describe('search', () => { + it('should error if modules is invalid', async () => { + const registry = new TiModuleRegistry(); + await expect(registry.search({ modules: undefined as any })).rejects.toThrow( + 'Expected modules to be an array' + ); + await expect(registry.search({ modules: 'foo' as any })).rejects.toThrow( + 'Expected modules to be an array' + ); + }); + + it('should error if module has invalid version', async () => { + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + data.modules[0].version = 'foo'; + + const registry = await detectTiModules(); + + await expect(registry.search({ modules: data.modules })).rejects.toThrow( + 'Module "ti.map" has invalid version "foo"' + ); + }); + + it('should return nothing if modules is empty', async () => { + const registry = new TiModuleRegistry(); + const modules = await registry.search({ modules: [] }); + expect(modules).toEqual({ found: [], missing: [], incompatible: [], conflict: [] }); + }); + + it('should error if module does not have an id', async () => { + const data = new TiappXML() + .parse(` + + + foo + +`) + .data(); + data.modules[0].moduleid = ''; + const registry = new TiModuleRegistry(); + await expect(registry.search({ modules: data.modules })).rejects.toThrow( + 'Module has no module id' + ); + }); + + it('should search for modules by module id and find conflicts with different platforms', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + // match module id only - same moduleid with different platforms (android, commonjs, ios) = conflict + expect(await registry.search({ modules: data.modules })).toEqual({ + found: [], + missing: [], + incompatible: [], + conflict: [TiMapAndroid, TiMapIos], + }); + }); + + it('should search for modules by module id without version and choose latest', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + cjs-module + +`) + .data(); + const registry = await detectTiModules(); + + // match module id only - same moduleid with different platforms (android, commonjs, ios) = conflict + expect(await registry.search({ modules: data.modules })).toEqual({ + found: [CJSModule2], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search for modules by module id and platform', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + // match module id, platform, and version + expect(await registry.search({ modules: data.modules, platform: ['android'] })).toEqual({ + found: [TiMapAndroid], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search for modules by module id and multiple platforms', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + // match module id, platform, and version + expect(await registry.search({ modules: data.modules, platform: ['android'] })).toEqual({ + found: [TiMapAndroid], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search by module id, platform, and version', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + cjs-module + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, platform: ['commonjs'] })).toEqual({ + found: [CJSModule1], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search modules by module id and array of multiple platforms', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect( + await registry.search({ + modules: data.modules, + platform: ['iphone', 'ios'], + sdkVersion: '12.8.0', + }) + ).toEqual({ + found: [TiMapIos], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search modules by module id and string of multiple platforms', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect( + await registry.search({ + modules: data.modules, + platform: 'iphone,ios', + sdkVersion: '12.8.0', + }) + ).toEqual({ + found: [TiMapIos], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search and find a missing module', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.missing + +`) + .data(); + const registry = await detectTiModules(); + + // match module id, platform, and version + expect(await registry.search({ modules: data.modules, platform: ['android'] })).toEqual({ + found: [], + missing: [ + { + moduleid: 'ti.missing', + platform: 'android', + version: undefined, + deployType: undefined, + }, + ], + incompatible: [], + conflict: [], + }); + }); + + it('should search for module with deploy type', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, deployType: 'test' })).toEqual({ + found: [TiMapAndroid], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search for module with no versions', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules })).toEqual({ + found: [], + missing: [ + { + moduleid: 'ti.map', + platform: 'commonjs', + version: undefined, + deployType: undefined, + }, + ], + incompatible: [], + conflict: [], + }); + }); + + it('should search for module with incompatible API version', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, moduleAPIVersion: '2' })).toEqual({ + found: [], + missing: [], + incompatible: [TiMapAndroid], + conflict: [], + }); + }); + + it('should search for module with compatible API version', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, moduleAPIVersion: '4' })).toEqual({ + found: [TiMapAndroid], + missing: [], + incompatible: [], + conflict: [], + }); + }); + + it('should search for module with incompatible SDK version', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, sdkVersion: '10.0.0' })).toEqual({ + found: [], + missing: [], + incompatible: [TiMapAndroid], + conflict: [], + }); + }); + + it('should search for module with compatible SDK version', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'search-test'); + config.titanium.sdk.searchPaths[process.platform] = []; + + const data = new TiappXML() + .parse(` + + + ti.map + +`) + .data(); + const registry = await detectTiModules(); + + expect(await registry.search({ modules: data.modules, sdkVersion: '12.8.0' })).toEqual({ + found: [TiMapAndroid], + missing: [], + incompatible: [], + conflict: [], + }); + }); + }); +}); diff --git a/test/titanium/sdk/detect-titanium-sdks.test.ts b/test/titanium/sdk/detect-titanium-sdks.test.ts new file mode 100644 index 00000000..c4bc960c --- /dev/null +++ b/test/titanium/sdk/detect-titanium-sdks.test.ts @@ -0,0 +1,197 @@ +import { config, resetConfig } from '../../../src/config.js'; +import { detectTitaniumSDKs } from '../../../src/titanium/index.js'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +describe('Titanium SDK', function () { + afterEach(() => resetConfig()); + + describe('detectTitaniumSDKs()', () => { + it('should find Titanium SDKs', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'mock-sdk'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks, issues } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + + const sdk = sdks['0.0.0.GA']; + expect(sdk).toBeDefined(); + expect(sdk.manifest).toEqual({ + name: '0.0.0.GA', + version: '0.0.0', + moduleAPIVersion: { + android: '4', + iphone: '2', + }, + timestamp: '1/1/2023 00:00', + githash: '1234567890', + platforms: ['android'], + }); + expect(sdk.name).toBe('0.0.0.GA'); + expect(sdk.path).toBe(config.titanium.sdk.installPath[process.platform]); + expect(sdk.platforms).toEqual({ + android: { + path: join(config.titanium.sdk.installPath[process.platform], 'android'), + }, + }); + expect(sdk.type).toBe('ga'); + expect(sdk.version).toBe('0.0.0'); + expect(issues).toHaveLength(0); + + const cached = await detectTitaniumSDKs(); + expect(cached.sdks).toEqual(sdks); + }); + + it('should find Titanium SDKs in Titanium install directory', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'install-dir'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks, issues } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + + const os = process.platform === 'darwin' ? 'osx' : process.platform; + + const sdk = sdks['0.0.0.GA']; + expect(sdk).toBeDefined(); + expect(sdk.manifest).toEqual({ + name: '0.0.0.GA', + version: '0.0.0', + moduleAPIVersion: { + android: '4', + iphone: '2', + }, + timestamp: '1/1/2023 00:00', + githash: '1234567890', + platforms: ['android'], + }); + expect(sdk.name).toBe('0.0.0.GA'); + expect(sdk.path).toBe( + join(config.titanium.sdk.installPath[process.platform], 'mobilesdk', os, '0.0.0.GA') + ); + expect(sdk.platforms).toEqual({ + android: { + path: join(sdk.path, 'android'), + }, + }); + expect(sdk.type).toBe('ga'); + expect(sdk.version).toBe('0.0.0'); + expect(issues).toHaveLength(0); + }); + + it('should find Titanium SDKs using search paths', async () => { + const sdkDir = join(__dirname, 'mocks', 'mock-sdk'); + config.titanium.sdk.installPath[process.platform] = null; + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks, issues } = await detectTitaniumSDKs({ + searchPaths: [sdkDir], + }); + expect(Object.keys(sdks)).toHaveLength(1); + + const sdk = sdks['0.0.0.GA']; + expect(sdk).toBeDefined(); + expect(sdk.manifest).toEqual({ + name: '0.0.0.GA', + version: '0.0.0', + moduleAPIVersion: { + android: '4', + iphone: '2', + }, + timestamp: '1/1/2023 00:00', + githash: '1234567890', + platforms: ['android'], + }); + expect(sdk.name).toBe('0.0.0.GA'); + expect(sdk.path).toBe(sdkDir); + expect(sdk.platforms).toEqual({ + android: { + path: join(sdkDir, 'android'), + }, + }); + expect(sdk.type).toBe('ga'); + expect(sdk.version).toBe('0.0.0'); + expect(issues).toHaveLength(0); + }); + + it('should find Titanium SDKs using config paths', async () => { + const sdkDir = join(__dirname, 'mocks', 'mock-sdk'); + config.titanium.sdk.installPath[process.platform] = null; + config.titanium.sdk.searchPaths[process.platform] = [sdkDir]; + const { sdks, issues } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + + const sdk = sdks['0.0.0.GA']; + expect(sdk).toBeDefined(); + expect(sdk.manifest).toEqual({ + name: '0.0.0.GA', + version: '0.0.0', + moduleAPIVersion: { + android: '4', + iphone: '2', + }, + timestamp: '1/1/2023 00:00', + githash: '1234567890', + platforms: ['android'], + }); + expect(sdk.name).toBe('0.0.0.GA'); + expect(sdk.path).toBe(sdkDir); + expect(sdk.platforms).toEqual({ + android: { + path: join(sdkDir, 'android'), + }, + }); + expect(sdk.type).toBe('ga'); + expect(sdk.version).toBe('0.0.0'); + expect(issues).toHaveLength(0); + }); + + it('should return issues if no Titanium SDKs are found', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'empty'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks, issues } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(0); + expect(issues).toHaveLength(1); + expect(issues[0].id).toBe('TITANIUM_SDK_NOT_FOUND'); + expect(issues[0].type).toBe('warning'); + expect(issues[0].details).toBe( + 'No Titanium SDKs found. Please install the Titanium SDK and try again.' + ); + }); + + it('should not load an SDK without a name', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'no-name-sdk'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks, issues } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(0); + expect(issues).toHaveLength(1); + expect(issues[0].id).toBe('TITANIUM_SDK_NOT_FOUND'); + }); + + it('should find RC SDK', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'rc-release'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + expect(sdks['0.0.0.RC']).toBeDefined(); + expect(sdks['0.0.0.RC'].type).toBe('rc'); + }); + + it('should find Beta SDK', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'beta-release'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + expect(sdks['0.0.0.beta']).toBeDefined(); + expect(sdks['0.0.0.beta'].type).toBe('beta'); + }); + + it('should find CI Build SDK', async () => { + config.titanium.sdk.installPath[process.platform] = join(__dirname, 'mocks', 'ci-build'); + config.titanium.sdk.searchPaths[process.platform] = []; + const { sdks } = await detectTitaniumSDKs(); + expect(Object.keys(sdks)).toHaveLength(1); + expect(sdks['0.0.0.v20260226111717']).toBeDefined(); + expect(sdks['0.0.0.v20260226111717'].type).toBe('nightly'); + }); + }); +}); diff --git a/test/titanium/sdk/fixtures/mock-sdk.zip b/test/titanium/sdk/fixtures/mock-sdk.zip new file mode 100644 index 00000000..f898c006 Binary files /dev/null and b/test/titanium/sdk/fixtures/mock-sdk.zip differ diff --git a/test/titanium/sdk/fixtures/not_a_zip b/test/titanium/sdk/fixtures/not_a_zip new file mode 100644 index 00000000..1c0aec0e --- /dev/null +++ b/test/titanium/sdk/fixtures/not_a_zip @@ -0,0 +1 @@ +This is not a zip file diff --git a/test/titanium/sdk/mocks/beta-release/manifest.json b/test/titanium/sdk/mocks/beta-release/manifest.json new file mode 100644 index 00000000..b2990f4c --- /dev/null +++ b/test/titanium/sdk/mocks/beta-release/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.beta","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/ci-build/manifest.json b/test/titanium/sdk/mocks/ci-build/manifest.json new file mode 100644 index 00000000..e9eacf81 --- /dev/null +++ b/test/titanium/sdk/mocks/ci-build/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.v20260226111717","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/empty/.gitkeep b/test/titanium/sdk/mocks/empty/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/titanium/sdk/mocks/install-dir/mobilesdk/linux/0.0.0.GA/manifest.json b/test/titanium/sdk/mocks/install-dir/mobilesdk/linux/0.0.0.GA/manifest.json new file mode 100644 index 00000000..901c8ef8 --- /dev/null +++ b/test/titanium/sdk/mocks/install-dir/mobilesdk/linux/0.0.0.GA/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.GA","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/install-dir/mobilesdk/osx/0.0.0.GA/manifest.json b/test/titanium/sdk/mocks/install-dir/mobilesdk/osx/0.0.0.GA/manifest.json new file mode 100644 index 00000000..901c8ef8 --- /dev/null +++ b/test/titanium/sdk/mocks/install-dir/mobilesdk/osx/0.0.0.GA/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.GA","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/install-dir/mobilesdk/win32/0.0.0.GA/manifest.json b/test/titanium/sdk/mocks/install-dir/mobilesdk/win32/0.0.0.GA/manifest.json new file mode 100644 index 00000000..901c8ef8 --- /dev/null +++ b/test/titanium/sdk/mocks/install-dir/mobilesdk/win32/0.0.0.GA/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.GA","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_build.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_build.js new file mode 100644 index 00000000..d0b9b3ba --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_build.js @@ -0,0 +1,715 @@ +'use strict'; + +const ADB = require('node-titanium-sdk/lib/adb'); +const android = require('node-titanium-sdk/lib/android'); +const androidDetect = require('../lib/detect').detect; +const Builder = require('../../../cli/lib/node-titanium-sdk/builder'); +const EmulatorManager = require('node-titanium-sdk/lib/emulator'); +const fields = require('fields'); +const fs = require('fs'); +const path = require('path'); +const util = require('util'); + +const version = '0.0.0'; + +function AndroidBuilder() { + Builder.apply(this, arguments); + + this.devices = null; // set by findTargetDevices() during 'config' phase + this.devicesToAutoSelectFrom = []; + + this.keystoreAliases = []; + + this.tiSymbols = {}; + + this.validABIs = this.packageJson.architectures; + this.compileSdkVersion = this.packageJson.compileSDKVersion; // this should always be >= maxSupportedApiLevel + this.minSupportedApiLevel = parseInt(this.packageJson.minSDKVersion); + this.minTargetApiLevel = parseInt(version.parseMin(this.packageJson.vendorDependencies['android sdk'])); + this.maxSupportedApiLevel = parseInt(version.parseMax(this.packageJson.vendorDependencies['android sdk'])); + + this.deployTypes = { + emulator: 'development', + device: 'test', + 'dist-playstore': 'production' + }; + + this.targets = ['emulator', 'device', 'dist-playstore']; +} + +util.inherits(AndroidBuilder, Builder); + +AndroidBuilder.prototype.config = function config(logger, config, cli) { + Builder.prototype.config.apply(this, arguments); + + const _t = this; + + function assertIssue(logger, issues, name) { + for (let i = 0; i < issues.length; i++) { + if ((typeof name === 'string' && issues[i].id === name) || (typeof name === 'object' && name.test(issues[i].id))) { + issues[i].message.split('\n').forEach(function (line) { + logger[issues[i].type === 'error' ? 'error' : 'warn'](line.replace(/(__(.+?)__)/g, '$2'.bold)); + }); + logger.log(); + if (issues[i].type === 'error') { + process.exit(1); + } + } + } + } + + // we hook into the pre-validate event so that we can stop the build before + // prompting if we know the build is going to fail. + // + // this is also where we can detect Android and JDK environments before + // prompting occurs. because detection is expensive we also do it here instead + // of during config() because there's no sense detecting if config() is being + // called because of the help command. + cli.on('cli:pre-validate', function (_obj, callback) { + if (cli.argv.platform && cli.argv.platform !== 'android') { + return callback(); + } + + _t.buildOnly = cli.argv['build-only']; + _t.jdkInfo = {}; // mock? + + // detect Android environment + androidDetect(config, { packageJson: _t.packageJson }, androidInfo => { + _t.androidInfo = androidInfo; + assertIssue(logger, androidInfo.issues, 'ANDROID_JDK_NOT_FOUND'); + assertIssue(logger, androidInfo.issues, 'ANDROID_JDK_PATH_CONTAINS_AMPERSANDS'); + + // if --android-sdk was not specified, then we simply try to set a default Android SDK + if (!cli.argv['android-sdk']) { + let androidSdkPath = config.android && config.android.sdkPath; + if (!androidSdkPath && androidInfo.sdk) { + androidSdkPath = androidInfo.sdk.path; + } + androidSdkPath && (cli.argv['android-sdk'] = path.resolve(androidSdkPath)); + } + + callback(); + }); + }); + + const targetDeviceCache = {}; + const findTargetDevices = function findTargetDevices(target, callback) { + if (targetDeviceCache[target]) { + return callback(null, targetDeviceCache[target]); + } + + if (target === 'device') { + new ADB(config).devices(function (err, devices) { + if (err) { + callback(err); + } else { + this.devices = devices.filter(function (d) { + return !d.emulator && d.state === 'device'; + }); + if (this.devices.length > 1) { + // we have more than 1 device, so we should show 'all' + this.devices.push({ + id: 'all', + model: 'All Devices' + }); + } + callback(null, targetDeviceCache[target] = this.devices.map(function (d) { + return { + name: d.model || d.manufacturer, + id: d.id, + version: d.release, + abi: Array.isArray(d.abi) ? d.abi.join(',') : d.abi, + type: 'device' + }; + })); + } + }.bind(this)); + } else if (target === 'emulator') { + new EmulatorManager(config).detect(function (err, emus) { + if (err) { + callback(err); + } else { + this.devices = emus; + callback(null, targetDeviceCache[target] = emus.map(function (emu) { + // normalize the emulator info + if (emu.type === 'avd') { + return { + name: emu.name, + id: emu.id, + api: emu['api-level'], + version: emu['sdk-version'], + abi: emu.abi, + type: emu.type, + googleApis: emu.googleApis, + sdcard: emu.sdcard + }; + } else if (emu.type === 'genymotion') { + return { + name: emu.name, + id: emu.name, + api: emu['api-level'], + version: emu['sdk-version'], + abi: emu.abi, + type: emu.type, + googleApis: emu.googleApis, + sdcard: true + }; + } + return emu; // not good + })); + } + }.bind(this)); + } else { + callback(); + } + }.bind(this); + + return function (finished) { + cli.createHook('build.android.config', this, callback => { + const conf = { + flags: { + launch: { + desc: 'disable launching the app after installing', + default: true, + hideDefault: true, + negate: true + } + }, + options: { + alias: { + abbr: 'L', + desc: 'the alias for the keystore', + hint: 'alias', + order: 155, + prompt(callback) { + callback(fields.select({ + title: 'What is the name of the keystore\'s certificate alias?', + promptLabel: 'Select a certificate alias by number or name', + margin: '', + optionLabel: 'name', + optionValue: 'name', + numbered: true, + relistOnError: true, + complete: true, + suggest: false, + options: _t.keystoreAliases, + validate: conf.options.alias.validate + })); + }, + validate(value, callback) { + // if there's a value, then they entered something, otherwise let the CLI prompt + if (value) { + const selectedAlias = value.toLowerCase(), + alias = _t.keystoreAlias = _t.keystoreAliases.filter(function (a) { return a.name && a.name.toLowerCase() === selectedAlias; }).shift(); + if (!alias) { + return callback(new Error(`Invalid "--alias" value "${value}"`)); + } + } + callback(null, value); + } + }, + 'android-sdk': { + abbr: 'A', + default: config.android && config.android.sdkPath && path.resolve(config.android.sdkPath), + desc: 'the path to the Android SDK', + hint: 'path', + order: 100, + prompt: function (callback) { + let androidSdkPath = config.android && config.android.sdkPath; + if (!androidSdkPath && _t.androidInfo.sdk) { + androidSdkPath = _t.androidInfo.sdk.path; + } + if (androidSdkPath) { + androidSdkPath = path.resolve(androidSdkPath); + if (process.platform === 'win32' || androidSdkPath.indexOf('&') !== -1) { + androidSdkPath = undefined; + } + } + + callback(fields.file({ + promptLabel: 'Where is the Android SDK?', + default: androidSdkPath, + complete: true, + showHidden: true, + ignoreDirs: _t.ignoreDirs, + ignoreFiles: _t.ignoreFiles, + validate: _t.conf.options['android-sdk'].validate.bind(_t) + })); + }, + required: true, + validate: function (value, callback) { + if (!value) { + callback(new Error('Invalid Android SDK path')); + } else if (process.platform === 'win32' && value.indexOf('&') !== -1) { + callback(new Error('The Android SDK path cannot contain ampersands (&) on Windows')); + } else if (_t.androidInfo.sdk && _t.androidInfo.sdk.path === path.resolve(value)) { + callback(null, value); + } else { + // attempt to find Android SDK + const pkginfo = {}; // appc.pkginfo.package(module) + + android.findSDK(value, config, pkginfo, () => { + + // NOTE: ignore errors when finding SDK, let gradle validate the SDK + + function next() { + // set the Android SDK in the config just in case a plugin or something needs it + config.set('android.sdkPath', value); + + // path looks good, do a full scan again + androidDetect(config, { packageJson: _t.packageJson, bypassCache: true }, androidInfo => { + + // assume SDK is valid, let gradle validate the SDK + if (!androidInfo.sdk) { + androidInfo.sdk = { path: value }; + } + + _t.androidInfo = androidInfo; + callback(null, value); + }); + } + + // new Android SDK path looks good + // if we found an Android SDK in the pre-validate hook, then we need to kill the other SDK's adb server + if (_t.androidInfo.sdk) { + new ADB(config).stopServer(next); + } else { + next(); + } + }); + } + } + }, + 'avd-abi': { + abbr: 'B', + desc: 'the ABI for the Android emulator; deprecated, use --device-id', + hint: 'abi' + }, + 'avd-id': { + abbr: 'I', + desc: 'the id for the Android emulator; deprecated, use --device-id', + hint: 'id' + }, + 'avd-skin': { + abbr: 'S', + desc: 'the skin for the Android emulator; deprecated, use --device-id', + hint: 'skin' + }, + 'build-type': { + hidden: true + }, + 'debug-host': { + hidden: true + }, + 'deploy-type': { + abbr: 'D', + desc: `the type of deployment; only used when target is ${'emulator'.cyan} or ${'device'.cyan}`, + hint: 'type', + order: 110, + values: ['test', 'development'] + }, + 'device-id': { + abbr: 'C', + desc: 'the id of the Android emulator or the device id to install the application to', + hint: 'name', + order: 130, + prompt(callback) { + findTargetDevices(cli.argv.target, (_err, results) => { + let opts = {}; + let title; + let promptLabel; + + // we need to sort all results into groups for the select field + if (cli.argv.target === 'device' && results.length) { + opts['Devices'] = results; + title = 'Which device do you want to install your app on?'; + promptLabel = 'Select a device by number or name'; + } else if (cli.argv.target === 'emulator') { + // for emulators, we sort by type + let emus = results.filter(function (e) { + return e.type === 'avd'; + }); + + if (emus.length) { + opts['Android Emulators'] = emus; + } + + emus = results.filter(function (e) { + return e.type === 'genymotion'; + }); + if (emus.length) { + opts['Genymotion Emulators'] = emus; + + logger.log('NOTE: Genymotion emulator must be running to detect Google API support'.magenta + '\n'); + } + + title = 'Which emulator do you want to launch your app in?'; + promptLabel = 'Select an emulator by number or name'; + } + + // if there are no devices/emulators, error + if (!Object.keys(opts).length) { + if (cli.argv.target === 'device') { + logger.warn('Unable to find any devices, possibly due to missing dependencies.\n'); + logger.log('Continuing with build... (will attempt to install missing dependencies)\n'); + } else { + logger.warn('Unable to find any emulators, possibly due to missing dependencies.\n'); + logger.log('Continuing with build... (will attempt to install missing dependencies)\n'); + } + _t.buildOnly = true; + return callback(); + } + + callback(fields.select({ + title: title, + promptLabel: promptLabel, + formatters: { + option: function (opt, idx, num) { + return ' ' + num + opt.name.cyan + (opt.version ? ' (' + opt.version + ')' : '') + (opt.googleApis + ? ' (Google APIs supported)'.grey + : opt.googleApis === null + ? ' (Google APIs support unknown)'.grey + : ''); + } + }, + autoSelectOne: true, + margin: '', + optionLabel: 'name', + optionValue: 'id', + numbered: true, + relistOnError: true, + complete: true, + suggest: true, + options: opts + })); + }); + }, + required: true, + validate(device, callback) { + const dev = device.toLowerCase(); + findTargetDevices(cli.argv.target, function (_err, devices) { + if (cli.argv.target === 'device' && dev === 'all') { + // we let 'all' slide by + return callback(null, dev); + } + for (let i = 0; i < devices.length; i++) { + if (devices[i].id.toLowerCase() === dev) { + return callback(null, devices[i].id); + } + } + callback(new Error(cli.argv.target ? `Invalid Android device "${device}"` : `Invalid Android emulator "${device}"`)); + }); + }, + verifyIfRequired(callback) { + if (_t.buildOnly) { + // not required if we're build only + return callback(); + } + + findTargetDevices(cli.argv.target, function (err, results) { + if (cli.argv.target === 'emulator' && cli.argv['device-id'] === undefined && cli.argv['avd-id']) { + // if --device-id was not specified, but --avd-id was, then we need to + // try to resolve a device based on the legacy --avd-* options + let avds = results.filter(function (a) { + return a.type === 'avd'; + }).map(function (a) { + return a.name; + }), + name = 'titanium_' + cli.argv['avd-id'] + '_'; + + if (avds.length) { + // try finding the first AVD that starts with the AVD id + avds = avds.filter(function (avd) { + return avd.indexOf(name) === 0; + }); + if (avds.length === 1) { + cli.argv['device-id'] = avds[0]; + return callback(); + } else if (avds.length > 1) { + // next try using the AVD skin + if (!cli.argv['avd-skin']) { + // we have more than one match + logger.error(`Found ${avds.length} AVD with id "${cli.argv['avd-id']}"`); + logger.error('Specify --avd-skin and --avd-abi to select a specific emulator\n'); + } else { + name += cli.argv['avd-skin']; + // try exact match + let tmp = avds.filter(function (avd) { + return avd === name; + }); + if (tmp.length) { + avds = tmp; + } else { + // try partial match + avds = avds.filter(function (avd) { + return avd.indexOf(name + '_') === 0; + }); + } + if (avds.length === 0) { + logger.error(`No emulators found with id "${cli.argv['avd-id']}" and skin "${cli.argv['avd-skin']}"\n`); + } else if (avds.length === 1) { + cli.argv['device-id'] = avds[0]; + return callback(); + } else if (!cli.argv['avd-abi']) { + // we have more than one matching AVD, but no ABI to filter by so we have to error + logger.error(`Found ${avds.length} AVD with id "${cli.argv['avd-id']}" and skin "${cli.argv['avd-skin']}"`); + logger.error('Specify --avd-abi to select a specific emulator\n'); + } else { + name += '_' + cli.argv['avd-abi']; + // try exact match + tmp = avds.filter(function (avd) { + return avd === name; + }); + if (tmp.length) { + avds = tmp; + } else { + avds = avds.filter(function (avd) { + return avd.indexOf(name + '_') === 0; + }); + } + if (avds.length === 0) { + logger.error(`No emulators found with id "${cli.argv['avd-id']}", skin "${cli.argv['avd-skin']}", and ABI "${cli.argv['avd-abi']}"\n`); + } else { + // there is one or more AVDs, but we'll just return the first one + cli.argv['device-id'] = avds[0]; + return callback(); + } + } + } + } + + logger.warn(`${'--avd-*'.cyan} options have been ${'deprecated'.red}, please use ${'--device-id'.cyan}\n`); + + // print list of available AVDs + if (results.length && !cli.argv.prompt) { + logger.log('Available Emulators:'); + results.forEach(function (emu) { + logger.log(' ' + emu.name.cyan + ' (' + emu.version + ')'); + }); + logger.log(); + } + } + + } else if (cli.argv['device-id'] === undefined && results && results.length && config.get('android.autoSelectDevice', true)) { + // we set the device-id to an array of devices so that later in validate() + // after the tiapp.xml has been parsed, we can auto select the best device + _t.devicesToAutoSelectFrom = results.sort((a, b) => { + const eq = a.api && b.api && a.api === b.api; + const gt = a.api && b.api && a.api.localeCompare(b.api) === 1; + + if (eq) { + if (a.type === b.type) { + if (a.googleApis === b.googleApis) { + return 0; + } else if (b.googleApis) { + return 1; + } else if (a.googleApis === false && b.googleApis === null) { + return 1; + } + return -1; + } + return a.type === 'avd' ? -1 : 1; + } + + return gt ? 1 : -1; + }); + return callback(); + } + + // Failed to find devices, fallback to buildOnly. + logger.warn('Unable to find any emulators or devices, possibly due to missing dependencies.'); + logger.warn('Continuing with build... (will attempt to install missing dependencies)'); + _t.buildOnly = true; + return callback(); + }); + } + }, + 'key-password': { + desc: 'the password for the keystore private key (defaults to the store-password)', + hint: 'keypass', + order: 160, + prompt: function (callback) { + callback(fields.text({ + promptLabel: 'What is the keystore\'s __key password__? ' + '(leave blank to use the store password)'.grey, + password: true, + validate: _t.conf.options['key-password'].validate.bind(_t) + })); + }, + secret: true, + validate: function (keyPassword, callback) { + // sanity check the keystore and store password + _t.conf.options['store-password'].validate(cli.argv['store-password'], function (err, _storePassword) { + if (err) { + // we have a bad --keystore or --store-password arg + cli.argv.keystore = cli.argv['store-password'] = undefined; + return callback(err); + } + + callback(null, keyPassword); + }); + } + }, + keystore: { + abbr: 'K', + callback() { + _t.conf.options['alias'].required = true; + _t.conf.options['store-password'].required = true; + }, + desc: 'the location of the keystore file', + hint: 'path', + order: 140, + prompt(callback) { + _t.conf.options['key-password'].required = true; + callback(fields.file({ + promptLabel: 'Where is the __keystore file__ used to sign the app?', + complete: true, + showHidden: true, + ignoreDirs: _t.ignoreDirs, + ignoreFiles: _t.ignoreFiles, + validate: _t.conf.options.keystore.validate.bind(_t) + })); + }, + validate(keystoreFile, callback) { + if (!keystoreFile) { + callback(new Error('Please specify the path to your keystore file')); + } else { + keystoreFile = path.resolve(keystoreFile); + if (!fs.existsSync(keystoreFile) || !fs.statSync(keystoreFile).isFile()) { + callback(new Error('Invalid keystore file')); + } else { + callback(null, keystoreFile); + } + } + } + }, + 'output-dir': { + abbr: 'O', + desc: `the output directory when using ${'dist-playstore'.cyan}`, + hint: 'dir', + order: 180, + prompt: function (callback) { + callback(fields.file({ + promptLabel: 'Where would you like the output APK file saved?', + default: cli.argv['project-dir'] && path.resolvePath(cli.argv['project-dir'], 'dist'), + complete: true, + showHidden: true, + ignoreDirs: _t.ignoreDirs, + ignoreFiles: /.*/, + validate: _t.conf.options['output-dir'].validate.bind(_t) + })); + }, + validate: function (outputDir, callback) { + callback(outputDir || !_t.conf.options['output-dir'].required ? null : new Error('Invalid output directory'), outputDir); + } + }, + 'profiler-host': { + hidden: true + }, + 'store-password': { + abbr: 'P', + desc: 'the password for the keystore', + hint: 'password', + order: 150, + prompt(callback) { + callback(fields.text({ + next: function (err) { + return err && err.next || null; + }, + promptLabel: 'What is the keystore\'s __password__?', + password: true, + // if the password fails due to bad keystore file, + // we need to prompt for the keystore file again + repromptOnError: false, + validate: _t.conf.options['store-password'].validate.bind(_t) + })); + }, + secret: true, + validate(storePassword, callback) { + if (!storePassword) { + return callback(new Error('Please specify a keystore password')); + } + + // sanity check the keystore + _t.conf.options.keystore.validate(cli.argv.keystore, function (err, _keystoreFile) { + if (err) { + // we have a bad --keystore arg + cli.argv.keystore = undefined; + return callback(err); + } + + callback(null, storePassword); + }); + } + }, + target: { + abbr: 'T', + callback(value) { + // as soon as we know the target, toggle required options for validation + if (value === 'dist-playstore') { + _t.conf.options['alias'].required = true; + _t.conf.options['deploy-type'].values = ['production']; + _t.conf.options['device-id'].required = false; + _t.conf.options['keystore'].required = true; + _t.conf.options['output-dir'].required = true; + _t.conf.options['store-password'].required = true; + } + }, + default: 'emulator', + desc: 'the target to build for', + order: 120, + required: true, + values: _t.targets + }, + sigalg: { + desc: 'the type of a digital signature algorithm. only used when overriding keystore signing algorithm', + hint: 'signing', + order: 170, + values: ['MD5withRSA', 'SHA1withRSA', 'SHA256withRSA'] + } + } + }; + + callback(null, _t.conf = conf); + })((_err, result) => finished(result)); + }; +}; + +AndroidBuilder.prototype.validate = function validate(_logger, _config, _cli) { + Builder.prototype.validate.apply(this, arguments); + + return function (callback) { + this.validateTiModules('android', this.deployType, (_err, _modules) => { + callback(); + }); + }.bind(this); +}; + +AndroidBuilder.prototype.run = async function run(_logger, _config, cli, finished) { + try { + Builder.prototype.run.apply(this, arguments); + + await new Promise(resolve => cli.emit('build.pre.construct', this, resolve)); + + await new Promise((resolve, reject) => { + cli.emit('build.pre.compile', this, e => (e ? reject(e) : resolve())); + }); + + await new Promise(resolve => cli.emit('build.pre.build', this, resolve)); + await new Promise(resolve => cli.emit('build.post.build', this, resolve)); + await new Promise(resolve => cli.emit('build.post.compile', this, resolve)); + await new Promise(resolve => cli.emit('build.finalize', this, resolve)); + } catch { + process.exit(1); + } + + if (finished) { + finished(); + } +}; + +// create the builder instance and expose the public API +(function (androidBuilder) { + exports.config = androidBuilder.config.bind(androidBuilder); + exports.validate = androidBuilder.validate.bind(androidBuilder); + exports.run = androidBuilder.run.bind(androidBuilder); +}(new AndroidBuilder(module))); diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_buildModule.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_buildModule.js new file mode 100644 index 00000000..16162e7f --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_buildModule.js @@ -0,0 +1,117 @@ +'use strict'; + +const androidDetect = require('../lib/detect').detect; +const Builder = require('../../../cli/lib/node-titanium-sdk/builder'); +const fields = require('fields'); +const util = require('util'); +const version = '0.0.0'; + +function AndroidModuleBuilder() { + Builder.apply(this, arguments); + + this.requiredArchitectures = this.packageJson.architectures; + this.compileSdkVersion = this.packageJson.compileSDKVersion; // this should always be >= maxSupportedApiLevel + this.minSupportedApiLevel = parseInt(this.packageJson.minSDKVersion); + this.minTargetApiLevel = parseInt(version.parseMin(this.packageJson.vendorDependencies['android sdk'])); + this.maxSupportedApiLevel = parseInt(version.parseMax(this.packageJson.vendorDependencies['android sdk'])); +} + +util.inherits(AndroidModuleBuilder, Builder); + +AndroidModuleBuilder.prototype.validate = function validate(logger, config, cli) { + Builder.prototype.config.apply(this, arguments); + Builder.prototype.validate.apply(this, arguments); + + return finished => { + this.projectDir = cli.argv['project-dir']; + this.buildOnly = cli.argv['build-only']; + this.target = cli.argv['target']; + this.deviceId = cli.argv['device-id']; + + this.cli = cli; + this.logger = logger; + fields.setup({ colors: cli.argv.colors }); + + this.manifest = this.cli.manifest; + + // detect Android environment + androidDetect(config, { packageJson: this.packageJson }, androidInfo => { + this.androidInfo = androidInfo; + + const targetSDKMap = { + + // placeholder for gradle to use + [this.compileSdkVersion]: { + sdk: this.compileSdkVersion + } + }; + Object.keys(this.androidInfo.targets).forEach(function (id) { + var t = this.androidInfo.targets[id]; + if (t.type === 'platform') { + targetSDKMap[t.id.replace('android-', '')] = t; + } + }, this); + + // check the Android SDK we require to build exists + this.androidCompileSDK = targetSDKMap[this.compileSdkVersion]; + + // if no target SDK, then default to most recent supported/installed + if (!this.targetSDK) { + this.targetSDK = this.maxSupportedApiLevel; + } + this.androidTargetSDK = targetSDKMap[this.targetSDK]; + + if (!this.androidTargetSDK) { + this.androidTargetSDK = { + sdk: this.targetSDK + }; + } + + if (this.targetSDK < this.minSDK) { + logger.error(`Target Android SDK version must be ${this.minSDK} or newer\n`); + process.exit(1); + } + + if (this.maxSDK && this.maxSDK < this.targetSDK) { + logger.error(`Maximum Android SDK version must be greater than or equal to the target SDK ${this.targetSDK}, but is currently set to ${this.maxSDK}\n`); + process.exit(1); + } + + if (this.maxSupportedApiLevel && this.targetSDK > this.maxSupportedApiLevel) { + // print warning that version this.targetSDK is not tested + logger.warn(`Building with Android SDK ${('' + this.targetSDK).cyan} which hasn't been tested against Titanium SDK ${this.titaniumSdkVersion}`); + } + + // get javac params + this.javacMaxMemory = config.get('android.javac.maxMemory', '3072M'); + + // TODO remove in the next SDK + if (cli.timodule.properties['android.javac.maxmemory'] && cli.timodule.properties['android.javac.maxmemory'].value) { + logger.error('android.javac.maxmemory is deprecated and will be removed in the next version. Please use android.javac.maxMemory\n'); + this.javacMaxMemory = cli.timodule.properties['android.javac.maxmemory'].value; + } + + if (cli.timodule.properties['android.javac.maxMemory'] && cli.timodule.properties['android.javac.maxMemory'].value) { + this.javacMaxMemory = cli.timodule.properties['android.javac.maxMemory'].value; + } + + // detect JDK + this.jdkInfo = {}; // mocked + + finished(); + }); + }; +}; + +AndroidModuleBuilder.prototype.run = function run(_logger, _config, _cli, finished) { + if (finished) { + finished(); + } +}; + +// create the builder instance and expose the public API +(function (androidModuleBuilder) { + exports.config = androidModuleBuilder.config.bind(androidModuleBuilder); + exports.validate = androidModuleBuilder.validate.bind(androidModuleBuilder); + exports.run = androidModuleBuilder.run.bind(androidModuleBuilder); +}(new AndroidModuleBuilder(module))); diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_cleanModule.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_cleanModule.js new file mode 100644 index 00000000..7903a6ad --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/commands/_cleanModule.js @@ -0,0 +1,5 @@ +'use strict'; + +exports.run = async function run(_logger, _config, _cli, finished) { + finished(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/package.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/package.js new file mode 100644 index 00000000..35f754ae --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/package.js @@ -0,0 +1,12 @@ +'use strict'; + +exports.cliVersion = '>=3.2'; + +exports.init = function (_logger, _config, cli) { + cli.on('build.post.compile', { + priority: 10000, + post(_builder, finished) { + finished(); + } + }); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/run.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/run.js new file mode 100644 index 00000000..cbf0f618 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/hooks/run.js @@ -0,0 +1,46 @@ +'use strict'; + +exports.cliVersion = '>=3.2'; + +exports.init = function (logger, config, cli) { + let deviceInfo = []; + const ignoreLog = config.cli.ignoreLog || []; + + cli.on('build.pre.compile', { + priority: 8000, + post(builder, finished) { + if (builder.buildOnly) { + return finished(); + } + + if (builder.target === 'emulator') { + cli.createHook('build.android.startEmulator', function (_deviceId, _opts, cb) { + setTimeout(() => cb(), 100); + })(builder.deviceId, { + logger: logger + }, finished); + + } else if (builder.target === 'device') { + setTimeout(() => finished(), 100); + } else { + finished(); + } + } + }); + + cli.on('build.post.compile', { + priority: 10000, + post(builder, finished) { + if (builder.target !== 'emulator' && builder.target !== 'device') { + return finished(); + } + + if (builder.buildOnly) { + return finished(); + } + + cli.emit('build.post.install', builder, finished); + } + }); + +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/detect.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/detect.js new file mode 100644 index 00000000..b4ef3d25 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/detect.js @@ -0,0 +1,71 @@ +/** + * Detects the Android development environment and its dependencies. + * + * @module lib/detect + * + * @copyright + * Copyright TiDev, Inc. 04/07/2022-Present + * + * @license + * Licensed under the terms of the Apache Public License + * Please see the LICENSE included with this distribution for details. + */ + +'use strict'; + +const android = require('node-titanium-sdk/lib/android'), + ADB = require('node-titanium-sdk/lib/adb'), + EmulatorManager = require('node-titanium-sdk/lib/emulator'), + appc = require('node-appc'), + __ = appc.i18n(__dirname).__; + +/** + * Detects current Android environment. + * @param {Object} config - The CLI config object + * @param {CLI} cli - The CLI instance + * @param {Object} opts - Detection options; currently only 'bypassCache' + * @param {Function} finished - Callback when detection is finished + */ +exports.detect = android.detect; + +/** + * Detects connected Android emulators. + * @param {Object} config - The CLI config object + * @param {Object} [opts] - Detection options + * @param {String} [opts.type] - The type of emulator to load (avd, genymotion); defaults to all + * @param {Function} finished - Callback when detection is finished + */ +exports.detectEmulators = function detectEmulators(config, opts, finished) { + if (opts && typeof opts === 'function') { + finished = opts; + opts = {}; + } + + new EmulatorManager(config).detect(opts, function (err, emus) { + if (err) { + finished(err); + } else { + finished(null, emus); + } + }); +}; + +/** + * Detects connected Android devices. + * @param {Object} config - The CLI config object + * @param {Function} finished - Callback when detection is finished + */ +exports.detectDevices = function detectDevices(config, finished) { + new ADB(config).devices(function (err, devices) { + if (err) { + return finished(err); + } + + finished(null, devices.filter(function (d) { + return !d.emulator; + }).map(function (d) { + d.name = d.model || d.manufacturer || d.name || (d.release ? __('Android %s Device', d.release) : __('Android Device')); + return d; + })); + }); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/info.js b/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/info.js new file mode 100644 index 00000000..90709dbe --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/cli/lib/info.js @@ -0,0 +1,208 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); + +exports.name = 'android'; + +exports.title = 'Android'; + +exports.detect = function (_types, config, next) { + const tisdk = path.basename((function scan(dir) { + const file = path.join(dir, 'manifest.json'); + if (fs.existsSync(file)) { + return dir; + } + dir = path.dirname(dir); + return dir !== '/' && scan(dir); + }(__dirname))); + + const mod = require('./detect'); + + // detect Android environment + mod.detect(config, null, result => { + // detect devices + mod.detectDevices(config, (_err, devices) => { + // detect emulators + mod.detectEmulators(config, (_err, emus) => { + result.tisdk = tisdk; + result.devices = devices; + result.emulators = emus; + delete result.avds; + + this.data = result; + if (result.issues.length) { + this.issues = this.issues.concat(result.issues); + } + + next(null, { android: result }); + }); + }); + }); +}; + +exports.render = function (logger, _config, rpad, styleHeading, styleValue, styleBad) { + const data = this.data; + if (!data) { + return; + } + + logger.log(styleHeading('Android SDK') + '\n' + + ' ' + rpad('Android Executable') + ' = ' + styleValue(data.sdk && data.sdk.executables.android || 'not found') + '\n' + + ' ' + rpad('ADB Executable') + ' = ' + styleValue(data.sdk && data.sdk.executables.adb || 'not found') + '\n' + + ' ' + rpad('SDK Path') + ' = ' + styleValue(data.sdk && data.sdk.path || 'not found') + '\n' + ); + + logger.log(styleHeading('Android NDK') + '\n' + + ' ' + rpad('NDK Path') + ' = ' + styleValue(data.ndk && data.ndk.path || 'not found') + '\n' + + ' ' + rpad('NDK Version') + ' = ' + styleValue(data.ndk && data.ndk.version || 'not found') + '\n' + ); + + let androidPlatforms = ''; + let androidAddons = ''; + const apiLevelMap = {}; + + if (data.targets && Object.keys(data.targets).length) { + Object.keys(data.targets).forEach(function (targetId) { + var target = data.targets[targetId], + supported = (target.supported === 'maybe' + ? ` (not supported by Titanium SDK ${data.tisdk}, but may work)`.yellow + : target.supported + ? '' + : styleBad(` **Not supported by Titanium SDK ${data.tisdk}**`)); + + if (target.type === 'platform') { + const m = target.name.match(/Android\s+(\d(?:\.\d(?:\.\d)?)?)/); + if (m) { + apiLevelMap[m[1]] = target['api-level']; + } + androidPlatforms += ' ' + `${targetId}) ${target.id}`.cyan + '\n' + + ' ' + rpad(' Name') + ' = ' + styleValue(target.name) + supported + '\n' + + ' ' + rpad(' API Level') + ' = ' + styleValue(target['api-level']) + '\n' + + ' ' + rpad(' Revision') + ' = ' + styleValue(target.revision) + '\n' + + ' ' + rpad(' Skins') + ' = ' + styleValue(target.skins.join(', ')) + '\n' + + ' ' + rpad(' ABIs') + ' = ' + styleValue(target.abis.join(', ')) + '\n' + + ' ' + rpad(' Path') + ' = ' + styleValue(target.path) + '\n'; + } else if (target.type === 'add-on') { + androidAddons += ' ' + (targetId + ') ' + target.id).cyan + '\n' + + ' ' + rpad(' Name') + ' = ' + styleValue(target.name + + ' (' + (target['based-on'] ? `Android ${target['based-on']['android-version']} (API level ${target['based-on']['api-level']})` : 'unknown') + ')') + supported + '\n' + + ' ' + rpad(' Vendor') + ' = ' + styleValue(target.vendor || 'n/a') + '\n' + + ' ' + rpad(' Revision') + ' = ' + styleValue(target.revision) + '\n' + + ' ' + rpad(' Description') + ' = ' + styleValue(target.description || 'n/a') + '\n' + + ' ' + rpad(' Skins') + ' = ' + styleValue(target.skins && target.skins.length ? target.skins.join(', ') : 'none') + '\n' + + ' ' + rpad(' ABIs') + ' = ' + styleValue(target.abis && target.abis.length ? target.abis.join(', ') : 'none') + '\n' + + ' ' + rpad(' Path') + ' = ' + styleValue(target.path) + '\n'; + + if (target.libraries && Object.keys(target.libraries).length) { + Object.keys(target.libraries).forEach(function (lib, i) { + androidAddons += ' ' + (i === 0 ? rpad(' Libraries') + ' = ' : rpad('') + ' ') + + styleValue(lib + ': ' + target.libraries[lib].description + ' (' + target.libraries[lib].jar + ')') + '\n'; + }); + androidAddons += '\n'; + } else { + androidAddons += ' ' + rpad(' ' + 'Libraries') + ' = ' + styleValue('none') + '\n'; + } + } + }); + } + + logger.log(styleHeading('Android Platforms') + '\n' + (androidPlatforms ? androidPlatforms : ' ' + 'none'.grey + '\n')); + logger.log(styleHeading('Android Add-Ons') + '\n' + (androidAddons ? androidAddons : ' ' + 'none'.grey + '\n')); + + logger.log(styleHeading('Android Emulators')); + if (data.emulators) { + const emus = data.emulators.filter(function (e) { + return e.type === 'avd'; + }); + if (emus.length) { + logger.log(emus.map(function (emu) { + return ' ' + emu.name.cyan + '\n' + + ' ' + rpad(' ID') + ' = ' + styleValue(emu.id) + '\n' + + ' ' + rpad(' SDK Version') + ' = ' + styleValue(emu.target || 'not installed') + '\n' + + ' ' + rpad(' ABI') + ' = ' + styleValue(emu.abi) + '\n' + + ' ' + rpad(' Skin') + ' = ' + styleValue(emu.skin) + '\n' + + ' ' + rpad(' Path') + ' = ' + styleValue(emu.path) + '\n' + + ' ' + rpad(' SD Card') + ' = ' + styleValue(emu.sdcard || 'no sd card') + '\n' + + (emu['based-on'] + ? ' ' + rpad(' ' + 'Based On') + ' = ' + styleValue(`Android ${emu['based-on']['android-version']} (API level ${emu['based-on']['api-level']})`) + '\n' + : '' + ) + + ' ' + rpad(' ' + 'Google APIs') + ' = ' + styleValue(emu.googleApis ? 'yes' : 'no'); + }).join('\n') + '\n'); + } else { + logger.log(' ' + 'none'.grey + '\n'); + } + } else { + logger.log(' ' + 'none'.grey + '\n'); + } + + logger.log(styleHeading('Genymotion Emulators')); + if (data.emulators) { + const emus = data.emulators.filter(function (e) { + return e.type === 'genymotion'; + }); + if (emus.length) { + logger.log(emus.map(function (emu) { + return ' ' + emu.name.cyan + '\n' + + ' ' + rpad(' ID') + ' = ' + styleValue(emu.id) + '\n' + + ' ' + rpad(' SDK Version') + ' = ' + styleValue(emu.target + (apiLevelMap[emu.target] ? ' (android-' + apiLevelMap[emu.target] + ')' : '')) + '\n' + + ' ' + rpad(' ABI') + ' = ' + styleValue(emu.abi || 'unknown') + '\n' + + ' ' + rpad(' Genymotion Version') + ' = ' + styleValue(emu.genymotion || 'unknown') + '\n' + + ' ' + rpad(' Display') + ' = ' + styleValue(emu.display || 'unknown') + '\n' + + ' ' + rpad(' DPI') + ' = ' + styleValue(emu.dpi || 'unknown') + '\n' + + ' ' + rpad(' OpenGL Acceleration') + ' = ' + styleValue(emu.hardwareOpenGL ? 'yes' : 'no') + '\n' + + ' ' + rpad(' Google APIs') + ' = ' + styleValue(emu.googleApis === null ? 'unknown, emulator not running' : emu.googleApis ? 'yes' : 'no'); + }).join('\n') + '\n'); + } else { + logger.log(' ' + 'none'.grey + '\n'); + } + } else { + logger.log(' ' + 'none'.grey + '\n'); + } + + logger.log(styleHeading('Connected Android Devices')); + if (data.devices && data.devices.length) { + logger.log(data.devices.map(function (device) { + var name = device.name, + result = [ + ' ' + rpad('ID') + ' = ' + styleValue(device.id), + ' ' + rpad('State') + ' = ' + styleValue(device.state) + ]; + + if (device.release) { + result.push(' ' + rpad('SDK Version') + ' = ' + styleValue(device.release + ' (android-' + device.sdk + ')')); + } + + if (Array.isArray(device.abi)) { + result.push(' ' + rpad('ABIs') + ' = ' + styleValue(device.abi.join(', '))); + } + + if (device.emulator) { + switch (device.emulator.type) { + case 'avd': + name = 'Android Emulator: ' + device.emulator.name; + result.push(' ' + rpad('Skin') + ' = ' + styleValue(device.emulator.skin || 'unknown')); + result.push(' ' + rpad('SD Card') + ' = ' + styleValue(device.emulator.sdcard || 'unknown')); + result.push(' ' + rpad('Google APIs') + ' = ' + styleValue(device.emulator.googleApis ? 'yes' : 'no')); + break; + + case 'genymotion': + name = 'Genymotion Emulator: ' + device.emulator.name; + result.push(' ' + rpad('Genymotion Version') + ' = ' + styleValue(device.emulator.genymotion || 'unknown')); + result.push(' ' + rpad('Display') + ' = ' + styleValue(device.emulator.display || 'unknown')); + result.push(' ' + rpad('DPI') + ' = ' + styleValue(device.emulator.dpi || 'unknown')); + result.push(' ' + rpad('OpenGL Acceleration') + ' = ' + styleValue(device.emulator.hardwareOpenGL ? 'yes' : 'no')); + result.push(' ' + rpad('Google APIs') + ' = ' + styleValue(device.emulator.googleApis ? 'yes' : 'no')); + break; + } + + return name.cyan + '\n' + result.join('\n'); + } else { + return name.cyan + '\n' + result.join('\n'); + } + }).join('\n') + '\n'); + } else { + logger.log(' ' + 'none'.grey + '\n'); + } +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/android/package.json b/test/titanium/sdk/mocks/mock-sdk/android/package.json new file mode 100644 index 00000000..a0a43816 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/android/package.json @@ -0,0 +1,25 @@ +{ + "name": "titanium-mobile-android", + "title": "Android", + "description": "TiDev Titanium Mobile Android", + "version": "12.2.0", + "architectures": ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"], + "v8": { + "version": "8.8.278.17", + "mode": "release", + "integrity": "sha512-A0tV+fYtkpKfIF5roRTCFPtdULMFygmfWlEuuHOBjC3q4rz/mKnAsJTYBlqayC/4oYEWehj867Oh1o6vy26XHQ==" + }, + "minSDKVersion": "21", + "compileSDKVersion": "33", + "vendorDependencies": { + "android sdk": ">=23.x <=33.x", + "android build tools": ">=30.0.2 <=33.x", + "android platform tools": "33.x", + "android tools": "<=26.x", + "android ndk": ">=r21 <=r22b", + "java": ">=11.x" + }, + "engines": { + "node": ">=12.13.0" + } +} diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/commands/build.js b/test/titanium/sdk/mocks/mock-sdk/cli/commands/build.js new file mode 100644 index 00000000..325be880 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/commands/build.js @@ -0,0 +1,399 @@ +'use strict'; + +const fields = require('fields'); +const fs = require('fs'); +const path = require('path'); +const ti = require('../lib/node-titanium-sdk/ti'); + +fields.setup({ + formatters: { + error(err) { + if (err instanceof Error) { + return `[ERROR] ${err.message}`.red + '\n'; + } + err = '' + err; + return '\n' + (/^(\[ERROR\])/i.test(err) ? err : '[ERROR] ' + err.replace(/^Error:/i, '').trim()).red; + } + }, + style: { + accelerator: 'cyan' + } +}); + +exports.cliVersion = '>=3.2.1'; +exports.title = 'Build'; +exports.desc = 'builds a project'; +exports.extendedDesc = 'Builds an existing app or module project.'; + +exports.config = function config(logger, config, cli) { + fields.setup({ colors: cli.argv.colors }); + + // start patching the logger here + patchLogger(logger, cli); + + return finished => { + cli.createHook('build.config', callback => { + // note: it's currently impossible for the module build to declare any + // config options/flags. + ti.platformOptions(logger, config, cli, 'build', platformConf => { + var conf = { + flags: { + 'build-only': { + abbr: 'b', + desc: 'only perform the build; if true, does not install or run the app' + }, + force: { + abbr: 'f', + desc: 'force a full rebuild' + }, + legacy: { + desc: 'build using the old Python-based builder.py; deprecated' + }, + 'skip-js-minify': { + default: false, + desc: `bypasses JavaScript minification; ${'simulator'.cyan} builds are never minified; only supported for ${'Android'.cyan} and ${'iOS'.cyan}` + }, + 'source-maps': { + desc: 'generate inline source maps for transpiled JS files' + }, + }, + options: Object.assign({ + platform: { + abbr: 'p', + callback(platform) { + if (!cli.argv.$originalPlatform) { + cli.argv.$originalPlatform = platform; + } + platform = cli.argv.platform = ti.resolvePlatform(platform); + + const p = platformConf[platform]; + p && p.options && Object.keys(p.options).forEach(name => { + if (p.options[name].default && cli.argv[name] === undefined) { + cli.argv[name] = p.options[name].default; + } + }); + + return platform; + }, + desc: 'the target build platform', + hint: 'platform', + order: 2, + prompt: { + label: 'Target platform', + error: 'Invalid platform', + validator(platform) { + if (!platform) { + throw new Error('Invalid platform'); + } else if (ti.availablePlatforms.indexOf(platform) === -1) { + throw new Error(`Invalid platform: ${platform}`); + } + return true; + } + }, + required: true, + skipValueCheck: true, + values: ti.targetPlatforms + }, + 'project-dir': { + abbr: 'd', + callback(projectDir) { + if (projectDir === '') { + // no option value was specified + // set project dir to current directory + projectDir = conf.options['project-dir'].default; + } + + projectDir = path.resolve(projectDir); + + // load the tiapp.xml/timodule.xml + if (fs.existsSync(path.join(projectDir, 'tiapp.xml'))) { + let tiapp; + try { + tiapp = cli.tiapp = {}; + } catch (ex) { + logger.error(ex); + logger.log(); + process.exit(1); + } + + tiapp.properties || (tiapp.properties = {}); + + cli.argv.type = 'app'; + + } else if (fs.existsSync(path.join(projectDir, 'timodule.xml'))) { + let timodule; + try { + timodule = cli.tiapp = cli.timodule = {}; + } catch (ex) { + logger.error(ex); + logger.log(); + process.exit(1); + } + + const manifest = cli.manifest = ti.loadModuleManifest(logger, path.join(projectDir, 'manifest')); + + // if they didn't explicitly set --platform and we have a platform in the manifest, + // then just use that and skip the platform prompting + if (!cli.argv.platform && manifest.platform) { + cli.argv.platform = ti.resolvePlatform(manifest.platform); + conf.options.platform.required = false; + } + + timodule.properties || (timodule.properties = {}); + + cli.argv.type = 'module'; + + } else { + // neither app nor module + return; + } + + cli.scanHooks(path.join(projectDir, 'hooks')); + + return projectDir; + }, + desc: 'the directory containing the project', + default: process.env.SOURCE_ROOT ? path.join(process.env.SOURCE_ROOT, '..', '..') : '.', + order: 1, + prompt(callback) { + callback(fields.file({ + promptLabel: 'Where is the __project directory__?', + complete: true, + showHidden: true, + ignoreDirs: new RegExp(config.get('cli.ignoreDirs')), + ignoreFiles: /.*/, + validate: conf.options['project-dir'].validate + })); + }, + required: true, + validate(projectDir, callback) { + const isDefault = (projectDir == conf.options['project-dir'].default); + let dir = path.resolve(projectDir); + + if (!fs.existsSync(dir)) { + return callback(new Error('Project directory does not exist')); + } + + const root = path.resolve('/'); + let isFound, + projDir = dir; + + ['tiapp.xml', 'timodule.xml'].some(tiXml => { + let tiFile = path.join(dir, tiXml); + + while (!fs.existsSync(tiFile)) { + dir = path.dirname(dir); + if (dir == root) { + isFound = false; + break; + } + tiFile = path.join(dir, tiXml); + } + + // Found the XML file, break the loop + if (fs.existsSync(tiFile)) { + isFound = true; + return true; + } + + dir = projDir; + }); + + if (!isFound && dir == root && isDefault) { + callback(true); + return; + } + + if (!isFound) { + callback(new Error(`Invalid project directory "${projectDir}" because tiapp.xml or timodule.xml not found`)); + return; + } + callback(null, dir); + } + } + }, ti.commonOptions(logger, config)), + platforms: platformConf + }; + callback(null, conf); + }); + })((_err, result) => finished(result)); + }; +}; + +exports.validate = function validate(logger, config, cli) { + + // Determine if the project is an app or a module, run appropriate build command + if (cli.argv.type === 'module') { + + // make sure the module manifest is sane + ti.validateModuleManifest(logger, cli, cli.manifest); + + return finished => { + logger.log.init(() => { + const result = ti.validatePlatformOptions(logger, config, cli, 'buildModule'); + if (result && typeof result === 'function') { + result(finished); + } else { + finished(result); + } + }); + }; + + } else { + + ti.validatePlatform(logger, cli, 'platform'); + + // since we need validate() to be async, we return a function in which the cli + // will immediately call + return function (finished) { + logger.log.init(function () { + function next(result) { + if (result !== false) { + // no error, load the tiapp.xml plugins + ti.loadPlugins(logger, config, cli, cli.argv['project-dir'], function () { + finished(result); + }); + } else { + finished(result); + } + } + + // loads the platform specific build command and runs its validate() function + const result = ti.validatePlatformOptions(logger, config, cli, 'build'); + if (result && typeof result === 'function') { + result(next); + } else { + next(result); + } + }); + }; + } +}; + +exports.run = function run(logger, config, cli, finished) { + const buildFile = cli.argv.type === 'module' ? '_buildModule.js' : '_build.js', + platform = ti.resolvePlatform(cli.argv.platform), + buildModule = path.join(__dirname, '..', '..', platform, 'cli', 'commands', buildFile); + + if (!fs.existsSync(buildModule)) { + logger.error('Unable to find platform specific build command\n'); + logger.log(`Your SDK installation may be corrupt. You can reinstall it by running '${(cli.argv.$ + ' sdk install --force --default').cyan}'.\n`); + process.exit(1); + } + + let counter = 0; + require(buildModule).run(logger, config, cli, function (err) { + if (!counter++) { + const delta = String(cli.startTime - Date.now()); + if (err) { + logger.error(`An error occurred during build after ${delta}`); + if (err instanceof Error) { + err.dump(logger.error); + } else if (err !== true) { + (err.message || err.toString()).trim().split('\n').forEach(function (msg) { + logger.error(msg); + }); + } + logger.log(); + process.exit(1); + } else { + // eventually all platforms will just show how long the build took since they + // are responsible for showing the own logging + if (platform !== 'iphone' || cli.argv['build-only']) { + logger.info(`Project built successfully in ${delta.cyan}\n`); + } + } + + finished(); + } + }); +}; + +/** + * Monkey-patch the logger object to enable file logging during build + * @param {Object} logger - The logger instance + * @param {Object} cli - The CLI instance + */ +function patchLogger(logger, cli) { + var origLoggerLog = logger.log; + + // override the existing log function + logger.log = function patchedLog() { + // most of this copied from the CLI's logger.js logger.log() function + let args = Array.prototype.slice.call(arguments); + let padLevels = logger.padLevels; + + // if there are no args (e.g. a blank line), we need at least one space + args.length || args.unshift(' '); + + // if we're not being called from info/warn/error/debug, then set this as a general log entry + args[0] in logger.levels || args.unshift('_'); + + // turn off padding + logger.padLevels = args[0] !== '_'; + + // get rid of any null args + while (args.length && args[args.length - 1] == null) { + args.pop(); + } + + // if we're logging an error, we need to cast to a string so that sprintf doesn't complain + if (args[1] instanceof Error || Object.prototype.toString.call(args[1]) === '[object Error]') { + args[1] = (args[1].stack || args[1].toString()) + '\n'; + } else if (args[1] === null || args[1] === undefined) { + args[1] = ''; + } + + typeof type !== 'string' && (args[1] = '' + args[1]); + + // call the original logger with our cleaned up args + origLoggerLog.apply(logger, arguments); + + // restore padding + logger.padLevels = padLevels; + }; + + logger.log.init = function (callback) { + function styleHeading(s) { + return ('' + s).bold; + } + + function styleValue(s) { + return ('' + s).magenta; + } + + function rpad(s) { + return s.padEnd(27); + } + + cli.env.getOSInfo(function (osInfo) { + logger.log([ + new Date().toLocaleString(), + '', + styleHeading('Operating System'), + ' ' + rpad('Name') + ' = ' + styleValue(osInfo.os), + ' ' + rpad('Version') + ' = ' + styleValue(osInfo.osver), + ' ' + rpad('Architecture') + ' = ' + styleValue(osInfo.ostype), + ' ' + rpad('# CPUs') + ' = ' + styleValue(osInfo.oscpu), + ' ' + rpad('Memory') + ' = ' + styleValue(osInfo.memory), + '', + styleHeading('Node.js'), + ' ' + rpad('Node.js Version') + ' = ' + styleValue(osInfo.node), + ' ' + rpad('npm Version') + ' = ' + styleValue(osInfo.npm), + '', + styleHeading('Titanium CLI'), + ' ' + rpad('CLI Version') + ' = ' + styleValue(cli.version), + '', + styleHeading('Titanium SDK'), + ' ' + rpad('SDK Version') + ' = ' + styleValue(cli.argv.sdk), + ' ' + rpad('SDK Path') + ' = ' + styleValue(cli.sdk.path), + ' ' + rpad('Target Platform') + ' = ' + styleValue(ti.resolvePlatform(cli.argv.platform)), + '', + styleHeading('Command'), + ' ' + styleValue(process.argv.join(' ')), + '' + ].join('\n')); + callback(); + }); + }; +} diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/commands/clean.js b/test/titanium/sdk/mocks/mock-sdk/cli/commands/clean.js new file mode 100644 index 00000000..6ea8f3c7 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/commands/clean.js @@ -0,0 +1,337 @@ +'use strict'; + +const ti = require('../lib/node-titanium-sdk/ti'); +const fs = require('fs'); +const path = require('path'); +const fields = require('fields'); + +exports.cliVersion = '>=3.2.1'; +exports.desc = 'removes previous build directories'; + +exports.config = function (logger, config, cli) { + // start patching the logger here + patchLogger(logger, cli); + + return (finished) => { + cli.createHook('clean.config', callback => { + var conf = { + options: Object.assign({ + platform: { + // this is for backwards compatibility and eventually should be dropped + hidden: true + }, + platforms: { + // note: --platforms is not required for the clean command + abbr: 'p', + desc: 'one or more platforms to clean', + values: ['android'], + skipValueCheck: true // we do our own validation + }, + 'project-dir': { + abbr: 'd', + callback: function (projectDir) { + if (projectDir === '') { + // no option value was specified + // set project dir to current directory + projectDir = conf.options['project-dir'].default; + } + + projectDir = path.resolve(projectDir); + + // load the tiapp.xml/timodule.xml + if (fs.existsSync(path.join(projectDir, 'tiapp.xml'))) { + cli.tiapp = {}; + cli.tiapp.properties ||= {}; + cli.argv.type = 'app'; + + } else if (fs.existsSync(path.join(projectDir, 'timodule.xml'))) { + cli.tiapp = cli.timodule = {}; + cli.manifest = { + platform: 'android' + }; + + if (!cli.argv.platform) { + cli.argv.platform = cli.manifest.platform; + conf.options.platform.required = false; + } + + cli.timodule.properties ||= {}; + cli.argv.type = 'module'; + + } else { + // neither app nor module + return; + } + + cli.scanHooks(path.join(projectDir, 'hooks')); + + return projectDir; + }, + desc: 'the directory containing the project, otherwise the current working directory', + default: '.', + order: 1, + prompt(callback) { + callback(fields.file({ + promptLabel: 'Where is the __project directory__?', + complete: true, + showHidden: true, + ignoreDirs: new RegExp(config.get('cli.ignoreDirs')), + ignoreFiles: /.*/, + validate: conf.options['project-dir'].validate + })); + }, + validate: function (projectDir, callback) { + const isDefault = (projectDir == conf.options['project-dir'].default); + let dir = path.resolve(projectDir); + + if (!fs.existsSync(dir)) { + return callback(new Error('Project directory does not exist')); + } + + const root = path.resolve('/'); + let isFound; + let projDir = dir; + + ['tiapp.xml', 'timodule.xml'].some(tiXml => { + let tiFile = path.join(dir, tiXml); + + while (!fs.existsSync(tiFile)) { + dir = path.dirname(dir); + if (dir == root) { + isFound = false; + break; + } + tiFile = path.join(dir, tiXml); + } + + // Found the XML file, break the loop + if (fs.existsSync(tiFile)) { + isFound = true; + return true; + } + + dir = projDir; + }); + + if (!isFound && dir == root && isDefault) { + callback(true); + return; + } + + if (!isFound) { + callback(new Error(`Invalid project directory "${projectDir}" because tiapp.xml or timodule.xml not found`)); + return; + } + callback(null, dir); + } + } + }, ti.commonOptions(logger, config)) + }; + callback(null, conf); + })((_err, result) => finished(result)); + }; +}; + +exports.validate = function (logger, config, cli) { + // Determine if the project is an app or a module, run appropriate clean command + if (cli.argv.type === 'module') { + + // make sure the module manifest is sane + ti.validateModuleManifest(logger, cli, cli.manifest); + + return finished => { + logger.log.init(() => { + const result = ti.validatePlatformOptions(logger, config, cli, 'cleanModule'); + if (result && typeof result === 'function') { + result(finished); + } else { + finished(result); + } + }); + }; + + } else { + let platforms = cli.argv.platforms || cli.argv.platform; + if (platforms) { + platforms = ti.scrubPlatforms(platforms); + + if (platforms.bad.length) { + logger.error(`Invalid platform${platforms.bad.length === 1 ? '' : 's'}: ${platforms.bad.join(', ')}\n`); + logger.log(`Available platforms for SDK version ${ti.manifest.sdkVersion}:\n`); + ti.targetPlatforms.forEach(function (p) { + logger.log(' ' + p.cyan); + }); + logger.log(); + process.exit(1); + } + + cli.argv.platforms = platforms.scrubbed; + } else { + cli.argv.platforms = null; + } + + ti.validateProjectDir(logger, cli, cli.argv, 'project-dir'); + + return finished =>{ + ti.loadPlugins(logger, config, cli, cli.argv['project-dir'], () => finished()); + }; + } +}; + +exports.run = function (logger, config, cli) { + if (cli.argv.type === 'module') { + const platform = ti.resolvePlatform(cli.argv.platform); + const cleanModule = path.join(__dirname, '..', '..', platform, 'cli', 'commands', '_cleanModule.js'); + if (!fs.existsSync(cleanModule)) { + process.exit(1); + } + + // Now wrap the actual cleaning of the module (specific to a given platform), + // in hooks so a module itself could potentially do additional cleanup itself + cli.fireHook('clean.module.pre', function () { + cli.fireHook(`clean.module.${platform}.pre`, () => { + cli.fireHook(`clean.module.${platform}.post`, () => { + cli.fireHook('clean.module.post', () => {}); + }); + }); + }); + } else { + const buildDir = path.join(cli.argv['project-dir'], 'build'); + + if (cli.argv.platforms) { + cli.argv.platforms.reduce((prom, platform) => { + return prom.then(new Promise(resolve => { + // scan platform SDK specific clean hooks + cli.scanHooks(path.join(__dirname, '..', '..', platform, 'cli', 'hooks')); + cli.fireHook('clean.pre', function () { + cli.fireHook(`clean.${platform}.pre`, function () { + cli.fireHook(`clean.${platform}.post`, function () { + cli.fireHook('clean.post', () => resolve()); + }); + }); + }); + })); + }, Promise.resolve()); + } else if (fs.existsSync(buildDir)) { + logger.debug('Deleting all platform build directories'); + + // scan platform SDK specific clean hooks + if (ti.targetPlatforms) { + ti.targetPlatforms.forEach(platform => { + cli.scanHooks(path.join(__dirname, '..', '..', platform, 'cli', 'hooks')); + }); + } + + cli.fireHook('clean.pre', function () { + fs.readdirSync(buildDir).reduce((prom, dir) => { + return prom.then(new Promise(resolve => { + cli.fireHook(`clean.${dir}.pre`, () => { + cli.fireHook(`clean.${dir}.post`, () => resolve()); + }); + })); + }, Promise.resolve()).then(new Promise(resolve => { + cli.fireHook('clean.post', () => resolve()); + })); + }); + } + } +}; + +/** + * Monkey-patch the logger object to enable file logging during build + * @param {Object} logger - The logger instance + * @param {Object} cli - The CLI instance + */ +function patchLogger(logger, cli) { + var origLoggerLog = logger.log; + + // override the existing log function + logger.log = function patchedLog() { + // most of this copied from the CLI's logger.js logger.log() function + let args = Array.prototype.slice.call(arguments); + let padLevels = logger.padLevels; + + // if there are no args (e.g. a blank line), we need at least one space + args.length || args.unshift(' '); + + // if we're not being called from info/warn/error/debug, then set this as a general log entry + args[0] in logger.levels || args.unshift('_'); + + // turn off padding + logger.padLevels = args[0] !== '_'; + + // get rid of any null args + while (args.length && args[args.length - 1] == null) { + args.pop(); + } + + // if we're logging an error, we need to cast to a string so that sprintf doesn't complain + if (args[1] instanceof Error || Object.prototype.toString.call(args[1]) === '[object Error]') { + args[1] = (args[1].stack || args[1].toString()) + '\n'; + } else if (args[1] === null || args[1] === undefined) { + args[1] = ''; + } + + typeof type !== 'string' && (args[1] = '' + args[1]); + + // call the original logger with our cleaned up args + origLoggerLog.apply(logger, arguments); + + // restore padding + logger.padLevels = padLevels; + }; + + logger.log.init = function (callback) { + function styleHeading(s) { + return ('' + s).bold; + } + + function styleValue(s) { + return ('' + s).magenta; + } + + function rpad(s) { + return s.padEnd(27); + } + + cli.env.getOSInfo(function (osInfo) { + logger.log([ + new Date().toLocaleString(), + '', + styleHeading('Operating System'), + ' ' + rpad('Name') + ' = ' + styleValue(osInfo.os), + ' ' + rpad('Version') + ' = ' + styleValue(osInfo.osver), + ' ' + rpad('Architecture') + ' = ' + styleValue(osInfo.ostype), + ' ' + rpad('# CPUs') + ' = ' + styleValue(osInfo.oscpu), + ' ' + rpad('Memory') + ' = ' + styleValue(osInfo.memory), + '', + styleHeading('Node.js'), + ' ' + rpad('Node.js Version') + ' = ' + styleValue(osInfo.node), + ' ' + rpad('npm Version') + ' = ' + styleValue(osInfo.npm), + '', + styleHeading('Titanium CLI'), + ' ' + rpad('CLI Version') + ' = ' + styleValue(cli.version), + '', + styleHeading('Titanium SDK'), + ' ' + rpad('SDK Version') + ' = ' + styleValue(cli.argv.sdk), + ' ' + rpad('SDK Path') + ' = ' + styleValue(cli.sdk.path), + ' ' + rpad('Target Platform') + ' = ' + styleValue(ti.resolvePlatform(cli.argv.platform)), + '', + styleHeading('Command'), + ' ' + styleValue(process.argv.join(' ')), + '' + ].join('\n')); + + logger.log.flush(); + callback(); + }); + }; + + logger.log.flush = function () { + }; + + logger.log.end = function () { + }; + + logger.log.buffer = ''; +} diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/commands/create.js b/test/titanium/sdk/mocks/mock-sdk/cli/commands/create.js new file mode 100644 index 00000000..8ba1e084 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/commands/create.js @@ -0,0 +1,123 @@ +'use strict'; + +const fields = require('fields'); +const fs = require('fs'); +const path = require('path'); +const ti = require('../lib/node-titanium-sdk/ti'); + +exports.cliVersion = '>=3.2.1'; +exports.title = 'Create'; +exports.desc = 'creates a new project'; +exports.extendedDesc = 'Creates a new Titanium application, native module, or Apple Watch™ app.\n\n' + + 'Apple, iPhone, and iPad are registered trademarks of Apple Inc. Apple Watch is a trademark of Apple Inc.\n\n' + + 'Android is a trademark of Google Inc.'; + +function CreateCommand() { + this.creators = {}; +} + +CreateCommand.prototype.config = function config(logger, config, cli) { + this.logger = logger; + this.config = config; + this.cli = cli; + + fields.setup({ colors: cli.argv.colors }); + + return finished => { + // find and load the creators + const creatorDir = path.join(__dirname, '..', 'lib', 'creators'); + const jsRegExp = /\.js$/; + const typeConf = {}; + + fs.readdirSync(creatorDir).reduce((promise, filename) => { + return promise.then(() => new Promise(resolve => { + if (!jsRegExp.test(filename)) { + return resolve(); + } + + const CreatorConstructor = require(path.join(creatorDir, filename)); + const creator = new CreatorConstructor(logger, config, cli); + this.creators[creator.type] = creator; + + try { + if (typeof creator.init === 'function') { + if (creator.init.length > 1) { + typeConf[creator.type] = creator.init(function (conf) { + typeConf[creator.type] = conf; + resolve(); + }); + return; + } + typeConf[creator.type] = creator.init(); + } + } catch (ex) { + // squeltch + delete this.creators[creator.type]; + } finally { + resolve(); + } + })); + }, Promise.resolve()) + .then(() => { + cli.createHook('create.config', this, callback => { + const conf = { + flags: { + force: { + abbr: 'f', + desc: 'force project creation even if path already exists' + } + }, + options: Object.assign({ + type: { + abbr: 't', + default: cli.argv.prompt ? undefined : 'app', + desc: 'the type of project to create', + order: 100, + prompt: callback => { + callback(fields.select({ + title: 'What type of project would you like to create?', + promptLabel: 'Select a type by number or name', + default: 'app', + margin: '', + numbered: true, + relistOnError: true, + complete: true, + suggest: false, + options: Object.keys(this.creators) + .map(function (type) { + return { + label: this.creators[type].title || type, + value: type, + order: this.creators[type].titleOrder + }; + }, this) + .sort(function (a, b) { + return a.order < b.order ? -1 : a.order > b.order ? 1 : 0; + }) + })); + }, + required: true, + values: Object.keys(this.creators) + } + }, ti.commonOptions(logger, config)), + type: typeConf + }; + + callback(null, conf); + })((_err, result) => finished(result)); + }) + .catch(err => { + console.log(err); + }); + }; +}; + +CreateCommand.prototype.run = function run(_logger, _config, _cli, finished) { + finished(); +}; + +// create the builder instance and expose the public API +(function (createCommand) { + exports.config = createCommand.config.bind(createCommand); + exports.run = createCommand.run.bind(createCommand); +}(new CreateCommand())); diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/commands/project.js b/test/titanium/sdk/mocks/mock-sdk/cli/commands/project.js new file mode 100644 index 00000000..b5533a29 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/commands/project.js @@ -0,0 +1,70 @@ +'use strict'; + +const ti = require('../lib/node-titanium-sdk/ti'); + +exports.cliVersion = '>=3.2.1'; +exports.desc = 'get and set tiapp.xml settings'; +exports.extendedDesc = [ + 'Get and set tiapp.xml settings.', + `Run ${'titanium project --project-dir /path/to/project'.cyan} to see all available entries that can be changed.`, + [ + `When setting the ${'deployment-targets'.cyan} entry, it will non-destructively copy each specified `, + 'platform\'s default resources into your project\'s Resources folder. For ', + `example, if your app currently supports ${'iphone'.cyan} and you wish to add Android `, + `support, you must specify ${'iphone,android'.cyan}, otherwise only specifying ${'android'.cyan} will remove `, + 'support for iPhone.' + ].join('') +].join('\n\n'); + +exports.config = function (logger, config) { + return { + skipBanner: true, + options: Object.assign({ + output: { + abbr: 'o', + default: 'report', + desc: 'output format', + values: ['report', 'json', 'text'] + }, + 'project-dir': { + desc: 'the directory of the project to analyze', + default: '.' + }, + template: { + desc: 'the name of the project template to use', + default: 'default' + } + }, ti.commonOptions(logger, config)), + args: [ + { + name: 'key', + desc: 'the key to get or set' + }, + { + name: 'value', + desc: 'the value to set the specified key' + } + ] + }; +}; + +exports.validate = function (logger, config, cli) { + ti.validateProjectDir(logger, cli, cli.argv, 'project-dir'); + + // Validate the key, if it exists + if (cli.argv._.length > 0) { + const key = cli.argv._[0]; + if (!/^([A-Za-z_]{1}[A-Za-z0-9-_]*(\.[A-Za-z-_]{1}[A-Za-z0-9-_]*)*)$/.test(key)) { + logger.error(`Invalid key "${key}"\n`); + process.exit(1); + } + } + + return function (finished) { + ti.loadPlugins(null, config, cli, cli.argv['project-dir'], finished, cli.argv.output !== 'report' || cli.argv._.length, false); + }; +}; + +exports.run = function (_logger, _config, _cli, finished) { + finished(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/hooks/hyperloop-fix.js b/test/titanium/sdk/mocks/mock-sdk/cli/hooks/hyperloop-fix.js new file mode 100644 index 00000000..52589070 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/hooks/hyperloop-fix.js @@ -0,0 +1,9 @@ +'use strict'; + +exports.id = 'com.appcelerator.hyperloop-fix'; + +exports.init = function init(_logger, _config, cli, _appc) { + cli.env.os.sdkPaths.forEach(_sdkPath => { + // noop + }); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/creator.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creator.js new file mode 100644 index 00000000..d8dfc2af --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creator.js @@ -0,0 +1,336 @@ +'use strict'; + +const fields = require('fields'); +const fs = require('fs'); +const http = require('http'); +const path = require('path'); +const ti = require('./node-titanium-sdk/ti'); + +module.exports = Creator; + +function Creator(logger, config, cli) { + this.logger = logger; + this.config = config; + this.cli = cli; + + this.availablePlatforms = []; + this.validPlatforms = {}; +} + +Creator.prototype.init = function init() { + // stub +}; + +Creator.prototype.run = function run() { + this.projectType = this.cli.argv.type; + this.sdk = this.cli.env.getSDK(this.cli.argv.sdk); +}; + +Creator.prototype.configOptionId = function configOptionId(order) { + const cli = this.cli, + config = this.config, + logger = this.logger, + idPrefix = config.get('app.idprefix'); + + function validate(value, callback) { + if (!value) { + logger.error('Please specify an App ID\n'); + return callback(true); + } + + // general app id validation + if (!/^([a-zA-Z_]{1}[a-zA-Z0-9_-]*(\.[a-zA-Z0-9_-]*)*)$/.test(value)) { + logger.error(`Invalid App ID "${value}"`); + logger.error('The App ID must consist of letters, numbers, dashes, and underscores.'); + logger.error('Note: Android does not allow dashes and iOS does not allow underscores.'); + logger.error('The first character must be a letter or underscore.'); + logger.error('Usually the App ID is your company\'s reversed Internet domain name. (e.g. com.example.myapp)\n'); + return callback(true); + } + + if (cli.argv.type !== 'app' || cli.argv.platforms.indexOf('android') !== -1) { + if (value.indexOf('-') !== -1) { + logger.error(`Invalid App ID "${value}"`); + logger.error(`Dashes are not allowed in the App ID when targeting ${'Android'.cyan}.\n`); + return callback(true); + } + + if (!/^([a-zA-Z_]{1}[a-zA-Z0-9_]*(\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*)$/.test(value)) { + logger.error(`Invalid App ID "${value}"`); + logger.error(`Numbers are not allowed directly after periods when targeting ${'Android'.cyan}.\n`); + return callback(true); + } + + if (!ti.validAppId(value)) { + logger.error(`Invalid App ID "${value}"`); + logger.error(`The app must not contain Java reserved words when targeting ${'Android'.cyan}.\n`); + return callback(true); + } + } else { + // Android is not in the list of platforms + let counter = 0; + + if (value.indexOf('-') !== -1) { + logger.warn('The specified App ID is not compatible with the Android platform.'); + logger.warn('Android does not allow dashes in the App ID.'); + counter++; + } + + if (!/^([a-zA-Z_]{1}[a-zA-Z0-9_]*(\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*)$/.test(value)) { + counter || logger.warn('The specified App ID is not compatible with the Android platform.'); + logger.warn('Android does not allow numbers directly following periods in the App ID.'); + counter++; + } + + if (!ti.validAppId(value)) { + counter || logger.warn('The specified App ID is not compatible with the Android platform.'); + logger.warn('Android does not allow Java reserved words in the App ID.'); + counter++; + } + + counter && logger.warn('If you wish to add Android support, you will need to fix the in the tiapp.xml.\n'); + } + + if (value.indexOf('_') !== -1) { + if (cli.argv.type !== 'app' && (cli.argv.platforms.indexOf('ios') !== -1 || cli.argv.platforms.indexOf('iphone') !== -1 || cli.argv.platforms.indexOf('ipad') !== -1)) { + logger.error(`Invalid App ID "${value}"`); + logger.error(`Underscores are not allowed in the App ID when targeting ${'iOS'.cyan}.\n`); + return callback(true); + } else { + logger.warn('The specified App ID is not compatible with the iOS platform.'); + logger.warn('iOS does not allow underscores in the App ID.'); + logger.warn('If you wish to add iOS support, you will need to fix the in the tiapp.xml.\n'); + } + } + + callback(null, value); + } + + return { + desc: 'the App ID in the format \'com.companyname.appname\'', + order: order, + prompt(callback) { + let defaultValue; + const name = cli.argv.name.replace(/[^a-zA-Z0-9]/g, ''); + if (idPrefix) { + defaultValue = idPrefix.replace(/\.$/, '') + '.' + (/^[a-zA-Z]/.test(name) || (cli.argv.type === 'app' && cli.argv.platforms.indexOf('android') === -1) ? '' : 'my') + name; + } + + callback(fields.text({ + default: defaultValue, + promptLabel: 'App ID', + validate: validate + })); + }, + required: true, + validate: validate + }; +}; + +Creator.prototype.configOptionCodeBase = function configCodeBase(order) { + const cli = this.cli; + const validTypes = ['swift', 'objc']; + const logger = this.logger; + + function validate(value, callback) { + if (!value || !validTypes.includes(value)) { + logger.error('Please specify a valid code base\n'); + return callback(true); + } + callback(null, value); + } + + return { + abbr: 'c', + desc: 'the code base of the iOS project', + order: order, + default: !cli.argv.prompt ? 'objc' : undefined, // if we're prompting, then force the platforms to be prompted for, otherwise force 'all' + required: false, + validate: validate, + values: validTypes, + hidden: true + }; +}; + +Creator.prototype.configOptionName = function configOptionName(order) { + const cli = this.cli; + const config = this.config; + const logger = this.logger; + + function validate(value, callback) { + if (!value) { + logger.error('Please specify a project name\n'); + return callback(true); + } + + if ((cli.argv.type !== 'app' || cli.argv.platforms.indexOf('android') !== -1) && value.indexOf('&') !== -1) { + if (config.get('android.allowAppNameAmpersands', false)) { + logger.warn('The project name contains an ampersand (&) which will most likely cause problems.'); + logger.warn('It is recommended that you change the app name in the tiapp.xml or define the app name using i18n strings.'); + logger.warn('Refer to %s for more information.', 'https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_How-tos/Cross-Platform_Mobile_Development_In_Titanium/Internationalization.html'.cyan); + } else { + logger.error('The project name contains an ampersand (&) which will most likely cause problems.'); + logger.error('It is recommended that you change the app name in the tiapp.xml or define the app name using i18n strings.'); + logger.error('Refer to %s for more information.', 'https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_How-tos/Cross-Platform_Mobile_Development_In_Titanium/Internationalization.html'); + logger.error('To allow ampersands in the app name, run:'); + logger.error(' %sti config android.allowAppNameAmpersands true\n', process.env.APPC_ENV ? 'appc ' : ''); + return callback(true); + } + } + + callback(null, value); + } + + return { + abbr: 'n', + desc: 'the name of the project', + order: order, + prompt(callback) { + callback(fields.text({ + promptLabel: 'Project name', + validate: validate + })); + }, + required: true, + validate: validate + }; +}; + +Creator.prototype.configOptionPlatforms = function configOptionPlatforms(order) { + const cli = this.cli; + const logger = this.logger; + const availablePlatforms = this.availablePlatforms; + const validPlatforms = this.validPlatforms; + + function validate(value, callback) { + // just in case they set -p or --platforms without a value + if (value === true || value === '') { + logger.error(`Invalid platforms value "${value}"\n`); + return callback(true); + } + + let goodValues = {}; + const badValues = {}; + value.trim().toLowerCase().split(',').forEach(function (s) { + if (s = s.trim()) { + if (validPlatforms[s]) { + goodValues[s] = 1; + } else { + badValues[s] = 1; + } + } + }, this); + + const badLen = Object.keys(badValues).length; + if (badLen) { + logger.error(`Invalid platform: ${Object.keys(badValues).join(', ')}\n`); + return callback(true); + } + + if (goodValues.ios) { + goodValues.iphone = 1; + goodValues.ipad = 1; + delete goodValues.ios; + } + + if (goodValues.all) { + goodValues = {}; + availablePlatforms.forEach(function (p) { + if (p !== 'all') { + goodValues[p] = 1; + } + }); + } + + callback(null, Object.keys(goodValues).join(',')); + } + + return { + abbr: 'p', + default: !cli.argv.prompt ? 'all' : undefined, // if we're prompting, then force the platforms to be prompted for, otherwise force 'all' + desc: 'one or more target platforms.', + order: order, + prompt(callback) { + callback(fields.text({ + promptLabel: `Target platform (${availablePlatforms.join('|')})`, + default: 'all', + validate: validate + })); + }, + required: true, + skipValueCheck: true, + validate: validate, + values: availablePlatforms + }; +}; + +Creator.prototype.configOptionTemplate = function configOptionTemplate(order, defaultValue) { + return { + desc: 'the name of the project template, path to template dir, path to zip file, or URL to zip file', + default: defaultValue || 'default', + order: order, + required: true + }; +}; + +Creator.prototype.configOptionWorkspaceDir = function configOptionWorkspaceDir(order) { + const cli = this.cli, + config = this.config, + logger = this.logger; + let workspaceDir = config.app.workspace ? path.resolve(config.app.workspace) : null; + + workspaceDir && !fs.existsSync(workspaceDir) && (workspaceDir = null); + + function validate(dir, callback) { + if (!dir) { + logger.error('Please specify the workspace directory\n'); + return callback(true); + } + + dir = path.resolve(dir); + + // check if the directory is writable + let prev = null; + let curr = dir; + while (curr != prev) { + if (fs.existsSync(curr)) { + break; + } + + prev = curr; + curr = path.dirname(curr); + } + + // check if the project already exists + if (cli.argv.name && !cli.argv.force && dir) { + const projectDir = path.join(dir, cli.argv.name); + if (fs.existsSync(projectDir)) { + logger.error(`Project already exists: ${projectDir}`); + logger.error('Either change the project name, workspace directory, or re-run this command with the --force flag.\n'); + process.exit(1); + } + } + + callback(null, dir); + } + + return { + abbr: 'd', + default: !cli.argv.prompt && workspaceDir || undefined, + desc: 'the directory to place the project in', + order: order, + prompt(callback) { + callback(fields.file({ + complete: true, + default: workspaceDir || '.', + ignoreDirs: new RegExp(config.get('cli.ignoreDirs')), + ignoreFiles: new RegExp(config.get('cli.ignoreFiles')), + promptLabel: 'Directory to place project', + showHidden: true, + validate: validate + })); + }, + required: true, + validate: validate + }; +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/app.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/app.js new file mode 100644 index 00000000..c3681a45 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/app.js @@ -0,0 +1,53 @@ +'use strict'; + +const Creator = require('../creator'); +const ti = require('../node-titanium-sdk/ti'); +const util = require('util'); + +module.exports = AppCreator; + +function AppCreator(_logger, _config, _cli) { + Creator.apply(this, arguments); + + this.title = 'Titanium App'; + this.titleOrder = 1; + this.type = 'app'; + + // build list of all valid platforms + const availablePlatforms = {}; + const validPlatforms = {}; + + ti.platforms.forEach(platform => { + if (/^iphone|ios|ipad$/.test(platform)) { + validPlatforms['iphone'] = availablePlatforms['iphone'] = 1; + validPlatforms['ipad'] = availablePlatforms['ipad'] = 1; + validPlatforms['ios'] = 1; + } else { + validPlatforms[platform] = availablePlatforms[platform] = 1; + } + }); + + // add "all" + validPlatforms['all'] = 1; + + this.availablePlatforms = ['all', ...Object.keys(availablePlatforms)]; + this.validPlatforms = validPlatforms; +} + +util.inherits(AppCreator, Creator); + +AppCreator.prototype.init = function init() { + return { + options: { + id: this.configOptionId(150), + name: this.configOptionName(140), + platforms: this.configOptionPlatforms(120), + template: this.configOptionTemplate(110), + 'workspace-dir': this.configOptionWorkspaceDir(170) + } + }; +}; + +AppCreator.prototype.run = function run(callback) { + callback(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/module.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/module.js new file mode 100644 index 00000000..521e7dbf --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/creators/module.js @@ -0,0 +1,130 @@ +'use strict'; + +const Creator = require('../creator'); +const ti = require('../node-titanium-sdk/ti'); +const util = require('util'); +const fields = require('fields'); + +module.exports = ModuleCreator; + +function ModuleCreator(_logger, _config, _cli) { + Creator.apply(this, arguments); + + this.title = 'Titanium Module'; + this.titleOrder = 2; + this.type = 'module'; + + // build list of all valid platforms + const availablePlatforms = {}; + const validPlatforms = {}; + + ti.platforms.forEach(platform => { + if (/^iphone|ios|ipad$/.test(platform)) { + validPlatforms['iphone'] = 1; + validPlatforms['ipad'] = 1; + validPlatforms['ios'] = availablePlatforms['ios'] = 1; + } else { + validPlatforms[platform] = availablePlatforms[platform] = 1; + } + }); + + // add "all" + validPlatforms['all'] = 1; + + this.availablePlatforms = ['all', ...Object.keys(availablePlatforms)]; + this.validPlatforms = validPlatforms; +} + +util.inherits(ModuleCreator, Creator); + +ModuleCreator.prototype.init = function init() { + return { + options: { + id: this.configOptionId(150), + name: this.configOptionName(140), + platforms: this.configOptionPlatforms(120), + template: this.configOptionTemplate(110), + 'workspace-dir': this.configOptionWorkspaceDir(170), + 'code-base': this.configOptionCodeBase(150), + 'android-code-base': this.configOptionAndroidCodeBase(150), + 'ios-code-base': this.configOptionIosCodeBase(140) + + } + }; +}; + +ModuleCreator.prototype.configOptionAndroidCodeBase = function configAndroidCodeBase(order) { + const cli = this.cli; + const validTypes = ['java', 'kotlin']; + const logger = this.logger; + + function validate(value, callback) { + if (!value || !validTypes.includes(value)) { + logger.error('Please specify a valid code base\n'); + return callback(true); + } + callback(null, value); + } + + return { + desc: 'the code base of the Android project', + order: order, + default: !cli.argv.prompt ? 'java' : undefined, + prompt(callback) { + callback(fields.text({ + promptLabel: `Android code base (${validTypes.join('|')})`, + default: 'java', + validate: validate + })); + }, + required: true, + validate: validate, + values: validTypes, + verifyIfRequired(callback) { + if (cli.argv.platforms.includes('android')) { + return callback(true); + } + return callback(); + } + }; +}; + +ModuleCreator.prototype.configOptionIosCodeBase = function configIosCodeBase(order) { + const cli = this.cli; + const validTypes = ['swift', 'objc']; + const logger = this.logger; + + function validate(value, callback) { + if (!value || !validTypes.includes(value)) { + logger.error('Please specify a valid code base\n'); + return callback(true); + } + callback(null, value); + } + + return { + desc: 'the code base of the iOS project', + order: order, + default: !cli.argv.prompt ? 'objc' : undefined, // if we're prompting, then force the platforms to be prompted for, otherwise force 'all' + prompt(callback) { + callback(fields.text({ + promptLabel: `iOS code base (${validTypes.join('|')})`, + default: 'objc', + validate: validate + })); + }, + required: true, + validate: validate, + values: validTypes, + verifyIfRequired(callback) { + if (cli.argv.platforms.includes('ios') || cli.argv.platforms.includes('iphone') || cli.argv.platforms.includes('ipad')) { + return callback(true); + } + return callback(); + } + }; +}; + +ModuleCreator.prototype.run = function run(callback) { + callback(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/info.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/info.js new file mode 100644 index 00000000..88885e4d --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/info.js @@ -0,0 +1,70 @@ +/* + * info.js: Titanium Mobile General SDK-Level "info" command module. + * + * Copyright TiDev, Inc. 04/07/2022-Present All Rights Reserved. + * See the LICENSE file for more information. + */ + +'use strict'; + +const appc = require('node-appc'), + fs = require('fs'), + path = require('path'), + genymotion = require('node-titanium-sdk/lib/emulators/genymotion'), + __ = appc.i18n(__dirname).__; + +exports.name = 'miscinfo'; + +exports.title = 'Misc Info'; + +exports.detect = function (types, config, callback) { + const results = this.data = {}, + tisdk = path.basename((function scan(dir) { + const file = path.join(dir, 'manifest.json'); + if (fs.existsSync(file)) { + return dir; + } + dir = path.dirname(dir); + return dir !== '/' && scan(dir); + }(__dirname))); + + appc.async.parallel(this, [ + function (next) { + genymotion.detect(config, null, function (err, genymotionInfo) { + if (err) { + return next(err); + } + + genymotionInfo.tisdk = tisdk; + results.genymotion = genymotionInfo; + + if (genymotionInfo.issues.length) { + this.issues = this.issues.concat(genymotionInfo.issues); + } + + next(); + }.bind(this)); + } + ], function (err) { + callback(err, results); + }); +}; + +exports.render = function (logger, config, rpad, styleHeading, styleValue) { + const data = this.data; + if (!data) { + return; + } + + logger.log(styleHeading(__('Genymotion')) + '\n' + + ' ' + rpad(__('Path')) + ' = ' + styleValue(data.genymotion.path || __('not found')) + '\n' + + ' ' + rpad(__('Genymotion Executable')) + ' = ' + styleValue(data.genymotion.executables && data.genymotion.executables.genymotion || __('not found')) + '\n' + + ' ' + rpad(__('Genymotion Player')) + ' = ' + styleValue(data.genymotion.executables && data.genymotion.executables.player || __('not found')) + '\n' + + ' ' + rpad(__('Home')) + ' = ' + styleValue(data.genymotion.home || __('not found')) + '\n' + ); + + logger.log(styleHeading(__('VirtualBox')) + '\n' + + ' ' + rpad(__('Executable')) + ' = ' + styleValue(data.genymotion.executables && data.genymotion.executables.vboxmanage || __('not found')) + '\n' + + ' ' + rpad(__('Version')) + ' = ' + styleValue(data.genymotion.virtualbox || __('unknown')) + '\n' + ); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/builder.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/builder.js new file mode 100644 index 00000000..714cb7da --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/builder.js @@ -0,0 +1,72 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const ti = require('./ti'); + +module.exports = Builder; + +function Builder(buildModule) { + this.titaniumSdkPath = (function scan(dir) { + const file = path.join(dir, 'manifest.json'); + if (fs.existsSync(file)) { + return dir; + } + dir = path.dirname(dir); + return dir !== '/' && scan(dir); + }(__dirname)); + + this.titaniumSdkName = path.basename(this.titaniumSdkPath); + + this.titaniumSdkVersion = ti.manifest.version; + + this.platformPath = (function scan(dir) { + const file = path.join(dir, 'package.json'); + if (fs.existsSync(file)) { + return dir; + } + dir = path.dirname(dir); + return dir !== '/' && scan(dir); + }(path.dirname(buildModule.filename))); + + this.platformName = path.basename(this.platformPath); + + this.globalModulesPath = path.join(this.titaniumSdkPath, '..', '..', '..', 'modules'); + + this.packageJson = require(path.join(this.platformPath, 'package.json')); + + this.conf = {}; + + this.buildDirFiles = {}; +} + +Builder.prototype.config = function config(logger, config, cli) { + // note: this function must be sync! + this.logger = logger; + this.config = config; + this.cli = cli; + this.symlinkFilesOnCopy = false; + this.ignoreDirs = new RegExp(config.get('cli.ignoreDirs')); + this.ignoreFiles = new RegExp(config.get('cli.ignoreFiles')); +}; + +Builder.prototype.validate = function validate(logger, config, cli) { + // note: this function must be sync! + + this.tiapp = cli.tiapp; + this.timodule = cli.timodule; + this.projectDir = cli.argv['project-dir']; + this.buildDir = path.join(this.projectDir, 'build', this.platformName); + + this.defaultIcons = [ + path.join(this.projectDir, 'DefaultIcon-' + this.platformName + '.png'), + path.join(this.projectDir, 'DefaultIcon.png') + ]; +}; + +Builder.prototype.run = function run(_logger, _config, _cli, _finished) { +}; + +Builder.prototype.validateTiModules = function validateTiModules(_platformName, _deployType, callback) { + callback(null, []); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/ti.js b/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/ti.js new file mode 100644 index 00000000..70104213 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/cli/lib/node-titanium-sdk/ti.js @@ -0,0 +1,313 @@ +const fs = require('fs'); +const path = require('path'); + +const manifest = { + platforms: ['android'], + sdkVersion: '0.0.0.GA' +}; +const platformAliases = { + // add additional aliases here for new platforms + ipad: 'iphone', + ios: 'iphone' +}; + +exports.manifest = manifest; +exports.platforms = manifest.platforms; +exports.targetPlatforms = ['android']; +exports.availablePlatforms = ['android']; +exports.availablePlatformsNames = ['Android']; +exports.allPlatformNames = ['android', 'ios', 'iphone', 'ipad', 'mobileweb', 'blackberry', 'windows', 'tizen']; + +function commonOptions(logger, config) { + return { + 'log-level': { + abbr: 'l', + callback(value) { + Object.prototype.hasOwnProperty.call(logger.levels, value) && logger.setLevel(value); + }, + desc: 'minimum logging level', + default: config.cli.logLevel || 'trace', + hint: 'level', + values: logger.getLevels() + } + }; +} + +function loadPlugins(_logger, config, cli, projectDir, finished, silent, compact) { + let searchPaths = { + project: [path.join(projectDir, 'plugins')], + config: [], + global: [] + }; + let confPaths = config.get('paths.plugins'); + let defaultInstallLocation = cli.env.installPath; + let sdkLocations = cli.env.os.sdkPaths.map(function (p) { return path.resolve(p); }); + + // set our paths from the config file + Array.isArray(confPaths) || (confPaths = [ confPaths ]); + confPaths.forEach(function (p) { + p && fs.existsSync(p = path.resolve(p)) && searchPaths.project.indexOf(p) === -1 && searchPaths.config.indexOf(p) === -1 && (searchPaths.config.push(p)); + }); + + // add any plugins from various SDK locations + sdkLocations.indexOf(defaultInstallLocation) === -1 && sdkLocations.push(defaultInstallLocation); + cli.sdk && sdkLocations.push(path.resolve(cli.sdk.path, '..', '..', '..')); + sdkLocations.forEach(p => { + p = path.resolve(p, 'plugins'); + if (fs.existsSync(p) && searchPaths.project.indexOf(p) === -1 && searchPaths.config.indexOf(p) === -1 && searchPaths.global.indexOf(p) === -1) { + searchPaths.global.push(p); + } + }); + + if (!silent) { + cli.emit('cli:check-plugins', { compact: compact === undefined ? true : compact }); + } + + finished(); +} + +function platformOptions(logger, config, cli, commandName, finished) { + const result = {}; + let targetPlatform = !cli.argv.help && (cli.argv.platform || cli.argv.p); + + if (!commandName) { + finished(result); + return; + } + + function set(obj, title, platform) { + // add the platform and title to the options and flags + ['options', 'flags'].forEach(type => { + if (obj && obj[type]) { + result[platform] || (result[platform] = { + platform: platform, + title: title || platform + }); + result[platform][type] = obj[type]; + } + }); + } + + // translate the platform name + targetPlatform = platformAliases[targetPlatform] || targetPlatform; + + // for each platform, fetch their specific flags/options + manifest.platforms.reduce((promise, platform) => { + return promise.then(() => new Promise(resolve => { + // only configure target platform + if (targetPlatform && platform !== targetPlatform) { + return resolve(); + } + + let platformDir = path.join(path.dirname(module.filename), '..', '..', '..', platform); + let platformCommand = path.join(platformDir, 'cli', 'commands', '_' + commandName + '.js'); + let command; + let conf; + let title; + + if (!fs.existsSync(platformCommand)) { + return resolve(); + } + + command = require(platformCommand); + if (!command || !command.config) { + return resolve(); + } + + // try to get the platform specific configuration + conf = command.config(logger, config, cli); + + try { + // try to read a title from the platform's package.json + title = JSON.parse(fs.readFileSync(path.join(platformDir, 'package.json'))).title; + } catch (e) {} + + if (typeof conf === 'function') { + // async callback + conf(function (obj) { + set(obj, title, platform); + resolve(); + }); + return; + } + + set(conf, title, platform); + resolve(); + })); + }, Promise.resolve()) + .then(() => finished(result)) + .catch(() => finished(result)); +} + +function resolvePlatform(platform) { + return platformAliases[platform] || platform; +} + +function scrubPlatforms(platforms) { + const scrubbed = {}; // distinct list of un-aliased platforms + const original = {}; + const bad = {}; + + platforms.toLowerCase().split(',').forEach(platform => { + const name = platformAliases[platform] || platform; + // if name is falsey, then it's invalid anyways + if (name) { + if (manifest.platforms.indexOf(name) === -1) { + bad[platform] = 1; + } else { + scrubbed[name] = 1; + original[platform] = 1; + } + } + }); + + return { + scrubbed: Object.keys(scrubbed).sort(), // distinct list of un-aliased platforms + original: Object.keys(original).sort(), + bad: Object.keys(bad).sort() + }; +} + +function validAppId(id) { + const words = { + abstract: 1, + assert: 1, + boolean: 1, + break: 1, + byte: 1, + case: 1, + catch: 1, + char: 1, + class: 1, + const: 1, + continue: 1, + default: 1, + do: 1, + double: 1, + else: 1, + enum: 1, + extends: 1, + false: 1, + final: 1, + finally: 1, + float: 1, + for: 1, + goto: 1, + if: 1, + implements: 1, + import: 1, + instanceof: 1, + int: 1, + interface: 1, + long: 1, + native: 1, + new: 1, + null: 1, + package: 1, + private: 1, + protected: 1, + public: 1, + return: 1, + short: 1, + static: 1, + strictfp: 1, + super: 1, + switch: 1, + synchronized: 1, + this: 1, + throw: 1, + throws: 1, + transient: 1, + true: 1, + try: 1, + void: 1, + volatile: 1, + while: 1 + }; + const parts = id.split('.'); + const l = parts.length; + + for (let i = 0; i < l; i++) { + if (words[parts[i]]) { + return false; + } + } + + return true; +} + +function validateModuleManifest(logger, cli, manifest) { + const requiredModuleKeys = [ + 'name', + 'version', + 'moduleid', + 'description', + 'copyright', + 'license', + 'copyright', + 'platform', + 'minsdk', + 'architectures' + ]; + + // check if all the required module keys are in the list + requiredModuleKeys.forEach(function (key) { + if (!manifest[key]) { + logger.error(`Missing required manifest key "${key}"`); + logger.log(); + process.exit(1); + } + }); + + if (cli.argv.platform !== resolvePlatform(manifest.platform)) { + logger.error(`Unable to find "${cli.argv.platform}" module`); + logger.log(); + process.exit(1); + } +} + +function validatePlatformOptions(logger, config, cli, commandName) { + const platform = exports.resolvePlatform(cli.argv.platform), + platformCommand = path.join(path.dirname(module.filename), '..', '..', '..', manifest.platforms[manifest.platforms.indexOf(platform)], 'cli', 'commands', '_' + commandName + '.js'); + if (fs.existsSync(platformCommand)) { + const command = require(platformCommand); + return command && typeof command.validate === 'function' ? command.validate(logger, config, cli) : null; + } +} + +function validateProjectDir(logger, cli, argv, name) { + const dir = argv[name] || '.'; + let projectDir = argv[name] = path.resolve(dir); + + if (!fs.existsSync(projectDir)) { + logger.banner(); + logger.error('Project directory does not exist\n'); + process.exit(1); + } + + let tiapp = path.join(projectDir, 'tiapp.xml'); + while (!fs.existsSync(tiapp) && tiapp.split(path.sep).length > 2) { + projectDir = argv[name] = path.dirname(projectDir); + tiapp = path.join(projectDir, 'tiapp.xml'); + } + + if (tiapp.split(path.sep).length === 2) { + logger.banner(); + logger.error(`Invalid project directory "${dir}"\n`); + dir === '.' && logger.log(`Use the ${'--project-dir'.cyan} property to specify the project's directory\n`); + process.exit(1); + } + + // load the tiapp.xml + cli.tiapp = {}; +} + +exports.commonOptions = commonOptions; +exports.loadPlugins = loadPlugins; +exports.platformOptions = platformOptions; +exports.resolvePlatform = resolvePlatform; +exports.scrubPlatforms = scrubPlatforms; +exports.validAppId = validAppId; +exports.validateModuleManifest = validateModuleManifest; +exports.validatePlatformOptions = validatePlatformOptions; +exports.validateProjectDir = validateProjectDir; diff --git a/test/titanium/sdk/mocks/mock-sdk/manifest.json b/test/titanium/sdk/mocks/mock-sdk/manifest.json new file mode 100644 index 00000000..901c8ef8 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.GA","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/MIT-LICENSE.txt b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/MIT-LICENSE.txt new file mode 100644 index 00000000..7dca1070 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/MIT-LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/ReadMe.md b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/ReadMe.md new file mode 100644 index 00000000..0eda52db --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/ReadMe.md @@ -0,0 +1,77 @@ +# colors.js - get color and style in your node.js console ( and browser ) like what + + + + +## Installation + + npm install colors + +## colors and styles! + +- bold +- italic +- underline +- inverse +- yellow +- cyan +- white +- magenta +- green +- red +- grey +- blue +- rainbow +- zebra +- random + +## Usage + +``` js +var colors = require('./colors'); + +console.log('hello'.green); // outputs green text +console.log('i like cake and pies'.underline.red) // outputs red underlined text +console.log('inverse the color'.inverse); // inverses the color +console.log('OMG Rainbows!'.rainbow); // rainbow (ignores spaces) +``` + +# Creating Custom themes + +```js + +var colors = require('colors'); + +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); +``` + + +### Contributors + +Marak (Marak Squires) +Alexis Sellier (cloudhead) +mmalecki (Maciej Małecki) +nicoreed (Nico Reed) +morganrallen (Morgan Allen) +JustinCampbell (Justin Campbell) +ded (Dustin Diaz) + + +#### , Marak Squires , Justin Campbell, Dustin Diaz (@ded) diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/colors.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/colors.js new file mode 100644 index 00000000..7a537d8d --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/colors.js @@ -0,0 +1,342 @@ +/* +colors.js + +Copyright (c) 2010 + +Marak Squires +Alexis Sellier (cloudhead) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +var isHeadless = false; + +if (typeof module !== 'undefined') { + isHeadless = true; +} + +if (!isHeadless) { + var exports = {}; + var module = {}; + var colors = exports; + exports.mode = "browser"; +} else { + exports.mode = "console"; +} + +// +// Prototypes the string object to have additional method calls that add terminal colors +// +var addProperty = function (color, func) { + exports[color] = function (str) { + return func.apply(str); + }; + String.prototype.__defineGetter__(color, func); +}; + +function stylize(str, style) { + + var styles; + + if (exports.mode === 'console') { + styles = { + //styles + 'bold' : ['\x1B[1m', '\x1B[22m'], + 'italic' : ['\x1B[3m', '\x1B[23m'], + 'underline' : ['\x1B[4m', '\x1B[24m'], + 'inverse' : ['\x1B[7m', '\x1B[27m'], + 'strikethrough' : ['\x1B[9m', '\x1B[29m'], + //text colors + //grayscale + 'white' : ['\x1B[37m', '\x1B[39m'], + 'grey' : ['\x1B[90m', '\x1B[39m'], + 'black' : ['\x1B[30m', '\x1B[39m'], + //colors + 'blue' : ['\x1B[34m', '\x1B[39m'], + 'cyan' : ['\x1B[36m', '\x1B[39m'], + 'green' : ['\x1B[32m', '\x1B[39m'], + 'magenta' : ['\x1B[35m', '\x1B[39m'], + 'red' : ['\x1B[31m', '\x1B[39m'], + 'yellow' : ['\x1B[33m', '\x1B[39m'], + //background colors + //grayscale + 'whiteBG' : ['\x1B[47m', '\x1B[49m'], + 'greyBG' : ['\x1B[49;5;8m', '\x1B[49m'], + 'blackBG' : ['\x1B[40m', '\x1B[49m'], + //colors + 'blueBG' : ['\x1B[44m', '\x1B[49m'], + 'cyanBG' : ['\x1B[46m', '\x1B[49m'], + 'greenBG' : ['\x1B[42m', '\x1B[49m'], + 'magentaBG' : ['\x1B[45m', '\x1B[49m'], + 'redBG' : ['\x1B[41m', '\x1B[49m'], + 'yellowBG' : ['\x1B[43m', '\x1B[49m'] + }; + } else if (exports.mode === 'browser') { + styles = { + //styles + 'bold' : ['', ''], + 'italic' : ['', ''], + 'underline' : ['', ''], + 'inverse' : ['', ''], + 'strikethrough' : ['', ''], + //text colors + //grayscale + 'white' : ['', ''], + 'grey' : ['', ''], + 'black' : ['', ''], + //colors + 'blue' : ['', ''], + 'cyan' : ['', ''], + 'green' : ['', ''], + 'magenta' : ['', ''], + 'red' : ['', ''], + 'yellow' : ['', ''], + //background colors + //grayscale + 'whiteBG' : ['', ''], + 'greyBG' : ['', ''], + 'blackBG' : ['', ''], + //colors + 'blueBG' : ['', ''], + 'cyanBG' : ['', ''], + 'greenBG' : ['', ''], + 'magentaBG' : ['', ''], + 'redBG' : ['', ''], + 'yellowBG' : ['', ''] + }; + } else if (exports.mode === 'none') { + return str + ''; + } else { + console.log('unsupported mode, try "browser", "console" or "none"'); + } + return styles[style][0] + str + styles[style][1]; +} + +function applyTheme(theme) { + + // + // Remark: This is a list of methods that exist + // on String that you should not overwrite. + // + var stringPrototypeBlacklist = [ + '__defineGetter__', '__defineSetter__', '__lookupGetter__', '__lookupSetter__', 'charAt', 'constructor', + 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf', 'charCodeAt', + 'indexOf', 'lastIndexof', 'length', 'localeCompare', 'match', 'replace', 'search', 'slice', 'split', 'substring', + 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight' + ]; + + Object.keys(theme).forEach(function (prop) { + if (stringPrototypeBlacklist.indexOf(prop) !== -1) { + console.log('warn: '.red + ('String.prototype' + prop).magenta + ' is probably something you don\'t want to override. Ignoring style name'); + } + else { + if (typeof(theme[prop]) === 'string') { + addProperty(prop, function () { + return exports[theme[prop]](this); + }); + } + else { + addProperty(prop, function () { + var ret = this; + for (var t = 0; t < theme[prop].length; t++) { + ret = exports[theme[prop][t]](ret); + } + return ret; + }); + } + } + }); +} + + +// +// Iterate through all default styles and colors +// +var x = ['bold', 'underline', 'strikethrough', 'italic', 'inverse', 'grey', 'black', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta', 'greyBG', 'blackBG', 'yellowBG', 'redBG', 'greenBG', 'blueBG', 'whiteBG', 'cyanBG', 'magentaBG']; +x.forEach(function (style) { + + // __defineGetter__ at the least works in more browsers + // http://robertnyman.com/javascript/javascript-getters-setters.html + // Object.defineProperty only works in Chrome + addProperty(style, function () { + return stylize(this, style); + }); +}); + +function sequencer(map) { + return function () { + if (!isHeadless) { + return this.replace(/( )/, '$1'); + } + var exploded = this.split(""), i = 0; + exploded = exploded.map(map); + return exploded.join(""); + }; +} + +var rainbowMap = (function () { + var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta']; //RoY G BiV + return function (letter, i, exploded) { + if (letter === " ") { + return letter; + } else { + return stylize(letter, rainbowColors[i++ % rainbowColors.length]); + } + }; +})(); + +exports.themes = {}; + +exports.addSequencer = function (name, map) { + addProperty(name, sequencer(map)); +}; + +exports.addSequencer('rainbow', rainbowMap); +exports.addSequencer('zebra', function (letter, i, exploded) { + return i % 2 === 0 ? letter : letter.inverse; +}); + +exports.setTheme = function (theme) { + if (typeof theme === 'string') { + try { + exports.themes[theme] = require(theme); + applyTheme(exports.themes[theme]); + return exports.themes[theme]; + } catch (err) { + console.log(err); + return err; + } + } else { + applyTheme(theme); + } +}; + + +addProperty('stripColors', function () { + return ("" + this).replace(/\x1B\[\d+m/g, ''); +}); + +// please no +function zalgo(text, options) { + var soul = { + "up" : [ + '̍', '̎', '̄', '̅', + '̿', '̑', '̆', '̐', + '͒', '͗', '͑', '̇', + '̈', '̊', '͂', '̓', + '̈', '͊', '͋', '͌', + '̃', '̂', '̌', '͐', + '̀', '́', '̋', '̏', + '̒', '̓', '̔', '̽', + '̉', 'ͣ', 'ͤ', 'ͥ', + 'ͦ', 'ͧ', 'ͨ', 'ͩ', + 'ͪ', 'ͫ', 'ͬ', 'ͭ', + 'ͮ', 'ͯ', '̾', '͛', + '͆', '̚' + ], + "down" : [ + '̖', '̗', '̘', '̙', + '̜', '̝', '̞', '̟', + '̠', '̤', '̥', '̦', + '̩', '̪', '̫', '̬', + '̭', '̮', '̯', '̰', + '̱', '̲', '̳', '̹', + '̺', '̻', '̼', 'ͅ', + '͇', '͈', '͉', '͍', + '͎', '͓', '͔', '͕', + '͖', '͙', '͚', '̣' + ], + "mid" : [ + '̕', '̛', '̀', '́', + '͘', '̡', '̢', '̧', + '̨', '̴', '̵', '̶', + '͜', '͝', '͞', + '͟', '͠', '͢', '̸', + '̷', '͡', ' ҉' + ] + }, + all = [].concat(soul.up, soul.down, soul.mid), + zalgo = {}; + + function randomNumber(range) { + var r = Math.floor(Math.random() * range); + return r; + } + + function is_char(character) { + var bool = false; + all.filter(function (i) { + bool = (i === character); + }); + return bool; + } + + function heComes(text, options) { + var result = '', counts, l; + options = options || {}; + options["up"] = options["up"] || true; + options["mid"] = options["mid"] || true; + options["down"] = options["down"] || true; + options["size"] = options["size"] || "maxi"; + text = text.split(''); + for (l in text) { + if (is_char(l)) { + continue; + } + result = result + text[l]; + counts = {"up" : 0, "down" : 0, "mid" : 0}; + switch (options.size) { + case 'mini': + counts.up = randomNumber(8); + counts.min = randomNumber(2); + counts.down = randomNumber(8); + break; + case 'maxi': + counts.up = randomNumber(16) + 3; + counts.min = randomNumber(4) + 1; + counts.down = randomNumber(64) + 3; + break; + default: + counts.up = randomNumber(8) + 1; + counts.mid = randomNumber(6) / 2; + counts.down = randomNumber(8) + 1; + break; + } + + var arr = ["up", "mid", "down"]; + for (var d in arr) { + var index = arr[d]; + for (var i = 0 ; i <= counts[index]; i++) { + if (options[index]) { + result = result + soul[index][randomNumber(soul[index].length)]; + } + } + } + } + return result; + } + return heComes(text); +} + + +// don't summon zalgo +addProperty('zalgo', function () { + return zalgo(this); +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.html b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.html new file mode 100644 index 00000000..7a2ae605 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.html @@ -0,0 +1,76 @@ + + + + + Colors Example + + + + + + \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.js new file mode 100644 index 00000000..b1e03a4f --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/example.js @@ -0,0 +1,77 @@ +var colors = require('./colors'); + +//colors.mode = "browser"; + +var test = colors.red("hopefully colorless output"); +console.log('Rainbows are fun!'.rainbow); +console.log('So '.italic + 'are'.underline + ' styles! '.bold + 'inverse'.inverse); // styles not widely supported +console.log('Chains are also cool.'.bold.italic.underline.red); // styles not widely supported +//console.log('zalgo time!'.zalgo); +console.log(test.stripColors); +console.log("a".grey + " b".black); +console.log("Zebras are so fun!".zebra); +console.log('background color attack!'.black.whiteBG) + +// +// Remark: .strikethrough may not work with Mac OS Terminal App +// +console.log("This is " + "not".strikethrough + " fun."); +console.log(colors.rainbow('Rainbows are fun!')); +console.log(colors.italic('So ') + colors.underline('are') + colors.bold(' styles! ') + colors.inverse('inverse')); // styles not widely supported +console.log(colors.bold(colors.italic(colors.underline(colors.red('Chains are also cool.'))))); // styles not widely supported +//console.log(colors.zalgo('zalgo time!')); +console.log(colors.stripColors(test)); +console.log(colors.grey("a") + colors.black(" b")); + +colors.addSequencer("america", function(letter, i, exploded) { + if(letter === " ") return letter; + switch(i%3) { + case 0: return letter.red; + case 1: return letter.white; + case 2: return letter.blue; + } +}); + +colors.addSequencer("random", (function() { + var available = ['bold', 'underline', 'italic', 'inverse', 'grey', 'yellow', 'red', 'green', 'blue', 'white', 'cyan', 'magenta']; + + return function(letter, i, exploded) { + return letter === " " ? letter : letter[available[Math.round(Math.random() * (available.length - 1))]]; + }; +})()); + +console.log("AMERICA! F--K YEAH!".america); +console.log("So apparently I've been to Mars, with all the little green men. But you know, I don't recall.".random); + +// +// Custom themes +// + +// Load theme with JSON literal +colors.setTheme({ + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}); + +// outputs red text +console.log("this is an error".error); + +// outputs yellow text +console.log("this is a warning".warn); + +// outputs grey text +console.log("this is an input".input); + +// Load a theme from file +colors.setTheme('./themes/winston-dark.js'); + +console.log("this is an input".input); + diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/package.json b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/package.json new file mode 100644 index 00000000..7af24a19 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/package.json @@ -0,0 +1,17 @@ +{ + "name": "colors", + "description": "get colors in your node.js console like what", + "version": "0.6.2", + "author": "Marak Squires", + "homepage": "https://github.com/Marak/colors.js", + "bugs": "https://github.com/Marak/colors.js/issues", + "keywords": [ "ansi", "terminal", "colors" ], + "repository": { + "type": "git", + "url": "http://github.com/Marak/colors.js.git" + }, + "engines": { + "node": ">=0.1.90" + }, + "main": "colors" +} diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/test.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/test.js new file mode 100644 index 00000000..c32417d6 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/test.js @@ -0,0 +1,70 @@ +var assert = require('assert'), + colors = require('./colors'); + +var s = 'string'; + +function a(s, code) { + return '\x1B[' + code.toString() + 'm' + s + '\x1B[39m'; +} + +function aE(s, color, code) { + assert.equal(s[color], a(s, code)); + assert.equal(colors[color](s), a(s, code)); + assert.equal(s[color], colors[color](s)); + assert.equal(s[color].stripColors, s); + assert.equal(s[color].stripColors, colors.stripColors(s)); +} + +function h(s, color) { + return '' + s + ''; +} + +var stylesColors = ['white', 'black', 'blue', 'cyan', 'green', 'magenta', 'red', 'yellow']; +var stylesAll = stylesColors.concat(['bold', 'italic', 'underline', 'inverse', 'rainbow']); + +colors.mode = 'console'; +assert.equal(s.bold, '\x1B[1m' + s + '\x1B[22m'); +assert.equal(s.italic, '\x1B[3m' + s + '\x1B[23m'); +assert.equal(s.underline, '\x1B[4m' + s + '\x1B[24m'); +assert.equal(s.strikethrough, '\x1B[9m' + s + '\x1B[29m'); +assert.equal(s.inverse, '\x1B[7m' + s + '\x1B[27m'); +assert.ok(s.rainbow); +aE(s, 'white', 37); +aE(s, 'grey', 90); +aE(s, 'black', 30); +aE(s, 'blue', 34); +aE(s, 'cyan', 36); +aE(s, 'green', 32); +aE(s, 'magenta', 35); +aE(s, 'red', 31); +aE(s, 'yellow', 33); +assert.equal(s, 'string'); + +colors.setTheme({error:'red'}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); + +colors.mode = 'browser'; +assert.equal(s.bold, '' + s + ''); +assert.equal(s.italic, '' + s + ''); +assert.equal(s.underline, '' + s + ''); +assert.equal(s.strikethrough, '' + s + ''); +assert.equal(s.inverse, '' + s + ''); +assert.ok(s.rainbow); +stylesColors.forEach(function (color) { + assert.equal(s[color], h(s, color)); + assert.equal(colors[color](s), h(s, color)); +}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); + +colors.mode = 'none'; +stylesAll.forEach(function (style) { + assert.equal(s[style], s); + assert.equal(colors[style](s), s); +}); + +assert.equal(typeof("astring".red),'string'); +assert.equal(typeof("astring".error),'string'); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-dark.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-dark.js new file mode 100644 index 00000000..49a905ba --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-dark.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'black', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-light.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-light.js new file mode 100644 index 00000000..571972c1 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/colors/themes/winston-light.js @@ -0,0 +1,12 @@ +module['exports'] = { + silly: 'rainbow', + input: 'grey', + verbose: 'cyan', + prompt: 'grey', + info: 'green', + data: 'grey', + help: 'cyan', + warn: 'yellow', + debug: 'blue', + error: 'red' +}; \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/.npmignore b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/.npmignore new file mode 100644 index 00000000..52d9934c --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/.npmignore @@ -0,0 +1,5 @@ +._* +.DS_Store +.git* +node_modules +npm-debug.log diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/CHANGELOG.md b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/CHANGELOG.md new file mode 100644 index 00000000..86c854e6 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/CHANGELOG.md @@ -0,0 +1,140 @@ +0.1.23 (11/24/2014) +------------------- + * Fixed bug where select lists that have autoSelectOne enabled does not call + a user-defined validate() function. + +0.1.22 (11/12/2014) +------------------- + * Fixed bug with select list when value is falsey and field has zeroSkip and + numbered enabled. + +0.1.21 (11/11/2014) +------------------- + * Fixed bug where the wrong select list attribute was being checked when + creating the distinct values lookup. + +0.1.20 (11/6/2014) +------------------- + * Whoops, published a little too quick. Bug fix from 0.1.19 new feature. + +0.1.19 (11/6/2014) +------------------- + * Added ignoreCase flag for select lists when manually entering values. + +0.1.18 (11/6/2014) +------------------- + * Fixed bug with select lists that have multiple complete values and the value + is falsey. + +0.1.17 (10/9/2014) +------------------- + * Added the ability to autocomplete select list options based on multiple + values. + +0.1.16 (9/16/2014) +------------------- + * Fixed bug with the incorrect value being used in select fields. + * Changed 'keypress' back to v0.2.1 since upgrade was ok. + +0.1.15 (9/16/2014) +------------------- + * Downgraded 'keypress' dependency from v0.2.1 to v0.1.0 because of potential + issue. + +0.1.14 (9/15/2014) +------------------- + * Fixed bug where selecting an item by number would fail if there were multiple + items with the same value. + * Upgraded npm dependencies 'keypress' from v0.1.0 to v0.2.1 and 'sprintf' from + v0.1.2 to v0.1.4. + * Fixed a bug with the file field with tab completion where it wouldn't work if + using forward slashes on Windows or backslash+space on Linux/Mac. + +0.1.13 (8/21/2014) +------------------- + * Removed escape backslashes when a path is drag and dropped into a terminal on + Linux or Mac OS X. + +0.1.12 (1/30/2014) +------------------- + * Fixed bug where select field validate callbacks that fail were not triggering + the select field to reprompt correctly. + +0.1.11 (9/28/2013) +------------------- + * Fixed a bug where an exception thrown from a field's validate() function's + callback would be caught even though the error happened in the callback, + not the actual validate() function. Now exceptions from the callback are + rethrown. + +0.1.10 (9/28/2013) +------------------- + * Instead of extra whitespace after errors that was added in 0.1.9, now you can + just use a custom formatter and do whatever you'd like with the error. + +0.1.9 (9/27/2013) +------------------- + * Added one more line of whitespace after printing an error message. + +0.1.8 (9/25/2013) +------------------- + * Added missing "pre-prompt" event to File and Select fields. + +0.1.7 (9/18/2013) +------------------- + * Added "pre-prompt" and "post-prompt" events to all field types. + * Fixed bug when instantiating a Set using the method format. + * Moved Select field option pre-rendering to the prompt() function so that + options can be modified prior to prompting. + * Added "autoSelectOne" flag to Select fields to skip the prompting if there + is only one option. + * If a Select field doesn't have any options, it immediately fire the callback. + * Named all public anonymous functions. + +0.1.6 (9/13/2013) +------------------- + * Added stopOnError flag to Set field. By default, an field that errors will + break out of the set prompting, but now you can set this flag to false and it + will continue prompting. + * Added repromptOnError flag to all fields. If a field has a validate() + function, then by default if it fails, then the field is re-prompted. You now + can set this to false and it will stop prompting when an error occurs. + * Cleaned up readme so that it hopefully is more readable. + * Note: when a Set finished prompting for a field with a next() function, it + now passes the error as the first argument, then the value. Before it just + passed the value. + +0.1.5 (9/10/2013) +------------------- + * Fixed bug with file field tab completion not properly completing partial + matches. + * Fixed bug with file field tab completion causing an exception when + encountering a broken symlink. + +0.1.4 (7/30/2013) +------------------- + * Fixed bug with file field tab completion not properly handling '~' + (home directory) or directories containing a single file. + +0.1.3 (7/29/2013) +------------------- + * Fixed bug with select fields where relistOnError=true was not firing properly + if custom validators returned an error. + +0.1.2 (7/23/2013) +------------------- + * Fixed bug set, but undefined default values being rendered as an empty string. + * Fixed bug with default value being a number. + * Run a select field's validate() before checking values against options so + values can be transformed. + * Added support for accelerators such as "e__x__it" where "x" is the + accelerator and it maps to "exit". + +0.1.1 (7/22/2013) +------------------- + * Fixed bug with a select field instance is used more than once + * Added screenshots to readme + +0.1.0 (7/18/2013) +------------------- + * Initial release diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/LICENSE b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/LICENSE new file mode 100644 index 00000000..8a9a75b7 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2013-2014 Chris Barber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/README.md b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/README.md new file mode 100644 index 00000000..157cb54d --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/README.md @@ -0,0 +1,1101 @@ +# Fields + +Fields is a small library that provides a handful of useful input fields for use +at the command line. Each field type supports both an object-oriented and +chainable method-based API. + +[![NPM](https://nodei.co/npm/fields.png?downloads=true&stars=true)](https://nodei.co/npm/fields/) + +# Installation + + npm install fields + +# Features + +* Tab completion for File and Select fields +* Password masks +* Titles, descriptions, prompt labels +* Custom renderers and validation handler support +* Fully customizable appearance +* Command history +* Batch field prompting including flow control +* Support for select field option accelerators + +# Field Types + +## Text + +Simple prompt for capturing a string of text. Also supports password masks and history. + +![Text field](https://www.evernote.com/shard/s75/sh/0ff002b2-7b15-4442-8a3a-afb806dac932/9a9d355870fb90099c042dac4f5cf12d/deep/0/Screenshot%207/18/13%2010:02%20PM.jpg) + +## File + +Prompt for a specific file or directory. Supports tab completion. + +![File field](https://www.evernote.com/shard/s75/sh/f75b3e0a-ee8b-46bc-b0f7-1b93339de3ad/f53665b083f0a3cbcab0358a59a44ad1/deep/0/Screenshot%207/18/13%209:58%20PM.jpg) + +## Select list + +Displays a list of options which a single item can be selected. Supports tab +completion, numbered options, and setting the display method. + +![Select field](https://www.evernote.com/shard/s75/sh/872fdef6-b11a-4426-a6e9-ef07bd80a98e/801ffb85cd9d9247bee6bf33dcb0a940/deep/0/Screenshot%207/18/13%2010:09%20PM.jpg) + +## Set + +Group multiple fields into a single "set" and prompts for each field. Supports +skipping fields in the set. + +![Set field](https://www.evernote.com/shard/s75/sh/c1f725c2-c261-4a43-93ca-156899c18371/92acf90edb7a7a2775322d6c9595d506/deep/0/Screenshot%207/18/13%2010:12%20PM.jpg) + +# Getting Started + +Start by requiring the fields module: + +```js +var fields = require('fields'); +``` + +# Global Settings + +## fields.setup(opts) + +Sets default settings. + +* `{object}` `opts` Contains settings that will override the default values + +Example: + +```js +fields.setup({ + colors: false +}); +``` + +### Available Default Settings + +`{boolean}` `colors` + +* Enables colors. +* Scope: applies to all field types +* Default: `true` + +`{string}` `separator` + +* The separator between the promptLabel and the input. +* Scope: applies to all field types +* Default: `'> '` + +`{string}` `defaultLeft` + +* When a default value is set, this string is printed to the left of the + default value. +* Scope: applies to `File`, `Select`, and `Text` +* Default: `'['` + +`{string}` `defaultRight` + +* When a default value is set, this string is printed to the right of the + default value. +* Scope: applies to `File`, `Select`, and `Text` +* Default: `']'` + +`{string}` `promptValuesLeft` + +* When displaying a list of values in the prompt, this string is printed to + the left of the list of values. +* Scope: applies to `Select`, but will work with `File` and `Text` +* Default: `'('` + +`{string}` `promptValuesSeparator` + +* When displaying a list of values in the prompt, this string is printed + between each value. +* Scope: applies to `Select`, but will work with `File` and `Text` +* Default: `'|'` + +`{string}` `promptValuesRight` + +* When displaying a list of values in the prompt, this string is printed to + the right of the list of values. +* Scope: applies to `Select`, but will work with `File` and `Text` +* Default: `')'` + +`{string}` `mask` + +* The character to be rendered when prompting for a password. +* Scope: applies to `Text` when `password` = `true` +* Default: `'*'` + +`{string}` `fieldSeparator` + +* The string to be displayed between fields in a `Set`. +* Scope: applies to `Set` +* Default: `'\n'` + +`{object}` `style` + +* An object containing one or more style classes where the value is a color + or style or an array containg a color and one or more styles. Values may + also be `null`. +* Properties: + * `default` (default value: `'cyan'`) + * `title` (default value: `'magenta'`) + * `promptLabel` (default value: `'bold'`) + * `promptValues` (default value: `null`) + * `desc` (default value: `'grey'`) + * `mask` (default value: `'magenta'`) + * `group` (default value: `'grey'`) + * `error` (default value: `'red'`) + * `suggestion` (default value: `'cyan'`) + * `option` (default value: `'cyan'`) + * `accelerator` (default value `['underline', 'bold', 'cyan']`) +* Colors: + * `'red'` + * `'yellow'` + * `'green'` + * `'blue'` + * `'cyan'` + * `'magenta'` + * `'black'` + * `'grey'` + * `'white'` +* Styles: + * `'bold'` + * `'underline'` + * `'italic'` + * `'inverse'` + * NOTE: some styles, such as `italic`, may not work in all environments + and styles such as `white` or `black` may conflict with the background + color of the user's terminal. + +`{boolean}` `repromptOnError` + +* If the field has a `validate()` function, validation fails, and + `repromptOnError` is `true` (default), then it will reprompt for the value + again. If `repromptOnError` is false, then it will stop prompting. This is + useful when you have a `Set` and you need to prompt for multiple values, then + possibly return to a previous field if validation fails. For example, you + prompt for a username and password, but authentication fails, you may want to + re-prompt for the username again. +* Scope: applies to `File`, `Select`, and `Text` +* Default: `true` + +# fields.Text(opts) + +Creates a new Text field. + +* `{object}` `opts` Text field options. + + * Text field specific options: + + * `{object}` `opts.formatters` An object of specific formatting functions. + + * `{function}` `opts.formatters.desc(string)` + + Custom field description formatter. + + * `{function}` `opts.formatters.error(Error|string)` + + Error message formatter. + + * `{function}` `opts.formatters.title(string)` + + Custom field title formatter. + + * Standard options: + + * `{boolean}` `opts.colors` + + Enables text being rendered with color. Default value is `true`. + + * `{string}` `opts.default` + + The default value. Returned when the user enters an empty value at the + prompt. + + * `{string}` `opts.defaultLeft` + + A string displayed before the default value in the prompt. Default value is `'['`. + + * `{string}` `opts.defaultRight` + + A string displayed after the default value in the prompt. Default value is `']'`. + + * `{string}` `opts.desc` + + The description to print below the title, but above the prompt. + + * `{boolean}` `opts.hidden` + + When true, the value is still prompted, but it's not apart of the results. + Useful for decisions in a `Set`. + + * `{string}` `opts.mask` + + The character to be rendered when entering a password. The mask must be 1 + character. Default value is `'*'`. + + * `{function}` `opts.next(err, value, callback)` + + When this field is being prompted in a `Set`, the `next()` function is + called after prompting and `validate()` has completed to tell the `Set` + which field to visit next. + + If `validate()` fails and `repromptOnError` == `true`, then `next()` is not + called since the field will continue to re-prompt until `validate()` passes. + + `next()` may return the name or index of the next field or call the supplied + `callback()` with the name or index of the next field to visit. + + If `next()` returns nothing or `undefined`, it will assume you are planning + on calling the supplied `callback` function. + + If `next()` returns `null`, then the `Set` will proceed to the next field. + + If `next()` returns `false`, then it will tell the `Set` to stop prompting. + + * `{boolean}` `opts.password` + + Treat input as a secret. + + * `{string}` `opts.promptLabel` + + The label to display before prompt. + + * `{array}` `opts.promptValues` + + The values to print between the `promptLabel` and the prompt input. + + * `{string}` `opts.promptValuesLeft` + + A string displayed before the `promptValues`. Default value is `'('`. + + * `{string}` `opts.promptValuesRight` + + A string displayed after the `promptValues`. Default value is `')'`. + + * `{string}` `opts.promptValuesSeparator` + + A string used to separate the prompt values. Default value is `'|'`. + + * `{boolean}` `opts.repromptOnError` + + If the field has a `validate()` function, validation fails, and + `repromptOnError` is `true` (default), then it will reprompt for the value + again. + + If `repromptOnError` is false, then it will stop prompting. This is useful + when you have a `Set` and you need to prompt for multiple values, then + possibly return to a previous field if validation fails. + + For example, you prompt for a username and password, but authentication + fails, you may want to re-prompt for the username again. + + Default value is `true`. + + * `{string}` `opts.separator` + + A string displayed after the prompt, but before the prompt input. Default + value is `': '`. + + * `{string}` `opts.title` + + The title to print above the prompt. + + * `{boolean}` `opts.trim` + + Trim the input after entered. Default value is `true`. + + * `{function}` `opts.validate(value, callback(err, value), field)` + + A function to be called when a value is submitted. The `validate()` + function is passed in the `value` and a `callback`. + + If the `validate()` function returns `true`, validation passes. + + If it returns `false`, validation fails. + + If it returns `undefined`, then it will wait for the `callback()` parameter + to be called. The `callback(err, value)` function MUST pass the `value` + back. This allows the `callback()` to not only validate, but modify the + value. + +Returns a `Text` field instance with the following properties: + +* `{function}` `prompt(callback)` + + * `{function}` `callback(err, value)` + + A function that is called when prompting has completed. + +* `{Set}` `set` + + If the field is apart of a `Set`, then this property will reference the set, + otherwise `set` will be `null`. + +Events: + +* `pre-prompt` + + Emitted before the current field is prompted. + + * `{object}` `field` The current field + +* `post-prompt` + + Emitted after the current field has been prompted. + + * `{object}` `field` The current field + * `{anything}` `err` The error if something failed + * `{string}` `result` The result after the prompting + +Object-oriented example: + +```js +var nameField = new fields.Text({ + title: 'We would like to know your name', + promptLabel: 'What is your name?' +}); + +nameField.prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +Chainable function example: + +``` +var ageField = fields.text({ + title: 'What is your age?', + description: 'We promise not to tell anyone', + validate: function (value) { + return /^\d+$/.test(value); + } +}); + +ageField.prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +Callback validation example: + +``` +fields.text({ + title: 'What is your favorite food?' + validate: function (value, callback) { + callback(null, value.toLowerCase()); + } +}).prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +# fields.File(opts) + +Creates a new File field. + +* `{object}` `opts` File field options. + + * File field specific options: + + * `{object}` `opts.formatters` + + An object of specific formatting functions. + + * `{function}` `opts.formatters.desc(string)` + + Custom field description formatter. + + * `{function}` `opts.formatters.error(Error|string)` + + Error message formatter. + + * `{function}` `opts.formatters.title(string)` + + Custom field title formatter. + + * `{regexp}` `opts.ignoreDirs` + + A regular expression of directory names to ignore when autocompleting. + + * `{regexp}` `opts.ignoreFiles` + + A regular expression of filenames to ignore when autocompleting. + + * `{boolean}` `opts.showHidden` + + If true, will display files beginning with a '.' in the autocomplete + results. Defaults to `true`. + + * Autocomplete options: + + * `{boolean}` `opts.complete` + + If true, will autocomplete the current entry when the key is entered. + Default value is `false`. + + * Standard options: + + * `{boolean}` `opts.colors` + + Enables text being rendered with color. Default value is `true`. + + * `{string}` `opts.default` + + The default value. Returned when the user enters an empty value at the prompt. + + * `{string}` `opts.defaultLeft` + + A string displayed before the default value in the prompt. Default value is `'['`. + + * `{string}` `opts.defaultRight` + + A string displayed after the default value in the prompt. Default value is `']'`. + + * `{string}` `opts.desc` + + The description to print below the title, but above the prompt. + + * `{boolean}` `opts.hidden` + + When true, the value is still prompted, but it's not apart of the results. + Useful for decisions in a `Set`. + + * `{string}` `opts.mask` + + The character to be rendered when entering a password. The mask must be 1 + character. Default value is `'*'`. + + * `{function}` `opts.next(err, value, callback)` + + When this field is being prompted in a `Set`, the `next()` function is + called after prompting and `validate()` has completed to tell the `Set` + which field to visit next. + + If `validate()` fails and `repromptOnError` == `true`, then `next()` is not + called since the field will continue to re-prompt until `validate()` passes. + + `next()` may return the name or index of the next field or call the supplied + `callback()` with the name or index of the next field to visit. + + If `next()` returns nothing or `undefined`, it will assume you are planning + on calling the supplied `callback` function. + + If `next()` returns `null`, then the `Set` will proceed to the next field. + + If `next()` returns `false`, then it will tell the `Set` to stop prompting. + + * `{boolean}` `opts.password` + + Treat input as a secret. + + * `{string}` `opts.promptLabel` + + The label to display before prompt. + + * `{array}` `opts.promptValues` + + The values to print between the `promptLabel` and the prompt input. + + * `{string}` `opts.promptValuesLeft` + + A string displayed before the `promptValues`. Default value is `'('`. + + * `{string}` `opts.promptValuesRight` + + A string displayed after the `promptValues`. Default value is `')'`. + + * `{string}` `opts.promptValuesSeparator` + + A string used to separate the prompt values. Default value is `'|'`. + + * `{boolean}` `opts.repromptOnError` + + If the field has a `validate()` function, validation fails, and + `repromptOnError` is `true` (default), then it will reprompt for the value + again. + + If `repromptOnError` is false, then it will stop prompting. This is useful + when you have a `Set` and you need to prompt for multiple values, then + possibly return to a previous field if validation fails. + + For example, you prompt for a username and password, but authentication + fails, you may want to re-prompt for the username again. + + Default value is `true`. + + * `{string}` `opts.separator` + + A string displayed after the prompt, but before the prompt input. Default + value is `': '`. + + * `{string}` `opts.title` + + The title to print above the prompt. + + * `{boolean}` `opts.trim` + + Trim the input after entered. Default value is `true`. + + * `{function}` `opts.validate(value, callback(err, value), field)` + + A function to be called when a value is submitted. The `validate()` + function is passed in the `value` and a `callback`. + + If the `validate()` function returns `true`, validation passes. + + If it returns `false`, validation fails. + + If it returns `undefined`, then it will wait for the `callback()` parameter + to be called. The `callback(err, value)` function MUST pass the `value` + back. This allows the `callback()` to not only validate, but modify the + value. + +Returns a `File` field instance with the following properties: + +* `{function}` `prompt(callback)` + + * `{function}` `callback(err, value)` + + A function that is called when prompting has completed. + +* `{Set}` `set` + + If the field is apart of a `Set`, then this property will reference the set, + otherwise `set` will be `null`. + +Events: + +* `pre-prompt` + + Emitted before the current field is prompted. + + * `{object}` `field` The current field + +* `post-prompt` + + Emitted after the current field has been prompted. + + * `{object}` `field` The current field + * `{anything}` `err` The error if something failed + * `{string}` `result` The result after the prompting + +Example: + +``` +fields.file({ + title: 'Enter the project directory', + desc: 'Any directory will do', + complete: true, + showHidden: false, + ignoreDirs: /^(\.svn|\.git|\.hg)$'/, + ignoreFiles: /^(\.gitignore|\.npmignore|\.cvsignore|\.DS_store|\._\*)$/ +}).prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +# fields.Select(opts) + +Creates a new Select field. + +* `{object}` `opts` Select field options. + + * Select field specific options: + + * `{boolean}` `opts.autoSelectOne` + + If `true` and the `options` array contains a single entry, then it will skip + the prompting and immediately call the callback. Default value is `false`. + + * `{string}` `opts.display` + + Controls how autocomplete results are + printed. Possible values are `'grid'`, `'list'`, and `'prompt'`. + Default value is `'list'`. + + * `{object}` `opts.formatters` + + An object of specific formatting functions. + + * `{function}` `opts.formatters.desc(string)` + + Custom field description formatter. + + * `{function}` `opts.formatters.error(Error|string)` + + Error message formatter. + + * `{function}` `opts.formatters.option(string)` + + Custom select list option formatter. + + * `{function}` `opts.formatters.title(string)` + + Custom field title formatter. + + * `{boolean}` `opts.ignoreCase` + + When `true`, ignores the case of the value being entered. Default value is + `false`. + + * `{string}` `opts.margin` + + A string to print in the left margin for each item being rendered. Default + value is two spaces. + + * `{boolean}` `opts.numbered` + + If `true`, prints numbers for each list option in which the user can select + the item by entering the number. Default value is `false`. + + * `{array}` `opts.options` + + An array of options to display. Each option should have a label and a value. + You can name these properties whatever you'd like as long as you specify + their name using the `optionLabel` and `optionValue` options. + + * `{string}` `opts.optionLabel` + + The name of the key in each option's object that contains the label to print + for the option. Default value is `'label'`. + + * `{string}` `opts.optionValue` + + The name of the key in each option's object that contains the value that is + submitted if the option is selected. Default value is `'value'`. + + * `{boolean}` `opts.relistOnError` + + If `true`, after a invalid option is selected, then it will re-display all + available options. Default value is `false`. + + * `{object}` `opts.i18nStrings` + + An object containing internationalized strings. There currently are only two + strings that would need to be translated: + + * `'Invalid selection "%s"'` + + * `'Please select a valid option'` + + * `{boolean}` `opts.suggest` + + If `true`, it will display a list of possible suggestions that closest match + the submitted value. This uses the levenshtein algorithm to compare the + value with possible values. Default value is `false`. + + * `{number}` `opts.suggestThreshold` + + A threshold for the levenshtein algorithm. Default value is `3`. You may + want to use `2` if matching short strings. + + * `{boolean}` `opts.zeroSkip` + + If `true` and `numbered` is `true`, then allows the user to enter zero to + select nothing. Default value is `false`. + + * Autocomplete options: + + * `{boolean}|{array}` `opts.complete` + + If a boolean and `true`, will autocomplete the `value` when the key is + entered. Default value is `false`. + + If value is an array of strings of key names, then it will autocomplete the + values based specified option key name values. For example, if you set + `complete: ['id', 'value']`, then it will autocomplete either the `id` or + the `value`. + + * `{boolean}` `opts.completeIgnoreCase` + + If true, will ignore case when finding matches. Default value is `false`. + + * Standard options: + + * `{boolean}` `opts.colors` + + Enables text being rendered with color. Default value is `true`. + + * `{string}` `opts.default` + + The default value. Returned when the user enters an empty value at the + prompt. + + * `{string}` `opts.defaultLeft` + + A string displayed before the default value in the prompt. Default value + is `'['`. + + * `{string}` `opts.defaultRight` + + A string displayed after the default value in the prompt. Default value + is `']'`. + + * `{string}` `opts.desc` + + The description to print below the title, but above the prompt. + + * `{boolean}` `opts.hidden` + + When true, the value is still prompted, but it's not apart of the results. + Useful for decisions in a `Set`. + + * `{string}` `opts.mask` + + The character to be rendered when entering a password. The mask must be 1 + character. Default value is `'*'`. + + * `{function}` `opts.next(err, value, callback)` + + When this field is being prompted in a `Set`, the `next()` function is + called after prompting and `validate()` has completed to tell the `Set` + which field to visit next. + + If `validate()` fails and `repromptOnError` == `true`, then `next()` is not + called since the field will continue to re-prompt until `validate()` passes. + + `next()` may return the name or index of the next field or call the supplied + `callback()` with the name or index of the next field to visit. + + If `next()` returns nothing or `undefined`, it will assume you are planning + on calling the supplied `callback` function. + + If `next()` returns `null`, then the `Set` will proceed to the next field. + + If `next()` returns `false`, then it will tell the `Set` to stop prompting. + + * `{boolean}` `opts.password` + + Treat input as a secret. + + * `{string}` `opts.promptLabel` + + The label to display before prompt. + + * `{array}` `opts.promptValues` + + The values to print between the `promptLabel` and the prompt input. + + * `{string}` `opts.promptValuesLeft` + + A string displayed before the `promptValues`. Default value is `'('`. + + * `{string}` `opts.promptValuesRight` + + A string displayed after the `promptValues`. Default value is `')'`. + + * `{string}` `opts.promptValuesSeparator` + + A string used to separate the prompt values. Default value is `'|'`. + + * `{boolean}` `opts.repromptOnError` + + If the field has a `validate()` function, validation fails, and + `repromptOnError` is `true` (default), then it will reprompt for the value + again. + + If `repromptOnError` is false, then it will stop prompting. This is useful + when you have a `Set` and you need to prompt for multiple values, then + possibly return to a previous field if validation fails. + + For example, you prompt for a username and password, but authentication + fails, you may want to re-prompt for the username again. + + Default value is `true`. + + * `{string}` `opts.separator` + + A string displayed after the prompt, but before the prompt input. Default + value is `': '`. + + * `{string}` `opts.title` + + The title to print above the prompt. + + * `{boolean}` `opts.trim` + + Trim the input after entered. Default value is `true`. + + * `{function}` `opts.validate(value, callback(err, value), field)` + + A function to be called when a value is submitted. The `validate()` + function is passed in the `value` and a `callback`. + + If the `validate()` function returns `true`, validation passes. + + If it returns `false`, validation fails. + + If it returns `undefined`, then it will wait for the `callback()` parameter + to be called. The `callback(err, value)` function MUST pass the `value` + back. This allows the `callback()` to not only validate, but modify the + value. + +Returns a `Select` field instance with the following properties: + +* `{function}` `prompt(callback)` + + * `{function}` `callback(err, value)` + + A function that is called when prompting has completed. + +* `{Set}` `set` + + If the field is apart of a `Set`, then this property will reference the set, + otherwise `set` will be `null`. + +If an option label contains double underscores that wrap a character like +`some__t__hing`, then `t` will become an accelerator that automatically maps `t` +with `something`. Use the `accelerator` style to style it. + +Events: + +* `pre-prompt` + + Emitted before the current field is prompted. + + * `{object}` `field` The current field + +* `post-prompt` + + Emitted after the current field has been prompted. + + * `{object}` `field` The current field + * `{anything}` `err` The error if something failed + * `{string}` `result` The result after the prompting + +Simple example: + +``` +var list = new fields.Select({ + title: 'What is your favorite milkshake?', + options: [ + '__v__anilla', + 'stra__w__berry', + 'cho__c__olate' + ], + complete: true, + suggest: true +}); + +list.prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('Your favorite milkshake is ' + value + '. Yum!'); + } +}); +``` + +Slightly more complex example: + +``` +fields.select({ + title: 'Select a UUID by number or name', + formatters: { + option: function (opt, idx, num) { + return ' ' + num + opt.value.cyan + ' ' + opt.name; + } + }, + numbered: true, + relistOnError: true, + complete: true, + suggest: true, + options: { + 'Available UUIDs:': [ + { name: 'uuid 1', value: '43C5E7DE-F6BB-4AEF-98F0-0A33990EA280' }, + { name: 'uuid 2', value: '4F562E96-C933-4367-B6BD-89CA7D6EE400' }, + { name: 'uuid 3', value: '31D3AC10-99F4-43E1-997B-980E70EC706B' }, + { name: 'uuid 4', value: 'E1512AE0-FEBB-43A2-9C9C-E1D2F4D6C51F' }, + { name: 'uuid 5', value: 'F624D6BA-5FF3-4E48-B9F2-BC7DD1A8EA97' }, + { name: 'uuid 6', value: '3C12C8D9-C05F-4834-BA7E-9C55CB8C9287' }, + { name: 'uuid 7', value: 'BB91EDBF-2A97-4227-B5B2-5943BAB30304' }, + { name: 'uuid 8', value: '204C6E4A-FA9C-48BB-9D84-709A10A690AB' }, + { name: 'uuid 9', value: '05282F35-42BB-40F3-8C20-3EC1739AB414' }, + { name: 'uuid 10', value: '5EC586D9-7E2B-4F55-834D-CD8199DD92B8' }, + { name: 'uuid 11', value: 'A4BD1980-8C4B-4DBB-8FBE-5A52E36DFA63' }, + { name: 'uuid 12', value: '99C49052-E280-48D3-B881-E8112B7DFCF1' }, + { name: 'uuid 13', value: 'A057301B-B38D-40B6-A6A4-B582AE5EAABE' }, + { name: 'uuid 14', value: 'D39B019B-3EF0-4BCA-A1E9-FC2F5063097F' }, + { name: 'uuid 15', value: 'C9A11E0C-5FF4-4B55-890F-F7715194CAB3' }, + { name: 'uuid 16', value: 'B1E31DD0-8968-4A32-B210-A0558302F65B' } + ] + } +}).prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You selected ' + value); + } +}); +``` + +# fields.Set(fields, opts) + +Creates a new field Set. Sets batch prompt several fields including other sets. + +* `{object|array}` `fields` An object or array of field instances to prompt for. + +* `{object}` `opts` Select field options. + + * `{string}` `opts.fieldSeparator` + + A string to render between each field being prompted. Default value is `'\n'`. + + * `{boolean}` `opts.stopOnError` + + If `true` and a field's `validate()` fails, then the `Set` will stop + prompting, otherwise if `false`, it will continue to the next field. Default + value is `true`. You may want to set this `false` when using + `repromptOnError=false` (see `repromptOnError`). + +Returns a `Set` field instance with the following properties: + +* `{function}` `prompt(callback)` + + * `{function}` `callback(err, value)` + + A function that is called when prompting has completed. + +Events: + +* `pre-prompt` + + Emitted before the current field is prompted. + + * `{object}` `field` The current field + +* `post-prompt` + + Emitted after the current field has been prompted. + + * `{object}` `field` The current field + * `{anything}` `err` The error if something failed + * `{string}` `result` The result after the prompting + +Object-based example: + +``` +fields.set({ + something: fields.text({ + promptLabel: 'Username', + validate: function (value, callback) { + callback(!value.length && new Error('Please enter a username'), value); + } + }), + + changePass: fields.select({ + promptLabel: 'Change password?', + display: 'prompt', + options: [ 'yes', 'no' ], + next: function (value) { + if (value == 'no') { + return 'favfood'; + } + } + }), + + password: fields.text({ + promptLabel: 'Enter a password', + password: true, + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + favfood: fields.text({ + promptLabel: 'What is your favorite food?' + }) +}, { stopOnError: true }).prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +Array-based example: + +``` +fields.set([ + fields.text({ + promptLabel: 'Username', + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + fields.select({ + promptLabel: 'Change password?', + display: 'prompt', + options: [ 'yes', 'no' ], + next: function (value) { + if (value == 'no') { + return 3; + } + } + }), + + fields.text({ + promptLabel: 'Enter a password', + password: true, + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + fields.text({ + promptLabel: 'What is your favorite food?' + }) +]).prompt(function (err, value) { + if (err) { + console.error('There was an error!\n' + err); + } else { + console.log('You entered ' + value); + } +}); +``` + +# License + +(The MIT License) + +Copyright (c) 2013-2014 Chris Barber + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/common.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/common.js new file mode 100644 index 00000000..62b09d1a --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/common.js @@ -0,0 +1,102 @@ +var vsprintf = require('sprintf').vsprintf, + path = require('path'), + tildeRegExp = /^(~)([/\\].*)?$/, + winEnvVarRegExp = /(%([^%]*)%)/g; + +exports.mix = function mix(dest) { + var i = 1, + l = arguments.length, + p, + src; + dest || (dest = {}); + while (i < l) { + src = arguments[i++]; + for (p in src) { + if (src.hasOwnProperty(p)) { + if (dest.hasOwnProperty(p) && Object.prototype.toString.call(dest[p]) == '[object Object]') { + exports.mix(dest[p], src[p]); + } else { + dest[p] = src[p]; + } + } + } + } + return dest; +}; + +exports.__ = function __(obj, message) { + var strings = obj && obj.i18nStrings || {}; + return vsprintf(strings[message] || message, Array.prototype.slice.call(arguments, 2)); +}; + +exports.resolvePath = function resolvePath() { + var p = path.join.apply(null, arguments); + return path.resolve(p.replace(tildeRegExp, function (s, m, n) { + return process.env[process.platform == 'win32' ? 'USERPROFILE' : 'HOME'] + (n || '/'); + }).replace(winEnvVarRegExp, function (s, m, n) { + return process.platform == 'win32' && process.env[n] || m; + })); +}; + +exports.renderGrid = function renderGrid(margin, items) { + var margin = (margin || ''), + longest = items.reduce(function (a, b) { return Math.max(a, b.stripColors.length);}, 0) + 4, + width = process.stdout.columns || 80, + i, j, spaces, + len = items.length, + cols = Math.floor((width - margin.length) / longest), + rows = Math.ceil(len / cols), + buffer = ''; + + for (i = 0; i < rows; i++) { + buffer += margin; + for (j = 0; j < len; j += rows) { + if (j + i < len) { + buffer += items[i + j]; + spaces = longest - items[i + j].stripColors.length; + if (spaces > 0) { + buffer += Array.from({ length: spaces }).join(' '); + } + } + } + buffer += '\n'; + } + + return buffer; +}; + +exports.levenshtein = function levenshtein(s, c) { + var len1 = (s = s.split('')).length, + len2 = (c = c.split('')).length, + a = [], + i = len1 + 1, + j; + + if (!(len1 || len2)) { + return Math.max(len1, len2); + } + for (; i; a[--i] = [i]); + for (i = len2 + 1; a[0][--i] = i;); + for (i = -1; ++i < len1;) { + for (j = -1; ++j < len2;) { + a[i + 1][j + 1] = Math.min(a[i][j + 1] + 1, a[i + 1][j] + 1, a[i][j] + (s[i] != c[j])); + } + } + return a[len1][len2]; +}; + +exports.suggest = function suggest(obj, value, options, logger, threshold) { + value = '' + value; + threshold = threshold || 3; + + var suggestions = options.filter(function (opt) { + return opt.indexOf(value) == 0 || exports.levenshtein(value, opt) <= threshold; + }); + + if (suggestions.length) { + logger(exports.__(obj, 'Did you mean this?')); + suggestions.forEach(function (s) { + logger(' ' + obj._format(s, 'suggestion')); + }); + } +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/index.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/index.js new file mode 100644 index 00000000..c4d27351 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/index.js @@ -0,0 +1,47 @@ +var fs = require('fs'), + path = require('path'), + colors = require('colors'), + common = require('./common'), + // Windows PowerShell translates magenta to the same blue as the background. So use white, instead. + inputAndMaskColor = process.platform === 'win32' && process.title.indexOf('PowerShell') >= 0 ? 'white' : 'magenta', + defaults = { + colors: true, + separator: ': ', + defaultLeft: '[', + defaultRight: ']', + promptValuesLeft: '(', + promptValuesSeparator: '|', + promptValuesRight: ')', + mask: '*', + fieldSeparator: '\n', + style: { + default: 'cyan', + input: inputAndMaskColor, + title: 'bold', + promptLabel: 'bold', + promptValues: null, + desc: 'grey', + mask: inputAndMaskColor, + group: 'grey', + error: 'red', + suggestion: 'cyan', + option: 'cyan', + accelerator: ['underline', 'bold', 'cyan'] + } + }; + +['File', 'Select', 'Text'].forEach(function (name) { + var m = exports[name] = require('./types/' + name.toLowerCase()); + Object.defineProperty(m.prototype, '_defaults', { value: defaults }); + exports[name.toLowerCase()] = function createField(opts) { return new m(opts); }; +}); + +exports.Set = require('./types/set'); +Object.defineProperty(exports.Set.prototype, '_defaults', { value: defaults }); +exports.set = function createSet(fields, opts) { return new exports.Set(fields, opts); }; + +exports.setup = function setup(opts) { + common.mix(defaults, opts); + colors.mode = defaults.colors ? 'console' : 'none'; + return exports; +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/prompter.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/prompter.js new file mode 100644 index 00000000..1afe54c4 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/prompter.js @@ -0,0 +1,335 @@ +var common = require('./common'), + keypress = require('keypress'), + events = require('events'), + util = require('util'), + history = []; + +module.exports = Prompter; + +function Prompter() { + this.complete = false; + this.formatters = {}; + this.style = {}; + this.trim = true; + this.repromptOnError = true; +} + +util.inherits(Prompter, events.EventEmitter); + +Prompter.prototype._format = function _format(str, style) { + str = String(str); + + if (!style && this.hasOwnProperty(str)) { + return this._format(this[str], str); + } + + str = str.split(/(__.+?__)/); + + if (this.colors && Array.isArray(style)) { + style.forEach(function (s) { + try { + if (this.style.hasOwnProperty(s)) { + str = str.map(function (i) { + return /^__.+__$/.test(i) ? i : str[this.style[s]]; + }.bind(this)); + } else { + str = str.map(function (i) { + return /^__.+__$/.test(i) ? i : (s in i ? i[s] : i); + }); + } + } catch (ex) {} + }); + } else if (this.colors && style && typeof style == 'string') { + try { + if (this.style.hasOwnProperty(style)) { + var ss = this.style[style]; + if (ss) { + if (Array.isArray(ss)) { + ss.forEach(function (x) { + str = str.map(function (i) { + return /^__.+__$/.test(i) ? i : i[x]; + }); + }); + } else { + str = str.map(function (i) { + return /^__.+__$/.test(i) ? i : i[ss]; + }); + } + } + } else { + str = str.map(function (i) { + return /^__.+__$/.test(i) ? i : (style in i ? i[style] : i); + }); + } + } catch (ex) {} + } + + return str.map(function (i) { + return i.replace(/__(.+?)__/, function (s, m) { + var ss = this.style.accelerator; + if (Array.isArray(ss)) { + ss.forEach(function (x) { + m = m[x]; + }); + } else { + m = m[ss]; + } + return m; + }.bind(this)); + }.bind(this)).join(''); +}; + +Prompter.prototype.reset = function reset() { + history = []; +}; + +Prompter.prototype._print = function _print(str) { + process.stdout.write(str || ''); +}; + +Prompter.prototype._println = function _println(str) { + process.stdout.write((str || '') + '\n'); +}; + +Prompter.prototype._getByNumber = function _getByNumber(value) { + return value; +}; + +/** + * Default wrapper around the user-defined validate(). + * + * @param {String} value - The value that was entered at the prompt. + * @param {Function} callback() - A function to call after validation completes. + * + * @returns {Boolean|undefined} - Returns true or false if value passes validation or undefined if this validate() is async. + */ +Prompter.prototype._validate = function _validate(value, callback) { + if (typeof this.validate === 'function') { + return this.validate(value, callback); + } + return true; +}; + +/** + * Performs the prompting. + * + * @param {Function} callback - A function to call after prompting completes. + */ +Prompter.prototype._get = function _get(callback) { + var prompt = '', + margin = 0, + caret = 0, + historyIdx = history.length, + mask = this._format(this.mask != undefined && (''+this.mask).charAt(0) || '*', 'mask'), + hidden = this.hidden, + reset = function (value) { + process.stdout.write(prompt); + history[++historyIdx] = ''; + caret = 0; + process.stdout.cursorTo(margin); + }, + done = function (err, value) { + process.stdin.pause(); + process.stdin.removeAllListeners('keypress'); + process.stdin.setRawMode(false); + this.emit('post-prompt', this, err, value); + callback(err, hidden ? undefined : value); + }.bind(this), + next = function (err, value) { + if (this.repromptOnError) { + reset(value); + } else { + done(err, value); + } + }.bind(this); + + if (this.promptLabel) { + prompt += this._format('promptLabel') + (this.promptValues || this.default ? ' ' : ''); + } + if (this.promptValues) { + prompt += this._format(this.promptValuesLeft + (Array.isArray(this.promptValues) ? this.promptValues.join(this.promptValuesSeparator) : this.promptValues) + this.promptValuesRight, 'promptValues') + (this.default ? ' ' : ''); + } + if (this.hasOwnProperty('default') && this.default !== void 0) { + prompt += this._format('defaultLeft') + this._format('default') + this._format('defaultRight'); + } + prompt += this._format('separator'); + + margin = prompt.stripColors.length; + + history[historyIdx] = ''; + keypress(process.stdin); + + process.stdout.write(prompt); + + process.stdin.on('keypress', function(c, key) { + var value, last; + switch (key && key.name || c) { + case 'enter': + case 'return': + process.stdout.write('\n'); + + value = history[historyIdx].length ? history[historyIdx] : '' + (this.default || ''); + if (process.platform !== 'win32') { + value = value.replace(/\\/g, ''); + } + this.trim && (value = value.trim()); + + // if this is a password or the value is empty, remove it from the history + if (this.password || !value) { + history.pop(); + historyIdx--; + } + + if (this.numbered) { + value = this._getByNumber(value); + } + + try { + var rethrow = false, + result = this._validate(value, function (err, value) { + // at this point validate() is done and if there is any exceptions + // that are thrown, then simply rethrow them + rethrow = true; + if (err) { + if (typeof err == 'string' || err instanceof Error) { + process.stdout.write((this.formatters.error ? this.formatters.error(err) : this._format(err, 'error')) + '\n'); + } + next(err, value); + } else { + done(null, value); + } + }.bind(this), this); + + // if result is undefined, then we assume they are going to call the callback + if (result === false) { + next(true, value); + } else if (result === true) { + done(null, value); + } + } catch (ex) { + if (rethrow) { + throw ex; + } else { + process.stdout.write((this.formatters.error ? this.formatters.error(ex) : this._format(ex, 'error')) + '\n'); + next(ex, value); + } + } + + return; + + case 'backspace': + if (caret && history[historyIdx].length) { + history[historyIdx] = history[historyIdx].substring(0, caret - 1) + history[historyIdx].substring(caret); + process.stdout.cursorTo(--caret + margin); + if (this.password) { + process.stdout.write((new Array(history[historyIdx].length - caret + 1)).join(mask) + ' '); + } else { + process.stdout.write(this._format(history[historyIdx].substring(caret), 'input') + ' '); + } + process.stdout.cursorTo(caret + margin); + } else { + process.stdout.write('\007'); // beep beep! + } + break; + + case 'delete': + if (history[historyIdx].length) { + history[historyIdx] = history[historyIdx].substring(0, caret) + history[historyIdx].substring(caret + 1); + if (this.password) { + process.stdout.write((new Array(history[historyIdx].length - caret + 1)).join(mask) + ' '); + } else { + process.stdout.write(this._format(history[historyIdx].substring(caret), 'input') + ' '); + } + process.stdout.cursorTo(caret + margin); + } + break; + + case 'left': + if (caret) { + process.stdout.cursorTo(--caret + margin); + } + break; + + case 'right': + if (caret < history[historyIdx].length) { + process.stdout.cursorTo(++caret + margin); + } + break; + + case 'home': + caret = 0; + process.stdout.cursorTo(margin); + break; + + case 'end': + caret = history[historyIdx].length + process.stdout.cursorTo(caret + margin); + break; + + case 'up': + if (!this.password && historyIdx) { + value = history[--historyIdx]; + last = history[historyIdx + 1]; + process.stdout.cursorTo(margin); + process.stdout.write(this._format(value, 'input') + (value.length < last.length ? (new Array(last.length - value.length + 1)).join(' ') : '')); + caret = history[historyIdx].length; + process.stdout.cursorTo(caret + margin); + } + break; + + case 'down': + if (!this.password && historyIdx < history.length - 1) { + value = history[++historyIdx]; + last = history[historyIdx - 1]; + process.stdout.cursorTo(margin); + process.stdout.write(this._format(value, 'input') + (value.length < last.length ? (new Array(last.length - value.length + 1)).join(' ') : '')); + caret = history[historyIdx].length; + process.stdout.cursorTo(caret + margin); + } + break; + + case 'tab': + if (this.complete && this._complete && history[historyIdx].length) { + this._complete(history[historyIdx], function (value, matches) { + if (this._lastKey && this._lastKey.name == 'tab' && matches && matches.length) { + this._print('\n' + common.renderGrid(this.margin, matches.map(function (m) { + return this._format(m, 'suggestion'); + }.bind(this)))); + process.stdout.write(prompt + this._format(value, 'input')); + } else { + process.stdout.cursorTo(margin); + process.stdout.write(this._format(value, 'input')); + } + history[historyIdx] = value; + caret = value.length; + process.stdout.cursorTo(caret + margin); + }.bind(this)); + } + break; + + case 'escape': case 'pageup': case 'pagedown': case 'undefined': case 'clear': case 'insert': + case 'f1': case 'f2': case 'f3': case 'f4': case 'f5': case 'f6': + case 'f7': case 'f8': case 'f9': case 'f10': case 'f11': case 'f12': + // do nothing + break; + + case 'c': + if (key.ctrl) { + return done(new Error('cancelled')); + } + // fall through + + default: + var remainder = history[historyIdx].substring(caret); + process.stdout.write(this.password ? mask + (remainder.length ? (new Array(remainder.length + 1)).join(mask) : '') : this._format(c + remainder, 'input')); + history[historyIdx] = history[historyIdx].substring(0, caret) + c + remainder; + process.stdout.cursorTo(++caret + margin); + } + + this._lastChar = c; + this._lastKey = key; + }.bind(this)); + + process.stdin.setRawMode(true); + process.stdin.resume(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/file.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/file.js new file mode 100644 index 00000000..c10e9313 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/file.js @@ -0,0 +1,88 @@ +var common = require('../common'), + Prompter = require('../prompter'), + fs = require('fs'), + path = require('path'), + util = require('util'), + trailingSepRegExp = /[\/\\]$/; + +module.exports = File; + +function File(opts) { + if (!(this instanceof File)) return new File(opts); + File.super_.call(this); + this.showHidden = true; + common.mix(this, this._defaults, opts); +} + +util.inherits(File, Prompter); + +File.prototype._complete = function _complete(value, callback) { + var isWin = process.platform === 'win32', + caseSensitive = !isWin, + p = (isWin ? Math.max(value.lastIndexOf('/'), value.lastIndexOf('\\')) : value.lastIndexOf(path.sep)) + 1, + filename = p === 0 ? '' : caseSensitive ? value.substring(p) : value.substring(p).toLowerCase(), + dir = p === 0 ? value : value.substring(0, p), + absDir = common.resolvePath(isWin ? dir.replace(/\//g, '\\') : dir.replace(/\\ /g, ' ')), + matches = [], + shortestMatch = null; + + if (fs.existsSync(absDir) && fs.statSync(absDir).isDirectory()) { + // we have to try/catch just in case we don't have access + try { + fs.readdirSync(absDir).forEach(function (name) { + var file = path.join(absDir, name), + isDirectory = fs.existsSync(file) && fs.statSync(file).isDirectory(); + if ((!isDirectory || !this.ignoreDirs || !this.ignoreDirs.test(name)) + && (isDirectory || !this.ignoreFiles || !this.ignoreFiles.test(name)) + && (this.showHidden || name.charAt(0) !== '.') + && (filename === '' + || (caseSensitive && name.indexOf(filename) === 0) + || (!caseSensitive && name.toLowerCase().indexOf(filename) === 0)) + ) { + try { + if (isDirectory) { + matches.push([name, true]); + } else { + matches.push([name, false]); + } + } catch (ex) { + matches.push([name, false]); + } + if (filename) { + if (shortestMatch === null) { + shortestMatch = name; + } else { + for (var i = 0; i < name.length && i < shortestMatch.length; i++) { + if (name[i] !== shortestMatch[i]) { + shortestMatch = shortestMatch.substring(0, i); + break; + } + } + } + } + } + }.bind(this)); + } catch (ex) {} + } + + if (matches.length === 1) { + // only 1 match, so just return it now + callback(path.join(dir, matches[0][0]) + (matches[0][1] ? path.sep : '')); + } else if (matches.length > 1) { + if (shortestMatch) { + value += shortestMatch.substring(filename.length); + } + callback(value, matches.map(function (f) { + return f[0] + (f[1] ? path.sep : ''); + })); + } else { + callback(value); + } +}; + +File.prototype.prompt = function prompt(callback) { + this.emit('pre-prompt', this); + this.title && this._println(this.formatters.title ? this.formatters.title(this) : this._format('title')); + this.desc && this._println(this.formatters.desc ? this.formatters.desc(this) : this._format('desc')); + this._get(callback); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/select.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/select.js new file mode 100644 index 00000000..69253ecf --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/select.js @@ -0,0 +1,327 @@ +var common = require('../common'), + Prompter = require('../prompter'), + util = require('util'); + +module.exports = Select; + +function Select(opts) { + if (!(this instanceof Select)) return new Select(opts); + + Select.super_.call(this); + + // defaults + this.display = 'list'; // possible values: list, prompt, grid + this.margin = ' '; + this.numbered = false; + this.zeroSkip = false; + this.autoSelectOne = false; + this.ignoreCase = false; + this.suggest = false; + this.suggestThreshold = 3; + this.relistOnError = false; + this.options = []; + this.optionLabel = 'label'; + this.optionValue = 'value'; + this.i18nStrings = {}; + + common.mix(this, this._defaults, opts); +} + +util.inherits(Select, Prompter); + +Select.prototype._validate = function _validate(value, cb) { + if (value === 0 && this.numbered && this.zeroSkip) { + return true; + } + + var self = this; + + function relist() { + if (self.relistOnError) { + if (self.display === 'grid') { + self._println(common.renderGrid(self.margin, self._prerenderedOptions)); + } else if (self.display === 'list') { + self._println(self.margin + self._prerenderedOptions.join('\n' + self.margin)); + } + } + } + + function checkValues(val) { + var ival = self.ignoreCase && typeof val === 'string' ? val.toLowerCase() : val; + + if (self._distinctValues.hasOwnProperty(ival)) { + value = self._distinctValues[ival]; + } else { + if (ival !== void 0 && ival !== null) { + var err = common.__(self, 'Invalid selection "%s"', val); + self._println((self.formatters.error ? self.formatters.error(err) : self._format(err, 'error')) + '\n'); + if (self.suggest) { + common.suggest(self, val, Object.keys(self._distinctValues), self._println, self.suggestThreshold); + } + } else { + var err = common.__(self, 'Please select a valid option'); + self._println((self.formatters.error ? self.formatters.error(err) : self._format(err, 'error')) + '\n'); + } + return false; + } + + return true; + } + + if (this._accelerators[value]) { + value = this._accelerators[value]; + if (value && typeof value === 'object') { + value = value[this.optionValue || 'value']; + } + } + + if (this.validate) { + var result = this.validate(value, function (err, val) { + if (err || !checkValues(val)) { + relist(); + return cb(true); + } + cb(null, val); + }); + + if (result === void 0) return; + + result || relist(); + return result; + } + + if (!checkValues(value)) { + relist(); + return false; + } + + cb(null, value); +}; + +Select.prototype._complete = function _complete(value, callback) { + var matches = [], + diff = [], + shortest = -1, + i, j, same; + + Object.keys(this._distinctValues).forEach(function (v) { + if (v.indexOf(value) === 0) { + matches.push(v); + var s = v.substring(value.length); + if (s.length) { + if (shortest === -1) { + shortest = s.length; + } else { + shortest = Math.min(shortest, s.length); + } + diff.push(s); + } + } + }); + + // if no matches and we are permitted to ignore case, try again + if (matches.length === 0 && this.completeIgnoreCase) { + var lvalue = value.toLowerCase(); + Object.keys(this._distinctValues).forEach(function (v) { + if (v.toLowerCase().indexOf(lvalue) === 0) { + matches.push(v); + value = v.substring(0, lvalue.length); + var s = v.substring(lvalue.length); + if (s.length) { + if (shortest === -1) { + shortest = s.length; + } else { + shortest = Math.min(shortest, s.length); + } + diff.push(s); + } + } + }); + } + + if (matches.length === 1) { + // only 1 match, so just return it now + callback(matches[0]); + } else if (diff.length > 1) { + // auto complete as much as we can + for (i = 0; i < shortest; i++) { + same = true; + for (j = 1; j < diff.length; j++) { + if (diff[j][i] !== diff[j-1][i]) { + same = false; + break; + } + } + if (same) { + value += diff[0][i]; // if char at "i" is the same, then just take it from the first string + } else { + break; + } + } + callback(value, matches); + } else { + callback(value); + } +}; + +Select.prototype._getByNumber = function _getByNumber(value) { + if (this.numbered) { + // did they enter a number? + var num = parseInt(value); + if (!isNaN(num) && ''+num === value) { + if (num === 0 && this.zeroSkip) { + return ''; + } + if (num >= 1 && num <= this._allValues.length) { + return this._allValues[num - 1]; + } + } + } + return value; +}; + +/** + * Renders the select list and prompts for a selection. + * + * @param {Function} callback - A function to call after prompting with the selected item. + */ +Select.prototype.prompt = function prompt(callback) { + var self = this; + + this.emit('pre-prompt', this); + this._distinctValues = {}; + this._prerenderedOptions = []; + this._allValues = []; + + var counter = 1; + + (function prepareOptions(options) { + if (Array.isArray(options)) { + options.forEach(function (opt, idx) { + var num = (new Array(3 - ('' + counter).length)).join(' ') + counter + ') ', + label = typeof opt === 'string' ? opt : (self.optionLabel ? opt[self.optionLabel] : opt.label) || (self.optionValue ? opt[self.optionValue] : opt.value), + val = typeof opt === 'string' ? opt.replace(/__(.+?)__/g, '$1') : (self.optionValue ? opt[self.optionValue] : opt.value); + + counter++; + self._allValues.push(val); + + if (self.formatters.option) { + self._prerenderedOptions.push(self.formatters.option.call(self, opt, idx, num)); + } else { + self._prerenderedOptions.push( + (self.numbered ? num : '') + + self._format(label, 'option') + ); + } + + if (Array.isArray(self.complete)) { + self.complete.forEach(function (key) { + if (opt.hasOwnProperty(key)) { + self._distinctValues[self.ignoreCase && typeof opt[key] === 'string' ? opt[key].toLowerCase() : opt[key]] = val; + } + }); + } else { + self._distinctValues[self.ignoreCase && typeof val === 'string' ? val.toLowerCase() : val] = val; + } + }); + } else if (options && typeof options === 'object') { + Object.keys(options).forEach(function (group) { + self._prerenderedOptions.push(self._format(group, 'group')); + prepareOptions(options[group]); + }); + } + })(this.options); + + var numOpts = Object.keys(this._allValues).length; + if (numOpts === 0) { + return callback(null, null); + + } else if (this.autoSelectOne && numOpts === 1) { + // there's only one option, so select it + var value = Object.keys(this._distinctValues).shift(); + + function check(val) { + var ival = self.ignoreCase && typeof val === 'string' ? val.toLowerCase() : val; + + if (self._distinctValues.hasOwnProperty(ival)) { + callback(null, self._distinctValues[ival]); + } else if (ival !== void 0 && ival !== null) { + callback(new Error(common.__(self, 'Invalid selection "%s"', val))); + } else { + callback(new Error(common.__(self, 'Please select a valid option'))); + } + } + + if (typeof this.validate === 'function') { + + var result = this.validate(value, function (err, val) { + if (err) { + callback(err); + } else { + check(val); + } + }); + + // if result is undefined, then we assume they are going to call the callback + if (result === void 0) return; + + if (result === false) { + callback(true); + } else { + callback(null, value); + } + } else { + check(value); + } + return; + } + + var a = this._accelerators = {}, + re = /__(.+?)__/; + + if (Array.isArray(this.options)) { + this.options.forEach(function (opt, i) { + var m = String(opt && typeof opt === 'object' ? opt[this.optionLabel || (opt.label ? 'label' : this.optionValue || 'value')] : opt).match(re); + if (m) { + if (typeof opt === 'string') { + a[m[1]] = opt.replace(re, m[1]); + this.options[i] = opt.replace(re, m[1]); + } else { + a[m[1]] = opt; + } + } + }, this); + } else if (this.options && typeof this.options === 'object') { + Object.keys(this.options).forEach(function (group) { + this.options[group].forEach(function (opt, i) { + var m = String(opt && typeof opt === 'object' ? opt[this.optionLabel || (opt.label ? 'label' : this.optionValue || 'value')] : opt).match(re); + if (m) { + if (typeof opt === 'string') { + a[m[1]] = opt.replace(re, m[1]); + this.options[group][i] = opt.replace(re, m[1]); + } else { + a[m[1]] = opt; + } + } + }, this); + }, this); + } + + var margin = (this.margin || ''); + + this.title && this._println(this.formatters.title ? this.formatters.title(this) : this._format('title')); + this.desc && this._println(this.formatters.desc ? this.formatters.desc(this) : this._format('desc')); + + if (this.display === 'prompt') { + this.promptValues = ''; + Object.keys(this._distinctValues).forEach(function (value, idx) { + this.promptValues += (idx ? this.promptValuesSeparator : '') + value; + }, this); + } else if (this.display === 'grid') { + this._println(common.renderGrid(margin, this._prerenderedOptions)); + } else if (this.display === 'list') { + this._println(margin + this._prerenderedOptions.join('\n' + margin)); + } + + this._get(callback); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/set.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/set.js new file mode 100644 index 00000000..1214543f --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/set.js @@ -0,0 +1,134 @@ +var common = require('../common'), + events = require('events'), + util = require('util'); + +module.exports = Set; + +function Set(fields, opts) { + if (!(this instanceof Set)) return new Set(fields, opts); + this.fields = fields; + this.stopOnError = true; + common.mix(this, this._defaults, opts); +} + +util.inherits(Set, events.EventEmitter); + +function next(results, key, callback) { + var obj = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; // either the 2nd arg or undefined + } + args !== undefined && (results[key] = args); + callback.call(obj, err); + }; + obj.goto = function (i) { + obj._goto = i; + return this; + }; + return obj; +} + +function seriesArray(tasks, done) { + var results = [], + idx = 0, + fs = this.fieldSeparator, + go = function (key, field, err) { + var then = function (go2) { + if (go2) { + idx = go2; + if (idx < 0 || idx >= tasks.length) { + return done(new Error('Invalid goto index: ' + idx), results); + } + } else if (go2 === false) { + idx = tasks.length; + } else { + idx += 1; + } + if (idx === tasks.length) { + done(null, results); + } else { + iterate(); + } + }.bind(this), + go2 = field && field.next ? field.next.call(field, err, results[key], then) : NaN; + + go2 !== void 0 && then(go2); + }.bind(this), + iterate = function () { + var field = tasks[idx]; + this.emit('pre-prompt', field); + field.prompt(next(results, idx, function (err) { + fs && process.stdout.write(fs); + this.emit('post-prompt', field, err, results[idx]); + if (err && (this.stopOnError || (err instanceof Error && err.message == 'cancelled'))) { + done(err, results); + } else { + go(idx, field, err); + } + }.bind(this))); + }.bind(this); + + if (!tasks.length) { + return done(null, results); + } + + iterate(); +} + +function seriesObject(obj, done) { + var results = {}, + idx = 0, + keys = Object.keys(obj), + fs = this.fieldSeparator, + go = function (key, field, err) { + var then = function (go2) { + if (go2) { + idx = keys.indexOf(go2); + if (idx == -1) { + return done(new Error('Invalid goto key: ' + go2), results); + } + } else if (go2 === false) { + idx = keys.length; + } else { + idx += 1; + } + if (idx === keys.length) { + done(null, results); + } else { + iterate(); + } + }.bind(this), + go2 = field && field.next ? field.next.call(field, err, results[key], then) : NaN; + go2 !== void 0 && then(go2); + }.bind(this), + iterate = function () { + var key = keys[idx], + field = obj[key]; + + if (field) { + this.emit('pre-prompt', field); + field.prompt(next(results, key, function (err) { + fs && process.stdout.write(fs); + this.emit('post-prompt', field, err, results[key]); + if (err && (this.stopOnError || (err instanceof Error && err.message == 'cancelled'))) { + done(err, results); + } else { + go(key, field, err); + } + }.bind(this))); + } else { + go(key, field); + } + }.bind(this); + + if (!keys.length) { + return done(null, results); + } + + iterate(); +} + +Set.prototype.prompt = function prompt(callback) { + this.fields && (Array.isArray(this.fields) ? seriesArray : seriesObject).call(this, this.fields, callback); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/text.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/text.js new file mode 100644 index 00000000..8d52fc41 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/lib/types/text.js @@ -0,0 +1,20 @@ +var common = require('../common'), + Prompter = require('../prompter'), + util = require('util'); + +module.exports = Text; + +function Text(opts) { + if (!(this instanceof Text)) return new Text(opts); + Text.super_.call(this); + common.mix(this, this._defaults, opts); +} + +util.inherits(Text, Prompter); + +Text.prototype.prompt = function prompt(callback) { + this.emit('pre-prompt', this); + this.title && this._println(this.formatters.title ? this.formatters.title(this) : this._format('title')); + this.desc && this._println(this.formatters.desc ? this.formatters.desc(this) : this._format('desc')); + this._get(callback); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/package.json b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/package.json new file mode 100644 index 00000000..795af851 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/package.json @@ -0,0 +1,32 @@ +{ + "name": "fields", + "description": "Creates fields to prompt for input at the command line", + "main": "./lib/index", + "author": { + "name": "Chris Barber" + }, + "version": "0.1.24", + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cb1kenobi/fields/raw/master/LICENSE" + } + ], + "engines": { + "node": ">=0.8.0" + }, + "directories": { + "lib": "./lib" + }, + "dependencies": { + "colors": "~0.6.2", + "keypress": "~0.2.1", + "sprintf": "~0.1.4" + }, + "homepage": "https://github.com/cb1kenobi/fields", + "bugs": "https://github.com/cb1kenobi/fields/issues", + "repository": { + "type": "git", + "url": "git://github.com/cb1kenobi/fields.git" + } +} diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file.js new file mode 100644 index 00000000..afab2200 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file.js @@ -0,0 +1,17 @@ +var fields = require('../lib'); + +fields.file({ + title: 'Enter the project directory', + desc: 'Any directory will do', + complete: true, + showHidden: false, + ignoreDirs: /^(\$RECYCLE\.BIN)$'/, + ignoreFiles: /file/ +}).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + console.log('you entered ' + value); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file_escaped_path.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file_escaped_path.js new file mode 100644 index 00000000..0a34e6e2 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_file_escaped_path.js @@ -0,0 +1,20 @@ +var fields = require('../lib'), + fs = require('fs'); + +fields.file({ + title: 'Enter the project directory', + desc: 'Any directory will do', + complete: true, + showHidden: false, + ignoreDirs: /^(\$RECYCLE\.BIN)$'/, + ignoreFiles: /file/ +}).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + fs.exists(value, function(exists) { + console.log(value + (exists ? ' exists' : ' does not exist')); + }); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_issue_4.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_issue_4.js new file mode 100644 index 00000000..e1da3457 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_issue_4.js @@ -0,0 +1,17 @@ +var fields = require('../lib'); + +fields.select({ + promptLabel: 'Please press "2"', + display: 'list', + numbered: true, + options: [ 'foo', 'foo', 'bar' ] +}).prompt(function (err, value) { + if (err) { + console.error(err); + } else if (value === 'foo') { + console.log('It works!'); + } else { + console.log('Failed: expected "' + value + '" to equal "foo"'); + } + console.log(); +}); \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select.js new file mode 100644 index 00000000..ae4e2359 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select.js @@ -0,0 +1,105 @@ +var fields = require('../lib'); + +fields.setup({ +}); + +var yesno = fields.select({ + promptLabel: 'Do it?', + display: 'prompt', + default: 'yes', + options: [ 'yes', 'no' ] +}); + +var milkshakes = fields.select({ + title: 'What is your favorite milkshake?', + options: [ + '__v__anilla', + 'st__r__awberry', + 'cho__c__olate' + ], + complete: true, + ignoreCase: true, + suggest: true, + suggestThreshold: 3 +}); + +var autoselect = fields.select({ + title: 'This should not be prompted for because there is only one option', + options: [ + 'foo', + ], + autoSelectOne: true +}) + +var actest = fields.select({ + title: 'Auto-complete test', + desc: 'Just type "he" and hit tab', + options: [ + 'hello', + 'hellothere', + 'helloworld' + ], + complete: true, + suggest: true, + suggestThreshold: 3 +}); + +var colors = fields.select({ + title: 'Choose your favorite color', + desc: 'It can be any of these colors', + options: [ + { label: 'red'.red + ' #f00', value: 'red' }, + { label: 'green'.green + ' #0f0', value: 'green' }, + { label: 'blue'.blue + ' #00f', value: 'blue' } + ], + relistOnError: true +}); + +var ppuuid = fields.select({ + title: 'Select a UUID by number or name', + formatters: { + option: function (opt, idx, num) { + return num + opt.value.cyan + ' ' + opt.name; + } + }, + numbered: true, + relistOnError: true, + complete: true, + suggest: true, + options: { + 'Available UUIDs:': [ + { name: 'uuid 1', value: '43C5E7DE-F6BB-4AEF-98F0-0A33990EA280' }, + { name: 'uuid 2', value: '4F562E96-C933-4367-B6BD-89CA7D6EE400' }, + { name: 'uuid 3', value: '31D3AC10-99F4-43E1-997B-980E70EC706B' }, + { name: 'uuid 4', value: 'E1512AE0-FEBB-43A2-9C9C-E1D2F4D6C51F' }, + { name: 'uuid 5', value: 'F624D6BA-5FF3-4E48-B9F2-BC7DD1A8EA97' }, + { name: 'uuid 6', value: '3C12C8D9-C05F-4834-BA7E-9C55CB8C9287' }, + { name: 'uuid 7', value: 'BB91EDBF-2A97-4227-B5B2-5943BAB30304' }, + { name: 'uuid 8', value: '204C6E4A-FA9C-48BB-9D84-709A10A690AB' }, + { name: 'uuid 9', value: '05282F35-42BB-40F3-8C20-3EC1739AB414' }, + { name: 'uuid 10', value: '5EC586D9-7E2B-4F55-834D-CD8199DD92B8' }, + { name: 'uuid 11', value: 'A4BD1980-8C4B-4DBB-8FBE-5A52E36DFA63' }, + { name: 'uuid 12', value: '99C49052-E280-48D3-B881-E8112B7DFCF1' }, + { name: 'uuid 13', value: 'A057301B-B38D-40B6-A6A4-B582AE5EAABE' }, + { name: 'uuid 14', value: 'D39B019B-3EF0-4BCA-A1E9-FC2F5063097F' }, + { name: 'uuid 15', value: 'C9A11E0C-5FF4-4B55-890F-F7715194CAB3' }, + { name: 'uuid 16', value: 'B1E31DD0-8968-4A32-B210-A0558302F65B' } + ] + } +}); + +fields.set([ + yesno, + milkshakes, + autoselect, + actest, + colors, + ppuuid +]).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + console.log('you entered ' + value); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_autoselectone_validate.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_autoselectone_validate.js new file mode 100644 index 00000000..7bb0bb8b --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_autoselectone_validate.js @@ -0,0 +1,76 @@ +var fields = require('../lib'), + worked = false; + +fields.select({ + autoSelectOne: true, + promptLabel: 'Select by id or name', + options: [ + { label: 'foo', value: 123 } + ], + validate: function (value, callback) { + worked = true; + callback(null, value); + } +}).prompt(function (err, value) { + if (err) { + console.log('Got error', err); + } else if (worked) { + console.log('It works!'); + } else { + console.log('Custom validate() not called!'); + } + + fields.select({ + autoSelectOne: true, + promptLabel: 'Select by id or name', + options: [ + { label: 'foo', value: 123 } + ], + validate: function (value, callback) { + callback(new Error('foo')); + } + }).prompt(function (err, value) { + if (err) { + console.log('It works!', err); + } else { + console.log('Failed, expected an error'); + } + + fields.select({ + autoSelectOne: true, + promptLabel: 'Select by id or name', + options: [ + { label: 'foo', value: 123 } + ], + validate: function (value, callback) { + return true; + } + }).prompt(function (err, value) { + if (err) { + console.log('Got error', err); + } else { + console.log('It works!'); + } + + fields.select({ + autoSelectOne: true, + promptLabel: 'Select by id or name', + options: [ + { label: 'foo', value: 123 } + ], + validate: function (value, callback) { + return false; + } + }).prompt(function (err, value) { + if (err) { + console.log('It works!', err); + } else { + console.log('Failed, expected an error'); + } + }); + + }); + + }); + +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_key_value.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_key_value.js new file mode 100644 index 00000000..14fcf411 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_select_key_value.js @@ -0,0 +1,57 @@ +var colors = require('colors'), + fields = require('../lib'); + +/* + +The goal here is to: + - select fruit by `id` + - select fruit by `name` + - be able to tab complete the `name` or `id` + - hit enter to accept default which is the `name` + - the final value must be the `id` + +*/ + +fields.select({ + title: 'Select a fruit by number or name', + formatters: { + option: function (opt, idx, num) { + return opt.id + ') ' + opt.name.cyan; + } + }, + complete: true, + numbered: false, + relistOnError: true, + complete: ['id', 'name'], + completeIgnoreCase: true, + suggest: true, + default: 'Apple', + promptLabel: 'Select by id or name', + optionLabel: 'name', + optionValue: 'id', + options: [ + { id: 0, name: 'Apple' }, + { id: 1, name: 'Orange' }, + { id: 2, name: 'Banana' }, + { id: 3, name: 'Peach' }, + { id: 4, name: 'Strawberry' }, + { id: 5, name: 'Lemon' }, + { id: 6, name: 'Grape' }, + { id: 7, name: 'Cherry' }, + { id: 8, name: 'Pear' }, + { id: 9, name: 'Pineapple' }, + { id: 10, name: 'Coconut' }, + { id: 11, name: 'Kiwi' }, + { id: 12, name: 'Watermelon' }, + { id: 13, name: 'Lime' }, + { id: 14, name: 'Cantaloupe' }, + { id: 15, name: 'Raspberry' } + ] +}).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + console.log('you selected ' + value); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set.js new file mode 100644 index 00000000..49a683f4 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set.js @@ -0,0 +1,95 @@ +var fields = require('../lib'); + +fields.setup({ +// colors: false +}); + +console.log('Object Test:\n'); + +fields.set({ + something: fields.text({ + promptLabel: 'Username', + validate: function (value, callback) { + callback(!value.length && new Error('Please enter a username'), value); + } + }), + + changePass: fields.select({ + promptLabel: 'Change password?', + display: 'prompt', + options: [ 'yes', 'no' ], + next: function (err, value, callback) { + if (value == 'no') { + callback('favfood'); + } else { + return null; + } + } + }), + + password: fields.text({ + promptLabel: 'Enter a password', + password: true, + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + favfood: fields.text({ + promptLabel: 'What is your favorite food?' + }) +}).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + console.error('Error occured! ', err); + process.exit(0); + } else { + console.log('you entered:'); + console.log(value); + } + + console.log('\nArray Test:\n'); + + fields.set([ + fields.text({ + promptLabel: 'Username', + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + fields.select({ + promptLabel: 'Change password?', + display: 'prompt', + options: [ 'yes', 'no' ], + next: function (err, value, callback) { + if (value == 'no') { + callback(3); + } else { + return null; + } + } + }), + + fields.text({ + promptLabel: 'Enter a password', + password: true, + validate: function (value, callback) { + callback(!value.length, value); + } + }), + + fields.text({ + promptLabel: 'What is your favorite food?' + }) + ]).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + console.log('you entered:'); + console.log(value); + } + }); + +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set_next.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set_next.js new file mode 100644 index 00000000..4ab27379 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_set_next.js @@ -0,0 +1,46 @@ +var fields = require('../lib'); + +fields.setup({ +// colors: false +}); + +fields.set({ + username: fields.text({ + promptLabel: 'Username', + validate: function (value, callback) { + callback(!value.length && new Error('Please enter a username'), value); + } + }), + + password: fields.text({ + title: 'Enter "123123" to login, otherwise you\'ll have to enter your username again', + promptLabel: 'Password', + validate: function (value, callback) { + if (!value.length) { + callback(new Error('Please enter a password')); + } else { + // try logging in + if (value != '123123') { + console.log('bad password'); + callback(true); + } else { + // success + callback(null, value); + } + } + }, + next: function (err, value, callback) { + return err ? 'username' : null; + }, + repromptOnError: false + }) +}, { stopOnError: false }).prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + console.error('Error occured! ', err); + process.exit(0); + } else { + console.log('you entered:'); + console.log(value); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_text.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_text.js new file mode 100644 index 00000000..fd2c9f11 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/fields/test/test_text.js @@ -0,0 +1,30 @@ +var fields = require('../lib'); + +var set = fields.set({ + text: fields.text({ + title: 'Enter something', + desc: 'It can be anything really', + default: 'Chris Barber', + validate: function (value, callback) { + callback(!value.length, value); + } + }), + password: fields.text({ + title: 'Enter a password', + index: 1, + password: true, + validate: function (value, callback) { + !value && console.error('you must enter a password'); + callback(!value, value); + } + }) +}); + +set.prompt(function (err, value) { + if (err) { + process.stdout.write('\n'); + process.exit(0); + } else { + console.log('you entered', value); + } +}); diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/README.md b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/README.md new file mode 100644 index 00000000..a768e8f5 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/README.md @@ -0,0 +1,101 @@ +keypress +======== +### Make any Node ReadableStream emit "keypress" events + + +Previous to Node `v0.8.x`, there was an undocumented `"keypress"` event that +`process.stdin` would emit when it was a TTY. Some people discovered this hidden +gem, and started using it in their own code. + +Now in Node `v0.8.x`, this `"keypress"` event does not get emitted by default, +but rather only when it is being used in conjuction with the `readline` (or by +extension, the `repl`) module. + +This module is the exact logic from the node `v0.8.x` releases ripped out into its +own module. + +__Bonus:__ Now with mouse support! + +Installation +------------ + +Install with `npm`: + +``` bash +$ npm install keypress +``` + +Or add it to the `"dependencies"` section of your _package.json_ file. + + +Example +------- + +#### Listening for "keypress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "keypress" events +keypress(process.stdin); + +// listen for the "keypress" event +process.stdin.on('keypress', function (ch, key) { + console.log('got "keypress"', key); + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause(); + } +}); + +process.stdin.setRawMode(true); +process.stdin.resume(); +``` + +#### Listening for "mousepress" events + +``` js +var keypress = require('keypress'); + +// make `process.stdin` begin emitting "mousepress" (and "keypress") events +keypress(process.stdin); + +// you must enable the mouse events before they will begin firing +keypress.enableMouse(process.stdout); + +process.stdin.on('mousepress', function (info) { + console.log('got "mousepress" event at %d x %d', info.x, info.y); +}); + +process.on('exit', function () { + // disable mouse on exit, so that the state + // is back to normal for the terminal + keypress.disableMouse(process.stdout); +}); +``` + + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/index.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/index.js new file mode 100644 index 00000000..5539dd68 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/index.js @@ -0,0 +1,408 @@ + +/** + * Module dependencies. + */ + +var EventEmitter = require('events').EventEmitter; + +/** + * Module exports. + */ + +var exports = module.exports = keypress; + +/** + * This module offers the internal "keypress" functionality from node-core's + * `readline` module, for your own programs and modules to use. + * + * The `keypress` function accepts a readable Stream instance and makes it + * emit "keypress" events. + * + * Usage: + * + * ``` js + * require('keypress')(process.stdin); + * + * process.stdin.on('keypress', function (ch, key) { + * console.log(ch, key); + * if (key.ctrl && key.name == 'c') { + * process.stdin.pause(); + * } + * }); + * proces.stdin.resume(); + * ``` + * + * @param {Stream} stream + * @api public + */ + +function keypress(stream) { + if (isEmittingKeypress(stream)) return; + + var StringDecoder = require('string_decoder').StringDecoder; // lazy load + stream._keypressDecoder = new StringDecoder('utf8'); + + function onData(b) { + if (listenerCount(stream, 'keypress') > 0) { + var r = stream._keypressDecoder.write(b); + if (r) emitKey(stream, r); + } else { + // Nobody's watching anyway + stream.removeListener('data', onData); + stream.on('newListener', onNewListener); + } + } + + function onNewListener(event) { + if (event == 'keypress') { + stream.on('data', onData); + stream.removeListener('newListener', onNewListener); + } + } + + if (listenerCount(stream, 'keypress') > 0) { + stream.on('data', onData); + } else { + stream.on('newListener', onNewListener); + } +} + +/** + * Returns `true` if the stream is already emitting "keypress" events. + * `false` otherwise. + * + * @param {Stream} stream readable stream + * @return {Boolean} `true` if the stream is emitting "keypress" events + * @api private + */ + +function isEmittingKeypress(stream) { + var rtn = !!stream._keypressDecoder; + if (!rtn) { + // XXX: for older versions of node (v0.6.x, v0.8.x) we want to remove the + // existing "data" and "newListener" keypress events since they won't include + // this `keypress` module extensions (like "mousepress" events). + stream.listeners('data').slice(0).forEach(function(l) { + if (l.name == 'onData' && /emitKey/.test(l.toString())) { + stream.removeListener('data', l); + } + }); + stream.listeners('newListener').slice(0).forEach(function(l) { + if (l.name == 'onNewListener' && /keypress/.test(l.toString())) { + stream.removeListener('newListener', l); + } + }); + } + return rtn; +} + +/** + * Enables "mousepress" events on the *input* stream. Note that `stream` must be + * an *output* stream (i.e. a Writable Stream instance), usually `process.stdout`. + * + * @param {Stream} stream writable stream instance + * @api public + */ + +exports.enableMouse = function (stream) { + stream.write('\x1b[?1000h'); +}; + +/** + * Disables "mousepress" events from being sent to the *input* stream. + * Note that `stream` must be an *output* stream (i.e. a Writable Stream instance), + * usually `process.stdout`. + * + * @param {Stream} stream writable stream instance + * @api public + */ + +exports.disableMouse = function (stream) { + stream.write('\x1b[?1000l'); +}; + +/** + * `EventEmitter.listenerCount()` polyfill, for backwards compat. + * + * @param {Emitter} emitter event emitter instance + * @param {String} event event name + * @return {Number} number of listeners for `event` + * @api public + */ + +var listenerCount = EventEmitter.listenerCount; +if (!listenerCount) { + listenerCount = function(emitter, event) { + return emitter.listeners(event).length; + }; +} + + +/////////////////////////////////////////////////////////////////////// +// Below this function is code from node-core's `readline.js` module // +/////////////////////////////////////////////////////////////////////// + + +/* + Some patterns seen in terminal key escape codes, derived from combos seen + at http://www.midnight-commander.org/browser/lib/tty/key.c + + ESC letter + ESC [ letter + ESC [ modifier letter + ESC [ 1 ; modifier letter + ESC [ num char + ESC [ num ; modifier char + ESC O letter + ESC O modifier letter + ESC O 1 ; modifier letter + ESC N letter + ESC [ [ num ; modifier char + ESC [ [ 1 ; modifier letter + ESC ESC [ num char + ESC ESC O letter + + - char is usually ~ but $ and ^ also happen with rxvt + - modifier is 1 + + (shift * 1) + + (left_alt * 2) + + (ctrl * 4) + + (right_alt * 8) + - two leading ESCs apparently mean the same as one leading ESC +*/ + +// Regexes used for ansi escape code splitting +var metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/; +var functionKeyCodeRe = + /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/; + +function emitKey(stream, s) { + var ch, + key = { + name: undefined, + ctrl: false, + meta: false, + shift: false + }, + parts; + + if (Buffer.isBuffer(s)) { + if (s[0] > 127 && s[1] === undefined) { + s[0] -= 128; + s = '\x1b' + s.toString(stream.encoding || 'utf-8'); + } else { + s = s.toString(stream.encoding || 'utf-8'); + } + } + + key.sequence = s; + + if (s === '\r') { + // carriage return + key.name = 'return'; + + } else if (s === '\n') { + // enter, should have been called linefeed + key.name = 'enter'; + + } else if (s === '\t') { + // tab + key.name = 'tab'; + + } else if (s === '\b' || s === '\x7f' || + s === '\x1b\x7f' || s === '\x1b\b') { + // backspace or ctrl+h + key.name = 'backspace'; + key.meta = (s.charAt(0) === '\x1b'); + + } else if (s === '\x1b' || s === '\x1b\x1b') { + // escape key + key.name = 'escape'; + key.meta = (s.length === 2); + + } else if (s === ' ' || s === '\x1b ') { + key.name = 'space'; + key.meta = (s.length === 2); + + } else if (s <= '\x1a') { + // ctrl+letter + key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1); + key.ctrl = true; + + } else if (s.length === 1 && s >= 'a' && s <= 'z') { + // lowercase letter + key.name = s; + + } else if (s.length === 1 && s >= 'A' && s <= 'Z') { + // shift+letter + key.name = s.toLowerCase(); + key.shift = true; + + } else if (parts = metaKeyCodeRe.exec(s)) { + // meta+character key + key.name = parts[1].toLowerCase(); + key.meta = true; + key.shift = /^[A-Z]$/.test(parts[1]); + + } else if (parts = functionKeyCodeRe.exec(s)) { + // ansi escape sequence + + // reassemble the key code leaving out leading \x1b's, + // the modifier key bitflag and any meaningless "1;" sequence + var code = (parts[1] || '') + (parts[2] || '') + + (parts[4] || '') + (parts[6] || ''), + modifier = (parts[3] || parts[5] || 1) - 1; + + // Parse the key modifier + key.ctrl = !!(modifier & 4); + key.meta = !!(modifier & 10); + key.shift = !!(modifier & 1); + key.code = code; + + // Parse the key itself + switch (code) { + /* xterm/gnome ESC O letter */ + case 'OP': key.name = 'f1'; break; + case 'OQ': key.name = 'f2'; break; + case 'OR': key.name = 'f3'; break; + case 'OS': key.name = 'f4'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[11~': key.name = 'f1'; break; + case '[12~': key.name = 'f2'; break; + case '[13~': key.name = 'f3'; break; + case '[14~': key.name = 'f4'; break; + + /* from Cygwin and used in libuv */ + case '[[A': key.name = 'f1'; break; + case '[[B': key.name = 'f2'; break; + case '[[C': key.name = 'f3'; break; + case '[[D': key.name = 'f4'; break; + case '[[E': key.name = 'f5'; break; + + /* common */ + case '[15~': key.name = 'f5'; break; + case '[17~': key.name = 'f6'; break; + case '[18~': key.name = 'f7'; break; + case '[19~': key.name = 'f8'; break; + case '[20~': key.name = 'f9'; break; + case '[21~': key.name = 'f10'; break; + case '[23~': key.name = 'f11'; break; + case '[24~': key.name = 'f12'; break; + + /* xterm ESC [ letter */ + case '[A': key.name = 'up'; break; + case '[B': key.name = 'down'; break; + case '[C': key.name = 'right'; break; + case '[D': key.name = 'left'; break; + case '[E': key.name = 'clear'; break; + case '[F': key.name = 'end'; break; + case '[H': key.name = 'home'; break; + + /* xterm/gnome ESC O letter */ + case 'OA': key.name = 'up'; break; + case 'OB': key.name = 'down'; break; + case 'OC': key.name = 'right'; break; + case 'OD': key.name = 'left'; break; + case 'OE': key.name = 'clear'; break; + case 'OF': key.name = 'end'; break; + case 'OH': key.name = 'home'; break; + + /* xterm/rxvt ESC [ number ~ */ + case '[1~': key.name = 'home'; break; + case '[2~': key.name = 'insert'; break; + case '[3~': key.name = 'delete'; break; + case '[4~': key.name = 'end'; break; + case '[5~': key.name = 'pageup'; break; + case '[6~': key.name = 'pagedown'; break; + + /* putty */ + case '[[5~': key.name = 'pageup'; break; + case '[[6~': key.name = 'pagedown'; break; + + /* rxvt */ + case '[7~': key.name = 'home'; break; + case '[8~': key.name = 'end'; break; + + /* rxvt keys with modifiers */ + case '[a': key.name = 'up'; key.shift = true; break; + case '[b': key.name = 'down'; key.shift = true; break; + case '[c': key.name = 'right'; key.shift = true; break; + case '[d': key.name = 'left'; key.shift = true; break; + case '[e': key.name = 'clear'; key.shift = true; break; + + case '[2$': key.name = 'insert'; key.shift = true; break; + case '[3$': key.name = 'delete'; key.shift = true; break; + case '[5$': key.name = 'pageup'; key.shift = true; break; + case '[6$': key.name = 'pagedown'; key.shift = true; break; + case '[7$': key.name = 'home'; key.shift = true; break; + case '[8$': key.name = 'end'; key.shift = true; break; + + case 'Oa': key.name = 'up'; key.ctrl = true; break; + case 'Ob': key.name = 'down'; key.ctrl = true; break; + case 'Oc': key.name = 'right'; key.ctrl = true; break; + case 'Od': key.name = 'left'; key.ctrl = true; break; + case 'Oe': key.name = 'clear'; key.ctrl = true; break; + + case '[2^': key.name = 'insert'; key.ctrl = true; break; + case '[3^': key.name = 'delete'; key.ctrl = true; break; + case '[5^': key.name = 'pageup'; key.ctrl = true; break; + case '[6^': key.name = 'pagedown'; key.ctrl = true; break; + case '[7^': key.name = 'home'; key.ctrl = true; break; + case '[8^': key.name = 'end'; key.ctrl = true; break; + + /* misc. */ + case '[Z': key.name = 'tab'; key.shift = true; break; + default: key.name = 'undefined'; break; + + } + } else if (s.length > 1 && s[0] !== '\x1b') { + // Got a longer-than-one string of characters. + // Probably a paste, since it wasn't a control sequence. + Array.prototype.forEach.call(s, function(c) { + emitKey(stream, c); + }); + return; + } + + // XXX: this "mouse" parsing code is NOT part of the node-core standard + // `readline.js` module, and is a `keypress` module non-standard extension. + if (key.code == '[M') { + key.name = 'mouse'; + var s = key.sequence; + var b = s.charCodeAt(3); + key.x = s.charCodeAt(4) - 040; + key.y = s.charCodeAt(5) - 040; + + key.scroll = 0; + + key.ctrl = !!(1<<4 & b); + key.meta = !!(1<<3 & b); + key.shift = !!(1<<2 & b); + + key.release = (3 & b) === 3; + + if (1<<6 & b) { //scroll + key.scroll = 1 & b ? 1 : -1; + } + + if (!key.release && !key.scroll) { + key.button = b & 3; + } + } + + // Don't emit a key if no name was found + if (key.name === undefined) { + key = undefined; + } + + if (s.length === 1) { + ch = s; + } + + if (key && key.name == 'mouse') { + stream.emit('mousepress', key); + } else if (key || ch) { + stream.emit('keypress', ch, key); + } +} diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/package.json b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/package.json new file mode 100644 index 00000000..96733471 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/package.json @@ -0,0 +1,20 @@ +{ + "name": "keypress", + "version": "0.2.1", + "description": "Make any Node ReadableStream emit \"keypress\" events", + "author": "Nathan Rajlich (http://tootallnate.net)", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git://github.com/TooTallNate/keypress.git" + }, + "keywords": [ + "keypress", + "readline", + "core" + ], + "license": "MIT" +} diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/test.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/test.js new file mode 100644 index 00000000..c3f61d79 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/keypress/test.js @@ -0,0 +1,28 @@ + +var keypress = require('./') +keypress(process.stdin) + +if (process.stdin.setRawMode) + process.stdin.setRawMode(true) +else + require('tty').setRawMode(true) + +process.stdin.on('keypress', function (c, key) { + console.log(0, c, key) + if (key && key.ctrl && key.name == 'c') { + process.stdin.pause() + } +}) +process.stdin.on('mousepress', function (mouse) { + console.log(mouse) +}) + +keypress.enableMouse(process.stdout) +process.on('exit', function () { + //disable mouse on exit, so that the state is back to normal + //for the terminal. + keypress.disableMouse(process.stdout) +}) + +process.stdin.resume() + diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/.npmignore b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/.npmignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/.npmignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/README.md b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/README.md new file mode 100644 index 00000000..be339fcc --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/README.md @@ -0,0 +1,60 @@ +# sprintf() for node + +## Disclaimer + +This was originally just an adoption of a browser library to node.js. +Since that library is now itself a node.js module, you should use that one: [alexei/sprintf.js](https://github.com/alexei/sprintf.js) + +Or just install it via npm: + + npm install sprintf-js + + +There is also a [built-in util.format](http://nodejs.org/api/util.html#util_util_format_format). + + + + +## Install + +**This package is not maintained anymore. See Disclaimer above.** + + npm install sprintf + + +## How to + +Works exactly like http://www.diveintojavascript.com/projects/javascript-sprintf, except that it exports those two functions: + + sprintf = require('sprintf').sprintf; + vsprintf = require('sprintf').vsprintf; + +Have fun! + + +## Copyright/License + +Copyright (c) 2007-2013, Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +* Neither the name of this software nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/lib/sprintf.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/lib/sprintf.js new file mode 100644 index 00000000..1ef42e25 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/lib/sprintf.js @@ -0,0 +1,249 @@ +/** +sprintf() for JavaScript 0.7-beta1 +http://www.diveintojavascript.com/projects/javascript-sprintf + +Copyright (c) Alexandru Marasteanu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Changelog: +2010.11.07 - 0.7-beta1-node + - converted it to a node.js compatible module + +2010.09.06 - 0.7-beta1 + - features: vsprintf, support for named placeholders + - enhancements: format cache, reduced global namespace pollution + +2010.05.22 - 0.6: + - reverted to 0.4 and fixed the bug regarding the sign of the number 0 + Note: + Thanks to Raphael Pigulla (http://www.n3rd.org/) + who warned me about a bug in 0.5, I discovered that the last update was + a regress. I appologize for that. + +2010.05.09 - 0.5: + - bug fix: 0 is now preceeded with a + sign + - bug fix: the sign was not at the right position on padded results (Kamal Abdali) + - switched from GPL to BSD license + +2007.10.21 - 0.4: + - unit test and patch (David Baird) + +2007.09.17 - 0.3: + - bug fix: no longer throws exception on empty paramenters (Hans Pufal) + +2007.09.11 - 0.2: + - feature: added argument swapping + +2007.04.03 - 0.1: + - initial release +**/ + +var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + // convert object to simple one line string without indentation or + // newlines. Note that this implementation does not print array + // values to their actual place for sparse arrays. + // + // For example sparse array like this + // l = [] + // l[4] = 1 + // Would be printed as "[1]" instead of "[, , , , 1]" + // + // If argument 'seen' is not null and array the function will check for + // circular object references from argument. + str_format.object_stringify = function(obj, depth, maxdepth, seen) { + var str = ''; + if (obj != null) { + switch( typeof(obj) ) { + case 'function': + return '[Function' + (obj.name ? ': '+obj.name : '') + ']'; + break; + case 'object': + if ( obj instanceof Error) { return '[' + obj.toString() + ']' }; + if (depth >= maxdepth) return '[Object]' + if (seen) { + // add object to seen list + seen = seen.slice(0) + seen.push(obj); + } + if (obj.length != null) { //array + str += '['; + var arr = [] + for (var i in obj) { + if (seen && seen.indexOf(obj[i]) >= 0) arr.push('[Circular]'); + else arr.push(str_format.object_stringify(obj[i], depth+1, maxdepth, seen)); + } + str += arr.join(', ') + ']'; + } else if ('getMonth' in obj) { // date + return 'Date(' + obj + ')'; + } else { // object + str += '{'; + var arr = [] + for (var k in obj) { + if(obj.hasOwnProperty(k)) { + if (seen && seen.indexOf(obj[k]) >= 0) arr.push(k + ': [Circular]'); + else arr.push(k +': ' +str_format.object_stringify(obj[k], depth+1, maxdepth, seen)); + } + } + str += arr.join(', ') + '}'; + } + return str; + break; + case 'string': + return '"' + obj + '"'; + break + } + } + return '' + obj; + } + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^sO]/.test(match[8]) && (get_type(arg) != 'number')) { + throw new Error(sprintf('[sprintf] expecting number but found %s "' + arg + '"', get_type(arg))); + } + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'O': arg = str_format.object_stringify(arg, 0, parseInt(match[7]) || 5); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosOuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw new Error('[sprintf] ' + replacement_field); + } + } + } + else { + throw new Error('[sprintf] ' + replacement_field); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw new Error('[sprintf] ' + _fmt); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; +})(); + +var vsprintf = function(fmt, argv) { + var argvClone = argv.slice(); + argvClone.unshift(fmt); + return sprintf.apply(null, argvClone); +}; + +module.exports = sprintf; +sprintf.sprintf = sprintf; +sprintf.vsprintf = vsprintf; diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/package.json b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/package.json new file mode 100644 index 00000000..bc18b191 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/package.json @@ -0,0 +1,26 @@ +{ + "name": "sprintf", + "version": "0.1.5", + "engines": { + "node" : ">=0.2.4" + }, + "author": "Moritz Peters", + "directories": { + "lib": "./lib" + }, + "description": "Sprintf() for node.js", + "main": "./lib/sprintf", + "homepage": "https://github.com/maritz/node-sprintf", + "repository": { + "type": "git", + "url": "https://github.com/maritz/node-sprintf.git" + }, + "license": "BSD-3-Clause", + "scripts": { + "test": "nodeunit test/function-export.js" + }, + "devDependencies": { + "nodeunit": "0.8.0" + } +} + diff --git a/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/test/function-export.js b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/test/function-export.js new file mode 100644 index 00000000..468e7604 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/node_modules/sprintf/test/function-export.js @@ -0,0 +1,9 @@ +var sprintf = require(__dirname + '/..'); + +exports['sprintf() export works'] = function(test) { + test.equal(sprintf('Hallo %s!', 'Welt'), 'Hallo Welt!'); + test.equal(sprintf.sprintf('Hallo %s!', 'Welt'), 'Hallo Welt!'); + test.equal(sprintf.vsprintf('Hallo %s!', ['Welt']), 'Hallo Welt!'); + + test.done(); +}; diff --git a/test/titanium/sdk/mocks/mock-sdk/package.json b/test/titanium/sdk/mocks/mock-sdk/package.json new file mode 100644 index 00000000..1f8335a3 --- /dev/null +++ b/test/titanium/sdk/mocks/mock-sdk/package.json @@ -0,0 +1,15 @@ +{ + "name": "titanium-mobile", + "description": "TiDev Titanium Mobile", + "version": "0.0.0", + "moduleApiVersion": { + "iphone": "2", + "android": "4" + }, + "vendorDependencies": { + "node": "12.x || 14.x || 16.x" + }, + "engines": { + "node": ">=12.13.0" + } +} diff --git a/test/titanium/sdk/mocks/no-name-sdk/manifest.json b/test/titanium/sdk/mocks/no-name-sdk/manifest.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/test/titanium/sdk/mocks/no-name-sdk/manifest.json @@ -0,0 +1 @@ +{} diff --git a/test/titanium/sdk/mocks/rc-release/manifest.json b/test/titanium/sdk/mocks/rc-release/manifest.json new file mode 100644 index 00000000..940cd5e9 --- /dev/null +++ b/test/titanium/sdk/mocks/rc-release/manifest.json @@ -0,0 +1 @@ +{"name":"0.0.0.RC","version":"0.0.0","moduleAPIVersion":{"iphone":"2","android":"4"},"timestamp":"1/1/2023 00:00","githash":"1234567890","platforms":["android"]} diff --git a/test/titanium/tiapp/fixtures/hassdk.xml b/test/titanium/tiapp/fixtures/hassdk.xml new file mode 100644 index 00000000..211be6ae --- /dev/null +++ b/test/titanium/tiapp/fixtures/hassdk.xml @@ -0,0 +1,4 @@ + + + 1.2.3 + diff --git a/test/titanium/tiapp/fixtures/invalid.xml b/test/titanium/tiapp/fixtures/invalid.xml new file mode 100644 index 00000000..9f599dc2 --- /dev/null +++ b/test/titanium/tiapp/fixtures/invalid.xml @@ -0,0 +1,3 @@ + + +bad diff --git a/test/titanium/tiapp/fixtures/nopin.xml b/test/titanium/tiapp/fixtures/nopin.xml new file mode 100644 index 00000000..c0daebde --- /dev/null +++ b/test/titanium/tiapp/fixtures/nopin.xml @@ -0,0 +1,3 @@ + + 1.2.3 + diff --git a/test/titanium/tiapp/fixtures/nosdk.xml b/test/titanium/tiapp/fixtures/nosdk.xml new file mode 100644 index 00000000..885cdb0f --- /dev/null +++ b/test/titanium/tiapp/fixtures/nosdk.xml @@ -0,0 +1,3 @@ + + + diff --git a/test/titanium/tiapp/fixtures/tiapp1.xml b/test/titanium/tiapp/fixtures/tiapp1.xml new file mode 100644 index 00000000..cd546d12 --- /dev/null +++ b/test/titanium/tiapp/fixtures/tiapp1.xml @@ -0,0 +1,19 @@ + + + ti.testapp + testapp + 1.0 + tester + https://titaniumsdk.com + not specified + 2022 by tester + appicon.png + false + false + default + false + 088dc83c-64af-4a81-b57c-7407649453f0 + system + + + diff --git a/test/titanium/tiapp/fixtures/tiapp2.xml b/test/titanium/tiapp/fixtures/tiapp2.xml new file mode 100644 index 00000000..5d3b74b1 --- /dev/null +++ b/test/titanium/tiapp/fixtures/tiapp2.xml @@ -0,0 +1,225 @@ + + + + true + true + true + + 2.2.0 + ti.testapp + ti.testapp.android + ti.testapp.ios + testapp + 1.0 + tester + http:// + not specified + 2012 by tester + appicon.png + false + false + default + false + false + false + 088dc83c-64af-4a81-b57c-7407649453f0 + system + production + true + false + false + this "one" with quotes + ti.testapp.invoke.push + ti.testapp.invoke.open + Some Title for BB Push, typically the app name" + false + false + + + + group.com.appc.foo + group.com.appc.bar + + + #FFFFFF + true + + + application-identifier + XXXXXXXXXX.com.test.app + aps-environment + production + beta-reports-active + + get-task-allow + + keychain-access-groups + + XXXXXXXXXX.com.test.app + + + + + + + + + + + + + abc + 123 + + + + + + + + + 10571 + 5.0 + + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIBackgroundModes + + audio + location + voip + newsstand-content + external-accessory + bluetooth-central + + UIRequiredDeviceCapabilities + + telephony + wifi + sms + still-camera + auto-focus-camera + front-facing-camera + camera-flash + video-camera + accelerometer + gyroscope + location-services + gps + magnetometer + gamekit + microphone + opengles-1 + opengles-2 + armv6 + armv7 + peer-peer + bluetooth-le + + UIRequiresPersistentWiFi + + UIPrerenderedIcon + + UIStatusBarHidden + + UIStatusBarStyle + UIStatusBarStyleBlackTranslucent + UIAppFonts + + /fonts/MyFont_1.otf + /fonts/MyFont_2.otf + + + + foo + true + true + true + true + + + + + + + + + + + + + + + + + + + + + 10 + armeabi,armeabi-v7a,x86 + + + activity2.js + activity3.js + + + + + testservice3.js + + + + ti.alltest + ti.cjstest + ti.androidtest + ti.iphonetest + + diff --git a/test/titanium/tiapp/tiapp-xml.test.ts b/test/titanium/tiapp/tiapp-xml.test.ts new file mode 100644 index 00000000..a0a4e82d --- /dev/null +++ b/test/titanium/tiapp/tiapp-xml.test.ts @@ -0,0 +1,793 @@ +import { TiappXML } from '../../../src/titanium/tiapp/tiapp-xml.js'; +import { rm } from 'node:fs/promises'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, describe, expect, it } from 'vitest'; + +const fixturesDir = join(fileURLToPath(import.meta.url), '../fixtures'); + +describe('TiappXML', () => { + describe('Basic Operations', () => { + it('should handle missing properties', () => { + const tiapp = new TiappXML().parse(` + + test +`); + const data = tiapp.data(); + expect(data).toMatchObject({ id: 'test' }); + }); + }); + + describe('Property Modification', () => { + it('should update properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + const data = tiapp.data(); + data.name = 'newname'; + tiapp.apply(data); + + expect(tiapp.data().name).toBe('newname'); + const xml = tiapp.toString(); + expect(xml).toContain('newname'); + }); + + it('should create new properties', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.publisher = 'Test Publisher'; + tiapp.apply(data); + + expect(tiapp.data().publisher).toBe('Test Publisher'); + const xml = tiapp.toString(); + expect(xml).toContain('Test Publisher'); + }); + + it('should handle property deletion', () => { + const tiapp = new TiappXML().parse(` + + test + test + icon.png +`); + + const data = tiapp.data(); + expect(data.icon).toBe('icon.png'); + delete data.icon; + tiapp.apply(data); + + expect(tiapp.data().icon).toBeUndefined(); + const xml = tiapp.toString(); + expect(xml).not.toContain(''); + }); + + it('should handle ios plists', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.ios = { + plist: { + UIBackgroundModes: [ + 'audio', + 'location', + 'voip', + 'newsstand-content', + 'external-accessory', + 'bluetooth-central', + ], + }, + }; + tiapp.apply(data); + const xml = tiapp.toString(); + expect(xml).toBe(` + + test + + + + UIBackgroundModes + + audio + location + voip + newsstand-content + external-accessory + bluetooth-central + + + + +`); + }); + }); + + describe('Platform-Specific Properties', () => { + it('should handle platform-specific ids', () => { + const xml = ` + + com.example.app + com.example.android +`; + + const tiapp = new TiappXML().parse(xml); + const data = tiapp.data(); + + expect(data.id).toBe('com.example.app'); + expect(data.idPlatformAndroid).toBe('com.example.android'); + }); + + it('should create platform-specific properties', () => { + const tiapp = new TiappXML().parse(` + + com.example.app +`); + + const data = tiapp.data(); + data.id = 'com.example.app2'; + data.idPlatformIos = 'com.example.ios'; + tiapp.apply(data); + + expect(tiapp.data().id).toBe('com.example.app2'); + expect(tiapp.data().idPlatformIos).toBe('com.example.ios'); + expect(tiapp.toString()).toContain('com.example.ios'); + }); + }); + + describe('Modules Array', () => { + it('should read modules array', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.modules).toBeDefined(); + expect(Array.isArray(data.modules)).toBe(true); + expect(data.modules!.length).toBeGreaterThan(0); + }); + + it('should handle module properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + const firstModule = data.modules![0]; + expect(firstModule).toBeDefined(); + expect(firstModule.moduleid).toBe('ti.alltest'); + expect(firstModule.version).toBe('1.2.3'); + }); + + it('should add modules', () => { + const tiapp = new TiappXML().parse(` + + test + +`); + + const data = tiapp.data(); + data.modules = data.modules || []; + data.modules.push({ moduleid: 'ti.test', platform: 'android', version: '1.0' }); + tiapp.apply(data); + + expect(tiapp.data().modules!.length).toBe(1); + + const xml = tiapp.toString(); + expect(xml).toContain('ti.test'); + }); + + it('should remove modules', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + const initialLength = data.modules!.length; + data.modules!.pop(); + tiapp.apply(data); + + expect(tiapp.data().modules!.length).toBe(initialLength - 1); + }); + + it('should error if module does not have an id', () => { + const tiapp = new TiappXML(); + expect(() => + tiapp.parse(` + + + + +`) + ).toThrow('Module must have an id'); + }); + + it('should error if module version is invalid', () => { + const tiapp = new TiappXML(); + expect(() => + tiapp.parse(` + + + foo + +`) + ).toThrow('Module version is invalid'); + }); + }); + + describe('Properties (Key-Value)', () => { + it('should read properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.properties!['ti.ui.defaultunit']).toBe('system'); + }); + + it('should handle boolean properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.properties!['ti.android.debug']).toBe(true); + }); + + it('should add properties', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.properties = data.properties || {}; + data.properties['my.prop'] = 'test'; + tiapp.apply(data); + + expect(tiapp.data().properties!['my.prop']).toBe('test'); + + const xml = tiapp.toString(); + expect(xml).toContain('name="my.prop"'); + }); + + it('should delete properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.properties!['ti.ui.defaultunit']).toBeDefined(); + delete data.properties!['ti.ui.defaultunit']; + tiapp.apply(data); + + expect(tiapp.data().properties!['ti.ui.defaultunit']).toBeUndefined(); + }); + }); + + describe('iOS Configuration', () => { + it('should read iOS config', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.ios).toBeDefined(); + expect(data.ios!.minIosVer).toBe('5.0'); + expect(data.ios!.teamId).toBe('foo'); + }); + + it('should read iOS plist', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.ios!.plist).toBeDefined(); + expect(typeof data.ios!.plist).toBe('object'); + expect(data.ios!.plist).toHaveProperty('UISupportedInterfaceOrientations'); + }); + + it('should read iOS capabilities', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.ios!.capabilities).toBeDefined(); + expect(data.ios!.capabilities!.appGroups).toBeDefined(); + expect(Array.isArray(data.ios!.capabilities!.appGroups)).toBe(true); + }); + }); + + describe('Android Configuration', () => { + it('should read Android config', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.android).toBeDefined(); + expect(data.android!.toolAPILevel).toBe(10); + }); + + it('should read Android ABI as array', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.android!.abi).toBeDefined(); + expect(Array.isArray(data.android!.abi)).toBe(true); + expect(data.android!.abi!.length).toBeGreaterThan(0); + }); + + it('should read Android manifest', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.android!.manifest).toBeDefined(); + expect(typeof data.android!.manifest).toBe('string'); + }); + }); + + describe('Deployment Targets', () => { + it('should read deployment targets', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data.deploymentTargets).toBeDefined(); + expect(data.deploymentTargets!.android).toBeDefined(); + }); + }); + + describe('Whitespace Preservation', () => { + it('should preserve whitespace when adding properties', () => { + const xml = ` + + com.test + test +`; + + const tiapp = new TiappXML().parse(xml); + const data = tiapp.data(); + data.version = '1.0.0'; + tiapp.apply(data); + + const output = tiapp.toString(); + expect(output).toContain('\n\t1.0.0'); + }); + + it('should preserve existing formatting', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + const data = tiapp.data(); + // eslint-disable-next-line @typescript-eslint/no-self-assign + data.name = data.name; // Set to same value + tiapp.apply(data); + + const newXml = tiapp.toString(); + expect(newXml.split('\n').length).toBeGreaterThan(5); + }); + }); + + describe('JSON Serialization', () => { + it('should support JSON.stringify', () => { + const tiapp = new TiappXML().parse(` + + com.test + testapp + 1.0 +`); + + const data = tiapp.data(); + const json = JSON.stringify(data); + const parsed = JSON.parse(json); + + expect(parsed.id).toBe('com.test'); + expect(parsed.name).toBe('testapp'); + expect(parsed.version).toBe('1.0'); + + expect(parsed.load).toBeUndefined(); + expect(parsed.save).toBeUndefined(); + }); + + it('should handle data as plain object', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + expect(data).toHaveProperty('id'); + expect(data).toHaveProperty('name'); + expect(Object.getPrototypeOf(data)).toBe(Object.prototype); + }); + + it('should handle JSON serialization with nested objects', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + + const json = JSON.stringify(data, null, 2); + const parsed = JSON.parse(json); + + expect(parsed.ios).toBeDefined(); + expect(parsed.modules).toBeDefined(); + expect(Array.isArray(parsed.modules)).toBe(true); + }); + + it('should handle platform-specific properties in JSON', () => { + const tiapp = new TiappXML().parse(` + + com.example.app + com.example.android + com.example.ios +`); + + const data = tiapp.data(); + const json = JSON.stringify(data); + const parsed = JSON.parse(json); + + expect(parsed.id).toBeDefined(); + expect(typeof parsed.id === 'object' || typeof parsed.id === 'string').toBe(true); + }); + + it('should output JSON format', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + const data = tiapp.data(); + expect(data.id).toBe('ti.testapp'); + }); + }); + + describe('Merge', () => { + it('should merge an object into the tiapp', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + tiapp.merge({ id: 'com.example.app' }); + expect(tiapp.data().id).toBe('com.example.app'); + expect(tiapp.toString()).toContain('com.example.app'); + }); + + it('should merge an object into the tiapp and overwrite the existing properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + tiapp.merge({ id: 'com.example.app', name: 'new name' }); + expect(tiapp.data().id).toBe('com.example.app'); + expect(tiapp.data().name).toBe('new name'); + const str = tiapp.toString(); + expect(str).toContain('com.example.app'); + expect(str).toContain('new name'); + }); + }); + + describe('toString()', () => { + it('should output XML format', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + const xml = tiapp.toString(); + + expect(xml).toContain(''); + }); + + it('should set xml version if not present', () => { + const tiapp = new TiappXML().parse(` +`); + expect(tiapp.toString()).toMatch(/^<\?xml/); + }); + }); + + describe('Edge Cases', () => { + it('should handle empty tiapp.xml', () => { + const tiapp = new TiappXML().parse(` + +`); + + const data = tiapp.data(); + expect(data.id).toBeUndefined(); + expect(data.name).toBeUndefined(); + }); + + it('should handle numeric values', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.version = '2.0'; + tiapp.apply(data); + + expect(tiapp.data().version).toBe('2.0'); + + const xml = tiapp.toString(); + expect(xml).toContain('2.0'); + }); + + it('should handle boolean values', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.persistentWifi = true; + tiapp.apply(data); + + expect(tiapp.data().persistentWifi).toBe(true); + + const xml = tiapp.toString(); + expect(xml).toContain('true'); + }); + + it('should error if file does not exist', () => { + const tiapp = new TiappXML(); + expect(() => tiapp.load(join(fixturesDir, 'does_not_exist.xml'))).toThrow( + 'tiapp.xml file does not exist' + ); + }); + }); + + describe('Save Operations', () => { + afterEach(async () => { + await rm('/tmp/test-tiapp.xml', { force: true }); + }); + + it('should save to file', async () => { + const tiapp = new TiappXML().parse(` + + test + test +`); + + const tmpFile = join('/tmp', 'test-tiapp.xml'); + tiapp.save(tmpFile); + + const tiapp2 = new TiappXML().load(tmpFile); + const data = tiapp2.data(); + expect(data.id).toBe('test'); + expect(data.name).toBe('test'); + }); + }); + + describe('Schema Validation', () => { + it('should throw on invalid data when applying', () => { + const tiapp = new TiappXML().parse(` + + test +`); + + const data = tiapp.data(); + data.modules = [{ id: 123 }] as any; // invalid: id should be string + + expect(() => tiapp.apply(data)).toThrow('Invalid tiapp data'); + }); + }); + + describe('Errors', () => { + it('should error if file does not exist', () => { + const tiapp = new TiappXML(); + expect(() => tiapp.load(join(fixturesDir, 'does_not_exist.xml'))).toThrow( + 'tiapp.xml file does not exist' + ); + }); + + it('should error if file is not a valid XML file', () => { + const tiapp = new TiappXML(); + expect(() => tiapp.load(join(fixturesDir, 'invalid.xml'))).toThrow('Invalid XML file'); + }); + }); + + describe('Sample Files', () => { + it('should load a tiapp during construction', () => { + const tiapp = new TiappXML(join(fixturesDir, 'hassdk.xml')); + const data = tiapp.data(); + expect(data.sdkVersion).toBe('1.2.3'); + }); + + it('should load a tiapp after construction', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'hassdk.xml')); + const data = tiapp.data(); + expect(data.sdkVersion).toBe('1.2.3'); + }); + + it('should read simple properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp1.xml')); + const data = tiapp.data(); + expect(data).toEqual({ + id: 'ti.testapp', + name: 'testapp', + version: '1.0', + publisher: 'tester', + url: 'https://titaniumsdk.com', + description: 'not specified', + copyright: '2022 by tester', + icon: 'appicon.png', + persistentWifi: false, + prerenderedIcon: false, + properties: { + 'ti.ui.defaultunit': 'system', + }, + statusbarStyle: 'default', + statusbarHidden: false, + guid: '088dc83c-64af-4a81-b57c-7407649453f0', + modules: [], + android: {}, + }); + }); + + it('should read complex properties', () => { + const tiapp = new TiappXML().load(join(fixturesDir, 'tiapp2.xml')); + const data = tiapp.data(); + expect(data).toEqual({ + deploymentTargets: { + iphone: true, + ipad: true, + android: true, + }, + sdkVersion: '2.2.0', + id: 'ti.testapp', + idPlatformAndroid: 'ti.testapp.android', + idPlatformIos: 'ti.testapp.ios', + name: 'testapp', + version: '1.0', + publisher: 'tester', + url: 'http://', + description: 'not specified', + copyright: '2012 by tester', + icon: 'appicon.png', + persistentWifi: false, + prerenderedIcon: false, + statusbarStyle: 'default', + statusbarHidden: false, + fullscreen: false, + navbarHidden: false, + guid: '088dc83c-64af-4a81-b57c-7407649453f0', + properties: { + 'ti.ui.defaultunit': 'system', + 'ti.deploytype': 'production', + 'ti.android.debug': true, + 'ti.android.loadfromsdcard': false, + 'ti.android.compilejs': false, + 'another property': 'this "one" with quotes', + 'ti.bb.invoke.target.key.push': 'ti.testapp.invoke.push', + 'ti.bb.invoke.target.key.open': 'ti.testapp.invoke.open', + push_title: 'Some Title for BB Push, typically the app name"', + 'ti.skipAppIdValidation': false, + 'ti.skipVersionValidation': false, + }, + ios: { + capabilities: { + appGroups: ['group.com.appc.foo', 'group.com.appc.bar'], + }, + defaultBackgroundColor: '#FFFFFF', + enableLaunchScreenStoryboard: true, + entitlements: { + 'application-identifier': 'XXXXXXXXXX.com.test.app', + 'aps-environment': 'production', + 'beta-reports-active': true, + 'get-task-allow': false, + 'keychain-access-groups': ['XXXXXXXXXX.com.test.app'], + }, + extensions: [ + { + projectPath: '/path/to/extention', + target: 'Some Target', + provisioningProfiles: [], + }, + { + projectPath: '/path/to/extention2', + target: 'Another Target', + provisioningProfiles: [ + { + device: 'abc', + distAppstore: '123', + distAdhoc: true, + }, + ], + }, + { + projectPath: '/path/to/another/extention', + target: 'Test WatchKit Extension', + }, + ], + logServerPort: 10571, + minIosVer: '5.0', + plist: { + UISupportedInterfaceOrientations: [ + 'UIInterfaceOrientationPortrait', + 'UIInterfaceOrientationPortraitUpsideDown', + 'UIInterfaceOrientationLandscapeLeft', + 'UIInterfaceOrientationLandscapeRight', + ], + UIBackgroundModes: [ + 'audio', + 'location', + 'voip', + 'newsstand-content', + 'external-accessory', + 'bluetooth-central', + ], + UIRequiredDeviceCapabilities: [ + 'telephony', + 'wifi', + 'sms', + 'still-camera', + 'auto-focus-camera', + 'front-facing-camera', + 'camera-flash', + 'video-camera', + 'accelerometer', + 'gyroscope', + 'location-services', + 'gps', + 'magnetometer', + 'gamekit', + 'microphone', + 'opengles-1', + 'opengles-2', + 'armv6', + 'armv7', + 'peer-peer', + 'bluetooth-le', + ], + UIRequiresPersistentWiFi: true, + UIPrerenderedIcon: true, + UIStatusBarHidden: true, + UIStatusBarStyle: 'UIStatusBarStyleBlackTranslucent', + UIAppFonts: ['/fonts/MyFont_1.otf', '/fonts/MyFont_2.otf'], + }, + teamId: 'foo', + useAppThinning: true, + useAutolayout: true, + useJscoreFramework: true, + useNewBuildSystem: true, + }, + android: { + manifest: ` + + + + + + + + + + + + + + + + + `, + services: [ + { + type: 'interval', + url: 'testservice.js', + }, + { + type: 'standard', + url: 'testservice2.js', + }, + { + url: 'testservice3.js', + }, + ], + activities: [ + { + url: 'activity.js', + extra: 'foo', + }, + { + url: 'activity2.js', + extra: 'foo', + }, + { + url: 'activity3.js', + }, + ], + abi: ['armeabi', 'armeabi-v7a', 'x86'], + toolAPILevel: 10, + }, + modules: [ + { + moduleid: 'ti.alltest', + version: '1.2.3', + }, + { + moduleid: 'ti.cjstest', + version: '1.2.3', + platform: 'commonjs', + }, + { + moduleid: 'ti.androidtest', + version: '7.8', + platform: 'android', + }, + { + moduleid: 'ti.iphonetest', + version: '9.0', + platform: 'iphone', + }, + ], + }); + }); + }); +}); diff --git a/test/titanium/valid-app-id.test.ts b/test/titanium/valid-app-id.test.ts new file mode 100644 index 00000000..c7d61b72 --- /dev/null +++ b/test/titanium/valid-app-id.test.ts @@ -0,0 +1,50 @@ +import { validAppId } from '../../src/titanium/valid-app-id.js'; +import { describe, expect, it } from 'vitest'; + +describe('validAppId', () => { + it('should return false for an invalid app id', () => { + expect(validAppId(null as unknown as string)).toBe(false); + expect(validAppId(undefined as unknown as string)).toBe(false); + expect(validAppId(123 as unknown as string)).toBe(false); + expect(validAppId({} as unknown as string)).toBe(false); + expect(validAppId([] as unknown as string)).toBe(false); + expect(validAppId(true as unknown as string)).toBe(false); + }); + + it('should return false for an app id that starts with a period', () => { + expect(validAppId('.com.example.app')).toBe(false); + }); + + it('should return false for an app id that ends with a period', () => { + expect(validAppId('com.example.app.')).toBe(false); + }); + + it('should return false for an app id that contains consecutive periods', () => { + expect(validAppId('com.example..app')).toBe(false); + }); + + it("should return false if the app id doesn't contain a period", () => { + expect(validAppId('example')).toBe(false); + }); + + it('should return false if the app id contains non-alphanumeric characters', () => { + expect(validAppId('com.example.underscore_app')).toBe(false); + expect(validAppId('com.example.app\twith whitespace')).toBe(false); + }); + + it('should return false if the app id segment starts with a dash', () => { + expect(validAppId('com.example.app.-with-dash')).toBe(false); + }); + + it('should return false if segment is longer than 255 characters', () => { + expect(validAppId('com.example.app.'.repeat(255))).toBe(false); + }); + + it('should return false for an app id that contains a reserved word', () => { + expect(validAppId('com.example.app.break')).toBe(false); + }); + + it('should return true for a valid app id', () => { + expect(validAppId('com.example.app')).toBe(true); + }); +}); diff --git a/test/util/assets/titanium-logo.png b/test/util/assets/titanium-logo.png new file mode 100644 index 00000000..fce99eaf Binary files /dev/null and b/test/util/assets/titanium-logo.png differ diff --git a/test/util/can-symlink.ts b/test/util/can-symlink.ts new file mode 100644 index 00000000..072f6879 --- /dev/null +++ b/test/util/can-symlink.ts @@ -0,0 +1,23 @@ +import { randomBytes } from 'node:crypto'; +import { mkdirSync, writeFileSync, symlinkSync, rmSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; + +export function canSymlink(): boolean { + const tmpDir = join( + tmpdir(), + 'node-titanium-sdk', + `symlink-test-${randomBytes(8).toString('hex')}` + ); + mkdirSync(tmpDir, { recursive: true }); + try { + writeFileSync(join(tmpDir, 'test.txt'), 'test'); + symlinkSync(join(tmpDir, 'test.txt'), join(tmpDir, 'link.txt')); + symlinkSync(join(tmpDir, 'does_not_exist.txt'), join(tmpDir, 'link2.txt')); + return true; + } catch { + return false; + } finally { + rmSync(tmpDir, { recursive: true, force: true }); + } +} diff --git a/test/util/capitalize.test.ts b/test/util/capitalize.test.ts new file mode 100644 index 00000000..155ac630 --- /dev/null +++ b/test/util/capitalize.test.ts @@ -0,0 +1,17 @@ +import { capitalize } from '../../src/util/capitalize.js'; +import { describe, expect, it } from 'vitest'; + +describe('capitalize', () => { + it('should capitalize the first letter of the string', () => { + expect(capitalize('hello')).toBe('Hello'); + }); + + it('should return an empty string if the input is an empty string', () => { + expect(capitalize('')).toBe(''); + }); + + it('should return the same string if the input is already capitalized', () => { + expect(capitalize('Hello')).toBe('Hello'); + expect(capitalize('HELLO')).toBe('HELLO'); + }); +}); diff --git a/test/util/exists.test.ts b/test/util/exists.test.ts new file mode 100644 index 00000000..fa88867f --- /dev/null +++ b/test/util/exists.test.ts @@ -0,0 +1,79 @@ +import { exists, existsSync } from '../../src/util/exists.js'; +import { canSymlink } from './can-symlink.js'; +import { randomBytes } from 'node:crypto'; +import { mkdir, rm, symlink, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +let tmpDir: string; +beforeEach(async () => { + tmpDir = join(tmpdir(), 'node-titanium-sdk', `zip-test-${randomBytes(8).toString('hex')}`); + await mkdir(tmpDir, { recursive: true }); +}); + +afterEach(async () => { + if (existsSync(tmpDir)) { + await rm(tmpDir, { force: true, recursive: true }); + } +}); + +describe('exists', () => { + it('should return true if a file exists', async () => { + await writeFile(join(tmpDir, 'test.txt'), 'test'); + expect(await exists(join(tmpDir, 'test.txt'))).toBe(true); + }); + + it('should return true if a directory exists', async () => { + await mkdir(join(tmpDir, 'test'), { recursive: true }); + expect(await exists(join(tmpDir, 'test'))).toBe(true); + }); + + it('should return false if a file does not exist', async () => { + expect(await exists(join(tmpDir, 'test.txt'))).toBe(false); + }); + + it('should return false if a directory does not exist', async () => { + expect(await exists(join(tmpDir, 'test'))).toBe(false); + }); + + it.skipIf(!canSymlink())('should return true if a symlink exists', async () => { + await symlink(join(tmpDir, 'test.txt'), join(tmpDir, 'link.txt')); + expect(await exists(join(tmpDir, 'link.txt'))).toBe(true); + }); + + it.skipIf(!canSymlink())('should return true if a broken symlink exists', async () => { + await symlink(join(tmpDir, 'does_not_exist.txt'), join(tmpDir, 'link.txt')); + expect(await exists(join(tmpDir, 'link.txt'))).toBe(true); + }); +}); + +describe('existsSync', () => { + it('should return true if a file exists', async () => { + await writeFile(join(tmpDir, 'test.txt'), 'test'); + expect(existsSync(join(tmpDir, 'test.txt'))).toBe(true); + }); + + it('should return true if a directory exists', async () => { + await mkdir(join(tmpDir, 'test'), { recursive: true }); + expect(existsSync(join(tmpDir, 'test'))).toBe(true); + }); + + it('should return false if a file does not exist', async () => { + expect(existsSync(join(tmpDir, 'test.txt'))).toBe(false); + }); + + it('should return false if a directory does not exist', async () => { + expect(existsSync(join(tmpDir, 'test'))).toBe(false); + }); + + it.skipIf(!canSymlink())('should return true if a symlink exists', async () => { + await symlink(join(tmpDir, 'test.txt'), join(tmpDir, 'link.txt')); + expect(existsSync(join(tmpDir, 'link.txt'))).toBe(true); + }); + + it.skipIf(!canSymlink())('should return true if a broken symlink exists', async () => { + await symlink(join(tmpDir, 'does_not_exist.txt'), join(tmpDir, 'link.txt')); + expect(existsSync(join(tmpDir, 'link.txt'))).toBe(true); + }); +}); diff --git a/test/util/expand.test.ts b/test/util/expand.test.ts new file mode 100644 index 00000000..adb515df --- /dev/null +++ b/test/util/expand.test.ts @@ -0,0 +1,57 @@ +import { expand } from '../../src/util/expand.js'; +import { afterEach, beforeAll, describe, expect, it } from 'vitest'; + +let HOME: string | undefined; +let USERPROFILE: string | undefined; +let SystemRoot: string | undefined; + +beforeAll(() => { + HOME = process.env.HOME; + USERPROFILE = process.env.USERPROFILE; + SystemRoot = process.env.SystemRoot; +}); + +afterEach(() => { + if (HOME !== undefined) { + process.env.HOME = HOME; + } + if (USERPROFILE !== undefined) { + process.env.USERPROFILE = USERPROFILE; + } + if (SystemRoot !== undefined) { + process.env.SystemRoot = SystemRoot; + } + delete process.env.TITANIUMLIB_TEST_PLATFORM; +}); + +const isWin = process.platform === 'win32'; + +describe('expand()', () => { + it('should resolve the home directory using HOME', () => { + process.env.HOME = isWin ? 'C:\\Users\\username' : '/Users/username'; + delete process.env.USERPROFILE; + + const p = expand('~/foo'); + expect(p).to.equal(isWin ? 'C:\\Users\\username\\foo' : '/Users/username/foo'); + }); + + it('should resolve the home directory using USERPROFILE', () => { + delete process.env.HOME; + process.env.USERPROFILE = isWin ? 'C:\\Users\\username' : '/Users/username'; + + const p = expand('~/foo'); + expect(p).to.equal(isWin ? 'C:\\Users\\username\\foo' : '/Users/username/foo'); + }); + + it('should collapse relative segments', () => { + const p = expand('/path/./to/../foo'); + expect(p).to.match(isWin ? /:\\path\\foo/ : /\/path\/foo/); + }); + + it.skipIf(!isWin)('should resolve environment paths (Windows)', () => { + process.env.TITANIUMLIB_TEST_PLATFORM = 'win32'; + process.env.SystemRoot = 'C:\\WINDOWS'; + const p = expand('%SystemRoot%\\foo'); + expect(isWin ? p : p.substring(process.cwd().length + 1)).to.equal('C:\\WINDOWS\\foo'); + }); +}); diff --git a/test/util/is-dir.test.ts b/test/util/is-dir.test.ts new file mode 100644 index 00000000..1c0f1db3 --- /dev/null +++ b/test/util/is-dir.test.ts @@ -0,0 +1,21 @@ +import { isDir } from '../../src/util/is-dir.js'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import { describe, expect, it } from 'vitest'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe('isDir()', () => { + it('should return true if the path is a directory', () => { + expect(isDir(__dirname)).toBe(true); + }); + + it("should return false if the path doesn't exist", () => { + expect(isDir(join(__dirname, 'does_not_exist'))).toBe(false); + }); + + it('should return false if the path is not a directory', () => { + expect(isDir(__filename)).toBe(false); + }); +}); diff --git a/test/util/is-file.test.ts b/test/util/is-file.test.ts new file mode 100644 index 00000000..b4c74639 --- /dev/null +++ b/test/util/is-file.test.ts @@ -0,0 +1,21 @@ +import { isFile } from '../../src/util/is-file.js'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import { describe, expect, it } from 'vitest'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +describe('isFile()', () => { + it('should return true if the path is a file', () => { + expect(isFile(__filename)).toBe(true); + }); + + it("should return false if the path doesn't exist", () => { + expect(isFile(join(__dirname, 'does_not_exist'))).toBe(false); + }); + + it('should return false if the path is not a file', () => { + expect(isFile(__dirname)).toBe(false); + }); +}); diff --git a/test/util/is-writable.test.ts b/test/util/is-writable.test.ts new file mode 100644 index 00000000..40491d4e --- /dev/null +++ b/test/util/is-writable.test.ts @@ -0,0 +1,72 @@ +import { isWritable, isWritableSync } from '../../src/util/is-writable.js'; +import { createTempDir } from '../../src/util/temp.js'; +import { chmod, mkdir, rm, writeFile } from 'node:fs/promises'; +import { join } from 'node:path'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +let tmpDir: string; +beforeEach(async () => { + tmpDir = await createTempDir({ prefix: 'node-titanium-sdk' }); +}); + +afterEach(() => rm(tmpDir, { force: true, recursive: true })); + +describe('isWritable()', () => { + it('should return true if the path is writable', async () => { + await expect(isWritable(tmpDir)).resolves.toBe(true); + await expect(isWritable(join(tmpDir, 'test.txt'))).resolves.toBe(true); + await expect(isWritable(join(tmpDir, 'dir'))).resolves.toBe(true); + await expect(isWritable(join(tmpDir, 'dir', 'test.txt'))).resolves.toBe(true); + + await writeFile(join(tmpDir, 'test.txt'), 'test'); + await expect(isWritable(join(tmpDir, 'test.txt'))).resolves.toBe(true); + await mkdir(join(tmpDir, 'dir'), { recursive: true }); + await expect(isWritable(join(tmpDir, 'dir'))).resolves.toBe(true); + }); + + it.skipIf(process.getuid?.() === 0)( + 'should return false if the path is not writable', + async () => { + if (process.platform === 'darwin' || process.platform === 'linux') { + await chmod(tmpDir, 0o444); + await expect(isWritable(join(tmpDir, 'test.txt'))).resolves.toBe(false); + await expect(isWritable(join(tmpDir, 'dir', 'test.txt'))).resolves.toBe(false); + } else if (process.platform === 'win32') { + const winSxS = join(process.env.SystemRoot ?? 'C:\\Windows', 'WinSxS'); + await expect(isWritable(winSxS)).resolves.toBe(false); + await expect(isWritable(join(winSxS, 'test.txt'))).resolves.toBe(false); + await expect(isWritable(join(winSxS, 'dir', 'test.txt'))).resolves.toBe(false); + } + } + ); +}); + +describe('isWritableSync()', () => { + it('should return true if the path is writable', async () => { + expect(isWritableSync(tmpDir)).toBe(true); + expect(isWritableSync(join(tmpDir, 'test.txt'))).toBe(true); + expect(isWritableSync(join(tmpDir, 'dir'))).toBe(true); + expect(isWritableSync(join(tmpDir, 'dir', 'test.txt'))).toBe(true); + + await writeFile(join(tmpDir, 'test.txt'), 'test'); + expect(isWritableSync(join(tmpDir, 'test.txt'))).toBe(true); + await mkdir(join(tmpDir, 'dir'), { recursive: true }); + expect(isWritableSync(join(tmpDir, 'dir'))).toBe(true); + }); + + it.skipIf(process.getuid?.() === 0)( + 'should return false if the path is not writable', + async () => { + if (process.platform === 'darwin' || process.platform === 'linux') { + await chmod(tmpDir, 0o444); + await expect(isWritable(join(tmpDir, 'test.txt'))).resolves.toBe(false); + await expect(isWritable(join(tmpDir, 'dir', 'test.txt'))).resolves.toBe(false); + } else if (process.platform === 'win32') { + const winSxS = join(process.env.SystemRoot ?? 'C:\\Windows', 'WinSxS'); + expect(isWritableSync(winSxS)).toBe(false); + expect(isWritableSync(join(winSxS, 'test.txt'))).toBe(false); + expect(isWritableSync(join(winSxS, 'dir', 'test.txt'))).toBe(false); + } + } + ); +}); diff --git a/test/util/merge-deep.test.ts b/test/util/merge-deep.test.ts new file mode 100644 index 00000000..a88a6500 --- /dev/null +++ b/test/util/merge-deep.test.ts @@ -0,0 +1,32 @@ +import { mergeDeep } from '../../src/util/merge-deep.js'; +import { describe, it, expect } from 'vitest'; + +describe('mergeDeep', () => { + it('should merge two objects', () => { + const target = { a: 1, b: 2 }; + const source = { b: 3, c: 4 }; + const result = mergeDeep(target, source); + expect(result).toEqual({ a: 1, b: 3, c: 4 }); + }); + + it('should merge two objects with nested objects', () => { + const target = { a: 1, b: { c: 2 } }; + const source = { b: { c: 3, d: 4 }, e: { f: 5 } }; + const result = mergeDeep(target, source); + expect(result).toEqual({ a: 1, b: { c: 3, d: 4 }, e: { f: 5 } }); + }); + + it('should merge two objects with nested objects and arrays', () => { + const target = { a: 1, b: { c: 2, d: [1, 2] } }; + const source = { b: { c: 3, d: [3, 4] } }; + const result = mergeDeep(target, source); + expect(result).toEqual({ a: 1, b: { c: 3, d: [3, 4] } }); + }); + + it('should merge two objects with nested objects and arrays and overwrite the target', () => { + const target = { a: 1, b: { c: 2, d: [1, 2] } }; + const source = { b: { c: 3, d: [3, 4], e: 5 } }; + const result = mergeDeep(target, source); + expect(result).toEqual({ a: 1, b: { c: 3, d: [3, 4], e: 5 } }); + }); +}); diff --git a/test/util/owner.test.ts b/test/util/owner.test.ts new file mode 100644 index 00000000..cc32cad8 --- /dev/null +++ b/test/util/owner.test.ts @@ -0,0 +1,28 @@ +import { getOwner, getOwnerSync } from '../../src/util/owner.js'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { describe, expect, it } from 'vitest'; + +const __filename = fileURLToPath(import.meta.url); + +describe('getOwner()', () => { + it('should get owner of a file', async () => { + const owner = await getOwner(__filename); + expect(owner.gid).toBeDefined(); + expect(owner.origin).toBe(dirname(__filename)); + expect(owner.target).toBe(__filename); + expect(owner.supported).toBe(process.platform !== 'win32'); + expect(owner.uid).toBeDefined(); + }); +}); + +describe('getOwnerSync()', () => { + it('should get owner of a file', () => { + const owner = getOwnerSync(__filename); + expect(owner.gid).toBeDefined(); + expect(owner.origin).toBe(dirname(__filename)); + expect(owner.target).toBe(__filename); + expect(owner.supported).toBe(process.platform !== 'win32'); + expect(owner.uid).toBeDefined(); + }); +}); diff --git a/test/util/plist/fixtures/Info.plist b/test/util/plist/fixtures/Info.plist new file mode 100644 index 00000000..9c3822d0 --- /dev/null +++ b/test/util/plist/fixtures/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleURLTypes + + + CFBundleURLName + __URL__ + CFBundleURLSchemes + + __URLSCHEME__ + __ADDITIONAL_URL_SCHEMES__ + + + + CFBundleIdentifier + com.titaniumsdk.titanium + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + CFBundleShortVersionString + 1.0 + LSRequiresIPhoneOS + + + diff --git a/test/util/plist/fixtures/invalid.txt b/test/util/plist/fixtures/invalid.txt new file mode 100644 index 00000000..81a410b7 --- /dev/null +++ b/test/util/plist/fixtures/invalid.txt @@ -0,0 +1 @@ +this is not a plist file diff --git a/test/util/plist/plist.test.ts b/test/util/plist/plist.test.ts new file mode 100644 index 00000000..96f202fa --- /dev/null +++ b/test/util/plist/plist.test.ts @@ -0,0 +1,161 @@ +import { + parsePlist, + readPlist, + readPlistSync, + writePlist, + writePlistSync, +} from '../../../src/util/plist.js'; +import { randomBytes } from 'node:crypto'; +import { existsSync } from 'node:fs'; +import { mkdir, rm } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +const fixturesDir = join(fileURLToPath(import.meta.url), '../fixtures'); + +let tmpDir: string; +beforeEach(async () => { + tmpDir = join(tmpdir(), 'node-titanium-sdk', `plist-test-${randomBytes(8).toString('hex')}`); + await mkdir(tmpDir, { recursive: true }); +}); + +afterEach(async () => { + if (existsSync(tmpDir)) { + await rm(tmpDir, { force: true, recursive: true }); + } +}); + +describe('Plist', () => { + describe('parse', () => { + it('should parse a plist string', () => { + const plist = parsePlist(` + + + + name + test + age + 20 + friends + + John + Jane + Jim + + address + + street + 123 Main St + city + Anytown + state + CA + zip + 12345 + + +`); + expect(plist).toEqual({ + name: 'test', + age: 20, + friends: ['John', 'Jane', 'Jim'], + address: { + street: '123 Main St', + city: 'Anytown', + state: 'CA', + zip: '12345', + }, + }); + }); + + it('should error if the plist is invalid', () => { + expect(() => parsePlist('not a plist file')).toThrow('Invalid plist:'); + }); + }); + + describe('read', () => { + it('should load a plist file synchronously', () => { + const plist = readPlistSync(join(fixturesDir, 'Info.plist')); + expect(plist).toEqual({ + CFBundleDevelopmentRegion: 'English', + CFBundleDisplayName: '${PRODUCT_NAME}', + CFBundleExecutable: '${EXECUTABLE_NAME}', + CFBundleURLTypes: [{ CFBundleURLName: '__URL__', CFBundleURLSchemes: ['__URLSCHEME__'] }], + CFBundleIdentifier: 'com.titaniumsdk.titanium', + CFBundleInfoDictionaryVersion: '6.0', + CFBundleName: '${PRODUCT_NAME}', + CFBundlePackageType: 'APPL', + CFBundleSignature: '????', + CFBundleVersion: '1.0', + CFBundleShortVersionString: '1.0', + LSRequiresIPhoneOS: true, + }); + }); + + it('should load a plist file asynchronously', async () => { + const plist = await readPlist(join(fixturesDir, 'Info.plist')); + expect(plist).toEqual({ + CFBundleDevelopmentRegion: 'English', + CFBundleDisplayName: '${PRODUCT_NAME}', + CFBundleExecutable: '${EXECUTABLE_NAME}', + CFBundleURLTypes: [{ CFBundleURLName: '__URL__', CFBundleURLSchemes: ['__URLSCHEME__'] }], + CFBundleIdentifier: 'com.titaniumsdk.titanium', + CFBundleInfoDictionaryVersion: '6.0', + CFBundleName: '${PRODUCT_NAME}', + CFBundlePackageType: 'APPL', + CFBundleSignature: '????', + CFBundleVersion: '1.0', + CFBundleShortVersionString: '1.0', + LSRequiresIPhoneOS: true, + }); + }); + + it('should throw an error if the plist file does not exist', () => { + expect(() => readPlistSync(join(fixturesDir, 'does-not-exist.plist'))).toThrow( + 'plist file does not exist' + ); + }); + + it('should throw an error if the plist file is not a valid plist', () => { + expect(() => readPlistSync(join(fixturesDir, 'invalid.txt'))).toThrow('Invalid plist:'); + }); + }); + + describe('write', () => { + it('should write a plist file synchronously', () => { + const obj = { + name: 'test', + age: 20, + friends: ['John', 'Jane', 'Jim'], + address: { + street: '123 Main St', + city: 'Anytown', + state: 'CA', + zip: '12345', + }, + }; + writePlistSync(join(tmpDir, 'test.plist'), obj); + const plist = readPlistSync(join(tmpDir, 'test.plist')); + expect(plist).toEqual(obj); + }); + + it('should write a plist file asynchronously', async () => { + const obj = { + name: 'test', + age: 20, + friends: ['John', 'Jane', 'Jim'], + address: { + street: '123 Main St', + city: 'Anytown', + state: 'CA', + zip: '12345', + }, + }; + await writePlist(join(tmpDir, 'test.plist'), obj); + const plist = await readPlist(join(tmpDir, 'test.plist')); + expect(plist).toEqual(obj); + }); + }); +}); diff --git a/test/util/png-info.test.ts b/test/util/png-info.test.ts new file mode 100644 index 00000000..d157be07 --- /dev/null +++ b/test/util/png-info.test.ts @@ -0,0 +1,87 @@ +import { pngInfo } from '../../src/util/png-info.js'; +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { describe, expect, it } from 'vitest'; + +describe('pngInfo', () => { + it('should return the width, height, and alpha channel of a PNG buffer', () => { + const buf = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x02, 0x00, 0x00, 0x00, 0x1f, + 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]); + expect(pngInfo(buf)).toEqual({ + width: 1, + height: 1, + alpha: false, + }); + }); + + it('should return the width, height, and alpha channel of a PNG buffer with an alpha channel', () => { + const buf = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, + 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4e, 0x53, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + ]); + expect(pngInfo(buf)).toEqual({ + width: 1, + height: 1, + alpha: true, + }); + }); + + it('should return the width, height, and alpha channel of a PNG buffer with a width and height of 0', () => { + const buf = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x1f, + 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + expect(pngInfo(buf)).toEqual({ + width: 0, + height: 0, + alpha: false, + }); + }); + + it('should return the width, height, and alpha channel of a PNG buffer with a width and height of 0 and an alpha channel', () => { + const buf = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, + 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + expect(pngInfo(buf)).toEqual({ + width: 0, + height: 0, + alpha: true, + }); + }); + + it('should return the width, height, and alpha channel of a PNG buffer with a width and height of 0 and an alpha channel', () => { + const buf = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, + 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x00, 0x00, 0x00, 0x1f, + 0x15, 0xc4, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + ]); + expect(pngInfo(buf)).toEqual({ + width: 0, + height: 0, + alpha: true, + }); + }); + + it('should return the width, height, and alpha channel of a PNG file', () => { + const bytes = readFileSync(join(import.meta.filename, '..', 'assets', 'titanium-logo.png')); + expect(pngInfo(bytes)).toEqual({ + width: 1024, + height: 1024, + alpha: true, + }); + }); +}); diff --git a/test/util/request.test.ts b/test/util/request.test.ts new file mode 100644 index 00000000..e519551d --- /dev/null +++ b/test/util/request.test.ts @@ -0,0 +1,56 @@ +import { config } from '../../src/config.js'; +import { request } from '../../src/util/request.js'; +import assert from 'node:assert'; +import { createServer } from 'node:http'; +import { Socket } from 'node:net'; +import { createProxy } from 'proxy'; +import { afterEach, beforeEach, describe, it } from 'vitest'; + +let origProxyUrl; + +describe('request', () => { + beforeEach(() => { + origProxyUrl = config.network.httpProxy; + config.network.httpProxy = null; + }); + + afterEach(() => { + config.network.httpProxy = origProxyUrl; + }); + + it('should fetch TiDev page', async () => { + const res = await request('https://github.com'); + await res.body.text(); + assert.strictEqual(res.statusCode, 200); + }); + + it.skipIf(typeof (globalThis as { Deno?: unknown }).Deno !== 'undefined')( + 'should fetch TiDev page via proxy', + async () => { + const connections: Record = {}; + const server = createServer(); + server.on('connection', function (conn) { + const key = `${conn.remoteAddress}:${conn.remotePort}`; + connections[key] = conn; + conn.on('close', () => { + delete connections[key]; + }); + }); + createProxy(server).listen(9999); + + try { + config.network.httpProxy = 'http://localhost:9999'; + + const res = await request('https://github.com'); + await res.body.text(); + assert.strictEqual(res.statusCode, 200); + } finally { + for (const conn of Object.values(connections)) { + conn.destroy(); + } + await new Promise((resolve) => server.close(resolve)); + } + }, + 10000 + ); +}); diff --git a/test/util/suggest.test.ts b/test/util/suggest.test.ts new file mode 100644 index 00000000..d37ade19 --- /dev/null +++ b/test/util/suggest.test.ts @@ -0,0 +1,20 @@ +import { suggest } from '../../src/util/suggest.js'; +import { describe, expect, it } from 'vitest'; + +describe('suggest', () => { + it('should recommend the best match', () => { + expect(suggest('hello', ['world', 'hello', 'foo'])).toBe('hello'); + }); + + it('should recommend mispelled word', () => { + expect(suggest('helo', ['world', 'hello', 'foo'])).toBe('hello'); + }); + + it('should recommend regardless of case', () => { + expect(suggest('Hello', ['world', 'hello', 'foo'])).toBe('hello'); + }); + + it('should recommend the best match with a prefix', () => { + expect(suggest('help', ['world', 'hello', 'foo'])).toBe('hello'); + }); +}); diff --git a/test/util/tailgate.test.ts b/test/util/tailgate.test.ts new file mode 100644 index 00000000..52b7871e --- /dev/null +++ b/test/util/tailgate.test.ts @@ -0,0 +1,33 @@ +import { tailgate } from '../../src/util/tailgate.js'; +import { setTimeout as delay } from 'node:timers/promises'; +import { describe, expect, it } from 'vitest'; + +describe('tailgate()', () => { + it('should queue up multiple calls', async () => { + let count = 0; + const fn = () => tailgate('foo', () => ++count); + const results = await Promise.all([fn(), fn(), fn()]); + expect(count).toBe(3); + expect(results).toEqual([1, 2, 3]); + }); + + it('should queue up multiple async calls', async () => { + let count = 0; + const fn = () => + tailgate('foo', async () => { + await delay(50); + return ++count; + }); + const results = await Promise.all([fn(), fn(), fn()]); + expect(count).toBe(1); + expect(results).toEqual([1, 1, 1]); + }); + + it('should catch errors', async () => { + await expect( + tailgate('foo', () => { + throw new Error('oh snap'); + }) + ).rejects.toThrow(/oh snap/); + }); +}); diff --git a/test/util/temp.test.ts b/test/util/temp.test.ts new file mode 100644 index 00000000..5d8fc46a --- /dev/null +++ b/test/util/temp.test.ts @@ -0,0 +1,200 @@ +import { isDir } from '../../src/util/is-dir.js'; +import { + createTempDir, + createTempName, + createTempPath, + createTempDirSync, +} from '../../src/util/temp.js'; +import { rm } from 'node:fs/promises'; +import { basename, isAbsolute } from 'node:path'; +import { afterEach, describe, expect, it } from 'vitest'; + +describe('createTempName', () => { + it('should create a temporary directory name', () => { + expect(createTempName()).toMatch(/^[0-9a-f]{32}$/); + }); + + it('should create a temporary directory name with a name', () => { + expect(createTempName({ name: 'test' })).toBe('test'); + }); + + it('should create a temporary directory name with a prefix', () => { + expect(createTempName({ prefix: 'prefix' })).toMatch(/^prefix-[0-9a-f]{32}$/); + }); + + it('should create a temporary directory name with a suffix', () => { + expect(createTempName({ suffix: 'suffix' })).toMatch(/^[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory name with a prefix and suffix', () => { + expect(createTempName({ prefix: 'prefix', suffix: 'suffix' })).toMatch( + /^prefix-[0-9a-f]{32}-suffix$/ + ); + }); + + it('should create a temporary directory name with a name, prefix, and suffix', () => { + expect(createTempName({ name: 'test', prefix: 'prefix', suffix: 'suffix' })).toBe( + 'prefix-test-suffix' + ); + }); +}); + +describe('createTempPath', () => { + it('should create a temporary directory path', () => { + const path = createTempPath(); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toMatch(/^[0-9a-f]{32}$/); + }); + + it('should create a temporary directory path with a name', () => { + const path = createTempPath({ name: 'test' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toBe('test'); + }); + + it('should create a temporary directory path with a prefix', () => { + const path = createTempPath({ prefix: 'prefix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toMatch(/^prefix-[0-9a-f]{32}$/); + }); + + it('should create a temporary directory path with a name and prefix', () => { + const path = createTempPath({ name: 'test', prefix: 'prefix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toBe('prefix-test'); + }); + + it('should create a temporary directory path with a suffix', () => { + const path = createTempPath({ suffix: 'suffix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toMatch(/^[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory path with a name and suffix', () => { + const path = createTempPath({ name: 'test', suffix: 'suffix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toBe('test-suffix'); + }); + + it('should create a temporary directory path with a prefix and suffix', () => { + const path = createTempPath({ prefix: 'prefix', suffix: 'suffix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toMatch(/^prefix-[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory path with a name, prefix, and suffix', () => { + const path = createTempPath({ name: 'test', prefix: 'prefix', suffix: 'suffix' }); + expect(isAbsolute(path)).toBe(true); + expect(basename(path)).toBe('prefix-test-suffix'); + }); +}); + +let tmpDir: string | undefined = undefined; + +describe('createTempDir', () => { + afterEach(async () => { + if (tmpDir) { + await rm(tmpDir, { force: true, recursive: true }); + tmpDir = undefined; + } + }); + + it('should create a temporary directory', async () => { + tmpDir = await createTempDir(); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^[0-9a-f]{32}$/); + }); + + it('should create a temporary directory with a name', async () => { + tmpDir = await createTempDir({ name: 'test' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('test'); + }); + + it('should create a temporary directory with a prefix', async () => { + tmpDir = await createTempDir({ prefix: 'prefix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^prefix-[0-9a-f]{32}$/); + }); + + it('should create a temporary directory with a name and prefix', async () => { + tmpDir = await createTempDir({ name: 'test', prefix: 'prefix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('prefix-test'); + }); + + it('should create a temporary directory with a suffix', async () => { + tmpDir = await createTempDir({ suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory with a name and suffix', async () => { + tmpDir = await createTempDir({ name: 'test', suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('test-suffix'); + }); + + it('should create a temporary directory with a name and prefix and suffix', async () => { + tmpDir = await createTempDir({ name: 'test', prefix: 'prefix', suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('prefix-test-suffix'); + }); +}); + +describe('createTempDirSync', () => { + afterEach(async () => { + if (tmpDir) { + await rm(tmpDir, { force: true, recursive: true }); + tmpDir = undefined; + } + }); + + it('should create a temporary directory synchronously', () => { + tmpDir = createTempDirSync(); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^[0-9a-f]{32}$/); + }); + + it('should create a temporary directory with a name synchronously', () => { + tmpDir = createTempDirSync({ name: 'test' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('test'); + }); + + it('should create a temporary directory with a prefix synchronously', () => { + tmpDir = createTempDirSync({ prefix: 'prefix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^prefix-[0-9a-f]{32}$/); + }); + + it('should create a temporary directory with a name and prefix synchronously', () => { + tmpDir = createTempDirSync({ name: 'test', prefix: 'prefix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('prefix-test'); + }); + + it('should create a temporary directory with a suffix synchronously', () => { + tmpDir = createTempDirSync({ suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory with a name and suffix synchronously', () => { + tmpDir = createTempDirSync({ name: 'test', suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('test-suffix'); + }); + + it('should create a temporary directory with a prefix and suffix synchronously', () => { + tmpDir = createTempDirSync({ prefix: 'prefix', suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toMatch(/^prefix-[0-9a-f]{32}-suffix$/); + }); + + it('should create a temporary directory with a name, prefix, and suffix synchronously', () => { + tmpDir = createTempDirSync({ name: 'test', prefix: 'prefix', suffix: 'suffix' }); + expect(isDir(tmpDir)).toBe(true); + expect(basename(tmpDir)).toBe('prefix-test-suffix'); + }); +}); diff --git a/test/util/time-diff.test.ts b/test/util/time-diff.test.ts new file mode 100644 index 00000000..0d67f782 --- /dev/null +++ b/test/util/time-diff.test.ts @@ -0,0 +1,46 @@ +import { timeDiff } from '../../src/util/time-diff.js'; +import { describe, expect, it } from 'vitest'; + +describe('timeDiff()', () => { + it('should render the time difference between two dates', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-02T00:00:00Z'); + expect(timeDiff(start, end)).toBe('1d'); + }); + + it('should render the time difference between two dates with hours', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T01:00:00Z'); + expect(timeDiff(start, end)).toBe('1h'); + }); + + it('should render the time difference between two dates with minutes', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T00:01:00Z'); + expect(timeDiff(start, end)).toBe('1m'); + }); + + it('should render the time difference between two dates with seconds', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T00:00:01Z'); + expect(timeDiff(start, end)).toBe('1s'); + }); + + it('should render the time difference between two dates with milliseconds', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T00:00:00.001Z'); + expect(timeDiff(start, end)).toBe('1ms'); + }); + + it('should render the time difference between two dates with multiple units', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T01:01:01.001Z'); + expect(timeDiff(start, end)).toBe('1h 1m 1s 1ms'); + }); + + it('should handle no time difference', () => { + const start = new Date('2025-01-01T00:00:00Z'); + const end = new Date('2025-01-01T00:00:00Z'); + expect(timeDiff(start, end)).toBe('0ms'); + }); +}); diff --git a/test/util/version.test.ts b/test/util/version.test.ts new file mode 100644 index 00000000..cc352170 --- /dev/null +++ b/test/util/version.test.ts @@ -0,0 +1,383 @@ +import * as version from '../../src/util/version.js'; +import { describe, expect, it } from 'vitest'; + +describe('version', () => { + describe('compare()', () => { + it('should compare two versions', () => { + expect(version.compare('1.0.0', '2.0.0')).toBe(-1); + expect(version.compare('2.0.0', '1.0.0')).toBe(1); + expect(version.compare('1.0.0', '1.0.0')).toBe(0); + + expect(version.compare('1.1.0', '1.2.0')).toBe(-1); + expect(version.compare('1.2.0', '1.1.0')).toBe(1); + expect(version.compare('1.1.0', '1.1.0')).toBe(0); + + expect(version.compare('1.1.1', '1.1.2')).toBe(-1); + expect(version.compare('1.1.2', '1.1.1')).toBe(1); + expect(version.compare('1.1.1', '1.1.1')).toBe(0); + }); + + it('should compare two versions with tags', () => { + expect(version.compare('1.0.0-beta', '1.0.0')).toBe(1); + expect(version.compare('1.0.0', '1.0.0-beta')).toBe(-1); + expect(version.compare('1.0.0-beta', '1.0.0-beta')).toBe(0); + + expect(version.compare('1.0.0-beta', '1.0.0-alpha')).toBe(1); + expect(version.compare('1.0.0-alpha', '1.0.0-beta')).toBe(-1); + expect(version.compare('1.0.0-beta', '1.0.0-beta')).toBe(0); + expect(version.compare('1.0.0-beta', '1.0.0-beta.1')).toBe(-1); + expect(version.compare('1.0.0-beta.1', '1.0.0-beta')).toBe(1); + }); + + it('should compare two versions with different number of segments', () => { + expect(version.compare('1.0.0', '1.0')).toBe(0); + expect(version.compare('1.0', '1.0.0')).toBe(0); + }); + + it('should compare two versions with different number of segments and tags', () => { + expect(version.compare('1.0.0-beta', '1.0')).toBe(1); + expect(version.compare('1.0', '1.0.0-beta')).toBe(-1); + expect(version.compare('1.0.0-beta', '1.0.0-beta')).toBe(0); + }); + + it('should compare two versions with different number of segments and tags', () => { + expect(version.compare('1.0.0-beta', '1.0')).toBe(1); + expect(version.compare('1.0', '1.0.0-beta')).toBe(-1); + expect(version.compare('1.0.0-beta', '1.0.0-beta')).toBe(0); + }); + + it('should compare two numbers', () => { + expect(version.compare(1, 2)).toBe(-1); + expect(version.compare(2, 1)).toBe(1); + expect(version.compare(1, 1)).toBe(0); + + expect(version.compare(1.2, 1.3)).toBe(-1); + expect(version.compare(1.3, 1.2)).toBe(1); + expect(version.compare(1.2, 1.2)).toBe(0); + }); + + it('should throw an error if the version is invalid', () => { + expect(() => version.compare('foo', 'bar')).toThrow('Invalid version format'); + }); + }); + + describe('format()', () => { + it('format integer versions', () => { + expect(version.format(1)).toBe('1'); + expect(version.format(1, 1)).toBe('1'); + expect(version.format(1, 2)).toBe('1.0'); + expect(version.format(1, 3)).toBe('1.0.0'); + expect(version.format(1, 4)).toBe('1.0.0.0'); + expect(version.format(1, 0, 1)).toBe('1'); + expect(version.format(1, 0, 2)).toBe('1'); + expect(version.format(1, 0, 3)).toBe('1'); + expect(version.format(1, 3, 3)).toBe('1.0.0'); + }); + + it('format float versions', () => { + expect(version.format(1.2)).toBe('1.2'); + expect(version.format(1.2, 1)).toBe('1.2'); + expect(version.format(1.2, 2)).toBe('1.2'); + expect(version.format(1.2, 3)).toBe('1.2.0'); + expect(version.format(1.2, 0, 1)).toBe('1'); + expect(version.format(1.2, 0, 2)).toBe('1.2'); + expect(version.format(1.2, 0, 3)).toBe('1.2'); + expect(version.format(1.2, 3, 3)).toBe('1.2.0'); + }); + + it('format single segment versions', () => { + expect(version.format('1')).toBe('1'); + expect(version.format('1', 1)).toBe('1'); + expect(version.format('1', 2)).toBe('1.0'); + expect(version.format('1', 3)).toBe('1.0.0'); + expect(version.format('1', 4)).toBe('1.0.0.0'); + expect(version.format('1', 0, 1)).toBe('1'); + expect(version.format('1', 0, 2)).toBe('1'); + expect(version.format('1', 0, 3)).toBe('1'); + expect(version.format('1', 3, 3)).toBe('1.0.0'); + expect(version.format('1-beta', 0, 1, true)).toBe('1'); + expect(version.format('1-beta', 0, 2, true)).toBe('1'); + expect(version.format('1-beta', 0, 3, true)).toBe('1'); + expect(version.format('1-beta', 3, 3, true)).toBe('1.0.0'); + }); + + it('format 2 segment versions', () => { + expect(version.format('1.2')).toBe('1.2'); + expect(version.format('1.2', 1)).toBe('1.2'); + expect(version.format('1.2', 2)).toBe('1.2'); + expect(version.format('1.2', 3)).toBe('1.2.0'); + expect(version.format('1.2', 4)).toBe('1.2.0.0'); + expect(version.format('1.2', 0, 1)).toBe('1'); + expect(version.format('1.2', 0, 2)).toBe('1.2'); + expect(version.format('1.2', 0, 3)).toBe('1.2'); + expect(version.format('1.2', 3, 3)).toBe('1.2.0'); + expect(version.format('1.2-beta', 0, 1, true)).toBe('1'); + expect(version.format('1.2-beta', 0, 2, true)).toBe('1.2'); + expect(version.format('1.2-beta', 0, 3, true)).toBe('1.2'); + expect(version.format('1.2-beta', 3, 3, true)).toBe('1.2.0'); + }); + + it('format 3 segment versions', () => { + expect(version.format('1.2.3')).toBe('1.2.3'); + expect(version.format('1.2.3', 1)).toBe('1.2.3'); + expect(version.format('1.2.3', 2)).toBe('1.2.3'); + expect(version.format('1.2.3', 3)).toBe('1.2.3'); + expect(version.format('1.2.3', 4)).toBe('1.2.3.0'); + expect(version.format('1.2.3', 0, 1)).toBe('1'); + expect(version.format('1.2.3', 0, 2)).toBe('1.2'); + expect(version.format('1.2.3', 0, 3)).toBe('1.2.3'); + expect(version.format('1.2.3', 3, 3)).toBe('1.2.3'); + expect(version.format('1.2.3-beta', 0, 1, true)).toBe('1'); + expect(version.format('1.2.3-beta', 0, 2, true)).toBe('1.2'); + expect(version.format('1.2.3-beta', 0, 3, true)).toBe('1.2.3'); + expect(version.format('1.2.3-beta', 3, 3, true)).toBe('1.2.3'); + expect(version.format('1.2.3-beta.foo', 3, 3, true)).toBe('1.2.3'); + }); + + it('format 4 segment versions', () => { + expect(version.format('1.2.3.4')).toBe('1.2.3.4'); + expect(version.format('1.2.3.4', 1)).toBe('1.2.3.4'); + expect(version.format('1.2.3.4', 2)).toBe('1.2.3.4'); + expect(version.format('1.2.3.4', 3)).toBe('1.2.3.4'); + expect(version.format('1.2.3.4', 4)).toBe('1.2.3.4'); + expect(version.format('1.2.3.4', 0, 1)).toBe('1'); + expect(version.format('1.2.3.4', 0, 2)).toBe('1.2'); + expect(version.format('1.2.3.4', 0, 3)).toBe('1.2.3'); + expect(version.format('1.2.3.4', 3, 3)).toBe('1.2.3'); + }); + + it('should throw an error if the version is invalid', () => { + expect(() => version.format(undefined as any)).toThrow('Invalid version "undefined"'); + expect(() => version.format(null as any)).toThrow('Invalid version "null"'); + }); + }); + + describe('isValid()', () => { + it('positive tests', () => { + expect(version.isValid('1')).toBe(true); + expect(version.isValid('1.0')).toBe(true); + expect(version.isValid('1.0.0')).toBe(true); + expect(version.isValid('1.0.0.0')).toBe(true); + }); + + it('negative tests', () => { + expect(version.isValid('a')).toBe(false); + expect(version.isValid(undefined as any)).toBe(false); + expect(version.isValid(null as any)).toBe(false); + }); + }); + + describe('eq()', () => { + it('positive tests', () => { + expect(version.eq(1, 1)).toBe(true); + expect(version.eq('1', 1)).toBe(true); + expect(version.eq(1, '1')).toBe(true); + expect(version.eq('1', '1')).toBe(true); + expect(version.eq('1.0', '1')).toBe(true); + expect(version.eq('1.0.0', '1')).toBe(true); + expect(version.eq('1', '1.0')).toBe(true); + expect(version.eq('1.0', '1.0')).toBe(true); + expect(version.eq('1.0.0', '1.0')).toBe(true); + expect(version.eq('1', '1.0.0')).toBe(true); + expect(version.eq('1.0', '1.0.0')).toBe(true); + expect(version.eq('1.0.0', '1.0.0')).toBe(true); + expect(version.eq('1.0.0', '1.0.0.2')).toBe(true); + expect(version.eq('1.0.0.1', '1.0.0.2')).toBe(true); + }); + + it('negative tests', () => { + expect(version.eq('1.0.0', '1.2')).toBe(false); + expect(version.eq('1.2.3', '1.2')).toBe(false); + expect(version.eq('1', '1.2')).toBe(false); + expect(version.eq('1', 2)).toBe(false); + expect(version.eq('1', 1.2)).toBe(false); + expect(version.eq('1', '2')).toBe(false); + expect(version.eq('1.3', '1')).toBe(false); + }); + }); + + describe('lt()', () => { + it('positive tests', () => { + expect(version.lt(1, 2)).toBe(true); + expect(version.lt(1.2, 1.3)).toBe(true); + expect(version.lt(1.2, 2)).toBe(true); + expect(version.lt('1.2', 2)).toBe(true); + expect(version.lt('1.2', '1.3')).toBe(true); + expect(version.lt('1.2', '2')).toBe(true); + expect(version.lt('1.2', '1.2.1')).toBe(true); + }); + + it('negative tests', () => { + expect(version.lt(1, 1)).toBe(false); + expect(version.lt(1.2, 1.2)).toBe(false); + expect(version.lt('1.2', 1.2)).toBe(false); + expect(version.lt(1.2, '1.2')).toBe(false); + expect(version.lt('1.2', '1.2')).toBe(false); + expect(version.lt('1.2.3', '1.2')).toBe(false); + expect(version.lt('1.2', '1.2.0')).toBe(false); + expect(version.lt('1.2.1', '1.2')).toBe(false); + expect(version.lt('1.0.0.1', '1.0.0')).toBe(false); + }); + }); + + describe('lte()', () => { + it('positive tests', () => { + expect(version.lte(1, 2)).toBe(true); + expect(version.lte(1.2, 1.2)).toBe(true); + expect(version.lte(1.2, 1.3)).toBe(true); + expect(version.lte(1.2, 2)).toBe(true); + expect(version.lte('1.2', 1.2)).toBe(true); + expect(version.lte('1.2', 2)).toBe(true); + expect(version.lte('1.2', '1.2')).toBe(true); + expect(version.lte('1.2', '1.3')).toBe(true); + expect(version.lte('1.2', '2')).toBe(true); + expect(version.lte('1.2', '1.2.0')).toBe(true); + expect(version.lte('1.2', '1.2.1')).toBe(true); + expect(version.lte('1.2.0', '1.2.0')).toBe(true); + expect(version.lte('1.2.0', '1.2.1')).toBe(true); + expect(version.lte('1.0.0.1', '1.0.0')).toBe(true); + }); + + it('negative tests', () => { + expect(version.lte(1.1, 1)).toBe(false); + expect(version.lte('1.0.1', 1)).toBe(false); + expect(version.lte(1.3, 1.2)).toBe(false); + expect(version.lte('1.3', 1.2)).toBe(false); + expect(version.lte(1.3, '1.2')).toBe(false); + expect(version.lte('1.3', '1.2')).toBe(false); + expect(version.lte('1.2.3', '1.2')).toBe(false); + expect(version.lte('1.2.3', '1.2.0')).toBe(false); + }); + }); + + describe('gt()', () => { + it('positive tests', () => { + expect(version.gt(2, 1)).toBe(true); + expect(version.gt(1.3, 1.2)).toBe(true); + expect(version.gt(2, 1.2)).toBe(true); + expect(version.gt(2, '1.2')).toBe(true); + expect(version.gt('1.3', '1.2')).toBe(true); + expect(version.gt('2', '1.2')).toBe(true); + expect(version.gt('1.2.1', '1.2')).toBe(true); + }); + + it('negative tests', () => { + expect(version.gt(1, 1)).toBe(false); + expect(version.gt(1.2, 1.2)).toBe(false); + expect(version.gt('1.2', 1.2)).toBe(false); + expect(version.gt(1.2, '1.2')).toBe(false); + expect(version.gt('1.2', '1.2')).toBe(false); + expect(version.gt('1.2', '1.2.3')).toBe(false); + expect(version.gt('1.2.0', '1.2')).toBe(false); + expect(version.gt('1.2', '1.2.1')).toBe(false); + expect(version.gt('1.0.0', '1.0.0.1')).toBe(false); + }); + }); + + describe('gte()', () => { + it('positive tests', () => { + expect(version.gte(2, 1)).toBe(true); + expect(version.gte(1.2, 1.2)).toBe(true); + expect(version.gte(1.3, 1.2)).toBe(true); + expect(version.gte(2, 1.2)).toBe(true); + expect(version.gte(1.2, '1.2')).toBe(true); + expect(version.gte(2, '1.2')).toBe(true); + expect(version.gte('1.2', '1.2')).toBe(true); + expect(version.gte('1.3', '1.2')).toBe(true); + expect(version.gte('2', '1.2')).toBe(true); + expect(version.gte('1.2.0', '1.2')).toBe(true); + expect(version.gte('1.2.1', '1.2')).toBe(true); + expect(version.gte('1.2.0', '1.2.0')).toBe(true); + expect(version.gte('1.2.1', '1.2.0')).toBe(true); + expect(version.gte('1.0.0', '1.0.0.1')).toBe(true); + }); + + it('negative tests', () => { + expect(version.gte(1, 1.1)).toBe(false); + expect(version.gte(1, '1.0.1')).toBe(false); + expect(version.gte(1.2, 1.3)).toBe(false); + expect(version.gte(1.2, '1.3')).toBe(false); + expect(version.gte('1.2', 1.3)).toBe(false); + expect(version.gte('1.2', '1.3')).toBe(false); + expect(version.gte('1.2', '1.2.3')).toBe(false); + expect(version.gte('1.2.0', '1.2.3')).toBe(false); + }); + }); + + describe('parseMin()', () => { + it('finds minimum version', () => { + expect(version.parseMin('1')).toBe('1'); + expect(version.parseMin('1.2')).toBe('1.2'); + expect(version.parseMin('>=1.0')).toBe('1.0'); + expect(version.parseMin('<1.0')).toBe('1.0'); + expect(version.parseMin('>=2.3.3 <=4.2')).toBe('2.3.3'); + expect(version.parseMin('>=2.3.3 <=4.2 || >=1.0')).toBe('1.0'); + expect(version.parseMin('>=2.3.3 <=4.2 || 2.0')).toBe('2.0'); + }); + }); + + describe('parseMax()', () => { + it('finds maximum version', () => { + expect(version.parseMax('1')).toBe('1'); + expect(version.parseMax('1.2')).toBe('1.2'); + expect(version.parseMax('>=1.0')).toBe('1.0'); + expect(version.parseMax('<1.0')).toBe('1.0'); + expect(version.parseMax('<18')).toBe('<18'); + expect(version.parseMax('>=2.3.3 <=4.2')).toBe('4.2'); + expect(version.parseMax('>=2.3.3 <=4.2.x')).toBe('4.2'); + expect(version.parseMax('>=2.3.3 <=4.2.x', true)).toBe('4.2.x'); + expect(version.parseMax('>=2.3.3 <=4.2 || >=1.0')).toBe('4.2'); + expect(version.parseMax('>=2.3.3 <=4.2 || 5.0')).toBe('5.0'); + }); + }); + + describe('satisfies()', () => { + it('in range', () => { + expect(version.satisfies('1.0.0', '1.0.0')).toBe(true); + expect(version.satisfies('1.0.0', '*')).toBe(true); + expect(version.satisfies('1.0.0', '>=2.0.0 || *')).toBe(true); + expect(version.satisfies('1.0.0', '>=1.0.0')).toBe(true); + expect(version.satisfies('3.0.0', '>=2.3.3 <=4.2')).toBe(true); + expect(version.satisfies('4', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(true); + expect(version.satisfies('5', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(true); + expect(version.satisfies('6', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(true); + expect(version.satisfies('7', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(true); + expect(version.satisfies('18.0.1', '<=18.x')).toBe(true); + expect(version.satisfies('18.0.1', '>=18.x')).toBe(true); + expect(version.satisfies('18.0.1', '>=19.x')).toBe(false); + }); + + it('not in range', () => { + expect(version.satisfies('2.0.0', '1.0.0')).toBe(false); + expect(version.satisfies('2.0.0', '>=2.3.3 <=4.2')).toBe(false); + expect(version.satisfies('2.3', '>=2.3.3 <=4.2')).toBe(false); + expect(version.satisfies('4.3', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(false); + expect(version.satisfies('5.1', '>=2.3.3 <=4.2 || 5.0 || >=6.0')).toBe(false); + }); + + it('maybe', () => { + expect(version.satisfies('2.0', '1.0', true)).toBe('maybe'); + expect(version.satisfies('2.0', '>=1.0', true)).toBe(true); + expect(version.satisfies('2.0', '<1.0', true)).toBe('maybe'); + expect(version.satisfies('2.0', '>=2.3.3 <=4.2', true)).toBe(false); + expect(version.satisfies('5.0', '>=2.3.3 <=4.2', true)).toBe('maybe'); + expect(version.satisfies('18', '>=10 <=18', true)).toBe(true); + }); + }); + + describe('sort()', () => { + it('should sort versions', () => { + expect(version.sort(['1.0.2', '1.0.1', '1.0.0'])).toEqual(['1.0.0', '1.0.1', '1.0.2']); + expect(version.sort(['1.0.2-beta', '1.0.1-beta', '1.0.0-beta'])).toEqual([ + '1.0.0-beta', + '1.0.1-beta', + '1.0.2-beta', + ]); + expect(version.sort(['1.0.2-beta', '1.0.1-beta', '1.0.0-beta'])).toEqual([ + '1.0.0-beta', + '1.0.1-beta', + '1.0.2-beta', + ]); + }); + }); +}); diff --git a/test/util/zip/extract-zip.test.ts b/test/util/zip/extract-zip.test.ts new file mode 100644 index 00000000..0cb6f029 --- /dev/null +++ b/test/util/zip/extract-zip.test.ts @@ -0,0 +1,142 @@ +import { exists, extractZip, isDir, isFile } from '../../../src/util/index.js'; +import { canSymlink } from '../can-symlink.js'; +import { randomBytes } from 'node:crypto'; +import { lstatSync, readlinkSync, statSync } from 'node:fs'; +import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join, posix } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { afterEach, beforeEach, describe, expect, it } from 'vitest'; + +const fixturesDir = join(fileURLToPath(import.meta.url), '../fixtures'); + +let tmpDir: string; +beforeEach(async () => { + tmpDir = join(tmpdir(), 'node-titanium-sdk', `zip-test-${randomBytes(8).toString('hex')}`); + await mkdir(tmpDir, { recursive: true }); +}); + +afterEach(() => rm(tmpDir, { force: true, recursive: true })); + +describe('extractZip()', () => { + it('should error if zip file is invalid', async () => { + await expect(extractZip(null as any, undefined as any)).rejects.toThrowError( + new TypeError('Expected zip file to be a non-empty string') + ); + await expect(extractZip(undefined as any, undefined as any)).rejects.toThrowError( + new TypeError('Expected zip file to be a non-empty string') + ); + await expect(extractZip(123 as any, undefined as any)).rejects.toThrowError( + new TypeError('Expected zip file to be a non-empty string') + ); + }); + + it('should error if zip file does not exist', async () => { + await expect(extractZip('does_not_exist.zip', undefined as any)).rejects.toThrow( + 'The specified zip file does not exist' + ); + }); + + it('should error if zip file is not a file', async () => { + await expect(extractZip(fixturesDir, undefined as any)).rejects.toThrowError( + new Error('The specified zip file is not a file') + ); + }); + + it('should error if dest is invalid', async () => { + await expect(extractZip(join(fixturesDir, 'files.zip'), 123 as any)).rejects.toThrowError( + new TypeError('Expected destination directory to be a non-empty string') + ); + await expect(extractZip(join(fixturesDir, 'files.zip'), null as any)).rejects.toThrowError( + new TypeError('Expected destination directory to be a non-empty string') + ); + await expect(extractZip(join(fixturesDir, 'files.zip'), undefined as any)).rejects.toThrowError( + new TypeError('Expected destination directory to be a non-empty string') + ); + }); + + it('should error if file is invalid', async () => { + await expect(() => extractZip(join(fixturesDir, 'invalid.zip'), tmpDir)).rejects.toThrow( + 'Invalid zip file:' + ); + }); + + it('should extract zip file to destination and overwrite', async () => { + await mkdir(join(tmpDir, 'testfiles'), { recursive: true }); + await writeFile(join(tmpDir, 'testfiles', 'a.txt'), 'I will be overwritten', 'utf8'); + + const files: string[] = []; + const expectedFiles = [ + 'testfiles/', + ...Array.from({ length: 26 }, (_, i) => + posix.join('testfiles', `${String.fromCharCode(97 + i)}.txt`) + ), + ].sort(); + + await extractZip(join(fixturesDir, 'files.zip'), tmpDir, { + onEntry: (entry) => { + files.push(entry.fileName); + }, + }); + + expect(files.sort()).toEqual(expectedFiles); + + let i = 0; + const listing = (await readdir(join(tmpDir, 'testfiles'))).sort(); + for (const file of listing) { + expect(file).toBe(`${String.fromCharCode(97 + i++)}.txt`); + expect(await readFile(join(tmpDir, 'testfiles', file), 'utf8')).toBe(`This is a test`); + } + }); + + it.skipIf(!canSymlink())('should extract a file with symlinks', async () => { + await extractZip(join(fixturesDir, 'symlinks.zip'), tmpDir); + + const folder = join(tmpDir, 'symlinks/folder'); + expect(isDir(folder)).toBe(true); + + const file = join(tmpDir, 'symlinks/folder/testfile.txt'); + expect(isFile(file)).toBe(true); + + const fileLink = join(tmpDir, 'symlinks/link.txt'); + expect(await exists(fileLink)).toBe(true); + const fileLinkStat = lstatSync(fileLink); + expect(fileLinkStat.isSymbolicLink()).toBe(true); + + const folderLink = join(tmpDir, 'symlinks/folderlink'); + const folderLinkStat = lstatSync(folderLink); + expect(folderLinkStat.isSymbolicLink()).toBe(true); + const target = readlinkSync(folderLink); + expect(target).to.equal('folder'); + }); + + it.skipIf(!canSymlink())('should handle if a symlink already exists', async () => { + await extractZip(join(fixturesDir, 'symlinks.zip'), tmpDir); + + await extractZip(join(fixturesDir, 'symlinks.zip'), tmpDir); + + const folder = join(tmpDir, 'symlinks/folder'); + expect(isDir(folder)).toBe(true); + + const file = join(tmpDir, 'symlinks/folder/testfile.txt'); + expect(isFile(file)).toBe(true); + + const fileLink = join(tmpDir, 'symlinks/link.txt'); + expect(await exists(fileLink)).toBe(true); + + const folderLink = join(tmpDir, 'symlinks/folderlink'); + const folderLinkStat = lstatSync(folderLink); + expect(folderLinkStat.isSymbolicLink()).toBe(true); + const target = readlinkSync(folderLink); + expect(target).toBe('folder'); + }); + + it.skipIf(process.platform === 'win32')('should preserve executable permissions', async () => { + await extractZip(join(fixturesDir, 'shellscript.zip'), tmpDir); + + const file = join(tmpDir, 'testexe/test.sh'); + expect(await exists(file)).toBe(true); + expect(isFile(file)).toBe(true); + expect(statSync(file).mode & 0o777).toBe(0o755); + }); +}); diff --git a/test/util/zip/fixtures/files.zip b/test/util/zip/fixtures/files.zip new file mode 100644 index 00000000..39835c64 Binary files /dev/null and b/test/util/zip/fixtures/files.zip differ diff --git a/test/util/zip/fixtures/invalid.zip b/test/util/zip/fixtures/invalid.zip new file mode 100644 index 00000000..1c0aec0e --- /dev/null +++ b/test/util/zip/fixtures/invalid.zip @@ -0,0 +1 @@ +This is not a zip file diff --git a/test/util/zip/fixtures/shellscript.zip b/test/util/zip/fixtures/shellscript.zip new file mode 100644 index 00000000..fe92b32f Binary files /dev/null and b/test/util/zip/fixtures/shellscript.zip differ diff --git a/test/util/zip/fixtures/symlinks.zip b/test/util/zip/fixtures/symlinks.zip new file mode 100644 index 00000000..7ae4a0a1 Binary files /dev/null and b/test/util/zip/fixtures/symlinks.zip differ diff --git a/tests/adb_test.js b/tests/adb_test.js deleted file mode 100644 index fd06549f..00000000 --- a/tests/adb_test.js +++ /dev/null @@ -1,230 +0,0 @@ -/* eslint no-unused-expressions: "off" */ -'use strict'; - -function MockConfig() { - this.get = function (s, d) { - return d; - }; -} - -const fs = require('fs'); -const path = require('path'); -const semver = require('semver'); -const should = require('should'); // eslint-disable-line no-unused-vars -const android = require('../lib/android'); -android.androidPackageJson({ - vendorDependencies: { - 'android sdk': '>=23.x <=27.x', - 'android build tools': '>=25.x <=27.x', - 'android platform tools': '27.x', - 'android tools': '<=26.x', - 'android ndk': '>=r11c <=r16c', - node: '>=4.0 <=8.x', - java: '>=1.8.x' - }, -}); - -const ADB = require('../lib/adb'); -const Emulator = require('../lib/emulator'); - -const config = new MockConfig(); -const adb = new ADB(config); -const emulator = new Emulator(config); - -describe('adb', function () { - - it('#version() returns a valid semver string', function (finished) { - adb.version(function (err, ver) { - if (err) { - return finished(err); - } - ver.should.match(/^1\.0\.\d+/); - should(semver.valid(ver)).not.be.null(); - finished(); - }); - }); - - // TODO: Add test where we start an emulator first, get it in listing, then stop it? - it('#devices() returns empty Array when no emulators running', function (finished) { - adb.devices(function (err, devices) { - if (err) { - return finished(err); - } - devices.should.be.an.Array(); - finished(); - }); - }); - - // TODO: Start an emulator, make sure we get event? - it('#trackDevices()', function (finished) { - let connection; - function done(e) { - connection.end(); - finished(e); - } - connection = adb.trackDevices(function (err, devices) { - if (err) { - return done(err); - } - // console.log('trackDevicesCallback: ' + JSON.stringify(devices)); - devices.should.be.an.Array(); - done(); - }); - }); - - describe('with an emulator running', function () { - let avd; - let device; - - before(function (finished) { - this.timeout(30000); - - emulator.detect(function (err, avds) { - if (err) { - return finished(err); - } - if (avds.length === 0) { - return finished(new Error('Tests require at least one emulator defined!')); - } - avd = avds[0]; - - emulator.start(avd.id, function (err, emu) { - if (err) { - return finished(err); - } - - emu.on('ready', function (d) { - device = d; - finished(); - }); - - emu.on('timeout', function () { - finished(new Error('emulator.start() timed out')); - }); - }); - }); - }); - - after(function (finished) { - this.timeout(35000); - // Just call finished if there is no device, there may have been an issue when starting - // the emulator in the before - if (!device) { - return finished(); - } - emulator.stop(device.emulator.id, function (errOrCode) { - errOrCode.should.eql(0); - setTimeout(finished, 5000); // let it wait 5 seconds or else adb will still report it as connected - }); - }); - - it('#shell()', function (finished) { - adb.shell(device.id, 'cat /system/build.prop', function (err, data) { - if (err) { - return finished(err); - } - - // data is a Buffer! - data.should.be.ok(); - // (typeof data).should.eql('Buffer'); - - finished(); - }); - }); - - it('#startApp(), #getPid() and #stopApp()', function (finished) { - this.timeout(30000); - - const appId = 'com.android.settings'; - adb.startApp(device.id, appId, 'wifi.WifiStatusTest', function (err, data) { - should(err).not.be.ok(); - - // data is a Buffer! - data.should.be.ok(); // TODO: Test data.toString() holds particular text? - - adb.getPid(device.id, appId, function (err, pid) { - should(err).not.be.ok(); - - pid.should.be.a.Number(); - pid.should.not.eql(0); - - adb.stopApp(device.id, appId, function (err) { - should(err).not.be.ok(); - - finished(); - }); - }); - }); - }); - - it('#pull()', function (finished) { - const dest = path.join(__dirname, 'hosts'); - fs.existsSync(dest).should.eql(false); - - adb.pull(device.id, '/system/etc/hosts', __dirname, function (err) { - should(err).not.be.ok(); - - // verify build.prop exists in current dir now! - try { - fs.existsSync(dest).should.eql(true); - } finally { - try { - fs.unlinkSync(dest); - } catch (_error) { - // squash - } - } - finished(); - }); - }); - - it('#push()', function (finished) { - const dest = '/mnt/sdcard/tmp/test-adb.js'; - - // Ensure dest file doesn't exist - adb.shell(device.id, 'rm -f ' + dest, function (err) { - should(err).not.be.ok(); - - // Then piush this file to dest - adb.push(device.id, __filename, dest, function (err) { - should(err).not.be.ok(); - - // verify it now exists and matches - adb.shell(device.id, 'cat ' + dest, function (err, data) { - should(err).not.be.ok(); - - // data is a Buffer! - data.should.be.ok(); - // normalize newlines, android uses \r\n - data.toString().replace(/\r\n/g, '\n').should.eql(fs.readFileSync(__filename).toString()); - - finished(); - }); - }); - }); - }); - }); // with running emulator - - // TODO: Install a pre-built test app! - // function testInstallApp() { - // adb.installApp('emulator-5554', '~/appc/workspace/testapp2/build/android/bin/app.apk', function (err, data) { - // if (err) { - // console.error('ERROR! ' + err + '\n'); - // } else { - // console.log('-----------------------------------------------------------------'); - // console.log(data); - // console.log(''); - // } - // }); - // } - // - // function testForward() { - // adb.forward('015d21d4ff181a17', 'tcp:5000', 'tcp:6000', function (err, data) { - // if (err) { - // console.error('ERROR! ' + err + '\n'); - // } else { - // console.log('result = ' + data + '\n'); - // } - // }); - // } -}); diff --git a/tests/avd_test.js b/tests/avd_test.js deleted file mode 100644 index ce9bdd49..00000000 --- a/tests/avd_test.js +++ /dev/null @@ -1,105 +0,0 @@ -/* eslint no-unused-expressions: "off" */ -'use strict'; - -function MockConfig() { - this.get = function (s, d) { - return d; - }; -} - -const should = require('should'); // eslint-disable-line no-unused-vars - -const config = new MockConfig(); -const Emulator = require('../lib/emulator'); -const android = require('../lib/android'); -android.androidPackageJson({ - vendorDependencies: { - 'android sdk': '>=23.x <=27.x', - 'android build tools': '>=25.x <=27.x', - 'android platform tools': '27.x', - 'android tools': '<=26.x', - 'android ndk': '>=r11c <=r16c', - node: '>=4.0 <=8.x', - java: '>=1.8.x' - }, -}); -const emulator = new Emulator(config); - -describe('emulator', function () { - it('#detect() any', function (finished) { - emulator.detect(function (err, avds) { - avds.should.be.an.Array; - finished(err); - }); - }); - - it('#detect() type: avd', function (finished) { - emulator.detect({ type: 'avd' }, function (err, avds) { - avds.should.be.an.Array; - finished(err); - }); - }); - - describe('lifecycle', function () { - let avd; - - before(function (finished) { - emulator.detect(function (err, avds) { - if (err) { - return finished(err); - } - if (avds.length === 0) { - return finished(new Error('Tests require at least one emulator defined!')); - } - avd = avds[0]; - finished(); - }); - }); - - it('#isRunning() returns null object when not running', function (finished) { - emulator.isRunning(avd.id, function (err, emu) { - should(emu).not.be.ok; - - finished(err); - }); - }); - - // FIXME: This test isn't right. I think it will only pass when the emulator is running and we pass in the id (that has port in the value)? - // it('#isEmulator() returns matching emulator?', function (finished) { - // emulator.isEmulator(avd.name, function (err, emu) { - // emu.should.be.ok; - // finished(err); - // }); - // }); - - it('#start(), #isRunning() and #stop()', function (finished) { - this.slow(30000); - this.timeout(280000); - - emulator.start(avd.id, function (err, emu) { - if (err) { - return finished(err); - } - - emu.should.be.ok(); - - emu.on('ready', function (device) { - device.should.be.ok(); - - emulator.isRunning(device.emulator.id, function (err, emu) { - emu.should.be.ok(); - - emulator.stop(device.emulator.id, function (errOrCode) { - errOrCode.should.eql(0); - setTimeout(finished, 6000); // let it wait 5 seconds or else adb will still report it as connected - }); - }); - }); - - emu.on('timeout', function () { - finished(new Error('emulator.start() timed out')); - }); - }); - }); - }); -}); diff --git a/tests/i18n/en/en.xml b/tests/i18n/en/en.xml deleted file mode 100644 index c31259ca..00000000 --- a/tests/i18n/en/en.xml +++ /dev/null @@ -1,3 +0,0 @@ - - value - diff --git a/tests/i18n/es/app.xml b/tests/i18n/es/app.xml deleted file mode 100644 index a70779a9..00000000 --- a/tests/i18n/es/app.xml +++ /dev/null @@ -1,3 +0,0 @@ - - my spanish value - diff --git a/tests/i18n_test.js b/tests/i18n_test.js deleted file mode 100644 index 8df9bfd7..00000000 --- a/tests/i18n_test.js +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint no-unused-expressions: "off" */ -'use strict'; - -const should = require('should'); // eslint-disable-line no-unused-vars -const i18n = require('../lib/i18n'); -const path = require('path'); - -describe('i18n', function () { - it('#load()', function () { - const result = i18n.load(__dirname); - result.should.be.an.Object; - // first language, places values into 'strings' property - result.should.have.ownProperty('en'); - result.en.should.have.ownProperty('strings'); - result.en.strings.should.have.ownProperty('whatever'); - result.en.strings.whatever.should.eql('value'); - - // second language, places app.xml values into 'app' property - result.should.have.ownProperty('es'); - result.es.should.have.ownProperty('app'); - result.es.app.should.have.ownProperty('whatever'); - result.es.app.whatever.should.eql('my spanish value'); - }); - - it('#findLaunchSreens()', function () { - const results = i18n.findLaunchScreens(__dirname, console); - - results.should.be.an.Array(); - results.length.should.equal(1); - results.should.deepEqual([ - path.join(__dirname, 'i18n', 'en', 'Default-568h@2x.png') - ]); - }); -}); diff --git a/tests/jsanalyze_test.js b/tests/jsanalyze_test.js deleted file mode 100644 index 37a789b0..00000000 --- a/tests/jsanalyze_test.js +++ /dev/null @@ -1,215 +0,0 @@ -/* eslint no-unused-expressions: "off" */ -'use strict'; - -const path = require('path'); -const fs = require('fs-extra'); -const should = require('should'); // eslint-disable-line no-unused-vars -const jsanalyze = require('../lib/jsanalyze'); -const sortObject = require('../lib/jsanalyze').sortObject; - -describe('jsanalyze', function () { - describe('#analyzeJs()', function () { - const tmpDir = path.join(__dirname, 'tmp'); - - before(function (finish) { - if (fs.existsSync(tmpDir)) { - fs.removeSync(tmpDir); - } - fs.ensureDir(tmpDir, finish); - }); - - after(function (finish) { - fs.remove(tmpDir, finish); - }); - - it('tracks Ti API symbols', function () { - const results = jsanalyze.analyzeJs('Ti.API.info("yeah");', {}); - results.symbols.should.eql([ 'API.info', 'API' ]); - }); - - it('Should ignore Ti in string', function () { - const results = jsanalyze.analyzeJs(` - Ti.API.info("Ti. In A String Causes Issues?".toUpperCase()); - Ti.API.info(\`Ti.UI.AlertDialog selected button at index: \${index}\`); - const message = \`Ti.UI.TabbedBar changed to index: \${index}\`; - const messageAfterTranspile = "Ti.UI.TabbedBar changed to index: ".concat(index); - const view = Ti.UI.createLabel(); - console.log(\`version is \${Ti.API.version}\`); - "Ti.Test".toUpperCase(); - Ti['UI'].createWebView(); - "Ti.Test"`, {}); - results.symbols.should.eql([ 'API.info', 'API', 'UI.createLabel', 'UI', 'API.version', 'UI.createWebView' ]); - }); - - it('tracks Ti API usage across multiple calls', function () { - const results = jsanalyze.analyzeJs('Ti.UI.createView({});', {}); - results.symbols.should.eql([ 'UI.createView', 'UI' ]); // symbols only includes from this call - // includes symbols from this test and the one above! - jsanalyze.getAPIUsage().should.eql({ - 'Titanium.API': 4, - 'Titanium.API.info': 3, - 'Titanium.API.version': 1, - 'Titanium.UI': 3, - 'Titanium.UI.createLabel': 1, - 'Titanium.UI.createView': 1, - 'Titanium.UI.createWebView': 1 - }); - }); - - it('converts global "this" references into "global" references when transpiling', function () { - const results = jsanalyze.analyzeJs('this.myGlobalMethod = function() {};', { transpile: true }); - results.contents.should.eql('global.myGlobalMethod = function () {};'); - }); - - it('doesn\'t converts function-scoped "this" references into "global" references when transpiling', function () { - const results = jsanalyze.analyzeJs('var myGlobalMethod = function() { return this; };', { transpile: true }); - results.contents.should.eql('var myGlobalMethod = function myGlobalMethod() {return this;};'); - }); - - it('generates source maps inline into generated js file', function () { - const inputJSFile = path.join(__dirname, 'resources/input.js'); - const contents = fs.readFileSync(inputJSFile, 'utf-8'); - let expectedSourceMap = fs.readJSONSync(`${inputJSFile}.map`); - - expectedSourceMap.sourceRoot = path.dirname(inputJSFile); - expectedSourceMap = sortObject(expectedSourceMap); - - const results = jsanalyze.analyzeJs(contents, - { - transpile: true, - sourceMap: true, - filename: inputJSFile - }); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - - it('generates source maps inline into generated js file and removes sourcesContent for android platform', function () { - const inputJSFile = path.join(__dirname, 'resources/input.js'); - const contents = fs.readFileSync(inputJSFile, 'utf-8'); - let expectedSourceMap = fs.readJSONSync(`${inputJSFile}.map`); - expectedSourceMap.sourceRoot = path.dirname(inputJSFile); - delete expectedSourceMap.sourcesContent; - expectedSourceMap = sortObject(expectedSourceMap); - const results = jsanalyze.analyzeJs(contents, - { - transpile: true, - sourceMap: true, - filename: inputJSFile, - platform: 'android', - }); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - - it('handles input JS file with existing sourceMappingURL pointing to file', function () { - const inputMapFile = path.join(__dirname, 'resources/input.js.map'); - const inputJSFile = path.join(__dirname, 'resources/input.js'); - const results = jsanalyze.analyzeJs(`var myGlobalMethod = function() { return this; };\n//# sourceMappingURL=file://${inputMapFile}`, - { - transpile: true, - sourceMap: true, - filename: 'intermediate.js' - }); - let expectedSourceMap = fs.readJSONSync(path.join(__dirname, 'resources/intermediate.js.map')); - expectedSourceMap.sourceRoot = path.dirname(inputJSFile); // passes along the original source file via sources/sourceRoot - expectedSourceMap = sortObject(expectedSourceMap); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - - it('handles input JS file with existing sourceMappingURL with data: uri', function () { - const originalSourceFile = path.join(__dirname, 'resources/input.js'); - // given that it's inlined, it will try to resolve the relative 'input.js' source as relative to the JS filename we pass along in options. - const results = jsanalyze.analyzeJs('var myGlobalMethod = function() { return this; };\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImlucHV0LmpzIl0sIm5hbWVzIjpbIm15R2xvYmFsTWV0aG9kIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxjQUFjLEdBQUcsU0FBakJBLGNBQWMsR0FBYyxDQUFFLE9BQU8sSUFBSSxDQUFFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgbXlHbG9iYWxNZXRob2QgPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH07Il19', - { - transpile: true, - sourceMap: true, - filename: path.join(__dirname, 'resources/intermediate.js') - }); - let expectedSourceMap = fs.readJSONSync(path.join(__dirname, 'resources/intermediate.js.map')); - expectedSourceMap.sourceRoot = path.dirname(originalSourceFile); // passes along the original source file via sources/sourceRoot - expectedSourceMap = sortObject(expectedSourceMap); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - - it('handles input JS file with existing sourceMappingURL pointing to non-existent file', function () { - // treat like there is no original input source map.... - // only difference here is that there's an extra newline to deal with versus the "base" test case - const inputJSFile = path.join(__dirname, 'resources/input.nonexistent.sourcemapfile.js'); - const contents = fs.readFileSync(inputJSFile, 'utf-8'); - let expectedSourceMap = fs.readJSONSync(path.join(__dirname, 'resources/input.nonexistent.sourcemapfile.js.map')); - expectedSourceMap.sourceRoot = path.dirname(inputJSFile); - expectedSourceMap = sortObject(expectedSourceMap); - const results = jsanalyze.analyzeJs(contents, - { - transpile: true, - sourceMap: true, - filename: inputJSFile - }); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - - // babel-plugin-transform-titanium - it('converts OS_IOS into boolean', () => { - const results = jsanalyze.analyzeJs('if (OS_IOS) {}', { transpile: true, transform: { platform: 'ios' } }); - results.contents.should.eql('if (true) {}'); - }); - - it('should fallback to looser parsing if required', () => { - const results = jsanalyze.analyzeJs('return "foo";'); - results.contents.should.eql('return "foo";'); - }); - - it('should handle errors', () => { - should(() => jsanalyze.analyzeJs('return foo!;console.log("bar");')).throw('Failed to parse undefined\nUnexpected token, expected ";" (1:10)'); - }); - }); - - describe('#analyzeJsFile()', function () { - it('should transform contents', function () { - const inputJSFile = path.join(__dirname, 'resources/input.js'); - - let expectedSourceMap = fs.readJSONSync(`${inputJSFile}.map`); - expectedSourceMap.sourceRoot = path.dirname(inputJSFile); - expectedSourceMap = sortObject(expectedSourceMap); - const results = jsanalyze.analyzeJsFile(inputJSFile, - { - transpile: true, - sourceMap: true - }); - const expectedBase64Map = Buffer.from(JSON.stringify(expectedSourceMap)).toString('base64'); - results.contents.should.eql(`var myGlobalMethod = function myGlobalMethod() {return this;};\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,${expectedBase64Map}\n`); - }); - }); - - describe('#analyzeHtml', function () { - it('should analyze an html file', function () { - const inputFile = path.join(__dirname, 'resources/hello.html'); - - const results = jsanalyze.analyzeHtml(fs.readFileSync(inputFile, 'utf8')); - results.should.be.an.Array(); - results.length.should.equal(2); - results.should.deepEqual([ - 'input.js', - 'resources/input.js' - ]); - }); - }); - - describe('#analyzeHtmlFile', function () { - it('should analyze an html file', function () { - const inputFile = path.join(__dirname, 'resources/hello.html'); - - const results = jsanalyze.analyzeHtmlFile(inputFile); - results.should.be.an.Array(); - results.length.should.equal(2); - results.should.deepEqual([ - 'input.js', - 'resources/input.js' - ]); - }); - }); -}); diff --git a/tests/resources/global-plugin/app.js b/tests/resources/global-plugin/app.js deleted file mode 100644 index 61271eb4..00000000 --- a/tests/resources/global-plugin/app.js +++ /dev/null @@ -1,21 +0,0 @@ -function foobar() { - var x = 'bar'; -} - -global.aGlobalVar = 'foobar'; - -const foo = () => {}; - -let win = Ti.UI.createWindow({ - backgroundColor: 'white' -}); -var textField = Ti.UI.createTextField({ - borderStyle: Ti.UI.INPUT_BORDERSTYLE_BEZEL, - color: '#336699', - top: 10, - left: 10, - width: 250, - height: 60 -}); -win.add(textField); -win.open(); diff --git a/tests/resources/global-plugin/output.js b/tests/resources/global-plugin/output.js deleted file mode 100644 index ee3566d2..00000000 --- a/tests/resources/global-plugin/output.js +++ /dev/null @@ -1,25 +0,0 @@ -function foobar() { - var x = 'bar'; -} - -global.foobar = foobar; -global.aGlobalVar = 'foobar'; - -const foo = () => {}; - -global.foo = foo; -let win = Ti.UI.createWindow({ - backgroundColor: 'white' -}); -global.win = win; -var textField = Ti.UI.createTextField({ - borderStyle: Ti.UI.INPUT_BORDERSTYLE_BEZEL, - color: '#336699', - top: 10, - left: 10, - width: 250, - height: 60 -}); -global.textField = textField; -win.add(textField); -win.open(); diff --git a/tests/resources/hello.html b/tests/resources/hello.html deleted file mode 100644 index 17fce6fa..00000000 --- a/tests/resources/hello.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - A Small Hello - - - -

Hi

-

This is very minimal "hello world" HTML document.

- - diff --git a/tests/resources/input.js b/tests/resources/input.js deleted file mode 100644 index 87a10626..00000000 --- a/tests/resources/input.js +++ /dev/null @@ -1 +0,0 @@ -var myGlobalMethod = function() { return this; }; \ No newline at end of file diff --git a/tests/resources/input.js.map b/tests/resources/input.js.map deleted file mode 100644 index baddf801..00000000 --- a/tests/resources/input.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["input.js"],"names":["myGlobalMethod"],"mappings":"AAAA,IAAIA,cAAc,GAAG,SAAjBA,cAAcA,CAAA,EAAc,CAAE,OAAO,IAAI,CAAE,CAAC","sourcesContent":["var myGlobalMethod = function() { return this; };"]} diff --git a/tests/resources/input.nonexistent.sourcemapfile.js b/tests/resources/input.nonexistent.sourcemapfile.js deleted file mode 100644 index b8c84af3..00000000 --- a/tests/resources/input.nonexistent.sourcemapfile.js +++ /dev/null @@ -1,2 +0,0 @@ -var myGlobalMethod = function() { return this; }; -//# sourceMappingURL=madeup.js.map \ No newline at end of file diff --git a/tests/resources/input.nonexistent.sourcemapfile.js.map b/tests/resources/input.nonexistent.sourcemapfile.js.map deleted file mode 100644 index 84d8fb4b..00000000 --- a/tests/resources/input.nonexistent.sourcemapfile.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["input.nonexistent.sourcemapfile.js"],"names":["myGlobalMethod"],"mappings":"AAAA,IAAIA,cAAc,GAAG,SAAjBA,cAAcA,CAAA,EAAc,CAAE,OAAO,IAAI,CAAE,CAAC","sourcesContent":["var myGlobalMethod = function() { return this; };\n//# sourceMappingURL=madeup.js.map"]} diff --git a/tests/resources/intermediate.js.map b/tests/resources/intermediate.js.map deleted file mode 100644 index 1a42595a..00000000 --- a/tests/resources/intermediate.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["input.js"],"names":["myGlobalMethod"],"mappings":"AAAA,IAAIA,cAAc,GAAdA,SAAAA,cAAc,CAAA,EAAdA,CAAAA,OAAAA,IAAc,CAAc,CAAE","sourcesContent":["var myGlobalMethod = function() { return this; };"]} diff --git a/tests/resources/tiapp1.xml b/tests/resources/tiapp1.xml deleted file mode 100644 index c82bcc59..00000000 --- a/tests/resources/tiapp1.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - ti.testapp - testapp - 1.0 - tester - http:// - not specified - 2012 by tester - appicon.png - false - false - default - false - false - false - false - 088dc83c-64af-4a81-b57c-7407649453f0 - system - - - Ti.UI.PORTRAIT - - - Ti.UI.PORTRAIT - Ti.UI.UPSIDE_PORTRAIT - Ti.UI.LANDSCAPE_LEFT - Ti.UI.LANDSCAPE_RIGHT - - - - - - - true - true - - default - - - diff --git a/tests/resources/tiapp2.xml b/tests/resources/tiapp2.xml deleted file mode 100644 index 7f7c874b..00000000 --- a/tests/resources/tiapp2.xml +++ /dev/null @@ -1,246 +0,0 @@ - - - - true - true - true - - 2.2.0 - ti.testapp - testapp - 1.0 - tester - http:// - not specified - 2012 by tester - appicon.png - false - false - default - false - false - false - false - 088dc83c-64af-4a81-b57c-7407649453f0 - system - production - true - false - false - false - this "one" with quotes - ti.testapp.invoke.push - ti.testapp.invoke.open - Some Title for BB Push, typically the app name" - true - - true - - ti-api-usage-finder - - - xyz - - - - true - true - true - true - #FFFFFF - 5.0 - foo - 10571 - - - group.com.appc.foo - group.com.appc.bar - - - - - application-identifier - XXXXXXXXXX.com.test.app - aps-environment - production - beta-reports-active - - get-task-allow - - keychain-access-groups - - XXXXXXXXXX.com.test.app - - - - - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIBackgroundModes - - audio - location - voip - newsstand-content - external-accessory - bluetooth-central - - UIRequiredDeviceCapabilities - - telephony - wifi - sms - still-camera - auto-focus-camera - front-facing-camera - camera-flash - video-camera - accelerometer - gyroscope - location-services - gps - magnetometer - gamekit - microphone - opengles-1 - opengles-2 - armv6 - armv7 - peer-peer - bluetooth-le - - UIRequiresPersistentWiFi - - UIPrerenderedIcon - - UIStatusBarHidden - - UIStatusBarStyle - UIStatusBarStyleBlackTranslucent - UIAppFonts - - /fonts/MyFont_1.otf - /fonts/MyFont_2.otf - - - - - - - - - - - - - - abc - 123 - - - - - - - - - - - - Ti.UI.PORTRAIT - - - Ti.UI.PORTRAIT - Ti.UI.UPSIDE_PORTRAIT - Ti.UI.LANDSCAPE_LEFT - Ti.UI.LANDSCAPE_RIGHT - - - audio - location - voip - - - telephony - wifi - sms - still-camera - auto-focus-camera - front-facing-camera - camera-flash - video-camera - accelerometer - gyroscope - location-services - gps - magnetometer - gamekit - microphone - opengles-1 - opengles-2 - armv6 - armv7 - peer-peer - - - - something - someicon.png - public.item,public.content - true - - - - - - - - - - - - - - - - - - - - - - - - 10 - true - armeabi,armeabi-v7a,x86 - - - - - - alloy - - some_module - - - - ti.alltest - ti.cjstest - ti.mwtest - ti.androidtest - ti.iphonetest - - - ti_sample_plugin - - diff --git a/tests/resources/tiapp3.xml b/tests/resources/tiapp3.xml deleted file mode 100644 index 109e00a5..00000000 --- a/tests/resources/tiapp3.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - activity2.js - activity3.js - - 10 - true - armeabi,armeabi-v7a,x86 - - - - testservice3.js - - - diff --git a/tests/resources/tiapp4.xml b/tests/resources/tiapp4.xml deleted file mode 100644 index c175d448..00000000 --- a/tests/resources/tiapp4.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - ti.testapp - testapp - 1.0 - tester - http:// - not specified - 2012 by tester - appicon.png - false - false - default - false - false - false - false - 088dc83c-64af-4a81-b57c-7407649453f0 - system - - - Ti.UI.PORTRAIT - - - Ti.UI.PORTRAIT - Ti.UI.UPSIDE_PORTRAIT - Ti.UI.LANDSCAPE_LEFT - Ti.UI.LANDSCAPE_RIGHT - - - - - - - true - true - - default - - - - com.windows.example - - diff --git a/tests/results/tiapp2.json b/tests/results/tiapp2.json deleted file mode 100644 index 668a74d9..00000000 --- a/tests/results/tiapp2.json +++ /dev/null @@ -1 +0,0 @@ -{"deployment-targets":{"iphone":true,"ipad":true,"android":true},"sdk-version":"2.2.0","id":"ti.testapp","name":"testapp","version":"1.0","publisher":"tester","url":"http://","description":"not specified","copyright":"2012 by tester","icon":"appicon.png","persistent-wifi":false,"prerendered-icon":false,"statusbar-style":"default","statusbar-hidden":false,"fullscreen":false,"navbar-hidden":false,"analytics":false,"guid":"088dc83c-64af-4a81-b57c-7407649453f0","properties":{"ti.ui.defaultunit":{"type":"string","value":"system"},"ti.deploytype":{"type":"string","value":"production"},"ti.android.debug":{"type":"bool","value":true},"ti.android.loadfromsdcard":{"type":"bool","value":false},"ti.android.compilejs":{"type":"bool","value":false},"ti.android.include_all_modules":{"type":"bool","value":false},"another property":{"type":"string","value":"this \"one\" with quotes"},"ti.bb.invoke.target.key.push":{"type":"string","value":"ti.testapp.invoke.push"},"ti.bb.invoke.target.key.open":{"type":"string","value":"ti.testapp.invoke.open"},"push_title":{"type":"string","value":"Some Title for BB Push, typically the app name\""},"run-on-main-thread":{"type":"bool","value":true}},"code-processor":{"enabled":true,"plugins":["ti-api-usage-finder"],"options":{"some-option":"xyz"}},"ios":{"enable-launch-screen-storyboard":true,"use-app-thinning":true,"enablecoverage":true,"enablemdfind":true,"default-background-color":"#FFFFFF","min-ios-ver":5,"team-id":"foo","log-server-port":10571,"capabilities":{"app-groups":["group.com.appc.foo","group.com.appc.bar"]},"entitlements":{"application-identifier":"XXXXXXXXXX.com.test.app","aps-environment":"production","beta-reports-active":true,"get-task-allow":false,"keychain-access-groups":["XXXXXXXXXX.com.test.app"]},"plist":{"UISupportedInterfaceOrientations":["UIInterfaceOrientationPortrait","UIInterfaceOrientationPortraitUpsideDown","UIInterfaceOrientationLandscapeLeft","UIInterfaceOrientationLandscapeRight"],"UIBackgroundModes":["audio","location","voip","newsstand-content","external-accessory","bluetooth-central"],"UIRequiredDeviceCapabilities":["telephony","wifi","sms","still-camera","auto-focus-camera","front-facing-camera","camera-flash","video-camera","accelerometer","gyroscope","location-services","gps","magnetometer","gamekit","microphone","opengles-1","opengles-2","armv6","armv7","peer-peer","bluetooth-le"],"UIRequiresPersistentWiFi":true,"UIPrerenderedIcon":true,"UIStatusBarHidden":true,"UIStatusBarStyle":"UIStatusBarStyleBlackTranslucent","UIAppFonts":["/fonts/MyFont_1.otf","/fonts/MyFont_2.otf"]},"extensions":[{"projectPath":"/path/to/extention","targets":[{"name":"Some Target","ppUUIDs":{}}]},{"projectPath":"/path/to/extention2","targets":[{"name":"Another Target","ppUUIDs":{"device":"abc","dist-appstore":123,"dist-adhoc":""}}]},{"projectPath":"/path/to/another/extention","targets":[{"name":"Test WatchKit Extension","ppUUIDs":{}}]}]},"iphone":{"orientations":{"iphone":["Ti.UI.PORTRAIT"],"ipad":["Ti.UI.PORTRAIT","Ti.UI.UPSIDE_PORTRAIT","Ti.UI.LANDSCAPE_LEFT","Ti.UI.LANDSCAPE_RIGHT"]},"backgroundModes":["audio","location","voip"],"requiredFeatures":["telephony","wifi","sms","still-camera","auto-focus-camera","front-facing-camera","camera-flash","video-camera","accelerometer","gyroscope","location-services","gps","magnetometer","gamekit","microphone","opengles-1","opengles-2","armv6","armv7","peer-peer"],"types":[{"name":"something","icon":"someicon.png","uti":["public.item","public.content"],"owner":true}]},"android":{"manifest":"\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t","tool-api-level":10,"abi":["armeabi","armeabi-v7a","x86"],"services":{"testservice.js":{"type":"interval","url":"testservice.js","classname":"TestserviceService"}}},"webpack":{"type":"alloy","transpileDependencies":["some_module"]},"modules":[{"id":"ti.alltest","platform":"","version":"1.2.3"},{"id":"ti.cjstest","platform":"commonjs","version":"1.2.3"},{"id":"ti.mwtest","platform":"mobileweb","version":"4.5.6"},{"id":"ti.androidtest","platform":"android","version":"7.8"},{"id":"ti.iphonetest","platform":"iphone","version":"9.0"}],"plugins":[{"id":"ti_sample_plugin","version":"1.0"}]} diff --git a/tests/results/tiapp2.pretty.json b/tests/results/tiapp2.pretty.json deleted file mode 100644 index bc10af5b..00000000 --- a/tests/results/tiapp2.pretty.json +++ /dev/null @@ -1,290 +0,0 @@ -{ - "deployment-targets": { - "iphone": true, - "ipad": true, - "android": true - }, - "sdk-version": "2.2.0", - "id": "ti.testapp", - "name": "testapp", - "version": "1.0", - "publisher": "tester", - "url": "http://", - "description": "not specified", - "copyright": "2012 by tester", - "icon": "appicon.png", - "persistent-wifi": false, - "prerendered-icon": false, - "statusbar-style": "default", - "statusbar-hidden": false, - "fullscreen": false, - "navbar-hidden": false, - "analytics": false, - "guid": "088dc83c-64af-4a81-b57c-7407649453f0", - "properties": { - "ti.ui.defaultunit": { - "type": "string", - "value": "system" - }, - "ti.deploytype": { - "type": "string", - "value": "production" - }, - "ti.android.debug": { - "type": "bool", - "value": true - }, - "ti.android.loadfromsdcard": { - "type": "bool", - "value": false - }, - "ti.android.compilejs": { - "type": "bool", - "value": false - }, - "ti.android.include_all_modules": { - "type": "bool", - "value": false - }, - "another property": { - "type": "string", - "value": "this \"one\" with quotes" - }, - "ti.bb.invoke.target.key.push": { - "type": "string", - "value": "ti.testapp.invoke.push" - }, - "ti.bb.invoke.target.key.open": { - "type": "string", - "value": "ti.testapp.invoke.open" - }, - "push_title": { - "type": "string", - "value": "Some Title for BB Push, typically the app name\"" - }, - "run-on-main-thread": { - "type": "bool", - "value": true - } - }, - "code-processor": { - "enabled": true, - "plugins": [ - "ti-api-usage-finder" - ], - "options": { - "some-option": "xyz" - } - }, - "ios": { - "enable-launch-screen-storyboard": true, - "use-app-thinning": true, - "enablecoverage": true, - "enablemdfind": true, - "default-background-color": "#FFFFFF", - "min-ios-ver": 5, - "team-id": "foo", - "log-server-port": 10571, - "capabilities": { - "app-groups": [ - "group.com.appc.foo", - "group.com.appc.bar" - ] - }, - "entitlements": { - "application-identifier": "XXXXXXXXXX.com.test.app", - "aps-environment": "production", - "beta-reports-active": true, - "get-task-allow": false, - "keychain-access-groups": [ - "XXXXXXXXXX.com.test.app" - ] - }, - "plist": { - "UISupportedInterfaceOrientations": [ - "UIInterfaceOrientationPortrait", - "UIInterfaceOrientationPortraitUpsideDown", - "UIInterfaceOrientationLandscapeLeft", - "UIInterfaceOrientationLandscapeRight" - ], - "UIBackgroundModes": [ - "audio", - "location", - "voip", - "newsstand-content", - "external-accessory", - "bluetooth-central" - ], - "UIRequiredDeviceCapabilities": [ - "telephony", - "wifi", - "sms", - "still-camera", - "auto-focus-camera", - "front-facing-camera", - "camera-flash", - "video-camera", - "accelerometer", - "gyroscope", - "location-services", - "gps", - "magnetometer", - "gamekit", - "microphone", - "opengles-1", - "opengles-2", - "armv6", - "armv7", - "peer-peer", - "bluetooth-le" - ], - "UIRequiresPersistentWiFi": true, - "UIPrerenderedIcon": true, - "UIStatusBarHidden": true, - "UIStatusBarStyle": "UIStatusBarStyleBlackTranslucent", - "UIAppFonts": [ - "/fonts/MyFont_1.otf", - "/fonts/MyFont_2.otf" - ] - }, - "extensions": [ - { - "projectPath": "/path/to/extention", - "targets": [ - { - "name": "Some Target", - "ppUUIDs": {} - } - ] - }, - { - "projectPath": "/path/to/extention2", - "targets": [ - { - "name": "Another Target", - "ppUUIDs": { - "device": "abc", - "dist-appstore": 123, - "dist-adhoc": "" - } - } - ] - }, - { - "projectPath": "/path/to/another/extention", - "targets": [ - { - "name": "Test WatchKit Extension", - "ppUUIDs": {} - } - ] - } - ] - }, - "iphone": { - "orientations": { - "iphone": [ - "Ti.UI.PORTRAIT" - ], - "ipad": [ - "Ti.UI.PORTRAIT", - "Ti.UI.UPSIDE_PORTRAIT", - "Ti.UI.LANDSCAPE_LEFT", - "Ti.UI.LANDSCAPE_RIGHT" - ] - }, - "backgroundModes": [ - "audio", - "location", - "voip" - ], - "requiredFeatures": [ - "telephony", - "wifi", - "sms", - "still-camera", - "auto-focus-camera", - "front-facing-camera", - "camera-flash", - "video-camera", - "accelerometer", - "gyroscope", - "location-services", - "gps", - "magnetometer", - "gamekit", - "microphone", - "opengles-1", - "opengles-2", - "armv6", - "armv7", - "peer-peer" - ], - "types": [ - { - "name": "something", - "icon": "someicon.png", - "uti": [ - "public.item", - "public.content" - ], - "owner": true - } - ] - }, - "android": { - "manifest": "\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\t\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\n\t\t", - "tool-api-level": 10, - "abi": [ - "armeabi", - "armeabi-v7a", - "x86" - ], - "services": { - "testservice.js": { - "type": "interval", - "url": "testservice.js", - "classname": "TestserviceService" - } - } - }, - "webpack": { - "type": "alloy", - "transpileDependencies": [ - "some_module" - ] - }, - "modules": [ - { - "id": "ti.alltest", - "platform": "", - "version": "1.2.3" - }, - { - "id": "ti.cjstest", - "platform": "commonjs", - "version": "1.2.3" - }, - { - "id": "ti.mwtest", - "platform": "mobileweb", - "version": "4.5.6" - }, - { - "id": "ti.androidtest", - "platform": "android", - "version": "7.8" - }, - { - "id": "ti.iphonetest", - "platform": "iphone", - "version": "9.0" - } - ], - "plugins": [ - { - "id": "ti_sample_plugin", - "version": "1.0" - } - ] -} diff --git a/tests/results/tiapp2.xml b/tests/results/tiapp2.xml deleted file mode 100644 index 50145e90..00000000 --- a/tests/results/tiapp2.xml +++ /dev/null @@ -1,240 +0,0 @@ - - - - true - true - true - - 2.2.0 - ti.testapp - testapp - 1.0 - tester - http:// - not specified - 2012 by tester - appicon.png - false - false - default - false - false - false - false - 088dc83c-64af-4a81-b57c-7407649453f0 - system - production - true - false - false - false - this "one" with quotes - ti.testapp.invoke.push - ti.testapp.invoke.open - Some Title for BB Push, typically the app name" - true - - true - - ti-api-usage-finder - - - xyz - - - - true - true - true - 5.0 - #FFFFFF - foo - true - 10571 - - - group.com.appc.foo - group.com.appc.bar - - - - - application-identifier - XXXXXXXXXX.com.test.app - aps-environment - production - beta-reports-active - - get-task-allow - - keychain-access-groups - - XXXXXXXXXX.com.test.app - - - - - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIBackgroundModes - - audio - location - voip - newsstand-content - external-accessory - bluetooth-central - - UIRequiredDeviceCapabilities - - telephony - wifi - sms - still-camera - auto-focus-camera - front-facing-camera - camera-flash - video-camera - accelerometer - gyroscope - location-services - gps - magnetometer - gamekit - microphone - opengles-1 - opengles-2 - armv6 - armv7 - peer-peer - bluetooth-le - - UIRequiresPersistentWiFi - - UIPrerenderedIcon - - UIStatusBarHidden - - UIStatusBarStyle - UIStatusBarStyleBlackTranslucent - UIAppFonts - - /fonts/MyFont_1.otf - /fonts/MyFont_2.otf - - - - - - - - - - - - abc - 123 - - - - - - - - - - - - - Ti.UI.PORTRAIT - - - Ti.UI.PORTRAIT - Ti.UI.UPSIDE_PORTRAIT - Ti.UI.LANDSCAPE_LEFT - Ti.UI.LANDSCAPE_RIGHT - - - audio - location - voip - - - telephony - wifi - sms - still-camera - auto-focus-camera - front-facing-camera - camera-flash - video-camera - accelerometer - gyroscope - location-services - gps - magnetometer - gamekit - microphone - opengles-1 - opengles-2 - armv6 - armv7 - peer-peer - - - - something - someicon.png - public.item,public.content - true - - - - - - - - - - - - - - - - - - - - - - - 10 - armeabi,armeabi-v7a,x86 - - - - - - alloy - - some_module - - - - ti.alltest - ti.cjstest - ti.mwtest - ti.androidtest - ti.iphonetest - - - ti_sample_plugin - - diff --git a/tests/tiappxml_test.js b/tests/tiappxml_test.js deleted file mode 100644 index 9c5eba31..00000000 --- a/tests/tiappxml_test.js +++ /dev/null @@ -1,127 +0,0 @@ -const should = require('should'); // eslint-disable-line no-unused-vars - -const ti = require('../lib/titanium'), - fs = require('fs'), - path = require('path'); - -describe('tiappxml', function () { -/* -(function () { - var tiapp = new ti.tiappxml(); - - console.log('\nCreating empty tiapp.xml'); - console.log('toString():') - console.log(tiapp.toString()); - console.log('\nJSON:') - console.log(tiapp.toString('json')); - console.log('\nPretty JSON:') - console.log(tiapp.toString('pretty-json')); - console.log('\nXML:'); - console.log(tiapp.toString('xml')); -}()); - -(function () { - var tiapp = new ti.tiappxml(); - - tiapp.id = 'com.another.app'; - tiapp.name = 'Another App'; - tiapp.version = '2.0'; - tiapp['deployment-targets'] = { android: false, iphone: true, mobileweb: true }; - tiapp['sdk-version'] = '2.2.0'; - tiapp.properties = { - prop1: 'value1', - prop2: 'value2', - prop3: 'value3', - prop4: 'value4' - }; - - console.log('\nCreating empty tiapp.xml and adding new nodes'); - console.log('toString():') - console.log(tiapp.toString()); - console.log('\nJSON:') - console.log(tiapp.toString('json')); - console.log('\nPretty JSON:') - console.log(tiapp.toString('pretty-json')); - console.log('\nXML:'); - console.log(tiapp.toString('xml')); -}()); - -(function () { - var tiapp = new ti.tiappxml(path.dirname(module.filename) + '/resources/tiapp1.xml'); - - console.log('\nReading tiapp1.xml'); - console.log('toString():') - console.log(tiapp.toString()); - console.log('\nJSON:') - console.log(tiapp.toString('json')); - console.log('\nPretty JSON:') - console.log(tiapp.toString('pretty-json')); - console.log('\nXML:'); - console.log(tiapp.toString('xml')); -}()); - -(function () { - var tiapp = new ti.tiappxml(path.dirname(module.filename) + '/resources/tiapp1.xml'); - - tiapp.id = 'com.another.app'; - tiapp.name = 'Another App'; - tiapp.version = '2.0'; - tiapp['deployment-targets'] = { android: false, iphone: true, mobileweb: true }; - tiapp['sdk-version'] = '2.2.0'; - - console.log('\nReading tiapp1.xml and modifying nodes'); - console.log('toString():') - console.log(tiapp.toString()); - console.log('\nJSON:') - console.log(tiapp.toString('json')); - console.log('\nPretty JSON:') - console.log(tiapp.toString('pretty-json')); - console.log('\nXML:'); - console.log(tiapp.toString('xml')); -}()); -*/ - - it('tiapp2.xml', function () { - var xmlPath = path.join(__dirname, 'resources', 'tiapp2.xml'), - tiapp = new ti.tiappxml(xmlPath); - - tiapp.toString().should.eql('[object Object]'); - (tiapp.toString('json') + '\n').should.eql(fs.readFileSync(path.join(__dirname, 'results', 'tiapp2.json')).toString()); - (tiapp.toString('pretty-json') + '\n').should.eql(fs.readFileSync(path.join(__dirname, 'results', 'tiapp2.pretty.json')).toString()); - // have to ignore newlines, since thye can differ in OS-style - (tiapp.toString('xml').replace(/(\r\n|\n|\r)/gm, '')).should.eql(fs.readFileSync(path.join(__dirname, 'results', 'tiapp2.xml')).toString().replace(/(\r\n|\n|\r)/gm, '')); - }); - - it('tiapp4.xml', function () { - var tiapp = new ti.tiappxml(path.join(__dirname, '/resources/tiapp4.xml')); - tiapp.id.should.eql('ti.testapp'); - }); - - it('should throw if file does not exist', function () { - should(() => new ti.tiappxml('foo')).throw('tiapp.xml file does not exist'); - }); - - it('should support parsing a tiapp from a string', function () { - var contents = fs.readFileSync(path.join(__dirname, 'resources', 'tiapp2.xml'), 'utf8'); - var tiapp = new ti.tiappxml(); - tiapp.parse(contents); - (tiapp.toString('json') + '\n').should.eql(fs.readFileSync(path.join(__dirname, 'results', 'tiapp2.json')).toString()); - }); -/* -(function () { - var tiapp = new ti.tiappxml(path.dirname(module.filename) + '/resources/tiapp3.xml'); - - console.log('\nReading tiapp3.xml'); - console.log('toString():') - console.log(tiapp.toString()); - console.log('\nJSON:') - console.log(tiapp.toString('json')); - console.log('\nPretty JSON:') - console.log(tiapp.toString('pretty-json')); - console.log('\nXML:'); - console.log(tiapp.toString('xml')); - console.log('\Original:'); - console.log(fs.readFileSync(__dirname + '/resources/tiapp3.xml').toString()); -}()); -*/ -}); diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..58fbd1d4 --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "Bundler", + "rootDir": "./src", + "sourceMap": true + }, + "extends": "./tsconfig.json", + "include": ["./src"] +} diff --git a/tsconfig.check.json b/tsconfig.check.json new file mode 100644 index 00000000..e8edd233 --- /dev/null +++ b/tsconfig.check.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": false, + "noEmit": true + }, + "include": ["./dist"], + "exclude": [] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..a69dc1b5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "composite": false, + "declaration": true, + "declarationMap": false, + "esModuleInterop": false, + "forceConsistentCasingInFileNames": true, + "inlineSources": false, + "isolatedDeclarations": false, + "isolatedModules": true, + "lib": ["esnext"], + "module": "NodeNext", + "moduleResolution": "nodenext", + "noImplicitAny": false, + "noUnusedLocals": false, + "noUnusedParameters": false, + "outDir": "./dist", + "preserveWatchOutput": true, + "removeComments": true, + "skipLibCheck": true, + "strict": true, + "sourceMap": false, + "target": "esnext", + "typeRoots": ["./node_modules/@types"], + "types": ["node"] + }, + "include": ["./tsdown.config.ts", "./src", "./test"] +} diff --git a/tsdown.config.ts b/tsdown.config.ts new file mode 100644 index 00000000..14e1fa89 --- /dev/null +++ b/tsdown.config.ts @@ -0,0 +1,15 @@ +import { defineConfig, type UserConfig } from 'tsdown'; + +const config: UserConfig = defineConfig({ + entry: { + index: './src/index.ts', + 'android/index': './src/android/index.ts', + 'jdk/index': './src/jdk/index.ts', + 'titanium/index': './src/titanium/index.ts', + 'util/index': './src/util/index.ts', + }, + format: ['es', 'cjs'], + platform: 'node', + tsconfig: './tsconfig.build.json', +}); +export default config; diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..93222892 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + allowOnly: true, + coverage: { + include: ['src/**/*.ts'], + reporter: ['html', 'lcov', 'text'], + }, + environment: 'node', + globals: false, + include: ['test/**/*.test.ts'], + reporters: ['verbose'], + silent: false, + watch: false, + }, +});