1
0
mirror of https://gitcode.com/github-mirrors/react-native-update-cli.git synced 2025-09-16 09:41:38 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Compare commits

...

142 Commits

Author SHA1 Message Date
sunnylqm
e713f4bbd1 Bump package version to 1.40.1 2025-02-15 23:14:41 +08:00
sunnylqm
5a6463de33 Remove debug console.log in zip utility 2025-02-15 23:14:11 +08:00
sunnylqm
1fb308af94 Refactor i18n locales from JSON to TypeScript modules 2025-02-15 22:51:26 +08:00
sunnylqm
f10d4d3004 Add option to disable Hermes for React Native bundle 2025-02-15 21:40:28 +08:00
sunnylqm
0f44de772f init i18n 2025-02-15 00:38:55 +08:00
Sunny Luo
814a9d10fb Update package.json 2025-02-13 17:17:31 +08:00
sunnylqm
c08c5c0b07 fix taro cli path 2025-02-13 16:13:48 +08:00
sunnylqm
dc8c134ff0 v1.40.0-beta.0 2025-02-13 16:07:25 +08:00
sunnylqm
1d1e6cde0f support taro 2025-02-13 16:02:04 +08:00
sunny.luo
f16aff5674 Improve file filtering during bundle packing
# Conflicts:
#	package.json
#	src/bundle.js
2025-02-10 17:22:00 +08:00
Sunny Luo
d7da311c5e Update package.json 2025-02-09 16:15:04 +08:00
波仔糕
abef760f43 add logic to remove soucemap and merge sourcemap params (#9)
* add logic to remove soucemap and merge sourcemap params

* Update bundle.js

---------

Co-authored-by: Sunny Luo <sunnylqm@gmail.com>
2025-02-09 16:14:45 +08:00
Sunny Luo
467ef0c60d Update package.json 2025-01-23 23:15:22 +08:00
波仔糕
0b08c7760d Support sentry (#8)
* add logic to support sentry

* udpate

* change reference path

* support git commits and version info

* udate

* add try catch for require.resolve

* update upload sourcemap workflow
2025-01-23 22:02:13 +08:00
sunnylqm
b24b27d100 ts 2025-01-11 20:23:25 +08:00
sunnylqm
4f0784172f fix expo cli 2025-01-11 20:20:16 +08:00
sunnylqm
26725200b7 bump 2025-01-11 15:47:29 +08:00
sunnylqm
8bd31b8dc1 fix get 2025-01-11 15:45:28 +08:00
Sunny Luo
59f2421067 Update package.json 2025-01-09 21:00:29 +08:00
sunnylqm
8f0ca60d24 fix error message 2025-01-09 20:58:06 +08:00
Sunny Luo
6fcdb988c8 Merge pull request #6 from bozaigao/master
implement getAppInfo and uploadApp methods
2025-01-07 14:19:42 +08:00
HeYanbo
040f723305 implement getAppInfo and uploadApp methods 2025-01-07 13:52:28 +08:00
sunnylqm
12bddc446d Enhance package.json: add lint script and update devDependencies 2025-01-05 21:22:14 +08:00
sunnylqm
ba3d88627a support harmony 2025-01-05 21:16:52 +08:00
Sunny Luo
3987a5191f Update publish.yml 2024-12-26 15:41:57 +08:00
Sunny Luo
9903fb97e4 bump 2024-12-26 15:40:05 +08:00
Sunny Luo
834c0bb351 Create lint.yml 2024-12-26 14:57:21 +08:00
Sunny Luo
fa8ba44bfa Create publish.yml 2024-12-26 14:56:49 +08:00
Sunny Luo
6e4e89428c Merge pull request #5 from bozaigao/master
适配鸿蒙
2024-12-26 12:14:14 +08:00
HeYanbo
e018761fc8 init 2024-12-25 23:38:29 +08:00
sunny.luo
6534379d81 use expo cli if available 2024-12-11 17:23:28 +08:00
sunny.luo
bb777bf973 update 2024-12-02 16:32:34 +08:00
sunny.luo
ea05d4ab66 fix chalk 2024-11-25 10:51:35 +08:00
sunny.luo
a259ff671d check latest version 2024-11-24 11:51:55 +08:00
sunny.luo
3f68fa0f11 compose sourcemap 2024-11-19 23:28:54 +08:00
sunnylqm
fa750ba157 update 2024-11-16 18:54:34 +08:00
sunnylqm
91fc0caa07 v1.32.3 2024-11-16 18:33:09 +08:00
sunnylqm
36e1be084d remove request 2024-11-16 08:24:18 +08:00
sunnylqm
e099002629 v1.32.0 2024-11-16 07:51:18 +08:00
sunnylqm
5dd3b64720 ts 2024-11-16 07:48:27 +08:00
sunnylqm
31ec3edc5a v1.31.2 2024-11-16 07:41:08 +08:00
Sunny Luo
4b772194d1 Update versions.js 2024-10-23 10:41:46 +08:00
sunnylqm
792418c964 add dep 2024-10-20 16:52:06 +08:00
sunnylqm
d5f468aa44 fix gradle check 2024-10-19 11:44:32 +08:00
sunnylqm
04f75cd51b add rollout 2024-10-19 11:31:50 +08:00
sunnylqm
5a05679e2b add version id null 2024-10-16 23:20:58 +08:00
sunny.luo
69f4372b63 note for apk permission 2024-10-15 14:56:41 +08:00
sunnylqm
dbfdce6412 v1.30.3 2024-10-09 20:31:48 +08:00
sunnylqm
1372a30ea3 show error 2024-10-08 19:32:52 +08:00
Sunny Luo
d51ef37a62 Update index.js 2024-10-08 13:16:23 +08:00
sunnylqm
90a59cfe7b support rn75 2024-09-24 21:20:42 +08:00
sunnylqm
ffcc6c9c96 v1.30.0 2024-09-24 21:20:18 +08:00
sunnylqm
b00b3144a3 v1.29.0 2024-09-22 17:45:10 +08:00
sunnylqm
d3ee908227 warn version 2024-09-22 17:44:31 +08:00
sunnylqm
5302c8968f fix expo cli on windows 2024-08-22 17:15:17 +08:00
sunnylqm
5740a3315c v1.28.0 2024-08-22 17:15:04 +08:00
sunnylqm
4a11a4118f add min/max packageverion 2024-07-21 23:12:15 +08:00
sunnylqm
feb1128748 v1.26.0 2024-07-10 09:48:06 +08:00
sunnylqm
8fd74d76b1 v1.25.1 2024-07-05 10:34:18 +08:00
sunnylqm
209a989a48 v1.25.0 2024-07-04 21:34:34 +08:00
sunnylqm
aab9ea6b98 v1.24.0 2024-07-04 18:01:51 +08:00
sunnylqm
5f45a66aad v1.23.1 2024-06-11 20:27:04 +08:00
sunnylqm
67f6aeef02 v1.23.0 2024-06-11 20:22:12 +08:00
sunnylqm
5a28847e46 v1.22.0 2024-03-21 21:04:16 +08:00
sunnylqm
54f7358357 chore: ignore sourcemap 2024-03-21 21:03:34 +08:00
sunnylqm
d2ec856756 v1.21.0 2024-03-07 21:08:30 +08:00
sunnylqm
84e5e34820 v1.20.6 2024-03-07 11:16:19 +08:00
sunnylqm
006951ae88 v1.20.5 2024-03-06 20:45:59 +08:00
sunnylqm
b1fda5ab9c v1.20.3 2024-03-06 20:36:25 +08:00
sunnylqm
385b974aff v1.20.2 2024-03-06 10:20:00 +08:00
sunnylqm
2a02deb015 v1.20.1 2024-03-06 09:55:48 +08:00
sunnylqm
8b7cb809f6 v1.20.0 2024-03-05 23:29:31 +08:00
sunnylqm
070991d08b fix: hermes path 2024-03-05 23:29:05 +08:00
sunnylqm
0d03e18c58 fix: version name 2024-03-05 23:03:10 +08:00
sunnylqm
a0dfcb5c4b v1.19.0 2024-02-18 20:04:05 +08:00
sunnylqm
587da8aaf9 Fix android crunchPngs option and add support for expo-router 2024-02-18 20:03:43 +08:00
sunnylqm
724088a810 v1.18.0 2024-02-03 21:28:38 +08:00
sunnylqm
7c20b30c85 feat: support expo 2024-02-03 21:27:47 +08:00
sunnylqm
6a053c6428 v1.17.0 2024-01-30 19:15:15 +08:00
sunnylqm
f202fc590d fix: rndir path 2024-01-30 19:15:00 +08:00
sunnylqm
0f8cf3c399 v1.16.0 2024-01-30 17:50:32 +08:00
sunnylqm
6a0d82c7a5 fix: rndir path 2024-01-30 17:50:09 +08:00
sunnylqm
eed19992d8 v1.15.0 2024-01-30 12:43:48 +08:00
sunnylqm
1b5078831c fix: require path 2024-01-30 12:43:31 +08:00
sunnylqm
bc9aff343a v1.14.0 2024-01-29 19:11:06 +08:00
sunnylqm
7aaa32a5a2 v1.14.0-beta.0 2024-01-29 19:02:01 +08:00
sunnylqm
ab7920fe38 feat: support symlink 2024-01-29 19:01:11 +08:00
sunnylqm
d912ace4a7 v1.13.0 2023-09-19 18:40:12 +08:00
sunnylqm
8af4d314ce fix appid equal 2023-09-19 18:36:26 +08:00
sunnylqm
f2d5269512 feat: support rn0.71 android hermes 2023-07-20 18:27:14 +08:00
sunnylqm
fe24c4ca36 v1.12.0 2023-07-20 18:25:47 +08:00
sunnylqm
cf61c297a6 update endpoint 2023-01-29 10:35:44 +08:00
sunnylqm
f9adc700ed v1.11.0 2023-01-11 23:36:13 +08:00
sunnylqm
dcff16cbb5 support source-map 2023-01-11 23:35:39 +08:00
sunnylqm
2bb8e83010 v1.10.0 2022-07-01 23:08:16 +08:00
sunnylqm
0cfc6e4f0d support rn 69 hermes 2022-07-01 23:02:20 +08:00
sunnylqm
da7bdbfdd2 v1.9.0 2022-06-29 09:42:05 +08:00
sunnylqm
07ee28ba3b add updateVersionInfo 2022-06-29 09:41:44 +08:00
sunnylqm
dae3e4024f v1.8.1 2021-12-24 17:55:15 +08:00
sunnylqm
d673b5736a Fix selectApp id 2021-12-24 17:53:14 +08:00
sunnylqm
732845faad Cleanup headers 2021-10-28 18:01:12 +08:00
sunnylqm
bcfdd67ea8 v1.8.0 2021-10-18 18:24:15 +08:00
sunnylqm
27ea54c1ec Update package output 2021-10-18 18:22:56 +08:00
sunnylqm
ba0fa836d1 v1.7.2 2021-10-18 18:02:43 +08:00
sunnylqm
bde76094fc v1.7.1 2021-10-18 18:00:21 +08:00
sunnylqm
f1d6c3744e v1.7.0 2021-10-18 17:54:07 +08:00
sunnylqm
768484d7b5 Add packageVersion 2021-10-18 17:53:29 +08:00
sunnylqm
d6632ffcc6 v1.7.0-beta.0 2021-10-18 17:28:01 +08:00
sunnylqm
24f5b316a9 v1.6.0 2021-10-10 12:39:29 +08:00
sunnylqm
03a4108a08 汉化 2021-10-10 12:39:00 +08:00
sunnylqm
32d7ed9b00 v1.5.0 2021-09-01 14:55:09 +08:00
sunnylqm
6f3d45c3f2 Add acc option 2021-09-01 14:54:17 +08:00
sunnylqm
25cb724921 v1.4.2 2021-06-23 10:05:55 +08:00
sunnylqm
a7b79a30e8 Print server error 2021-06-23 10:05:29 +08:00
sunnylqm
11799dd0c1 v1.4.1 2021-04-11 23:29:56 +08:00
sunnylqm
2ab0cad7e5 Detect hermes first 2021-04-11 23:29:44 +08:00
sunnylqm
ec8d6a767b v1.4.0 2021-04-11 23:26:59 +08:00
sunnylqm
fa8290fcbf Re-enable gradle check for hermes 2021-04-11 23:26:43 +08:00
sunnylqm
46d308c7c2 v1.4.0-beta1 2021-04-11 18:11:24 +08:00
sunnylqm
9e721e1858 try require diff separately 2021-04-11 18:11:08 +08:00
sunnylqm
c30454976c v1.4.0-beta0 2021-04-08 16:07:10 +08:00
sunnylqm
3d73b95140 Add hdiff 2021-04-07 22:09:48 +08:00
sunnylqm
32cafd92bf v1.3.2 2021-03-05 12:27:53 +08:00
sunnylqm
ea10cd7828 Show current filesize 2021-03-05 12:27:38 +08:00
sunnylqm
574a52b126 v1.3.1 2021-01-21 17:46:16 +08:00
sunnylqm
c00a7a72fe Disable crunchPngs check 2021-01-21 17:45:15 +08:00
sunnylqm
0e8e3aa420 v1.3.0 2021-01-20 23:30:26 +08:00
sunnylqm
7426e93647 Update gitignore 2021-01-20 23:30:04 +08:00
sunnylqm
b6fb2e7d2a Check does appId/appKey match 2021-01-20 23:29:53 +08:00
sunnylqm
7f1dcbb571 Use table for listApp 2021-01-20 23:29:31 +08:00
sunnylqm
59fad93832 Change local build foler name 2021-01-11 14:06:14 +08:00
sunnylqm
3db4f803e2 v1.2.3 2021-01-05 21:54:04 +08:00
sunnylqm
56d44b8c85 Update defaultEndpoint 2021-01-05 21:53:46 +08:00
sunnylqm
ecd951265f v1.2.2 2020-12-15 13:30:19 +08:00
sunnylqm
62d455ac07 Update app-info-parser 2020-12-15 13:30:04 +08:00
sunnylqm
acfc2dd65b v1.2.1 2020-11-04 14:48:03 +08:00
sunnylqm
7f062f681a v1.2.0 2020-10-21 17:33:01 +08:00
sunnylqm
7f5b9fd7fd Check gradleConfig 2020-10-21 15:50:44 +08:00
sunnylqm
13b21c49c1 Merge branch 'master' of github.com:sunnylqm/react-native-update-cli
# Conflicts:
#	package.json
2020-10-21 15:24:46 +08:00
sunnylqm
85db61704c v1.1.18 2020-10-18 12:16:35 +08:00
sunnylqm
57ddfc5d7d Add token when upload 2020-10-18 12:16:15 +08:00
sunnylqm
16b1cc3ed4 v1.1.15 2020-08-25 11:41:18 +08:00
42 changed files with 7503 additions and 3332 deletions

47
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: lint
on:
pull_request:
branches:
- master
push:
branches:
- master
# Cancel a currently running workflow from the same PR/branch/tag
# when a new workflow is triggered
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
- name: Install Dependency
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_OPTIONS: '--max_old_space_size=4096'
run: bun install --frozen-lockfile
- name: Run lint
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_OPTIONS: '--max_old_space_size=4096'
run: bun lint

22
.github/workflows/publish.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Publish Package to npmjs
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
# Setup .npmrc file to publish to npm
- uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- run: bun install --frozen-lockfile
- run: npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

1
.gitignore vendored
View File

@@ -104,3 +104,4 @@ dist
.tern-port
lib/
.DS_Store

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
registry = "https://registry.npmjs.org"

15
.swcrc Normal file
View File

@@ -0,0 +1,15 @@
{
"jsc": {
"loose": true,
"target": "es2018",
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": false,
"dynamicImport": false
}
},
"module": {
"type": "commonjs"
}
}

29
LICENSE
View File

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

39
biome.json Normal file
View File

@@ -0,0 +1,39 @@
{
"files": {
"ignore": ["lib"]
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"suspicious": {
"noExplicitAny": "off",
"noAssignInExpressions": "off",
"noDoubleEquals": "off"
},
"style": {
"noNonNullAssertion": "off"
},
"a11y": {
"useValidAnchor": "off"
},
"performance": {
"noDelete": "off"
}
}
},
"formatter": {
"enabled": true,
"formatWithErrors": false,
"indentStyle": "space",
"indentWidth": 2,
"lineEnding": "lf",
"lineWidth": 80,
"attributePosition": "auto"
},
"javascript": {
"formatter": {
"quoteStyle": "single"
}
}
}

914
bun.lock Normal file
View File

@@ -0,0 +1,914 @@
{
"lockfileVersion": 1,
"workspaces": {
"": {
"dependencies": {
"@badisi/latest-version": "^7.0.10",
"bplist-parser": "^0.3.2",
"bytebuffer": "^5.0.1",
"cgbi-to-png": "^1.0.7",
"chalk": "4",
"cli-arguments": "^0.2.1",
"commander": "^12.1.0",
"compare-versions": "^6.1.1",
"filesize-parser": "^1.5.1",
"form-data": "^4.0.1",
"fs-extra": "8",
"gradle-to-js": "^2.0.1",
"i18next": "^24.2.2",
"isomorphic-unzip": "^1.1.5",
"node-fetch": "^2.6.1",
"plist": "^3.1.0",
"progress": "^2.0.3",
"properties": "^1.2.1",
"read": "^4.0.0",
"semver": "^7.6.3",
"tcp-ping": "^0.1.1",
"tty-table": "4.2",
"update-notifier": "^5.1.0",
"yauzl": "^3.2.0",
"yazl": "3.3.1",
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "^0.5.1",
"@swc/core": "^1.9.3",
"@types/node": "^22.9.3",
"typescript": "^5.7.2",
},
},
},
"packages": {
"@babel/runtime": ["@babel/runtime@7.26.9", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg=="],
"@badisi/latest-version": ["@badisi/latest-version@7.0.10", "", { "dependencies": { "@colors/colors": "^1.6.0", "global-dirs": "3.0.1", "ora": "^8.1.0", "registry-auth-token": "^5.0.2", "semver": "^7.6.3" }, "bin": { "latest-version": "bin/latest-version", "lv": "bin/latest-version" } }, "sha512-1lX9wvXiJC552C+rrwwjEbpvvuDwYTU3OLFwFA1pTVYTnJGUkbBkfqz1MuTIPP1fL2LCvjd21ri/u39sSIcMTg=="],
"@biomejs/biome": ["@biomejs/biome@1.9.4", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "1.9.4", "@biomejs/cli-darwin-x64": "1.9.4", "@biomejs/cli-linux-arm64": "1.9.4", "@biomejs/cli-linux-arm64-musl": "1.9.4", "@biomejs/cli-linux-x64": "1.9.4", "@biomejs/cli-linux-x64-musl": "1.9.4", "@biomejs/cli-win32-arm64": "1.9.4", "@biomejs/cli-win32-x64": "1.9.4" }, "bin": { "biome": "bin/biome" } }, "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog=="],
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@1.9.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw=="],
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@1.9.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg=="],
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g=="],
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@1.9.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA=="],
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg=="],
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@1.9.4", "", { "os": "linux", "cpu": "x64" }, "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg=="],
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@1.9.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg=="],
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@1.9.4", "", { "os": "win32", "cpu": "x64" }, "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA=="],
"@colors/colors": ["@colors/colors@1.6.0", "", {}, "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA=="],
"@napi-rs/nice": ["@napi-rs/nice@1.0.1", "", { "optionalDependencies": { "@napi-rs/nice-android-arm-eabi": "1.0.1", "@napi-rs/nice-android-arm64": "1.0.1", "@napi-rs/nice-darwin-arm64": "1.0.1", "@napi-rs/nice-darwin-x64": "1.0.1", "@napi-rs/nice-freebsd-x64": "1.0.1", "@napi-rs/nice-linux-arm-gnueabihf": "1.0.1", "@napi-rs/nice-linux-arm64-gnu": "1.0.1", "@napi-rs/nice-linux-arm64-musl": "1.0.1", "@napi-rs/nice-linux-ppc64-gnu": "1.0.1", "@napi-rs/nice-linux-riscv64-gnu": "1.0.1", "@napi-rs/nice-linux-s390x-gnu": "1.0.1", "@napi-rs/nice-linux-x64-gnu": "1.0.1", "@napi-rs/nice-linux-x64-musl": "1.0.1", "@napi-rs/nice-win32-arm64-msvc": "1.0.1", "@napi-rs/nice-win32-ia32-msvc": "1.0.1", "@napi-rs/nice-win32-x64-msvc": "1.0.1" } }, "sha512-zM0mVWSXE0a0h9aKACLwKmD6nHcRiKrPpCfvaKqG1CqDEyjEawId0ocXxVzPMCAm6kkWr2P025msfxXEnt8UGQ=="],
"@napi-rs/nice-android-arm-eabi": ["@napi-rs/nice-android-arm-eabi@1.0.1", "", { "os": "android", "cpu": "arm" }, "sha512-5qpvOu5IGwDo7MEKVqqyAxF90I6aLj4n07OzpARdgDRfz8UbBztTByBp0RC59r3J1Ij8uzYi6jI7r5Lws7nn6w=="],
"@napi-rs/nice-android-arm64": ["@napi-rs/nice-android-arm64@1.0.1", "", { "os": "android", "cpu": "arm64" }, "sha512-GqvXL0P8fZ+mQqG1g0o4AO9hJjQaeYG84FRfZaYjyJtZZZcMjXW5TwkL8Y8UApheJgyE13TQ4YNUssQaTgTyvA=="],
"@napi-rs/nice-darwin-arm64": ["@napi-rs/nice-darwin-arm64@1.0.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-91k3HEqUl2fsrz/sKkuEkscj6EAj3/eZNCLqzD2AA0TtVbkQi8nqxZCZDMkfklULmxLkMxuUdKe7RvG/T6s2AA=="],
"@napi-rs/nice-darwin-x64": ["@napi-rs/nice-darwin-x64@1.0.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-jXnMleYSIR/+TAN/p5u+NkCA7yidgswx5ftqzXdD5wgy/hNR92oerTXHc0jrlBisbd7DpzoaGY4cFD7Sm5GlgQ=="],
"@napi-rs/nice-freebsd-x64": ["@napi-rs/nice-freebsd-x64@1.0.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-j+iJ/ezONXRQsVIB/FJfwjeQXX7A2tf3gEXs4WUGFrJjpe/z2KB7sOv6zpkm08PofF36C9S7wTNuzHZ/Iiccfw=="],
"@napi-rs/nice-linux-arm-gnueabihf": ["@napi-rs/nice-linux-arm-gnueabihf@1.0.1", "", { "os": "linux", "cpu": "arm" }, "sha512-G8RgJ8FYXYkkSGQwywAUh84m946UTn6l03/vmEXBYNJxQJcD+I3B3k5jmjFG/OPiU8DfvxutOP8bi+F89MCV7Q=="],
"@napi-rs/nice-linux-arm64-gnu": ["@napi-rs/nice-linux-arm64-gnu@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-IMDak59/W5JSab1oZvmNbrms3mHqcreaCeClUjwlwDr0m3BoR09ZiN8cKFBzuSlXgRdZ4PNqCYNeGQv7YMTjuA=="],
"@napi-rs/nice-linux-arm64-musl": ["@napi-rs/nice-linux-arm64-musl@1.0.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-wG8fa2VKuWM4CfjOjjRX9YLIbysSVV1S3Kgm2Fnc67ap/soHBeYZa6AGMeR5BJAylYRjnoVOzV19Cmkco3QEPw=="],
"@napi-rs/nice-linux-ppc64-gnu": ["@napi-rs/nice-linux-ppc64-gnu@1.0.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-lxQ9WrBf0IlNTCA9oS2jg/iAjQyTI6JHzABV664LLrLA/SIdD+I1i3Mjf7TsnoUbgopBcCuDztVLfJ0q9ubf6Q=="],
"@napi-rs/nice-linux-riscv64-gnu": ["@napi-rs/nice-linux-riscv64-gnu@1.0.1", "", { "os": "linux", "cpu": "none" }, "sha512-3xs69dO8WSWBb13KBVex+yvxmUeEsdWexxibqskzoKaWx9AIqkMbWmE2npkazJoopPKX2ULKd8Fm9veEn0g4Ig=="],
"@napi-rs/nice-linux-s390x-gnu": ["@napi-rs/nice-linux-s390x-gnu@1.0.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-lMFI3i9rlW7hgToyAzTaEybQYGbQHDrpRkg+1gJWEpH0PLAQoZ8jiY0IzakLfNWnVda1eTYYlxxFYzW8Rqczkg=="],
"@napi-rs/nice-linux-x64-gnu": ["@napi-rs/nice-linux-x64-gnu@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-XQAJs7DRN2GpLN6Fb+ZdGFeYZDdGl2Fn3TmFlqEL5JorgWKrQGRUrpGKbgZ25UeZPILuTKJ+OowG2avN8mThBA=="],
"@napi-rs/nice-linux-x64-musl": ["@napi-rs/nice-linux-x64-musl@1.0.1", "", { "os": "linux", "cpu": "x64" }, "sha512-/rodHpRSgiI9o1faq9SZOp/o2QkKQg7T+DK0R5AkbnI/YxvAIEHf2cngjYzLMQSQgUhxym+LFr+UGZx4vK4QdQ=="],
"@napi-rs/nice-win32-arm64-msvc": ["@napi-rs/nice-win32-arm64-msvc@1.0.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-rEcz9vZymaCB3OqEXoHnp9YViLct8ugF+6uO5McifTedjq4QMQs3DHz35xBEGhH3gJWEsXMUbzazkz5KNM5YUg=="],
"@napi-rs/nice-win32-ia32-msvc": ["@napi-rs/nice-win32-ia32-msvc@1.0.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-t7eBAyPUrWL8su3gDxw9xxxqNwZzAqKo0Szv3IjVQd1GpXXVkb6vBBQUuxfIYaXMzZLwlxRQ7uzM2vdUE9ULGw=="],
"@napi-rs/nice-win32-x64-msvc": ["@napi-rs/nice-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-JlF+uDcatt3St2ntBG8H02F1mM45i5SF9W+bIKiReVE6wiy3o16oBP/yxt+RZ+N6LbCImJXJ6bXNO2kn9AXicg=="],
"@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
"@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
"@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
"@pnpm/config.env-replace": ["@pnpm/config.env-replace@1.1.0", "", {}, "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w=="],
"@pnpm/network.ca-file": ["@pnpm/network.ca-file@1.0.2", "", { "dependencies": { "graceful-fs": "4.2.10" } }, "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA=="],
"@pnpm/npm-conf": ["@pnpm/npm-conf@2.3.1", "", { "dependencies": { "@pnpm/config.env-replace": "^1.1.0", "@pnpm/network.ca-file": "^1.0.1", "config-chain": "^1.1.11" } }, "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw=="],
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
"@sindresorhus/is": ["@sindresorhus/is@5.6.0", "", {}, "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g=="],
"@swc/cli": ["@swc/cli@0.5.1", "", { "dependencies": { "@swc/counter": "^0.1.3", "@xhmikosr/bin-wrapper": "^13.0.5", "commander": "^8.3.0", "fast-glob": "^3.2.5", "minimatch": "^9.0.3", "piscina": "^4.3.0", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^3.5.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-sxSXyjqFImYrqjhZSPymjmM/9V6auZG67UsDwbe7FZaBlyfW8ka3QG/zRjpJJ9+8Ahns/kKb8bXPKQq7V2MtBw=="],
"@swc/core": ["@swc/core@1.9.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.17" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.9.3", "@swc/core-darwin-x64": "1.9.3", "@swc/core-linux-arm-gnueabihf": "1.9.3", "@swc/core-linux-arm64-gnu": "1.9.3", "@swc/core-linux-arm64-musl": "1.9.3", "@swc/core-linux-x64-gnu": "1.9.3", "@swc/core-linux-x64-musl": "1.9.3", "@swc/core-win32-arm64-msvc": "1.9.3", "@swc/core-win32-ia32-msvc": "1.9.3", "@swc/core-win32-x64-msvc": "1.9.3" }, "peerDependencies": { "@swc/helpers": "*" }, "optionalPeers": ["@swc/helpers"] }, "sha512-oRj0AFePUhtatX+BscVhnzaAmWjpfAeySpM1TCbxA1rtBDeH/JDhi5yYzAKneDYtVtBvA7ApfeuzhMC9ye4xSg=="],
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.9.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-hGfl/KTic/QY4tB9DkTbNuxy5cV4IeejpPD4zo+Lzt4iLlDWIeANL4Fkg67FiVceNJboqg48CUX+APhDHO5G1w=="],
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.9.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-IaRq05ZLdtgF5h9CzlcgaNHyg4VXuiStnOFpfNEMuI5fm5afP2S0FHq8WdakUz5WppsbddTdplL+vpeApt/WCQ=="],
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.9.3", "", { "os": "linux", "cpu": "arm" }, "sha512-Pbwe7xYprj/nEnZrNBvZfjnTxlBIcfApAGdz2EROhjpPj+FBqBa3wOogqbsuGGBdCphf8S+KPprL1z+oDWkmSQ=="],
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.9.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-AQ5JZiwNGVV/2K2TVulg0mw/3LYfqpjZO6jDPtR2evNbk9Yt57YsVzS+3vHSlUBQDRV9/jqMuZYVU3P13xrk+g=="],
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.9.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-tzVH480RY6RbMl/QRgh5HK3zn1ZTFsThuxDGo6Iuk1MdwIbdFYUY034heWUTI4u3Db97ArKh0hNL0xhO3+PZdg=="],
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.9.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ivXXBRDXDc9k4cdv10R21ccBmGebVOwKXT/UdH1PhxUn9m/h8erAWjz5pcELwjiMf27WokqPgaWVfaclDbgE+w=="],
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.9.3", "", { "os": "linux", "cpu": "x64" }, "sha512-ILsGMgfnOz1HwdDz+ZgEuomIwkP1PHT6maigZxaCIuC6OPEhKE8uYna22uU63XvYcLQvZYDzpR3ms47WQPuNEg=="],
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.9.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-e+XmltDVIHieUnNJHtspn6B+PCcFOMYXNJB1GqoCcyinkEIQNwC8KtWgMqUucUbEWJkPc35NHy9k8aCXRmw9Kg=="],
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.9.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-rqpzNfpAooSL4UfQnHhkW8aL+oyjqJniDP0qwZfGnjDoJSbtPysHg2LpcOBEdSnEH+uIZq6J96qf0ZFD8AGfXA=="],
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.9.3", "", { "os": "win32", "cpu": "x64" }, "sha512-3YJJLQ5suIEHEKc1GHtqVq475guiyqisKSoUnoaRtxkDaW5g1yvPt9IoSLOe2mRs7+FFhGGU693RsBUSwOXSdQ=="],
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
"@swc/types": ["@swc/types@0.1.17", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ=="],
"@szmarczak/http-timer": ["@szmarczak/http-timer@5.0.1", "", { "dependencies": { "defer-to-connect": "^2.0.1" } }, "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw=="],
"@tokenizer/token": ["@tokenizer/token@0.3.0", "", {}, "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="],
"@types/http-cache-semantics": ["@types/http-cache-semantics@4.0.4", "", {}, "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA=="],
"@types/node": ["@types/node@22.9.3", "", { "dependencies": { "undici-types": "~6.19.8" } }, "sha512-F3u1fs/fce3FFk+DAxbxc78DF8x0cY09RRL8GnXLmkJ1jvx3TtPdWoTT5/NiYfI5ASqXBmfqJi9dZ3gxMx4lzw=="],
"@xhmikosr/archive-type": ["@xhmikosr/archive-type@7.0.0", "", { "dependencies": { "file-type": "^19.0.0" } }, "sha512-sIm84ZneCOJuiy3PpWR5bxkx3HaNt1pqaN+vncUBZIlPZCq8ASZH+hBVdu5H8znR7qYC6sKwx+ie2Q7qztJTxA=="],
"@xhmikosr/bin-check": ["@xhmikosr/bin-check@7.0.3", "", { "dependencies": { "execa": "^5.1.1", "isexe": "^2.0.0" } }, "sha512-4UnCLCs8DB+itHJVkqFp9Zjg+w/205/J2j2wNBsCEAm/BuBmtua2hhUOdAMQE47b1c7P9Xmddj0p+X1XVsfHsA=="],
"@xhmikosr/bin-wrapper": ["@xhmikosr/bin-wrapper@13.0.5", "", { "dependencies": { "@xhmikosr/bin-check": "^7.0.3", "@xhmikosr/downloader": "^15.0.1", "@xhmikosr/os-filter-obj": "^3.0.0", "bin-version-check": "^5.1.0" } }, "sha512-DT2SAuHDeOw0G5bs7wZbQTbf4hd8pJ14tO0i4cWhRkIJfgRdKmMfkDilpaJ8uZyPA0NVRwasCNAmMJcWA67osw=="],
"@xhmikosr/decompress": ["@xhmikosr/decompress@10.0.1", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.0.1", "@xhmikosr/decompress-tarbz2": "^8.0.1", "@xhmikosr/decompress-targz": "^8.0.1", "@xhmikosr/decompress-unzip": "^7.0.0", "graceful-fs": "^4.2.11", "make-dir": "^4.0.0", "strip-dirs": "^3.0.0" } }, "sha512-6uHnEEt5jv9ro0CDzqWlFgPycdE+H+kbJnwyxgZregIMLQ7unQSCNVsYG255FoqU8cP46DyggI7F7LohzEl8Ag=="],
"@xhmikosr/decompress-tar": ["@xhmikosr/decompress-tar@8.0.1", "", { "dependencies": { "file-type": "^19.0.0", "is-stream": "^2.0.1", "tar-stream": "^3.1.7" } }, "sha512-dpEgs0cQKJ2xpIaGSO0hrzz3Kt8TQHYdizHsgDtLorWajuHJqxzot9Hbi0huRxJuAGG2qiHSQkwyvHHQtlE+fg=="],
"@xhmikosr/decompress-tarbz2": ["@xhmikosr/decompress-tarbz2@8.0.1", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.0.1", "file-type": "^19.0.0", "is-stream": "^2.0.1", "seek-bzip": "^2.0.0", "unbzip2-stream": "^1.4.3" } }, "sha512-OF+6DysDZP5YTDO8uHuGG6fMGZjc+HszFPBkVltjoje2Cf60hjBg/YP5OQndW1hfwVWOdP7f3CnJiPZHJUTtEg=="],
"@xhmikosr/decompress-targz": ["@xhmikosr/decompress-targz@8.0.1", "", { "dependencies": { "@xhmikosr/decompress-tar": "^8.0.1", "file-type": "^19.0.0", "is-stream": "^2.0.1" } }, "sha512-mvy5AIDIZjQ2IagMI/wvauEiSNHhu/g65qpdM4EVoYHUJBAmkQWqcPJa8Xzi1aKVTmOA5xLJeDk7dqSjlHq8Mg=="],
"@xhmikosr/decompress-unzip": ["@xhmikosr/decompress-unzip@7.0.0", "", { "dependencies": { "file-type": "^19.0.0", "get-stream": "^6.0.1", "yauzl": "^3.1.2" } }, "sha512-GQMpzIpWTsNr6UZbISawsGI0hJ4KA/mz5nFq+cEoPs12UybAqZWKbyIaZZyLbJebKl5FkLpsGBkrplJdjvUoSQ=="],
"@xhmikosr/downloader": ["@xhmikosr/downloader@15.0.1", "", { "dependencies": { "@xhmikosr/archive-type": "^7.0.0", "@xhmikosr/decompress": "^10.0.1", "content-disposition": "^0.5.4", "defaults": "^3.0.0", "ext-name": "^5.0.0", "file-type": "^19.0.0", "filenamify": "^6.0.0", "get-stream": "^6.0.1", "got": "^13.0.0" } }, "sha512-fiuFHf3Dt6pkX8HQrVBsK0uXtkgkVlhrZEh8b7VgoDqFf+zrgFBPyrwCqE/3nDwn3hLeNz+BsrS7q3mu13Lp1g=="],
"@xhmikosr/os-filter-obj": ["@xhmikosr/os-filter-obj@3.0.0", "", { "dependencies": { "arch": "^3.0.0" } }, "sha512-siPY6BD5dQ2SZPl3I0OZBHL27ZqZvLEosObsZRQ1NUB8qcxegwt0T9eKtV96JMFQpIz1elhkzqOg4c/Ri6Dp9A=="],
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.10", "", {}, "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw=="],
"ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="],
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"arch": ["arch@3.0.0", "", {}, "sha512-AmIAC+Wtm2AU8lGfTtHsw0Y9Qtftx2YXEEtiBP10xFUtMOA+sHHx6OAddyL52mUKh1vsXQ6/w1mVDptZCyUt4Q=="],
"array-buffer-byte-length": ["array-buffer-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.5", "is-array-buffer": "^3.0.4" } }, "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg=="],
"array.prototype.flat": ["array.prototype.flat@1.3.2", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" } }, "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA=="],
"arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.5", "define-properties": "^1.2.1", "es-abstract": "^1.22.3", "es-errors": "^1.2.1", "get-intrinsic": "^1.2.3", "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" } }, "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A=="],
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
"b4a": ["b4a@1.6.7", "", {}, "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg=="],
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
"bare-events": ["bare-events@2.5.0", "", {}, "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A=="],
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
"big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="],
"bin-version": ["bin-version@6.0.0", "", { "dependencies": { "execa": "^5.0.0", "find-versions": "^5.0.0" } }, "sha512-nk5wEsP4RiKjG+vF+uG8lFsEn4d7Y6FVDamzzftSunXOoOcOOkzcWdKVlGgFFwlUQCj63SgnUkLLGF8v7lufhw=="],
"bin-version-check": ["bin-version-check@5.1.0", "", { "dependencies": { "bin-version": "^6.0.0", "semver": "^7.5.3", "semver-truncate": "^3.0.0" } }, "sha512-bYsvMqJ8yNGILLz1KP9zKLzQ6YpljV3ln1gqhuLkUtyfGi3qXKGuK2p+U4NAvjVFzDFiBBtOpCOSFNuYYEGZ5g=="],
"boxen": ["boxen@5.1.2", "", { "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", "chalk": "^4.1.0", "cli-boxes": "^2.2.1", "string-width": "^4.2.2", "type-fest": "^0.20.2", "widest-line": "^3.1.0", "wrap-ansi": "^7.0.0" } }, "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ=="],
"bplist-parser": ["bplist-parser@0.3.2", "", { "dependencies": { "big-integer": "1.6.x" } }, "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ=="],
"brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
"breakword": ["breakword@1.0.6", "", { "dependencies": { "wcwidth": "^1.0.1" } }, "sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw=="],
"buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
"buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="],
"bufferpack": ["bufferpack@0.0.6", "", {}, "sha512-MTWvLHElqczrIVhge9qHtqgNigJFyh0+tCDId5yCbFAfuekHWIG+uAgvoHVflwrDPuY/e47JE1ki5qcM7w4uLg=="],
"bytebuffer": ["bytebuffer@5.0.1", "", { "dependencies": { "long": "~3" } }, "sha512-IuzSdmADppkZ6DlpycMkm8l9zeEq16fWtLvunEwFiYciR/BHo4E8/xs5piFquG+Za8OWmMqHF8zuRviz2LHvRQ=="],
"cacheable-lookup": ["cacheable-lookup@7.0.0", "", {}, "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w=="],
"cacheable-request": ["cacheable-request@10.2.14", "", { "dependencies": { "@types/http-cache-semantics": "^4.0.2", "get-stream": "^6.0.1", "http-cache-semantics": "^4.1.1", "keyv": "^4.5.3", "mimic-response": "^4.0.0", "normalize-url": "^8.0.0", "responselike": "^3.0.0" } }, "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ=="],
"call-bind": ["call-bind@1.0.7", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.1" } }, "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w=="],
"camelcase": ["camelcase@6.3.0", "", {}, "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="],
"cgbi-to-png": ["cgbi-to-png@1.0.7", "", { "dependencies": { "bufferpack": "0.0.6", "crc": "^3.3.0", "stream-to-buffer": "^0.1.0", "streamifier": "^0.1.1" } }, "sha512-YR80kxTPuq9oRpZUdQmNEQWrmTKLINk1cfLVfyrV7Rfr9KLtLJdcockPKbreIr4JYAq+DhHBR7w+WA/tF5VDaQ=="],
"chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="],
"cli-arguments": ["cli-arguments@0.2.1", "", {}, "sha512-vaoTjiREjxKlpTNMiaJUkQnYRhgui8r+huhB6mMHcGQyz5F7Hd1o1jsW9C/wRKjlNYQ6fTvODLtZe7DxfEIz8g=="],
"cli-boxes": ["cli-boxes@2.2.1", "", {}, "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw=="],
"cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
"cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="],
"cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
"clone": ["clone@1.0.4", "", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="],
"clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
"commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
"compare-versions": ["compare-versions@6.1.1", "", {}, "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg=="],
"config-chain": ["config-chain@1.1.13", "", { "dependencies": { "ini": "^1.3.4", "proto-list": "~1.2.1" } }, "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ=="],
"configstore": ["configstore@5.0.1", "", { "dependencies": { "dot-prop": "^5.2.0", "graceful-fs": "^4.1.2", "make-dir": "^3.0.0", "unique-string": "^2.0.0", "write-file-atomic": "^3.0.0", "xdg-basedir": "^4.0.0" } }, "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA=="],
"content-disposition": ["content-disposition@0.5.4", "", { "dependencies": { "safe-buffer": "5.2.1" } }, "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ=="],
"crc": ["crc@3.8.0", "", { "dependencies": { "buffer": "^5.1.0" } }, "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ=="],
"cross-spawn": ["cross-spawn@7.0.3", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w=="],
"crypto-random-string": ["crypto-random-string@2.0.0", "", {}, "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA=="],
"csv": ["csv@5.5.3", "", { "dependencies": { "csv-generate": "^3.4.3", "csv-parse": "^4.16.3", "csv-stringify": "^5.6.5", "stream-transform": "^2.1.3" } }, "sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g=="],
"csv-generate": ["csv-generate@3.4.3", "", {}, "sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw=="],
"csv-parse": ["csv-parse@4.16.3", "", {}, "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg=="],
"csv-stringify": ["csv-stringify@5.6.5", "", {}, "sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A=="],
"data-view-buffer": ["data-view-buffer@1.0.1", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA=="],
"data-view-byte-length": ["data-view-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ=="],
"data-view-byte-offset": ["data-view-byte-offset@1.0.0", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA=="],
"decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="],
"decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
"deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
"defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="],
"defer-to-connect": ["defer-to-connect@2.0.1", "", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="],
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
"define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
"dot-prop": ["dot-prop@5.3.0", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q=="],
"duplexer3": ["duplexer3@0.1.5", "", {}, "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA=="],
"emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
"end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="],
"es-abstract": ["es-abstract@1.23.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "data-view-buffer": "^1.0.1", "data-view-byte-length": "^1.0.1", "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", "function.prototype.name": "^1.1.6", "get-intrinsic": "^1.2.4", "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2", "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "hasown": "^2.0.2", "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", "is-data-view": "^1.0.1", "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", "object-inspect": "^1.13.1", "object-keys": "^1.1.1", "object.assign": "^4.1.5", "regexp.prototype.flags": "^1.5.2", "safe-array-concat": "^1.1.2", "safe-regex-test": "^1.0.3", "string.prototype.trim": "^1.2.9", "string.prototype.trimend": "^1.0.8", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.2", "typed-array-byte-length": "^1.0.1", "typed-array-byte-offset": "^1.0.2", "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", "which-typed-array": "^1.1.15" } }, "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A=="],
"es-define-property": ["es-define-property@1.0.0", "", { "dependencies": { "get-intrinsic": "^1.2.4" } }, "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ=="],
"es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
"es-object-atoms": ["es-object-atoms@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw=="],
"es-set-tostringtag": ["es-set-tostringtag@2.0.3", "", { "dependencies": { "get-intrinsic": "^1.2.4", "has-tostringtag": "^1.0.2", "hasown": "^2.0.1" } }, "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ=="],
"es-shim-unscopables": ["es-shim-unscopables@1.0.2", "", { "dependencies": { "hasown": "^2.0.0" } }, "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw=="],
"es-to-primitive": ["es-to-primitive@1.2.1", "", { "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", "is-symbol": "^1.0.2" } }, "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA=="],
"escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
"escape-goat": ["escape-goat@2.1.1", "", {}, "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q=="],
"execa": ["execa@5.1.1", "", { "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" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
"ext-list": ["ext-list@2.2.2", "", { "dependencies": { "mime-db": "^1.28.0" } }, "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA=="],
"ext-name": ["ext-name@5.0.0", "", { "dependencies": { "ext-list": "^2.0.0", "sort-keys-length": "^1.0.0" } }, "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ=="],
"fast-fifo": ["fast-fifo@1.3.2", "", {}, "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ=="],
"fast-glob": ["fast-glob@3.3.2", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow=="],
"fastq": ["fastq@1.17.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w=="],
"fd-slicer": ["fd-slicer@1.1.0", "", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="],
"file-type": ["file-type@19.6.0", "", { "dependencies": { "get-stream": "^9.0.1", "strtok3": "^9.0.1", "token-types": "^6.0.0", "uint8array-extras": "^1.3.0" } }, "sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ=="],
"filename-reserved-regex": ["filename-reserved-regex@3.0.0", "", {}, "sha512-hn4cQfU6GOT/7cFHXBqeBg2TbrMBgdD0kcjLhvSQYYwm3s4B6cjvBfb7nBALJLAXqmU5xajSa7X2NnUud/VCdw=="],
"filenamify": ["filenamify@6.0.0", "", { "dependencies": { "filename-reserved-regex": "^3.0.0" } }, "sha512-vqIlNogKeyD3yzrm0yhRMQg8hOVwYcYRfjEoODd49iCprMn4HL85gK3HcykQE53EPIpX3HcAbGA5ELQv216dAQ=="],
"filesize-parser": ["filesize-parser@1.5.1", "", {}, "sha512-wRjdlQ5JM3WHZp6xpakIHQbkcGig8ANglYQDPcQSgZUN5kcDGOgmAwB0396BxzHxcl+kr+GLuusxBnsjdO6x9A=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="],
"find-versions": ["find-versions@5.1.0", "", { "dependencies": { "semver-regex": "^4.0.5" } }, "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg=="],
"for-each": ["for-each@0.3.3", "", { "dependencies": { "is-callable": "^1.1.3" } }, "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw=="],
"form-data": ["form-data@4.0.1", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="],
"form-data-encoder": ["form-data-encoder@2.1.4", "", {}, "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw=="],
"fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
"function.prototype.name": ["function.prototype.name@1.1.6", "", { "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", "es-abstract": "^1.22.1", "functions-have-names": "^1.2.3" } }, "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg=="],
"functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
"get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
"get-east-asian-width": ["get-east-asian-width@1.3.0", "", {}, "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ=="],
"get-intrinsic": ["get-intrinsic@1.2.4", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" } }, "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ=="],
"get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="],
"get-symbol-description": ["get-symbol-description@1.0.2", "", { "dependencies": { "call-bind": "^1.0.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4" } }, "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg=="],
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"global-dirs": ["global-dirs@3.0.1", "", { "dependencies": { "ini": "2.0.0" } }, "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA=="],
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
"gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="],
"got": ["got@13.0.0", "", { "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", "http2-wrapper": "^2.1.10", "lowercase-keys": "^3.0.0", "p-cancelable": "^3.0.0", "responselike": "^3.0.0" } }, "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA=="],
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"gradle-to-js": ["gradle-to-js@2.0.1", "", { "dependencies": { "lodash.merge": "^4.6.2" }, "bin": { "gradle-to-js": "cli.js" } }, "sha512-is3hDn9zb8XXnjbEeAEIqxTpLHUiGBqjegLmXPuyMBfKAggpadWFku4/AP8iYAGBX6qR9/5UIUIp47V0XI3aMw=="],
"grapheme-splitter": ["grapheme-splitter@1.0.4", "", {}, "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ=="],
"has-bigints": ["has-bigints@1.0.2", "", {}, "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ=="],
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
"has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
"has-proto": ["has-proto@1.0.3", "", {}, "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="],
"has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
"has-yarn": ["has-yarn@2.1.0", "", {}, "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw=="],
"hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
"http-cache-semantics": ["http-cache-semantics@4.1.1", "", {}, "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="],
"http2-wrapper": ["http2-wrapper@2.2.1", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" } }, "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ=="],
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
"i18next": ["i18next@24.2.2", "", { "dependencies": { "@babel/runtime": "^7.23.2" }, "peerDependencies": { "typescript": "^5" }, "optionalPeers": ["typescript"] }, "sha512-NE6i86lBCKRYZa5TaUDkU5S4HFgLIEJRLr3Whf2psgaxBleQ2LC1YW1Vc+SCgkAW7VEzndT6al6+CzegSUHcTQ=="],
"ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
"import-lazy": ["import-lazy@2.1.0", "", {}, "sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A=="],
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"ini": ["ini@2.0.0", "", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="],
"inspect-with-kind": ["inspect-with-kind@1.0.5", "", { "dependencies": { "kind-of": "^6.0.2" } }, "sha512-MAQUJuIo7Xqk8EVNP+6d3CKq9c80hi4tjIbIAT6lmGW9W6WzlHiu9PS8uSuUYU+Do+j1baiFp3H25XEVxDIG2g=="],
"internal-slot": ["internal-slot@1.0.7", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.0", "side-channel": "^1.0.4" } }, "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g=="],
"is-array-buffer": ["is-array-buffer@3.0.4", "", { "dependencies": { "call-bind": "^1.0.2", "get-intrinsic": "^1.2.1" } }, "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw=="],
"is-bigint": ["is-bigint@1.0.4", "", { "dependencies": { "has-bigints": "^1.0.1" } }, "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg=="],
"is-boolean-object": ["is-boolean-object@1.1.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA=="],
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
"is-ci": ["is-ci@2.0.0", "", { "dependencies": { "ci-info": "^2.0.0" }, "bin": { "is-ci": "bin.js" } }, "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w=="],
"is-data-view": ["is-data-view@1.0.1", "", { "dependencies": { "is-typed-array": "^1.1.13" } }, "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w=="],
"is-date-object": ["is-date-object@1.0.5", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ=="],
"is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-installed-globally": ["is-installed-globally@0.4.0", "", { "dependencies": { "global-dirs": "^3.0.0", "is-path-inside": "^3.0.2" } }, "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ=="],
"is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
"is-npm": ["is-npm@5.0.0", "", {}, "sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
"is-number-object": ["is-number-object@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ=="],
"is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="],
"is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="],
"is-plain-obj": ["is-plain-obj@1.1.0", "", {}, "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg=="],
"is-regex": ["is-regex@1.1.4", "", { "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" } }, "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg=="],
"is-shared-array-buffer": ["is-shared-array-buffer@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7" } }, "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg=="],
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
"is-string": ["is-string@1.0.7", "", { "dependencies": { "has-tostringtag": "^1.0.0" } }, "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg=="],
"is-symbol": ["is-symbol@1.0.4", "", { "dependencies": { "has-symbols": "^1.0.2" } }, "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg=="],
"is-typed-array": ["is-typed-array@1.1.13", "", { "dependencies": { "which-typed-array": "^1.1.14" } }, "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw=="],
"is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="],
"is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
"is-weakref": ["is-weakref@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2" } }, "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ=="],
"is-yarn-global": ["is-yarn-global@0.3.0", "", {}, "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw=="],
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
"isomorphic-unzip": ["isomorphic-unzip@1.1.5", "", { "dependencies": { "buffer": "^5.0.7", "yauzl": "^2.8.0" } }, "sha512-2McA51lWhmO3Kk438jxVcYeh6L+AOqVnl9XdX1yI7GlLA9RwEyTBgGem1rNuRIU2abAmOiv+IagThdUxASY4IA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
"jsonfile": ["jsonfile@4.0.0", "", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"kind-of": ["kind-of@6.0.3", "", {}, "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw=="],
"kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="],
"latest-version": ["latest-version@5.1.0", "", { "dependencies": { "package-json": "^6.3.0" } }, "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA=="],
"locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="],
"long": ["long@3.2.0", "", {}, "sha512-ZYvPPOMqUwPoDsbJaR10iQJYnMuZhRTvHYl62ErLIEX7RgFlziSBUUvrt3OVfc47QlHHpzPZYP17g3Fv7oeJkg=="],
"lowercase-keys": ["lowercase-keys@3.0.0", "", {}, "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ=="],
"make-dir": ["make-dir@3.1.0", "", { "dependencies": { "semver": "^6.0.0" } }, "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw=="],
"merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="],
"merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
"mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
"mixme": ["mixme@0.5.10", "", {}, "sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q=="],
"mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="],
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
"normalize-url": ["normalize-url@8.0.1", "", {}, "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w=="],
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
"object-inspect": ["object-inspect@1.13.2", "", {}, "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g=="],
"object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
"object.assign": ["object.assign@4.1.5", "", { "dependencies": { "call-bind": "^1.0.5", "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" } }, "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ=="],
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"ora": ["ora@8.1.1", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw=="],
"p-cancelable": ["p-cancelable@3.0.0", "", {}, "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw=="],
"p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="],
"p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="],
"p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="],
"package-json": ["package-json@6.5.0", "", { "dependencies": { "got": "^9.6.0", "registry-auth-token": "^4.0.0", "registry-url": "^5.0.0", "semver": "^6.2.0" } }, "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
"peek-readable": ["peek-readable@5.3.1", "", {}, "sha512-GVlENSDW6KHaXcd9zkZltB7tCLosKB/4Hg0fqBJkAoBgYG2Tn1xtMgXtSUuMU9AK/gCm/tTdT8mgAeF4YNeeqw=="],
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
"picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"piscina": ["piscina@4.7.0", "", { "optionalDependencies": { "@napi-rs/nice": "^1.0.1" } }, "sha512-b8hvkpp9zS0zsfa939b/jXbe64Z2gZv0Ha7FYPNUiDIB1y2AtxcOZdfP8xN8HFjUaqQiT9gRlfjAsoL8vdJ1Iw=="],
"plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="],
"possible-typed-array-names": ["possible-typed-array-names@1.0.0", "", {}, "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q=="],
"prepend-http": ["prepend-http@2.0.0", "", {}, "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA=="],
"progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
"properties": ["properties@1.2.1", "", {}, "sha512-qYNxyMj1JeW54i/EWEFsM1cVwxJbtgPp8+0Wg9XjNaK6VE/c4oRi6PNu5p7w1mNXEIQIjV5Wwn8v8Gz82/QzdQ=="],
"proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="],
"pump": ["pump@3.0.2", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw=="],
"pupa": ["pupa@2.1.1", "", { "dependencies": { "escape-goat": "^2.0.0" } }, "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A=="],
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
"queue-tick": ["queue-tick@1.0.1", "", {}, "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="],
"quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],
"rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
"read": ["read@4.0.0", "", { "dependencies": { "mute-stream": "^2.0.0" } }, "sha512-nbYGT3cec3J5NPUeJia7l72I3oIzMIB6yeNyDqi8CVHr3WftwjrCUqR0j13daoHEMVaZ/rxCpmHKrbods3hI2g=="],
"regenerator-runtime": ["regenerator-runtime@0.14.1", "", {}, "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="],
"regexp.prototype.flags": ["regexp.prototype.flags@1.5.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "set-function-name": "^2.0.2" } }, "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ=="],
"registry-auth-token": ["registry-auth-token@5.0.2", "", { "dependencies": { "@pnpm/npm-conf": "^2.1.0" } }, "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ=="],
"registry-url": ["registry-url@5.1.0", "", { "dependencies": { "rc": "^1.2.8" } }, "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
"require-main-filename": ["require-main-filename@2.0.0", "", {}, "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="],
"resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],
"responselike": ["responselike@3.0.0", "", { "dependencies": { "lowercase-keys": "^3.0.0" } }, "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg=="],
"restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
"reusify": ["reusify@1.0.4", "", {}, "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="],
"run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
"safe-array-concat": ["safe-array-concat@1.1.2", "", { "dependencies": { "call-bind": "^1.0.7", "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" } }, "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q=="],
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
"safe-regex-test": ["safe-regex-test@1.0.3", "", { "dependencies": { "call-bind": "^1.0.6", "es-errors": "^1.3.0", "is-regex": "^1.1.4" } }, "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw=="],
"seek-bzip": ["seek-bzip@2.0.0", "", { "dependencies": { "commander": "^6.0.0" }, "bin": { "seek-bunzip": "bin/seek-bunzip", "seek-table": "bin/seek-bzip-table" } }, "sha512-SMguiTnYrhpLdk3PwfzHeotrcwi8bNV4iemL9tx9poR/yeaMYwB9VzR1w7b57DuWpuqR8n6oZboi0hj3AxZxQg=="],
"semver": ["semver@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
"semver-diff": ["semver-diff@3.1.1", "", { "dependencies": { "semver": "^6.3.0" } }, "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg=="],
"semver-regex": ["semver-regex@4.0.5", "", {}, "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw=="],
"semver-truncate": ["semver-truncate@3.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-LJWA9kSvMolR51oDE6PN3kALBNaUdkxzAGcexw8gjMA8xr5zUqK0JiR3CgARSqanYF3Z1YHvsErb1KDgh+v7Rg=="],
"set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="],
"set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
"set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
"side-channel": ["side-channel@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.4", "object-inspect": "^1.13.1" } }, "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA=="],
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
"smartwrap": ["smartwrap@2.0.2", "", { "dependencies": { "array.prototype.flat": "^1.2.3", "breakword": "^1.0.5", "grapheme-splitter": "^1.0.4", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1", "yargs": "^15.1.0" }, "bin": { "smartwrap": "src/terminal-adapter.js" } }, "sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA=="],
"sort-keys": ["sort-keys@1.1.2", "", { "dependencies": { "is-plain-obj": "^1.0.0" } }, "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg=="],
"sort-keys-length": ["sort-keys-length@1.0.1", "", { "dependencies": { "sort-keys": "^1.0.0" } }, "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw=="],
"source-map": ["source-map@0.7.4", "", {}, "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA=="],
"stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="],
"stream-to": ["stream-to@0.2.2", "", {}, "sha512-Kg1BSDTwgGiVMtTCJNlo7kk/xzL33ZuZveEBRt6rXw+f1WLK/8kmz2NVCT/Qnv0JkV85JOHcLhD82mnXsR3kPw=="],
"stream-to-buffer": ["stream-to-buffer@0.1.0", "", { "dependencies": { "stream-to": "~0.2.0" } }, "sha512-Da4WoKaZyu3nf+bIdIifh7IPkFjARBnBK+pYqn0EUJqksjV9afojjaCCHUemH30Jmu7T2qcKvlZm2ykN38uzaw=="],
"stream-transform": ["stream-transform@2.1.3", "", { "dependencies": { "mixme": "^0.5.1" } }, "sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ=="],
"streamifier": ["streamifier@0.1.1", "", {}, "sha512-zDgl+muIlWzXNsXeyUfOk9dChMjlpkq0DRsxujtYPgyJ676yQ8jEm6zzaaWHFDg5BNcLuif0eD2MTyJdZqXpdg=="],
"streamx": ["streamx@2.20.2", "", { "dependencies": { "fast-fifo": "^1.3.2", "queue-tick": "^1.0.1", "text-decoder": "^1.1.0" }, "optionalDependencies": { "bare-events": "^2.2.0" } }, "sha512-aDGDLU+j9tJcUdPGOaHmVF1u/hhI+CsGkT02V3OKlHDV7IukOI+nTWAGkiZEKCO35rWN1wIr4tS7YFr1f4qSvA=="],
"string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
"string.prototype.trim": ["string.prototype.trim@1.2.9", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.0", "es-object-atoms": "^1.0.0" } }, "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw=="],
"string.prototype.trimend": ["string.prototype.trimend@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ=="],
"string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
"strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-dirs": ["strip-dirs@3.0.0", "", { "dependencies": { "inspect-with-kind": "^1.0.5", "is-plain-obj": "^1.1.0" } }, "sha512-I0sdgcFTfKQlUPZyAqPJmSG3HLO9rWDFnxonnIbskYNM3DwFOeTNB5KzVq3dA1GdRAc/25b5Y7UO2TQfKWw4aQ=="],
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
"strtok3": ["strtok3@9.0.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^5.3.1" } }, "sha512-ERPW+XkvX9W2A+ov07iy+ZFJpVdik04GhDA4eVogiG9hpC97Kem2iucyzhFxbFRvQ5o2UckFtKZdp1hkGvnrEw=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
"tar-stream": ["tar-stream@3.1.7", "", { "dependencies": { "b4a": "^1.6.4", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ=="],
"tcp-ping": ["tcp-ping@0.1.1", "", {}, "sha512-7Ed10Ds0hYnF+O1lfiZ2iSZ1bCAj+96Madctebmq7Y1ALPWlBY4YI8C6pCL+UTlshFY5YogixKLpgDP/4BlHrw=="],
"text-decoder": ["text-decoder@1.2.1", "", {}, "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ=="],
"through": ["through@2.3.8", "", {}, "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg=="],
"to-readable-stream": ["to-readable-stream@1.0.0", "", {}, "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q=="],
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
"token-types": ["token-types@6.0.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-lbDrTLVsHhOMljPscd0yitpozq7Ga2M5Cvez5AjGg8GASBjtt6iERCAJ93yommPmz62fb45oFIXHEZ3u9bfJEA=="],
"tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
"tty-table": ["tty-table@4.2.3", "", { "dependencies": { "chalk": "^4.1.2", "csv": "^5.5.3", "kleur": "^4.1.5", "smartwrap": "^2.0.2", "strip-ansi": "^6.0.1", "wcwidth": "^1.0.1", "yargs": "^17.7.1" }, "bin": { "tty-table": "adapters/terminal-adapter.js" } }, "sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA=="],
"type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="],
"typed-array-buffer": ["typed-array-buffer@1.0.2", "", { "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", "is-typed-array": "^1.1.13" } }, "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ=="],
"typed-array-byte-length": ["typed-array-byte-length@1.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13" } }, "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw=="],
"typed-array-byte-offset": ["typed-array-byte-offset@1.0.2", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13" } }, "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA=="],
"typed-array-length": ["typed-array-length@1.0.6", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0" } }, "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g=="],
"typedarray-to-buffer": ["typedarray-to-buffer@3.1.5", "", { "dependencies": { "is-typedarray": "^1.0.0" } }, "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q=="],
"typescript": ["typescript@5.7.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg=="],
"uint8array-extras": ["uint8array-extras@1.4.0", "", {}, "sha512-ZPtzy0hu4cZjv3z5NW9gfKnNLjoz4y6uv4HlelAjDK7sY/xOkKZv9xK/WQpcsBB3jEybChz9DPC2U/+cusjJVQ=="],
"unbox-primitive": ["unbox-primitive@1.0.2", "", { "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", "has-symbols": "^1.0.3", "which-boxed-primitive": "^1.0.2" } }, "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw=="],
"unbzip2-stream": ["unbzip2-stream@1.4.3", "", { "dependencies": { "buffer": "^5.2.1", "through": "^2.3.8" } }, "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg=="],
"undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
"unique-string": ["unique-string@2.0.0", "", { "dependencies": { "crypto-random-string": "^2.0.0" } }, "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg=="],
"universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
"update-notifier": ["update-notifier@5.1.0", "", { "dependencies": { "boxen": "^5.0.0", "chalk": "^4.1.0", "configstore": "^5.0.1", "has-yarn": "^2.1.0", "import-lazy": "^2.1.0", "is-ci": "^2.0.0", "is-installed-globally": "^0.4.0", "is-npm": "^5.0.0", "is-yarn-global": "^0.3.0", "latest-version": "^5.1.0", "pupa": "^2.1.1", "semver": "^7.3.4", "semver-diff": "^3.1.1", "xdg-basedir": "^4.0.0" } }, "sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw=="],
"url-parse-lax": ["url-parse-lax@3.0.0", "", { "dependencies": { "prepend-http": "^2.0.0" } }, "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ=="],
"wcwidth": ["wcwidth@1.0.1", "", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="],
"webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="],
"whatwg-url": ["whatwg-url@5.0.0", "", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="],
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
"which-boxed-primitive": ["which-boxed-primitive@1.0.2", "", { "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" } }, "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg=="],
"which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="],
"which-typed-array": ["which-typed-array@1.1.15", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "has-tostringtag": "^1.0.2" } }, "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA=="],
"widest-line": ["widest-line@3.1.0", "", { "dependencies": { "string-width": "^4.0.0" } }, "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg=="],
"wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
"write-file-atomic": ["write-file-atomic@3.0.3", "", { "dependencies": { "imurmurhash": "^0.1.4", "is-typedarray": "^1.0.0", "signal-exit": "^3.0.2", "typedarray-to-buffer": "^3.1.5" } }, "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q=="],
"xdg-basedir": ["xdg-basedir@4.0.0", "", {}, "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q=="],
"xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="],
"y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
"yargs": ["yargs@17.7.2", "", { "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" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
"yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
"yauzl": ["yauzl@3.2.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "pend": "~1.2.0" } }, "sha512-Ow9nuGZE+qp1u4JIPvg+uCiUr7xGQWdff7JQSk5VGYTAZMDe2q8lxJ10ygv10qmSj031Ty/6FNJpLO4o1Sgc+w=="],
"yazl": ["yazl@3.3.1", "", { "dependencies": { "buffer-crc32": "^1.0.0" } }, "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng=="],
"@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
"@swc/cli/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
"@xhmikosr/decompress/make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="],
"@xhmikosr/downloader/defaults": ["defaults@3.0.0", "", {}, "sha512-RsqXDEAALjfRTro+IFNKpcPCt0/Cy2FqHSIlnomiJp9YGadpQnrtbRpSgN2+np21qHcIKiva4fiOQGjS9/qR/A=="],
"ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"boxen/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"cacheable-request/mimic-response": ["mimic-response@4.0.0", "", {}, "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg=="],
"cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"config-chain/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"decompress-response/mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
"file-type/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
"isomorphic-unzip/yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
"log-symbols/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
"log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="],
"make-dir/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"ora/chalk": ["chalk@5.3.0", "", {}, "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="],
"ora/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"package-json/got": ["got@9.6.0", "", { "dependencies": { "@sindresorhus/is": "^0.14.0", "@szmarczak/http-timer": "^1.1.2", "cacheable-request": "^6.0.0", "decompress-response": "^3.3.0", "duplexer3": "^0.1.4", "get-stream": "^4.1.0", "lowercase-keys": "^1.0.1", "mimic-response": "^1.0.1", "p-cancelable": "^1.0.0", "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" } }, "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q=="],
"package-json/registry-auth-token": ["registry-auth-token@4.2.2", "", { "dependencies": { "rc": "1.2.8" } }, "sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg=="],
"package-json/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
"restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
"restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
"seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="],
"semver-diff/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"smartwrap/yargs": ["yargs@15.4.1", "", { "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" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="],
"string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"widest-line/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"wrap-ansi/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"yazl/buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="],
"ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"boxen/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"file-type/get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
"ora/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"package-json/got/@sindresorhus/is": ["@sindresorhus/is@0.14.0", "", {}, "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ=="],
"package-json/got/@szmarczak/http-timer": ["@szmarczak/http-timer@1.1.2", "", { "dependencies": { "defer-to-connect": "^1.0.1" } }, "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA=="],
"package-json/got/cacheable-request": ["cacheable-request@6.1.0", "", { "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^3.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^4.1.0", "responselike": "^1.0.2" } }, "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg=="],
"package-json/got/decompress-response": ["decompress-response@3.3.0", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA=="],
"package-json/got/get-stream": ["get-stream@4.1.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="],
"package-json/got/lowercase-keys": ["lowercase-keys@1.0.1", "", {}, "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="],
"package-json/got/p-cancelable": ["p-cancelable@1.1.0", "", {}, "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw=="],
"smartwrap/yargs/cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="],
"smartwrap/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"smartwrap/yargs/y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="],
"smartwrap/yargs/yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="],
"string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"widest-line/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"package-json/got/@szmarczak/http-timer/defer-to-connect": ["defer-to-connect@1.1.3", "", {}, "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="],
"package-json/got/cacheable-request/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"package-json/got/cacheable-request/keyv": ["keyv@3.1.0", "", { "dependencies": { "json-buffer": "3.0.0" } }, "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA=="],
"package-json/got/cacheable-request/lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],
"package-json/got/cacheable-request/normalize-url": ["normalize-url@4.5.1", "", {}, "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA=="],
"package-json/got/cacheable-request/responselike": ["responselike@1.0.2", "", { "dependencies": { "lowercase-keys": "^1.0.0" } }, "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ=="],
"smartwrap/yargs/cliui/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="],
"smartwrap/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"smartwrap/yargs/yargs-parser/camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="],
"package-json/got/cacheable-request/keyv/json-buffer": ["json-buffer@3.0.0", "", {}, "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ=="],
"package-json/got/cacheable-request/responselike/lowercase-keys": ["lowercase-keys@1.0.1", "", {}, "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA=="],
}
}

115
cli.json
View File

@@ -3,11 +3,9 @@
"defaultCommand": "help",
"commands": {
"help": {},
"login": {},
"logout": {},
"me": {},
"createApp": {
"options": {
"name": {
@@ -33,9 +31,10 @@
}
}
},
"uploadIpa": {},
"uploadApk": {},
"uploadApp": {},
"parseApp": {},
"parseIpa": {},
"parseApk": {},
"packages": {
@@ -45,7 +44,6 @@
}
}
},
"publish": {
"options": {
"platform": {
@@ -69,7 +67,6 @@
}
}
},
"update": {
"options": {
"platform": {
@@ -80,10 +77,43 @@
},
"packageId": {
"hasValue": true
},
"packageVersion": {
"hasValue": true
},
"minPackageVersion": {
"hasValue": true
},
"maxPackageVersion": {
"hasValue": true
},
"rollout": {
"hasValue": true
}
}
},
"updateVersionInfo": {
"options": {
"platform": {
"hasValue": true
},
"versionId": {
"hasValue": true
},
"name": {
"default": false,
"hasValue": true
},
"description": {
"default": false,
"hasValue": true
},
"metaInfo": {
"default": false,
"hasValue": true
}
}
},
"build": {
"description": "Bundle javascript and copy assets."
},
@@ -106,14 +136,28 @@
"hasValue": true
},
"intermediaDir": {
"default": "build/intermedia/${platform}",
"default": ".pushy/intermedia/${platform}",
"hasValue": true
},
"output": {
"default": "build/output/${platform}.${time}.ppk",
"default": ".pushy/output/${platform}.${time}.ppk",
"hasValue": true
},
"verbose": {}
"sourcemap": {
"default": false
},
"taro": {
"default": false
},
"expo": {
"default": false
},
"rncli": {
"default": false
},
"disableHermes": {
"default": false
}
}
},
"release": {
@@ -123,7 +167,7 @@
"description": "Create diff patch",
"options": {
"output": {
"default": "build/output/diff",
"default": ".pushy/output/diff",
"hasValue": true
}
}
@@ -132,7 +176,7 @@
"description": "Create diff patch from a Android package(.apk)",
"options": {
"output": {
"default": "build/output/diff-${time}.apk-patch",
"default": ".pushy/output/diff-${time}.apk-patch",
"hasValue": true
}
}
@@ -141,7 +185,52 @@
"description": "Create diff patch from a iOS package(.ipa)",
"options": {
"output": {
"default": "build/output/diff-${time}.ipa-patch",
"default": ".pushy/output/diff-${time}.ipa-patch",
"hasValue": true
}
}
},
"hdiff": {
"description": "Create hdiff patch",
"options": {
"output": {
"default": ".pushy/output/hdiff",
"hasValue": true
}
}
},
"hdiffFromApk": {
"description": "Create hdiff patch from a Android package(.apk)",
"options": {
"output": {
"default": ".pushy/output/hdiff-${time}.apk-patch",
"hasValue": true
}
}
},
"hdiffFromPPK": {
"description": "Create hdiff patch from a Prepare package(.ppk)",
"options": {
"output": {
"default": ".pushy/output/hdiff-${time}.ppk-patch",
"hasValue": true
}
}
},
"hdiffFromApp": {
"description": "Create hdiff patch from a Harmony package(.app)",
"options": {
"output": {
"default": ".pushy/output/hdiff-${time}.app-patch",
"hasValue": true
}
}
},
"hdiffFromIpa": {
"description": "Create hdiff patch from a iOS package(.ipa)",
"options": {
"output": {
"default": ".pushy/output/hdiff-${time}.ipa-patch",
"hasValue": true
}
}
@@ -152,4 +241,4 @@
"default": false
}
}
}
}

View File

@@ -1,4 +1 @@
/**
* Created by tdzl2003 on 2/22/16.
*/
module.exports = require('./lib');
module.exports = require('./lib');

View File

@@ -1,10 +1,11 @@
{
"name": "react-native-update-cli",
"version": "1.1.17",
"version": "1.40.1",
"description": "Command tools for javaScript updater with `pushy` service for react native apps.",
"main": "index.js",
"bin": {
"pushy": "lib/index.js"
"pushy": "lib/index.js",
"cresc": "lib/index.js"
},
"files": [
"lib",
@@ -12,8 +13,9 @@
"cli.json"
],
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "babel src --out-dir lib"
"build": "swc src -d lib --strip-leading-paths",
"prepare": "npm run build && chmod +x lib/index.js",
"lint": "tsc --noEmit & biome check --write ."
},
"repository": {
"type": "git",
@@ -23,6 +25,7 @@
"react-native",
"ios",
"android",
"harmony",
"update"
],
"author": "reactnativecn",
@@ -32,29 +35,40 @@
},
"homepage": "https://github.com/reactnativecn/react-native-pushy/tree/master/react-native-pushy-cli",
"dependencies": {
"app-info-parser": "^0.3.9",
"@badisi/latest-version": "^7.0.10",
"bplist-parser": "^0.3.2",
"bytebuffer": "^5.0.1",
"cgbi-to-png": "^1.0.7",
"chalk": "4",
"cli-arguments": "^0.2.1",
"filesize-parser": "^1.5.0",
"commander": "^12.1.0",
"compare-versions": "^6.1.1",
"filesize-parser": "^1.5.1",
"form-data": "^4.0.1",
"fs-extra": "8",
"gradle-to-js": "^2.0.0",
"node-fetch": "^2.6.0",
"gradle-to-js": "^2.0.1",
"i18next": "^24.2.2",
"isomorphic-unzip": "^1.1.5",
"node-fetch": "^2.6.1",
"plist": "^3.1.0",
"progress": "^2.0.3",
"read": "^1.0.7",
"request": "^2.88.2",
"properties": "^1.2.1",
"read": "^4.0.0",
"semver": "^7.6.3",
"tcp-ping": "^0.1.1",
"tty-table": "4.1",
"update-notifier": "^4.1.0",
"yauzl": "^2.10.0",
"yazl": "2.5.1"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-syntax-object-rest-spread": "^6.13.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.2",
"babel-plugin-transform-es2015-spread": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0"
"tty-table": "4.2",
"update-notifier": "^5.1.0",
"yauzl": "^3.2.0",
"yazl": "3.3.1"
},
"engines": {
"node": ">= 8"
"node": ">= 10"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "^0.5.1",
"@swc/core": "^1.9.3",
"@types/node": "^22.9.3",
"typescript": "^5.7.2"
}
}

View File

@@ -1,173 +0,0 @@
/**
* Created by tdzl2003 on 2/13/16.
*/
const fetch = require('node-fetch');
let host = process.env.PUSHY_REGISTRY || 'https://update.reactnative.cn/api';
const fs = require('fs');
import request from 'request';
import ProgressBar from 'progress';
const packageJson = require('../package.json');
const tcpp = require('tcp-ping');
const util = require('util');
const path = require('path');
import filesizeParser from 'filesize-parser';
import { pricingPageUrl } from './utils';
const tcpPing = util.promisify(tcpp.ping);
let session = undefined;
let savedSession = undefined;
const userAgent = `react-native-update-cli/${packageJson.version}`;
exports.loadSession = async function() {
if (fs.existsSync('.update')) {
try {
exports.replaceSession(JSON.parse(fs.readFileSync('.update', 'utf8')));
savedSession = session;
} catch (e) {
console.error(
'Failed to parse file `.update`. Try to remove it manually.',
);
throw e;
}
}
};
exports.getSession = function() {
return session;
};
exports.replaceSession = function(newSession) {
session = newSession;
};
exports.saveSession = function() {
// Only save on change.
if (session !== savedSession) {
const current = session;
const data = JSON.stringify(current, null, 4);
fs.writeFileSync('.update', data, 'utf8');
savedSession = current;
}
};
exports.closeSession = function() {
if (fs.existsSync('.update')) {
fs.unlinkSync('.update');
savedSession = undefined;
}
session = undefined;
host = process.env.PUSHY_REGISTRY || 'https://update.reactnative.cn/api';
};
async function query(url, options) {
const resp = await fetch(url, options);
const json = await resp.json();
if (resp.status !== 200) {
throw Object.assign(new Error(json.message || json.error), {
status: resp.status,
});
}
return json;
}
function queryWithoutBody(method) {
return function(api) {
return query(host + api, {
method,
headers: {
'User-Agent': userAgent,
'X-AccessToken': session ? session.token : '',
},
});
};
}
function queryWithBody(method) {
return function(api, body) {
return query(host + api, {
method,
headers: {
'User-Agent': userAgent,
'Content-Type': 'application/json',
'X-AccessToken': session ? session.token : '',
},
body: JSON.stringify(body),
});
};
}
exports.get = queryWithoutBody('GET');
exports.post = queryWithBody('POST');
exports.put = queryWithBody('PUT');
exports.doDelete = queryWithBody('DELETE');
async function uploadFile(fn, key) {
const { url, backupUrl, formData, maxSize } = await exports.post('/upload', {
ext: path.extname(fn)
});
let realUrl = url;
if (backupUrl) {
const pingResult = await tcpPing({
address: url.replace('https://', ''),
attempts: 4,
timeout: 1000,
});
// console.log({pingResult});
if (isNaN(pingResult.avg) || pingResult.avg > 150) {
realUrl = backupUrl;
}
// console.log({realUrl});
}
const fileSize = fs.statSync(fn).size;
if (maxSize && fileSize > filesizeParser(maxSize)) {
throw new Error(`此文件大小超出上限${maxSize}。您可以考虑升级付费业务以提升此限制。详情请访问:${pricingPageUrl}`)
}
const bar = new ProgressBar(' Uploading [:bar] :percent :etas', {
complete: '=',
incomplete: ' ',
total: fileSize,
});
const info = await new Promise((resolve, reject) => {
if (key) {
formData.key = key;
}
formData.file = fs.createReadStream(fn);
formData.file.on('data', function(data) {
bar.tick(data.length);
});
request.post(
realUrl,
{
formData,
},
(err, resp, body) => {
if (err) {
return reject(err);
}
if (resp.statusCode > 299) {
return reject(
Object.assign(new Error(body), { status: resp.statusCode }),
);
}
resolve(
body
? // qiniu
JSON.parse(body)
: // aliyun oss
{ hash: formData.key },
);
},
);
});
return info;
}
exports.uploadFile = uploadFile;

172
src/api.ts Normal file
View File

@@ -0,0 +1,172 @@
import fetch from 'node-fetch';
import fs from 'node:fs';
import util from 'node:util';
import path from 'node:path';
import ProgressBar from 'progress';
import packageJson from '../package.json';
import tcpp from 'tcp-ping';
import filesizeParser from 'filesize-parser';
import { pricingPageUrl } from './utils';
import type { Session } from 'types';
import FormData from 'form-data';
const tcpPing = util.promisify(tcpp.ping);
let session: Session | undefined;
let savedSession: Session | undefined;
const defaultEndpoint = 'https://update.reactnative.cn/api';
let host = process.env.PUSHY_REGISTRY || defaultEndpoint;
const userAgent = `react-native-update-cli/${packageJson.version}`;
export const getSession = () => session;
export const replaceSession = (newSession: { token: string }) => {
session = newSession;
};
export const loadSession = async () => {
if (fs.existsSync('.update')) {
try {
replaceSession(JSON.parse(fs.readFileSync('.update', 'utf8')));
savedSession = session;
} catch (e) {
console.error(
'Failed to parse file `.update`. Try to remove it manually.',
);
throw e;
}
}
};
export const saveSession = () => {
// Only save on change.
if (session !== savedSession) {
const current = session;
const data = JSON.stringify(current, null, 4);
fs.writeFileSync('.update', data, 'utf8');
savedSession = current;
}
};
export const closeSession = () => {
if (fs.existsSync('.update')) {
fs.unlinkSync('.update');
savedSession = undefined;
}
session = undefined;
host = process.env.PUSHY_REGISTRY || defaultEndpoint;
};
async function query(url: string, options: fetch.RequestInit) {
const resp = await fetch(url, options);
const text = await resp.text();
let json: any;
try {
json = JSON.parse(text);
} catch (e) {}
if (resp.status !== 200) {
const message = json?.message || resp.statusText;
if (resp.status === 401) {
throw new Error('登录信息已过期,请使用 pushy login 命令重新登录');
}
throw new Error(message);
}
return json;
}
function queryWithoutBody(method: string) {
return (api: string) =>
query(host + api, {
method,
headers: {
'User-Agent': userAgent,
'X-AccessToken': session ? session.token : '',
},
});
}
function queryWithBody(method: string) {
return (api: string, body: Record<string, any>) =>
query(host + api, {
method,
headers: {
'User-Agent': userAgent,
'Content-Type': 'application/json',
'X-AccessToken': session ? session.token : '',
},
body: JSON.stringify(body),
});
}
export const get = queryWithoutBody('GET');
export const post = queryWithBody('POST');
export const put = queryWithBody('PUT');
export const doDelete = queryWithBody('DELETE');
export async function uploadFile(fn: string, key?: string) {
const { url, backupUrl, formData, maxSize } = await post('/upload', {
ext: path.extname(fn),
});
let realUrl = url;
if (backupUrl) {
if (global.USE_ACC_OSS) {
realUrl = backupUrl;
} else {
const pingResult = await tcpPing({
address: url.replace('https://', ''),
attempts: 4,
timeout: 1000,
});
// console.log({pingResult});
if (Number.isNaN(pingResult.avg) || pingResult.avg > 150) {
realUrl = backupUrl;
}
}
// console.log({realUrl});
}
const fileSize = fs.statSync(fn).size;
if (maxSize && fileSize > filesizeParser(maxSize)) {
throw new Error(
`此文件大小 ${(fileSize / 1048576).toFixed(
1,
)}m , 超出当前额度 ${maxSize} 。您可以考虑升级付费业务以提升此额度。详情请访问: ${pricingPageUrl}`,
);
}
const bar = new ProgressBar(' 上传中 [:bar] :percent :etas', {
complete: '=',
incomplete: ' ',
total: fileSize,
});
const form = new FormData();
Object.entries(formData).forEach(([k, v]) => {
form.append(k, v);
});
const fileStream = fs.createReadStream(fn);
fileStream.on('data', (data) => {
bar.tick(data.length);
});
if (key) {
form.append('key', key);
}
form.append('file', fileStream);
const res = await fetch(realUrl, {
method: 'POST',
body: form,
});
if (res.status > 299) {
throw new Error(`${res.status}: ${res.statusText}`);
}
// const body = await response.json();
return { hash: key || formData.key };
}

View File

@@ -1,110 +0,0 @@
/**
* Created by tdzl2003 on 2/13/16.
*/
import {question} from './utils';
import fs from 'fs';
const {
post,
get,
doDelete,
} = require('./api');
const validPlatforms = {
ios: 1,
android: 1,
};
export function checkPlatform(platform) {
if (!validPlatforms[platform]) {
throw new Error(`Invalid platform '${platform}'`);
}
return platform
}
export function getSelectedApp(platform) {
checkPlatform(platform);
if (!fs.existsSync('update.json')){
throw new Error(`App not selected. run 'pushy selectApp --platform ${platform}' first!`);
}
const updateInfo = JSON.parse(fs.readFileSync('update.json', 'utf8'));
if (!updateInfo[platform]) {
throw new Error(`App not selected. run 'pushy selectApp --platform ${platform}' first!`);
}
return updateInfo[platform];
}
export async function listApp(platform){
const {data} = await get('/app/list');
const list = platform?data.filter(v=>v.platform===platform):data;
for (const app of list) {
console.log(`${app.id}) ${app.name}(${app.platform})`);
}
if (platform) {
console.log(`\nTotal ${list.length} ${platform} apps`);
} else {
console.log(`\nTotal ${list.length} apps`);
}
return list;
}
export async function chooseApp(platform) {
const list = await listApp(platform);
while (true) {
const id = await question('Enter appId:');
const app = list.find(v=>v.id === (id|0));
if (app) {
return app;
}
}
}
export const commands = {
createApp: async function ({options}) {
const name = options.name || await question('App Name:');
const {downloadUrl} = options;
const platform = checkPlatform(options.platform || await question('Platform(ios/android):'));
const {id} = await post('/app/create', {name, platform});
console.log(`Created app ${id}`);
await this.selectApp({
args: [id],
options: {platform, downloadUrl},
});
},
deleteApp: async function ({args, options}) {
const {platform} = options;
const id = args[0] || chooseApp(platform);
if (!id) {
console.log('Canceled');
}
await doDelete(`/app/${id}`);
console.log('Ok.');
},
apps: async function ({options}){
const {platform} = options;
listApp(platform);
},
selectApp: async function({args, options}) {
const platform = checkPlatform(options.platform || await question('Platform(ios/android):'));
const id = args[0] || (await chooseApp(platform)).id;
let updateInfo = {};
if (fs.existsSync('update.json')) {
try {
updateInfo = JSON.parse(fs.readFileSync('update.json', 'utf8'));
} catch (e) {
console.error('Failed to parse file `update.json`. Try to remove it manually.');
throw e;
}
}
const {appKey} = await get(`/app/${id}`);
updateInfo[platform] = {
appId: id,
appKey,
};
fs.writeFileSync('update.json', JSON.stringify(updateInfo, null, 4), 'utf8');
},
}

131
src/app.ts Normal file
View File

@@ -0,0 +1,131 @@
import { question } from './utils';
import fs from 'node:fs';
import Table from 'tty-table';
import { post, get, doDelete } from './api';
import type { Platform } from './types';
const validPlatforms = {
ios: 1,
android: 1,
harmony: 1,
};
export function checkPlatform(platform: Platform) {
if (!validPlatforms[platform]) {
throw new Error(`无法识别的平台 '${platform}'`);
}
return platform;
}
export function getSelectedApp(platform: Platform) {
checkPlatform(platform);
if (!fs.existsSync('update.json')) {
throw new Error(
`App not selected. run 'pushy selectApp --platform ${platform}' first!`,
);
}
const updateInfo = JSON.parse(fs.readFileSync('update.json', 'utf8'));
if (!updateInfo[platform]) {
throw new Error(
`App not selected. run 'pushy selectApp --platform ${platform}' first!`,
);
}
return updateInfo[platform];
}
export async function listApp(platform: Platform) {
const { data } = await get('/app/list');
const list = platform ? data.filter((v) => v.platform === platform) : data;
const header = [
{ value: '应用 id' },
{ value: '应用名称' },
{ value: '平台' },
];
const rows = [];
for (const app of list) {
rows.push([app.id, app.name, app.platform]);
}
console.log(Table(header, rows).render());
if (platform) {
console.log(`\${list.length} ${platform} 个应用`);
} else {
console.log(`\${list.length} 个应用`);
}
return list;
}
export async function chooseApp(platform: Platform) {
const list = await listApp(platform);
while (true) {
const id = await question('输入应用 id:');
const app = list.find((v) => v.id === Number(id));
if (app) {
return app;
}
}
}
export const commands = {
createApp: async function ({ options }) {
const name = options.name || (await question('应用名称:'));
const { downloadUrl } = options;
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { id } = await post('/app/create', { name, platform });
console.log(`已成功创建应用id: ${id}`);
await this.selectApp({
args: [id],
options: { platform, downloadUrl },
});
},
deleteApp: async ({ args, options }) => {
const { platform } = options;
const id = args[0] || chooseApp(platform);
if (!id) {
console.log('已取消');
}
await doDelete(`/app/${id}`);
console.log('操作成功');
},
apps: async ({ options }) => {
const { platform } = options;
listApp(platform);
},
selectApp: async ({ args, options }) => {
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const id = args[0]
? Number.parseInt(args[0])
: (await chooseApp(platform)).id;
let updateInfo = {};
if (fs.existsSync('update.json')) {
try {
updateInfo = JSON.parse(fs.readFileSync('update.json', 'utf8'));
} catch (e) {
console.error(
'Failed to parse file `update.json`. Try to remove it manually.',
);
throw e;
}
}
const { appKey } = await get(`/app/${id}`);
updateInfo[platform] = {
appId: id,
appKey,
};
fs.writeFileSync(
'update.json',
JSON.stringify(updateInfo, null, 4),
'utf8',
);
},
};

View File

@@ -1,575 +0,0 @@
/**
* Created by tdzl2003 on 2/22/16.
*/
const path = require('path');
import { getRNVersion, translateOptions } from './utils';
import * as fs from 'fs-extra';
import { ZipFile } from 'yazl';
import { open as openZipFile } from 'yauzl';
import { question, printVersionCommand } from './utils';
import { checkPlatform } from './app';
const { spawn, spawnSync } = require('child_process');
const g2js = require('gradle-to-js/lib/parser');
const os = require('os');
var diff;
try {
var bsdiff = require('node-bsdiff');
diff = typeof bsdiff != 'function' ? bsdiff.diff : bsdiff;
} catch (e) {
diff = function () {
console.warn(
'This function needs "node-bsdiff". Please run "npm i node-bsdiff" from your project directory first!',
);
throw new Error(
'This function needs module "node-bsdiff". Please install it first.',
);
};
}
async function runReactNativeBundleCommand(
bundleName,
development,
entryFile,
outputFolder,
platform,
sourcemapOutput,
config,
) {
let reactNativeBundleArgs = [];
let envArgs = process.env.PUSHY_ENV_ARGS;
if (envArgs) {
Array.prototype.push.apply(
reactNativeBundleArgs,
envArgs.trim().split(/\s+/),
);
}
fs.emptyDirSync(outputFolder);
Array.prototype.push.apply(reactNativeBundleArgs, [
path.join('node_modules', 'react-native', 'local-cli', 'cli.js'),
'bundle',
'--assets-dest',
outputFolder,
'--bundle-output',
path.join(outputFolder, bundleName),
'--dev',
development,
'--entry-file',
entryFile,
'--platform',
platform,
'--reset-cache',
]);
if (sourcemapOutput) {
reactNativeBundleArgs.push('--sourcemap-output', sourcemapOutput);
}
if (config) {
reactNativeBundleArgs.push('--config', config);
}
const reactNativeBundleProcess = spawn('node', reactNativeBundleArgs);
console.log(
`Running bundle command: node ${reactNativeBundleArgs.join(' ')}`,
);
return new Promise((resolve, reject) => {
reactNativeBundleProcess.stdout.on('data', (data) => {
console.log(data.toString().trim());
});
reactNativeBundleProcess.stderr.on('data', (data) => {
console.error(data.toString().trim());
});
reactNativeBundleProcess.on('close', async (exitCode) => {
if (exitCode) {
reject(
new Error(
`"react-native bundle" command exited with code ${exitCode}.`,
),
);
} else {
if (platform === 'android') {
await compileHermesByteCode(bundleName, outputFolder);
}
resolve(null);
}
});
});
}
function getHermesOSBin() {
if (os.platform() === 'win32') return 'win64-bin';
if (os.platform() === 'darwin') return 'osx-bin';
if (os.platform() === 'linux') return 'linux64-bin';
}
async function compileHermesByteCode(bundleName, outputFolder) {
let enableHermes = false;
try {
const gradleConfig = await g2js.parseFile('android/app/build.gradle');
const projectConfig = gradleConfig['project.ext.react'];
for (const packagerConfig of projectConfig) {
if (
packagerConfig.includes('enableHermes') &&
packagerConfig.includes('true')
) {
enableHermes = true;
break;
}
}
} catch (e) {}
if (enableHermes) {
console.log(`Hermes enabled, now compiling to hermes bytecode:\n`);
const hermesPackage = fs.existsSync('node_modules/hermes-engine')
? 'node_modules/hermes-engine' // 0.2+
: 'node_modules/hermesvm'; // < 0.2
const hermesPath = `${hermesPackage}/${getHermesOSBin()}`;
const hermesCommand = fs.existsSync(`${hermesPath}/hermesc`)
? `${hermesPath}/hermesc` // 0.5+
: `${hermesPath}/hermes`; // < 0.5
spawnSync(
path.join.apply(null, hermesCommand.split('/')),
[
'-emit-binary',
'-out',
path.join(outputFolder, bundleName),
path.join(outputFolder, bundleName),
'-O',
],
{ stdio: 'ignore' },
);
}
}
async function pack(dir, output) {
console.log('Packing');
fs.ensureDirSync(path.dirname(output));
await new Promise((resolve, reject) => {
var zipfile = new ZipFile();
function addDirectory(root, rel) {
if (rel) {
zipfile.addEmptyDirectory(rel);
}
const childs = fs.readdirSync(root);
for (const name of childs) {
if (name === '.' || name === '..') {
continue;
}
const fullPath = path.join(root, name);
const stat = fs.statSync(fullPath);
if (stat.isFile()) {
//console.log('adding: ' + rel+name);
zipfile.addFile(fullPath, rel + name);
} else if (stat.isDirectory()) {
//console.log('adding: ' + rel+name+'/');
addDirectory(fullPath, rel + name + '/');
}
}
}
addDirectory(dir, '');
zipfile.outputStream.on('error', (err) => reject(err));
zipfile.outputStream
.pipe(fs.createWriteStream(output))
.on('close', function () {
resolve();
});
zipfile.end();
});
console.log('Bundled saved to: ' + output);
}
function readEntire(entry, zipFile) {
const buffers = [];
return new Promise((resolve, reject) => {
zipFile.openReadStream(entry, (err, stream) => {
stream.pipe({
write(chunk) {
buffers.push(chunk);
},
end() {
resolve(Buffer.concat(buffers));
},
prependListener() {},
on() {},
once() {},
emit() {},
});
});
});
}
function basename(fn) {
const m = /^(.+\/)[^\/]+\/?$/.exec(fn);
return m && m[1];
}
async function diffFromPPK(origin, next, output) {
fs.ensureDirSync(path.dirname(output));
const originEntries = {};
const originMap = {};
let originSource;
await enumZipEntries(origin, (entry, zipFile) => {
originEntries[entry.fileName] = entry;
if (!/\/$/.test(entry.fileName)) {
// isFile
originMap[entry.crc32] = entry.fileName;
if (entry.fileName === 'index.bundlejs') {
// This is source.
return readEntire(entry, zipFile).then((v) => (originSource = v));
}
}
});
if (!originSource) {
throw new Error(
`Bundle file not found! Please use default bundle file name and path.`,
);
}
const copies = {};
var zipfile = new ZipFile();
const writePromise = new Promise((resolve, reject) => {
zipfile.outputStream.on('error', (err) => {
throw err;
});
zipfile.outputStream
.pipe(fs.createWriteStream(output))
.on('close', function () {
resolve();
});
});
const addedEntry = {};
function addEntry(fn) {
//console.log(fn);
if (!fn || addedEntry[fn]) {
return;
}
const base = basename(fn);
if (base) {
addEntry(base);
}
zipfile.addEmptyDirectory(fn);
}
const newEntries = {};
await enumZipEntries(next, (entry, nextZipfile) => {
newEntries[entry.fileName] = entry;
if (/\/$/.test(entry.fileName)) {
// Directory
if (!originEntries[entry.fileName]) {
addEntry(entry.fileName);
}
} else if (entry.fileName === 'index.bundlejs') {
//console.log('Found bundle');
return readEntire(entry, nextZipfile).then((newSource) => {
//console.log('Begin diff');
zipfile.addBuffer(
diff(originSource, newSource),
'index.bundlejs.patch',
);
//console.log('End diff');
});
} else {
// If same file.
const originEntry = originEntries[entry.fileName];
if (originEntry && originEntry.crc32 === entry.crc32) {
// ignore
return;
}
// If moved from other place
if (originMap[entry.crc32]) {
const base = basename(entry.fileName);
if (!originEntries[base]) {
addEntry(base);
}
copies[entry.fileName] = originMap[entry.crc32];
return;
}
// New file.
addEntry(basename(entry.fileName));
return new Promise((resolve, reject) => {
nextZipfile.openReadStream(entry, function (err, readStream) {
if (err) {
return reject(err);
}
zipfile.addReadStream(readStream, entry.fileName);
readStream.on('end', () => {
//console.log('add finished');
resolve();
});
});
});
}
});
const deletes = {};
for (var k in originEntries) {
if (!newEntries[k]) {
console.log('Delete ' + k);
deletes[k] = 1;
}
}
//console.log({copies, deletes});
zipfile.addBuffer(
Buffer.from(JSON.stringify({ copies, deletes })),
'__diff.json',
);
zipfile.end();
await writePromise;
}
async function diffFromPackage(
origin,
next,
output,
originBundleName,
transformPackagePath = (v) => v,
) {
fs.ensureDirSync(path.dirname(output));
const originEntries = {};
const originMap = {};
let originSource;
await enumZipEntries(origin, (entry, zipFile) => {
if (!/\/$/.test(entry.fileName)) {
const fn = transformPackagePath(entry.fileName);
if (!fn) {
return;
}
//console.log(fn);
// isFile
originEntries[fn] = entry.crc32;
originMap[entry.crc32] = fn;
if (fn === originBundleName) {
// This is source.
return readEntire(entry, zipFile).then((v) => (originSource = v));
}
}
});
if (!originSource) {
throw new Error(
`Bundle file not found! Please use default bundle file name and path.`,
);
}
const copies = {};
var zipfile = new ZipFile();
const writePromise = new Promise((resolve, reject) => {
zipfile.outputStream.on('error', (err) => {
throw err;
});
zipfile.outputStream
.pipe(fs.createWriteStream(output))
.on('close', function () {
resolve();
});
});
await enumZipEntries(next, (entry, nextZipfile) => {
if (/\/$/.test(entry.fileName)) {
// Directory
zipfile.addEmptyDirectory(entry.fileName);
} else if (entry.fileName === 'index.bundlejs') {
//console.log('Found bundle');
return readEntire(entry, nextZipfile).then((newSource) => {
//console.log('Begin diff');
zipfile.addBuffer(
diff(originSource, newSource),
'index.bundlejs.patch',
);
//console.log('End diff');
});
} else {
// If same file.
if (originEntries[entry.fileName] === entry.crc32) {
copies[entry.fileName] = '';
return;
}
// If moved from other place
if (originMap[entry.crc32]) {
copies[entry.fileName] = originMap[entry.crc32];
return;
}
return new Promise((resolve, reject) => {
nextZipfile.openReadStream(entry, function (err, readStream) {
if (err) {
return reject(err);
}
zipfile.addReadStream(readStream, entry.fileName);
readStream.on('end', () => {
//console.log('add finished');
resolve();
});
});
});
}
});
zipfile.addBuffer(Buffer.from(JSON.stringify({ copies })), '__diff.json');
zipfile.end();
await writePromise;
}
function enumZipEntries(zipFn, callback) {
return new Promise((resolve, reject) => {
openZipFile(zipFn, { lazyEntries: true }, (err, zipfile) => {
if (err) {
return reject(err);
}
zipfile.on('end', resolve);
zipfile.on('error', reject);
zipfile.on('entry', (entry) => {
const result = callback(entry, zipfile);
if (result && typeof result.then === 'function') {
result.then(() => zipfile.readEntry());
} else {
zipfile.readEntry();
}
});
zipfile.readEntry();
});
});
}
export const commands = {
bundle: async function ({ options }) {
const platform = checkPlatform(
options.platform || (await question('Platform(ios/android):')),
);
let {
bundleName,
entryFile,
intermediaDir,
output,
dev,
verbose,
} = translateOptions({
...options,
platform,
});
// const sourcemapOutput = path.join(intermediaDir, bundleName + ".map");
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
if (!platform) {
throw new Error('Platform must be specified.');
}
const { version, major, minor } = getRNVersion();
console.log('Bundling with react-native: ', version);
printVersionCommand();
await runReactNativeBundleCommand(
bundleName,
dev,
entryFile,
intermediaDir,
platform,
);
await pack(path.resolve(intermediaDir), realOutput);
const v = await question('Would you like to publish it?(Y/N)');
if (v.toLowerCase() === 'y') {
await this.publish({
args: [realOutput],
options: {
platform,
},
});
}
},
async diff({ args, options }) {
const [origin, next] = args;
const { output } = options;
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
if (!origin || !next) {
console.error('pushy diff <origin> <next>');
process.exit(1);
}
await diffFromPPK(origin, next, realOutput, 'index.bundlejs');
console.log(`${realOutput} generated.`);
},
async diffFromApk({ args, options }) {
const [origin, next] = args;
const { output } = options;
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
if (!origin || !next) {
console.error('pushy diffFromApk <origin> <next>');
process.exit(1);
}
await diffFromPackage(
origin,
next,
realOutput,
'assets/index.android.bundle',
);
console.log(`${realOutput} generated.`);
},
async diffFromIpa({ args, options }) {
const [origin, next] = args;
const { output } = options;
const realOutput = output.replace(/\$\{time\}/g, '' + Date.now());
if (!origin || !next) {
console.error('pushy diffFromIpa <origin> <next>');
process.exit(1);
}
await diffFromPackage(origin, next, realOutput, 'main.jsbundle', (v) => {
const m = /^Payload\/[^/]+\/(.+)$/.exec(v);
return m && m[1];
});
console.log(`${realOutput} generated.`);
},
};

1061
src/bundle.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,52 +0,0 @@
#!/usr/bin/env node
/**
* Created by tdzl2003 on 2/13/16.
*/
const {loadSession} = require('./api');
const updateNotifier = require('update-notifier');
import { printVersionCommand } from './utils/index.js';
const pkg = require('../package.json');
updateNotifier({pkg}).notify({isGlobal: true});
function printUsage({args}) {
// const commandName = args[0];
// TODO: print usage of commandName, or print global usage.
console.log('Usage is under development now.')
console.log('Visit `https://github.com/reactnativecn/react-native-pushy` for early document.');
process.exit(1);
}
const commands = {
...require('./user').commands,
...require('./bundle').commands,
...require('./app').commands,
...require('./package').commands,
...require('./versions').commands,
help: printUsage,
};
function run() {
if (process.argv.indexOf('-v') >= 0 || process.argv[2] === 'version') {
printVersionCommand();
process.exit();
}
const argv = require('cli-arguments').parse(require('../cli.json'));
global.NO_INTERACTIVE = argv.options['no-interactive'];
loadSession()
.then(()=>commands[argv.command](argv))
.catch(err=>{
if (err.status === 401) {
console.log('Not loggined.\nRun `pushy login` at your project directory to login.');
return;
}
console.error(err.stack);
process.exit(-1);
});
};
run();

74
src/index.ts Normal file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env node
import { loadSession } from './api';
import updateNotifier from 'update-notifier';
import { printVersionCommand } from './utils';
import pkg from '../package.json';
import path from 'node:path';
import i18next from 'i18next';
import en from './locales/en';
import zh from './locales/zh';
const scriptName: 'cresc' | 'pushy' = path.basename(process.argv[1]) as
| 'cresc'
| 'pushy';
global.IS_CRESC = scriptName === 'cresc';
i18next.init({
lng: global.IS_CRESC ? 'en' : 'zh',
// debug: process.env.NODE_ENV !== 'production',
resources: {
en,
zh,
},
});
updateNotifier({ pkg }).notify({
isGlobal: true,
message:
'建议运行 `{updateCommand}` 来更新命令行工具以获得功能、性能和安全性的持续改进',
});
function printUsage() {
// const commandName = args[0];
// TODO: print usage of commandName, or print global usage.
console.log('Usage is under development now.');
console.log(
'Visit `https://github.com/reactnativecn/react-native-pushy` for early document.',
);
process.exit(1);
}
const commands = {
...require('./user').commands,
...require('./bundle').commands,
...require('./app').commands,
...require('./package').commands,
...require('./versions').commands,
help: printUsage,
};
async function run() {
await printVersionCommand();
if (process.argv.indexOf('-v') >= 0 || process.argv[2] === 'version') {
process.exit();
}
const argv = require('cli-arguments').parse(require('../cli.json'));
global.NO_INTERACTIVE = argv.options['no-interactive'];
global.USE_ACC_OSS = argv.options['acc'];
loadSession()
.then(() => commands[argv.command](argv))
.catch((err) => {
if (err.status === 401) {
console.log('尚未登录。\n请在项目目录中运行`pushy login`命令来登录');
return;
}
console.error(err.stack);
process.exit(-1);
});
}
run();

1
src/locales/en.ts Normal file
View File

@@ -0,0 +1 @@
export default {};

1
src/locales/zh.ts Normal file
View File

@@ -0,0 +1 @@
export default {};

View File

@@ -1,107 +0,0 @@
/**
* Created by tdzl2003 on 4/2/16.
*/
const { get, post, uploadFile } = require('./api');
import { question, saveToLocal } from './utils';
import { checkPlatform, getSelectedApp } from './app';
import { getApkInfo, getIpaInfo } from './utils';
const Table = require('tty-table');
export async function listPackage(appId) {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const header = [{ value: 'Package Id' }, { value: 'Version' }];
const rows = [];
for (const pkg of data) {
const { version } = pkg;
let versionInfo = '';
if (version) {
versionInfo = ` - ${version.id} ${version.hash.slice(0, 8)} ${
version.name
}`;
} else {
versionInfo = ' (newest)';
}
rows.push([pkg.id, `${pkg.name}(${pkg.status})${versionInfo}`]);
}
console.log(Table(header, rows).render());
console.log(`\nTotal ${data.length} package(s).`);
return data;
}
export async function choosePackage(appId) {
const list = await listPackage(appId);
while (true) {
const id = await question('Enter Package Id:');
const app = list.find((v) => v.id === (id | 0));
if (app) {
return app;
}
}
}
export const commands = {
uploadIpa: async function ({ args }) {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('Usage: pushy uploadIpa <ipaFile>');
}
const { versionName, buildTime } = await getIpaInfo(fn);
const { appId } = await getSelectedApp('ios');
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
name: versionName,
hash,
buildTime,
});
saveToLocal(fn, `${appId}/package/${id}.ipa`);
console.log(`Ipa uploaded: ${id}`);
},
uploadApk: async function ({ args }) {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('Usage: pushy uploadApk <apkFile>');
}
const { versionName, buildTime } = await getApkInfo(fn);
const { appId } = await getSelectedApp('android');
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
name: versionName,
hash,
buildTime,
});
saveToLocal(fn, `${appId}/package/${id}.apk`);
console.log(`Apk uploaded: ${id}`);
},
parseIpa: async function ({ args }) {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('Usage: pushy parseIpa <ipaFile>');
}
console.log(await getIpaInfo(fn));
},
parseApk: async function ({ args }) {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('Usage: pushy parseApk <apkFile>');
}
console.log(await getApkInfo(fn));
},
packages: async function ({ options }) {
const platform = checkPlatform(
options.platform || (await question('Platform(ios/android):')),
);
const { appId } = await getSelectedApp(platform);
await listPackage(appId);
},
};

190
src/package.ts Normal file
View File

@@ -0,0 +1,190 @@
import { get, post, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { checkPlatform, getSelectedApp } from './app';
import { getApkInfo, getIpaInfo, getAppInfo } from './utils';
import Table from 'tty-table';
export async function listPackage(appId: string) {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const header = [{ value: '原生包 Id' }, { value: '原生版本' }];
const rows = [];
for (const pkg of data) {
const { version } = pkg;
let versionInfo = '';
if (version) {
versionInfo = `, 已绑定:${version.name} (${version.id})`;
} else {
// versionInfo = ' (newest)';
}
let output = pkg.name;
if (pkg.status === 'paused') {
output += '(已暂停)';
}
if (pkg.status === 'expired') {
output += '(已过期)';
}
output += versionInfo;
rows.push([pkg.id, output]);
}
console.log(Table(header, rows).render());
console.log(`\n共 ${data.length} 个包`);
return data;
}
export async function choosePackage(appId: string) {
const list = await listPackage(appId);
while (true) {
const id = await question('输入原生包 id:');
const app = list.find((v) => v.id === Number(id));
if (app) {
return app;
}
}
}
export const commands = {
uploadIpa: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('使用方法: pushy uploadIpa ipa后缀文件');
}
const {
versionName,
buildTime,
appId: appIdInPkg,
appKey: appKeyInPkg,
} = await getIpaInfo(fn);
const { appId, appKey } = await getSelectedApp('ios');
if (appIdInPkg && appIdInPkg != appId) {
throw new Error(
`appId不匹配当前ipa: ${appIdInPkg}, 当前update.json: ${appId}`,
);
}
if (appKeyInPkg && appKeyInPkg !== appKey) {
throw new Error(
`appKey不匹配当前ipa: ${appKeyInPkg}, 当前update.json: ${appKey}`,
);
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
name: versionName,
hash,
buildTime,
});
saveToLocal(fn, `${appId}/package/${id}.ipa`);
console.log(
`已成功上传ipa原生包id: ${id}, version: ${versionName}, buildTime: ${buildTime}`,
);
},
uploadApk: async ({ args }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('使用方法: pushy uploadApk apk后缀文件');
}
const {
versionName,
buildTime,
appId: appIdInPkg,
appKey: appKeyInPkg,
} = await getApkInfo(fn);
const { appId, appKey } = await getSelectedApp('android');
if (appIdInPkg && appIdInPkg != appId) {
throw new Error(
`appId不匹配当前apk: ${appIdInPkg}, 当前update.json: ${appId}`,
);
}
if (appKeyInPkg && appKeyInPkg !== appKey) {
throw new Error(
`appKey不匹配当前apk: ${appKeyInPkg}, 当前update.json: ${appKey}`,
);
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
name: versionName,
hash,
buildTime,
});
saveToLocal(fn, `${appId}/package/${id}.apk`);
console.log(
`已成功上传apk原生包id: ${id}, version: ${versionName}, buildTime: ${buildTime}`,
);
},
uploadApp: async ({ args }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.app')) {
throw new Error('使用方法: pushy uploadApp app后缀文件');
}
const {
versionName,
buildTime,
appId: appIdInPkg,
appKey: appKeyInPkg,
} = await getAppInfo(fn);
const { appId, appKey } = await getSelectedApp('harmony');
if (appIdInPkg && appIdInPkg != appId) {
throw new Error(
`appId不匹配当前app: ${appIdInPkg}, 当前update.json: ${appId}`,
);
}
if (appKeyInPkg && appKeyInPkg !== appKey) {
throw new Error(
`appKey不匹配当前app: ${appKeyInPkg}, 当前update.json: ${appKey}`,
);
}
const { hash } = await uploadFile(fn);
const { id } = await post(`/app/${appId}/package/create`, {
name: versionName,
hash,
buildTime,
});
saveToLocal(fn, `${appId}/package/${id}.app`);
console.log(
`已成功上传app原生包id: ${id}, version: ${versionName}, buildTime: ${buildTime}`,
);
},
parseApp: async ({ args }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.app')) {
throw new Error('使用方法: pushy parseApp app后缀文件');
}
console.log(await getAppInfo(fn));
},
parseIpa: async ({ args }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
throw new Error('使用方法: pushy parseIpa ipa后缀文件');
}
console.log(await getIpaInfo(fn));
},
parseApk: async ({ args }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.apk')) {
throw new Error('使用方法: pushy parseApk apk后缀文件');
}
console.log(await getApkInfo(fn));
},
packages: async ({ options }) => {
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { appId } = await getSelectedApp(platform);
await listPackage(appId);
},
};

11
src/types.ts Normal file
View File

@@ -0,0 +1,11 @@
declare global {
var NO_INTERACTIVE: boolean;
var USE_ACC_OSS: boolean;
var IS_CRESC: boolean;
}
export interface Session {
token: string;
}
export type Platform = 'ios' | 'android' | 'harmony';

View File

@@ -1,43 +0,0 @@
/**
* Created by tdzl2003 on 2/13/16.
*/
import {question} from './utils';
const {
post,
get,
replaceSession,
saveSession,
closeSession,
} = require('./api');
const crypto = require('crypto');
function md5(str) {
return crypto.createHash('md5').update(str).digest('hex');
}
exports.commands = {
login: async function ({args}){
const email = args[0] || await question('email:');
const pwd = args[1] || await question('password:', true);
const {token, info} = await post('/user/login', {
email,
pwd: md5(pwd),
});
replaceSession({token});
await saveSession();
console.log(`Welcome, ${info.name}.`);
},
logout: async function (){
await closeSession();
console.log('Logged out.');
},
me: async function (){
const me = await get('/user/me');
for (const k in me) {
if (k !== 'ok') {
console.log(`${k}: ${me[k]}`);
}
}
},
}

33
src/user.ts Normal file
View File

@@ -0,0 +1,33 @@
import { question } from './utils';
import { post, get, replaceSession, saveSession, closeSession } from './api';
import crypto from 'node:crypto';
function md5(str: string) {
return crypto.createHash('md5').update(str).digest('hex');
}
export const commands = {
login: async ({ args }: { args: string[] }) => {
const email = args[0] || (await question('email:'));
const pwd = args[1] || (await question('password:', true));
const { token, info } = await post('/user/login', {
email,
pwd: md5(pwd),
});
replaceSession({ token });
await saveSession();
console.log(`欢迎使用 pushy 热更新服务, ${info.name}.`);
},
logout: async () => {
await closeSession();
console.log('已退出登录');
},
me: async () => {
const me = await get('/user/me');
for (const k in me) {
if (k !== 'ok') {
console.log(`${k}: ${me[k]}`);
}
}
},
};

View File

@@ -0,0 +1,90 @@
const Zip = require('./zip')
const { mapInfoResource, findApkIconPath, getBase64FromBuffer } = require('./utils')
const ManifestName = /^androidmanifest\.xml$/
const ResourceName = /^resources\.arsc$/
const ManifestXmlParser = require('./xml-parser/manifest')
const ResourceFinder = require('./resource-finder')
class ApkParser extends Zip {
/**
* parser for parsing .apk file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
*/
constructor (file) {
super(file)
if (!(this instanceof ApkParser)) {
return new ApkParser(file)
}
}
parse () {
return new Promise((resolve, reject) => {
this.getEntries([ManifestName, ResourceName]).then(buffers => {
if (!buffers[ManifestName]) {
throw new Error('AndroidManifest.xml can\'t be found.')
}
let apkInfo = this._parseManifest(buffers[ManifestName])
let resourceMap
if (!buffers[ResourceName]) {
resolve(apkInfo)
} else {
// parse resourceMap
resourceMap = this._parseResourceMap(buffers[ResourceName])
// update apkInfo with resourceMap
apkInfo = mapInfoResource(apkInfo, resourceMap)
// find icon path and parse icon
const iconPath = findApkIconPath(apkInfo)
if (iconPath) {
this.getEntry(iconPath).then(iconBuffer => {
apkInfo.icon = iconBuffer ? getBase64FromBuffer(iconBuffer) : null
resolve(apkInfo)
}).catch(e => {
apkInfo.icon = null
resolve(apkInfo)
console.warn('[Warning] failed to parse icon: ', e)
})
} else {
apkInfo.icon = null
resolve(apkInfo)
}
}
}).catch(e => {
reject(e)
})
})
}
/**
* Parse manifest
* @param {Buffer} buffer // manifest file's buffer
*/
_parseManifest (buffer) {
try {
const parser = new ManifestXmlParser(buffer, {
ignore: [
'application.activity',
'application.service',
'application.receiver',
'application.provider',
'permission-group'
]
})
return parser.parse()
} catch (e) {
throw new Error('Parse AndroidManifest.xml error: ', e)
}
}
/**
* Parse resourceMap
* @param {Buffer} buffer // resourceMap file's buffer
*/
_parseResourceMap (buffer) {
try {
return new ResourceFinder().processResourceTable(buffer)
} catch (e) {
throw new Error('Parser resources.arsc error: ' + e)
}
}
}
module.exports = ApkParser

View File

@@ -0,0 +1,16 @@
const Zip = require('./zip')
class AppParser extends Zip {
/**
* parser for parsing .apk file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
*/
constructor (file) {
super(file)
if (!(this instanceof AppParser)) {
return new AppParser(file)
}
}
}
module.exports = AppParser

View File

@@ -0,0 +1,43 @@
const ApkParser = require('./apk');
const IpaParser = require('./ipa');
const AppParser = require('./app');
const supportFileTypes = ['ipa', 'apk', 'app'];
class AppInfoParser {
/**
* parser for parsing .ipa or .apk file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
*/
constructor(file) {
if (!file) {
throw new Error(
"Param miss: file(file's path in Node, instance of File or Blob in browser).",
);
}
const splits = (file.name || file).split('.');
const fileType = splits[splits.length - 1].toLowerCase();
if (!supportFileTypes.includes(fileType)) {
throw new Error(
'Unsupported file type, only support .ipa or .apk or .app file.',
);
}
this.file = file;
switch (fileType) {
case 'ipa':
this.parser = new IpaParser(this.file);
break;
case 'apk':
this.parser = new ApkParser(this.file);
break;
case 'app':
this.parser = new AppParser(this.file);
break;
}
}
parse() {
return this.parser.parse();
}
}
module.exports = AppInfoParser;

View File

@@ -0,0 +1,92 @@
const parsePlist = require('plist').parse
const parseBplist = require('bplist-parser').parseBuffer
const cgbiToPng = require('cgbi-to-png')
const Zip = require('./zip')
const { findIpaIconPath, getBase64FromBuffer, isBrowser } = require('./utils')
const PlistName = new RegExp('payload/[^/]+?.app/info.plist$', 'i')
const ProvisionName = /payload\/.+?\.app\/embedded.mobileprovision/
class IpaParser extends Zip {
/**
* parser for parsing .ipa file
* @param {String | File | Blob} file // file's path in Node, instance of File or Blob in Browser
*/
constructor (file) {
super(file)
if (!(this instanceof IpaParser)) {
return new IpaParser(file)
}
}
parse () {
return new Promise((resolve, reject) => {
this.getEntries([PlistName, ProvisionName]).then(buffers => {
if (!buffers[PlistName]) {
throw new Error('Info.plist can\'t be found.')
}
const plistInfo = this._parsePlist(buffers[PlistName])
// parse mobile provision
const provisionInfo = this._parseProvision(buffers[ProvisionName])
plistInfo.mobileProvision = provisionInfo
// find icon path and parse icon
const iconRegex = new RegExp(findIpaIconPath(plistInfo).toLowerCase())
this.getEntry(iconRegex).then(iconBuffer => {
try {
// In general, the ipa file's icon has been specially processed, should be converted
plistInfo.icon = iconBuffer ? getBase64FromBuffer(cgbiToPng.revert(iconBuffer)) : null
} catch (err) {
if (isBrowser()) {
// Normal conversion in other cases
plistInfo.icon = iconBuffer ? getBase64FromBuffer(window.btoa(String.fromCharCode(...iconBuffer))) : null
} else {
plistInfo.icon = null
console.warn('[Warning] failed to parse icon: ', err)
}
}
resolve(plistInfo)
}).catch(e => {
reject(e)
})
}).catch(e => {
reject(e)
})
})
}
/**
* Parse plist
* @param {Buffer} buffer // plist file's buffer
*/
_parsePlist (buffer) {
let result
const bufferType = buffer[0]
if (bufferType === 60 || bufferType === '<' || bufferType === 239) {
result = parsePlist(buffer.toString())
} else if (bufferType === 98) {
result = parseBplist(buffer)[0]
} else {
throw new Error('Unknown plist buffer type.')
}
return result
}
/**
* parse provision
* @param {Buffer} buffer // provision file's buffer
*/
_parseProvision (buffer) {
let info = {}
if (buffer) {
let content = buffer.toString('utf-8')
const firstIndex = content.indexOf('<?xml')
const endIndex = content.indexOf('</plist>')
content = content.slice(firstIndex, endIndex + 8)
if (content) {
info = parsePlist(content)
}
}
return info
}
}
module.exports = IpaParser

View File

@@ -0,0 +1,499 @@
/**
* Code translated from a C# project https://github.com/hylander0/Iteedee.ApkReader/blob/master/Iteedee.ApkReader/ApkResourceFinder.cs
*
* Decode binary file `resources.arsc` from a .apk file to a JavaScript Object.
*/
var ByteBuffer = require("bytebuffer");
var DEBUG = false;
var RES_STRING_POOL_TYPE = 0x0001;
var RES_TABLE_TYPE = 0x0002;
var RES_TABLE_PACKAGE_TYPE = 0x0200;
var RES_TABLE_TYPE_TYPE = 0x0201;
var RES_TABLE_TYPE_SPEC_TYPE = 0x0202;
// The 'data' holds a ResTable_ref, a reference to another resource
// table entry.
var TYPE_REFERENCE = 0x01;
// The 'data' holds an index into the containing resource table's
// global value string pool.
var TYPE_STRING = 0x03;
function ResourceFinder() {
this.valueStringPool = null;
this.typeStringPool = null;
this.keyStringPool = null;
this.package_id = 0;
this.responseMap = {};
this.entryMap = {};
}
/**
* Same to C# BinaryReader.readBytes
*
* @param bb ByteBuffer
* @param len length
* @returns {Buffer}
*/
ResourceFinder.readBytes = function(bb, len) {
var uint8Array = new Uint8Array(len);
for (var i = 0; i < len; i++) {
uint8Array[i] = bb.readUint8();
}
return ByteBuffer.wrap(uint8Array, "binary", true);
};
//
/**
*
* @param {ByteBuffer} bb
* @return {Map<String, Set<String>>}
*/
ResourceFinder.prototype.processResourceTable = function(resourceBuffer) {
const bb = ByteBuffer.wrap(resourceBuffer, "binary", true);
// Resource table structure
var type = bb.readShort(),
headerSize = bb.readShort(),
size = bb.readInt(),
packageCount = bb.readInt(),
buffer,
bb2;
if (type != RES_TABLE_TYPE) {
throw new Error("No RES_TABLE_TYPE found!");
}
if (size != bb.limit) {
throw new Error("The buffer size not matches to the resource table size.");
}
bb.offset = headerSize;
var realStringPoolCount = 0,
realPackageCount = 0;
while (true) {
var pos, t, hs, s;
try {
pos = bb.offset;
t = bb.readShort();
hs = bb.readShort();
s = bb.readInt();
} catch (e) {
break;
}
if (t == RES_STRING_POOL_TYPE) {
// Process the string pool
if (realStringPoolCount == 0) {
// Only the first string pool is processed.
if (DEBUG) {
console.log("Processing the string pool ...");
}
buffer = new ByteBuffer(s);
bb.offset = pos;
bb.prependTo(buffer);
bb2 = ByteBuffer.wrap(buffer, "binary", true);
bb2.LE();
this.valueStringPool = this.processStringPool(bb2);
}
realStringPoolCount++;
} else if (t == RES_TABLE_PACKAGE_TYPE) {
// Process the package
if (DEBUG) {
console.log("Processing the package " + realPackageCount + " ...");
}
buffer = new ByteBuffer(s);
bb.offset = pos;
bb.prependTo(buffer);
bb2 = ByteBuffer.wrap(buffer, "binary", true);
bb2.LE();
this.processPackage(bb2);
realPackageCount++;
} else {
throw new Error("Unsupported type");
}
bb.offset = pos + s;
if (!bb.remaining()) break;
}
if (realStringPoolCount != 1) {
throw new Error("More than 1 string pool found!");
}
if (realPackageCount != packageCount) {
throw new Error("Real package count not equals the declared count.");
}
return this.responseMap;
};
/**
*
* @param {ByteBuffer} bb
*/
ResourceFinder.prototype.processPackage = function(bb) {
// Package structure
var type = bb.readShort(),
headerSize = bb.readShort(),
size = bb.readInt(),
id = bb.readInt();
this.package_id = id;
for (var i = 0; i < 256; ++i) {
bb.readUint8();
}
var typeStrings = bb.readInt(),
lastPublicType = bb.readInt(),
keyStrings = bb.readInt(),
lastPublicKey = bb.readInt();
if (typeStrings != headerSize) {
throw new Error(
"TypeStrings must immediately following the package structure header."
);
}
if (DEBUG) {
console.log("Type strings:");
}
var lastPosition = bb.offset;
bb.offset = typeStrings;
var bbTypeStrings = ResourceFinder.readBytes(bb, bb.limit - bb.offset);
bb.offset = lastPosition;
this.typeStringPool = this.processStringPool(bbTypeStrings);
// Key strings
if (DEBUG) {
console.log("Key strings:");
}
bb.offset = keyStrings;
var key_type = bb.readShort(),
key_headerSize = bb.readShort(),
key_size = bb.readInt();
lastPosition = bb.offset;
bb.offset = keyStrings;
var bbKeyStrings = ResourceFinder.readBytes(bb, bb.limit - bb.offset);
bb.offset = lastPosition;
this.keyStringPool = this.processStringPool(bbKeyStrings);
// Iterate through all chunks
var typeSpecCount = 0;
var typeCount = 0;
bb.offset = keyStrings + key_size;
var bb2;
while (true) {
var pos = bb.offset;
try {
var t = bb.readShort();
var hs = bb.readShort();
var s = bb.readInt();
} catch (e) {
break;
}
if (t == RES_TABLE_TYPE_SPEC_TYPE) {
bb.offset = pos;
bb2 = ResourceFinder.readBytes(bb, s);
this.processTypeSpec(bb2);
typeSpecCount++;
} else if (t == RES_TABLE_TYPE_TYPE) {
bb.offset = pos;
bb2 = ResourceFinder.readBytes(bb, s);
this.processType(bb2);
typeCount++;
}
if (s == 0) {
break;
}
bb.offset = pos + s;
if (!bb.remaining()) {
break;
}
}
};
/**
*
* @param {ByteBuffer} bb
*/
ResourceFinder.prototype.processType = function(bb) {
var type = bb.readShort(),
headerSize = bb.readShort(),
size = bb.readInt(),
id = bb.readByte(),
res0 = bb.readByte(),
res1 = bb.readShort(),
entryCount = bb.readInt(),
entriesStart = bb.readInt();
var refKeys = {};
var config_size = bb.readInt();
// Skip the config data
bb.offset = headerSize;
if (headerSize + entryCount * 4 != entriesStart) {
throw new Error("HeaderSize, entryCount and entriesStart are not valid.");
}
// Start to get entry indices
var entryIndices = new Array(entryCount);
for (var i = 0; i < entryCount; ++i) {
entryIndices[i] = bb.readInt();
}
// Get entries
for (var i = 0; i < entryCount; ++i) {
if (entryIndices[i] == -1) continue;
var resource_id = (this.package_id << 24) | (id << 16) | i;
var pos = bb.offset,
entry_size,
entry_flag,
entry_key,
value_size,
value_res0,
value_dataType,
value_data;
try {
entry_size = bb.readShort()
entry_flag = bb.readShort()
entry_key = bb.readInt()
} catch (e) {
break
}
// Get the value (simple) or map (complex)
var FLAG_COMPLEX = 0x0001;
if ((entry_flag & FLAG_COMPLEX) == 0) {
// Simple case
value_size = bb.readShort();
value_res0 = bb.readByte();
value_dataType = bb.readByte();
value_data = bb.readInt();
var idStr = Number(resource_id).toString(16);
var keyStr = this.keyStringPool[entry_key];
var data = null;
if (DEBUG) {
console.log(
"Entry 0x" + idStr + ", key: " + keyStr + ", simple value type: "
);
}
var key = parseInt(idStr, 16);
var entryArr = this.entryMap[key];
if (entryArr == null) {
entryArr = [];
}
entryArr.push(keyStr);
this.entryMap[key] = entryArr;
if (value_dataType == TYPE_STRING) {
data = this.valueStringPool[value_data];
if (DEBUG) {
console.log(", data: " + this.valueStringPool[value_data] + "");
}
} else if (value_dataType == TYPE_REFERENCE) {
var hexIndex = Number(value_data).toString(16);
refKeys[idStr] = value_data;
} else {
data = "" + value_data;
if (DEBUG) {
console.log(", data: " + value_data + "");
}
}
this.putIntoMap("@" + idStr, data);
} else {
// Complex case
var entry_parent = bb.readInt();
var entry_count = bb.readInt();
for (var j = 0; j < entry_count; ++j) {
var ref_name = bb.readInt();
value_size = bb.readShort();
value_res0 = bb.readByte();
value_dataType = bb.readByte();
value_data = bb.readInt();
}
if (DEBUG) {
console.log(
"Entry 0x" +
Number(resource_id).toString(16) +
", key: " +
this.keyStringPool[entry_key] +
", complex value, not printed."
);
}
}
}
for (var refK in refKeys) {
var values = this.responseMap[
"@" +
Number(refKeys[refK])
.toString(16)
.toUpperCase()
];
if (values != null && Object.keys(values).length < 1000) {
for (var value in values) {
this.putIntoMap("@" + refK, values[value]);
}
}
}
};
/**
*
* @param {ByteBuffer} bb
* @return {Array}
*/
ResourceFinder.prototype.processStringPool = function(bb) {
// String pool structure
//
var type = bb.readShort(),
headerSize = bb.readShort(),
size = bb.readInt(),
stringCount = bb.readInt(),
styleCount = bb.readInt(),
flags = bb.readInt(),
stringsStart = bb.readInt(),
stylesStart = bb.readInt(),
u16len,
buffer;
var isUTF_8 = (flags & 256) != 0;
var offsets = new Array(stringCount);
for (var i = 0; i < stringCount; ++i) {
offsets[i] = bb.readInt();
}
var strings = new Array(stringCount);
for (var i = 0; i < stringCount; ++i) {
var pos = stringsStart + offsets[i];
bb.offset = pos;
strings[i] = "";
if (isUTF_8) {
u16len = bb.readUint8();
if ((u16len & 0x80) != 0) {
u16len = ((u16len & 0x7f) << 8) + bb.readUint8();
}
var u8len = bb.readUint8();
if ((u8len & 0x80) != 0) {
u8len = ((u8len & 0x7f) << 8) + bb.readUint8();
}
if (u8len > 0) {
buffer = ResourceFinder.readBytes(bb, u8len);
try {
strings[i] = ByteBuffer.wrap(buffer, "utf8", true).toString("utf8");
} catch (e) {
if (DEBUG) {
console.error(e);
console.log("Error when turning buffer to utf-8 string.");
}
}
} else {
strings[i] = "";
}
} else {
u16len = bb.readUint16();
if ((u16len & 0x8000) != 0) {
// larger than 32768
u16len = ((u16len & 0x7fff) << 16) + bb.readUint16();
}
if (u16len > 0) {
var len = u16len * 2;
buffer = ResourceFinder.readBytes(bb, len);
try {
strings[i] = ByteBuffer.wrap(buffer, "utf8", true).toString("utf8");
} catch (e) {
if (DEBUG) {
console.error(e);
console.log("Error when turning buffer to utf-8 string.");
}
}
}
}
if (DEBUG) {
console.log("Parsed value: {0}", strings[i]);
}
}
return strings;
};
/**
*
* @param {ByteBuffer} bb
*/
ResourceFinder.prototype.processTypeSpec = function(bb) {
var type = bb.readShort(),
headerSize = bb.readShort(),
size = bb.readInt(),
id = bb.readByte(),
res0 = bb.readByte(),
res1 = bb.readShort(),
entryCount = bb.readInt();
if (DEBUG) {
console.log("Processing type spec " + this.typeStringPool[id - 1] + "...");
}
var flags = new Array(entryCount);
for (var i = 0; i < entryCount; ++i) {
flags[i] = bb.readInt();
}
};
ResourceFinder.prototype.putIntoMap = function(resId, value) {
if (this.responseMap[resId.toUpperCase()] == null) {
this.responseMap[resId.toUpperCase()] = []
}
if(value){
this.responseMap[resId.toUpperCase()].push(value)
}
};
module.exports = ResourceFinder;

View File

@@ -0,0 +1,167 @@
function objectType (o) {
return Object.prototype.toString.call(o).slice(8, -1).toLowerCase()
}
function isArray (o) {
return objectType(o) === 'array'
}
function isObject (o) {
return objectType(o) === 'object'
}
function isPrimitive (o) {
return o === null || ['boolean', 'number', 'string', 'undefined'].includes(objectType(o))
}
function isBrowser () {
return (
typeof process === 'undefined' ||
Object.prototype.toString.call(process) !== '[object process]'
)
}
/**
* map file place with resourceMap
* @param {Object} apkInfo // json info parsed from .apk file
* @param {Object} resourceMap // resourceMap
*/
function mapInfoResource (apkInfo, resourceMap) {
iteratorObj(apkInfo)
return apkInfo
function iteratorObj (obj) {
for (var i in obj) {
if (isArray(obj[i])) {
iteratorArray(obj[i])
} else if (isObject(obj[i])) {
iteratorObj(obj[i])
} else if (isPrimitive(obj[i])) {
if (isResources(obj[i])) {
obj[i] = resourceMap[transKeyToMatchResourceMap(obj[i])]
}
}
}
}
function iteratorArray (array) {
const l = array.length
for (let i = 0; i < l; i++) {
if (isArray(array[i])) {
iteratorArray(array[i])
} else if (isObject(array[i])) {
iteratorObj(array[i])
} else if (isPrimitive(array[i])) {
if (isResources(array[i])) {
array[i] = resourceMap[transKeyToMatchResourceMap(array[i])]
}
}
}
}
function isResources (attrValue) {
if (!attrValue) return false
if (typeof attrValue !== 'string') {
attrValue = attrValue.toString()
}
return attrValue.indexOf('resourceId:') === 0
}
function transKeyToMatchResourceMap (resourceId) {
return '@' + resourceId.replace('resourceId:0x', '').toUpperCase()
}
}
/**
* find .apk file's icon path from json info
* @param info // json info parsed from .apk file
*/
function findApkIconPath (info) {
if (!info.application.icon || !info.application.icon.splice) {
return ''
}
const rulesMap = {
mdpi: 48,
hdpi: 72,
xhdpi: 96,
xxdpi: 144,
xxxhdpi: 192
}
const resultMap = {}
const maxDpiIcon = { dpi: 120, icon: '' }
for (const i in rulesMap) {
info.application.icon.some((icon) => {
if (icon && icon.indexOf(i) !== -1) {
resultMap['application-icon-' + rulesMap[i]] = icon
return true
}
})
// get the maximal size icon
if (
resultMap['application-icon-' + rulesMap[i]] &&
rulesMap[i] >= maxDpiIcon.dpi
) {
maxDpiIcon.dpi = rulesMap[i]
maxDpiIcon.icon = resultMap['application-icon-' + rulesMap[i]]
}
}
if (Object.keys(resultMap).length === 0 || !maxDpiIcon.icon) {
maxDpiIcon.dpi = 120
maxDpiIcon.icon = info.application.icon[0] || ''
resultMap['applicataion-icon-120'] = maxDpiIcon.icon
}
return maxDpiIcon.icon
}
/**
* find .ipa file's icon path from json info
* @param info // json info parsed from .ipa file
*/
function findIpaIconPath (info) {
if (
info.CFBundleIcons &&
info.CFBundleIcons.CFBundlePrimaryIcon &&
info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles &&
info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles.length
) {
return info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles[info.CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles.length - 1]
} else if (info.CFBundleIconFiles && info.CFBundleIconFiles.length) {
return info.CFBundleIconFiles[info.CFBundleIconFiles.length - 1]
} else {
return '.app/Icon.png'
}
}
/**
* transform buffer to base64
* @param {Buffer} buffer
*/
function getBase64FromBuffer (buffer) {
return 'data:image/png;base64,' + buffer.toString('base64')
}
/**
* 去除unicode空字符
* @param {String} str
*/
function decodeNullUnicode (str) {
if (typeof str === 'string') {
// eslint-disable-next-line
str = str.replace(/\u0000/g, '')
}
return str
}
module.exports = {
isArray,
isObject,
isPrimitive,
isBrowser,
mapInfoResource,
findApkIconPath,
findIpaIconPath,
getBase64FromBuffer,
decodeNullUnicode
}

View File

@@ -0,0 +1,674 @@
// From https://github.com/openstf/adbkit-apkreader
const NodeType = {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
CDATA_SECTION_NODE: 4
}
const ChunkType = {
NULL: 0x0000,
STRING_POOL: 0x0001,
TABLE: 0x0002,
XML: 0x0003,
XML_FIRST_CHUNK: 0x0100,
XML_START_NAMESPACE: 0x0100,
XML_END_NAMESPACE: 0x0101,
XML_START_ELEMENT: 0x0102,
XML_END_ELEMENT: 0x0103,
XML_CDATA: 0x0104,
XML_LAST_CHUNK: 0x017f,
XML_RESOURCE_MAP: 0x0180,
TABLE_PACKAGE: 0x0200,
TABLE_TYPE: 0x0201,
TABLE_TYPE_SPEC: 0x0202
}
const StringFlags = {
SORTED: 1 << 0,
UTF8: 1 << 8
}
// Taken from android.util.TypedValue
const TypedValue = {
COMPLEX_MANTISSA_MASK: 0x00ffffff,
COMPLEX_MANTISSA_SHIFT: 0x00000008,
COMPLEX_RADIX_0p23: 0x00000003,
COMPLEX_RADIX_16p7: 0x00000001,
COMPLEX_RADIX_23p0: 0x00000000,
COMPLEX_RADIX_8p15: 0x00000002,
COMPLEX_RADIX_MASK: 0x00000003,
COMPLEX_RADIX_SHIFT: 0x00000004,
COMPLEX_UNIT_DIP: 0x00000001,
COMPLEX_UNIT_FRACTION: 0x00000000,
COMPLEX_UNIT_FRACTION_PARENT: 0x00000001,
COMPLEX_UNIT_IN: 0x00000004,
COMPLEX_UNIT_MASK: 0x0000000f,
COMPLEX_UNIT_MM: 0x00000005,
COMPLEX_UNIT_PT: 0x00000003,
COMPLEX_UNIT_PX: 0x00000000,
COMPLEX_UNIT_SHIFT: 0x00000000,
COMPLEX_UNIT_SP: 0x00000002,
DENSITY_DEFAULT: 0x00000000,
DENSITY_NONE: 0x0000ffff,
TYPE_ATTRIBUTE: 0x00000002,
TYPE_DIMENSION: 0x00000005,
TYPE_FIRST_COLOR_INT: 0x0000001c,
TYPE_FIRST_INT: 0x00000010,
TYPE_FLOAT: 0x00000004,
TYPE_FRACTION: 0x00000006,
TYPE_INT_BOOLEAN: 0x00000012,
TYPE_INT_COLOR_ARGB4: 0x0000001e,
TYPE_INT_COLOR_ARGB8: 0x0000001c,
TYPE_INT_COLOR_RGB4: 0x0000001f,
TYPE_INT_COLOR_RGB8: 0x0000001d,
TYPE_INT_DEC: 0x00000010,
TYPE_INT_HEX: 0x00000011,
TYPE_LAST_COLOR_INT: 0x0000001f,
TYPE_LAST_INT: 0x0000001f,
TYPE_NULL: 0x00000000,
TYPE_REFERENCE: 0x00000001,
TYPE_STRING: 0x00000003
}
class BinaryXmlParser {
constructor (buffer, options = {}) {
this.buffer = buffer
this.cursor = 0
this.strings = []
this.resources = []
this.document = null
this.parent = null
this.stack = []
this.debug = options.debug || false
}
readU8 () {
this.debug && console.group('readU8')
this.debug && console.debug('cursor:', this.cursor)
const val = this.buffer[this.cursor]
this.debug && console.debug('value:', val)
this.cursor += 1
this.debug && console.groupEnd()
return val
}
readU16 () {
this.debug && console.group('readU16')
this.debug && console.debug('cursor:', this.cursor)
const val = this.buffer.readUInt16LE(this.cursor)
this.debug && console.debug('value:', val)
this.cursor += 2
this.debug && console.groupEnd()
return val
}
readS32 () {
this.debug && console.group('readS32')
this.debug && console.debug('cursor:', this.cursor)
const val = this.buffer.readInt32LE(this.cursor)
this.debug && console.debug('value:', val)
this.cursor += 4
this.debug && console.groupEnd()
return val
}
readU32 () {
this.debug && console.group('readU32')
this.debug && console.debug('cursor:', this.cursor)
const val = this.buffer.readUInt32LE(this.cursor)
this.debug && console.debug('value:', val)
this.cursor += 4
this.debug && console.groupEnd()
return val
}
readLength8 () {
this.debug && console.group('readLength8')
let len = this.readU8()
if (len & 0x80) {
len = (len & 0x7f) << 8
len += this.readU8()
}
this.debug && console.debug('length:', len)
this.debug && console.groupEnd()
return len
}
readLength16 () {
this.debug && console.group('readLength16')
let len = this.readU16()
if (len & 0x8000) {
len = (len & 0x7fff) << 16
len += this.readU16()
}
this.debug && console.debug('length:', len)
this.debug && console.groupEnd()
return len
}
readDimension () {
this.debug && console.group('readDimension')
const dimension = {
value: null,
unit: null,
rawUnit: null
}
const value = this.readU32()
const unit = dimension.value & 0xff
dimension.value = value >> 8
dimension.rawUnit = unit
switch (unit) {
case TypedValue.COMPLEX_UNIT_MM:
dimension.unit = 'mm'
break
case TypedValue.COMPLEX_UNIT_PX:
dimension.unit = 'px'
break
case TypedValue.COMPLEX_UNIT_DIP:
dimension.unit = 'dp'
break
case TypedValue.COMPLEX_UNIT_SP:
dimension.unit = 'sp'
break
case TypedValue.COMPLEX_UNIT_PT:
dimension.unit = 'pt'
break
case TypedValue.COMPLEX_UNIT_IN:
dimension.unit = 'in'
break
}
this.debug && console.groupEnd()
return dimension
}
readFraction () {
this.debug && console.group('readFraction')
const fraction = {
value: null,
type: null,
rawType: null
}
const value = this.readU32()
const type = value & 0xf
fraction.value = this.convertIntToFloat(value >> 4)
fraction.rawType = type
switch (type) {
case TypedValue.COMPLEX_UNIT_FRACTION:
fraction.type = '%'
break
case TypedValue.COMPLEX_UNIT_FRACTION_PARENT:
fraction.type = '%p'
break
}
this.debug && console.groupEnd()
return fraction
}
readHex24 () {
this.debug && console.group('readHex24')
var val = (this.readU32() & 0xffffff).toString(16)
this.debug && console.groupEnd()
return val
}
readHex32 () {
this.debug && console.group('readHex32')
var val = this.readU32().toString(16)
this.debug && console.groupEnd()
return val
}
readTypedValue () {
this.debug && console.group('readTypedValue')
const typedValue = {
value: null,
type: null,
rawType: null
}
const start = this.cursor
let size = this.readU16()
/* const zero = */ this.readU8()
const dataType = this.readU8()
// Yes, there has been a real world APK where the size is malformed.
if (size === 0) {
size = 8
}
typedValue.rawType = dataType
switch (dataType) {
case TypedValue.TYPE_INT_DEC:
typedValue.value = this.readS32()
typedValue.type = 'int_dec'
break
case TypedValue.TYPE_INT_HEX:
typedValue.value = this.readS32()
typedValue.type = 'int_hex'
break
case TypedValue.TYPE_STRING:
var ref = this.readS32()
typedValue.value = ref > 0 ? this.strings[ref] : ''
typedValue.type = 'string'
break
case TypedValue.TYPE_REFERENCE:
var id = this.readU32()
typedValue.value = `resourceId:0x${id.toString(16)}`
typedValue.type = 'reference'
break
case TypedValue.TYPE_INT_BOOLEAN:
typedValue.value = this.readS32() !== 0
typedValue.type = 'boolean'
break
case TypedValue.TYPE_NULL:
this.readU32()
typedValue.value = null
typedValue.type = 'null'
break
case TypedValue.TYPE_INT_COLOR_RGB8:
typedValue.value = this.readHex24()
typedValue.type = 'rgb8'
break
case TypedValue.TYPE_INT_COLOR_RGB4:
typedValue.value = this.readHex24()
typedValue.type = 'rgb4'
break
case TypedValue.TYPE_INT_COLOR_ARGB8:
typedValue.value = this.readHex32()
typedValue.type = 'argb8'
break
case TypedValue.TYPE_INT_COLOR_ARGB4:
typedValue.value = this.readHex32()
typedValue.type = 'argb4'
break
case TypedValue.TYPE_DIMENSION:
typedValue.value = this.readDimension()
typedValue.type = 'dimension'
break
case TypedValue.TYPE_FRACTION:
typedValue.value = this.readFraction()
typedValue.type = 'fraction'
break
default: {
const type = dataType.toString(16)
console.debug(`Not sure what to do with typed value of type 0x${type}, falling back to reading an uint32.`)
typedValue.value = this.readU32()
typedValue.type = 'unknown'
}
}
// Ensure we consume the whole value
const end = start + size
if (this.cursor !== end) {
const type = dataType.toString(16)
const diff = end - this.cursor
console.debug(`Cursor is off by ${diff} bytes at ${this.cursor} at supposed end \
of typed value of type 0x${type}. The typed value started at offset ${start} \
and is supposed to end at offset ${end}. Ignoring the rest of the value.`)
this.cursor = end
}
this.debug && console.groupEnd()
return typedValue
}
// https://twitter.com/kawasima/status/427730289201139712
convertIntToFloat (int) {
const buf = new ArrayBuffer(4)
;(new Int32Array(buf))[0] = int
return (new Float32Array(buf))[0]
}
readString (encoding) {
this.debug && console.group('readString', encoding)
switch (encoding) {
case 'utf-8':
var stringLength = this.readLength8(encoding)
this.debug && console.debug('stringLength:', stringLength)
var byteLength = this.readLength8(encoding)
this.debug && console.debug('byteLength:', byteLength)
var value = this.buffer.toString(encoding, this.cursor, (this.cursor += byteLength))
this.debug && console.debug('value:', value)
this.debug && console.groupEnd()
return value
case 'ucs2':
stringLength = this.readLength16(encoding)
this.debug && console.debug('stringLength:', stringLength)
byteLength = stringLength * 2
this.debug && console.debug('byteLength:', byteLength)
value = this.buffer.toString(encoding, this.cursor, (this.cursor += byteLength))
this.debug && console.debug('value:', value)
this.debug && console.groupEnd()
return value
default:
throw new Error(`Unsupported encoding '${encoding}'`)
}
}
readChunkHeader () {
this.debug && console.group('readChunkHeader')
var header = {
startOffset: this.cursor,
chunkType: this.readU16(),
headerSize: this.readU16(),
chunkSize: this.readU32()
}
this.debug && console.debug('startOffset:', header.startOffset)
this.debug && console.debug('chunkType:', header.chunkType)
this.debug && console.debug('headerSize:', header.headerSize)
this.debug && console.debug('chunkSize:', header.chunkSize)
this.debug && console.groupEnd()
return header
}
readStringPool (header) {
this.debug && console.group('readStringPool')
header.stringCount = this.readU32()
this.debug && console.debug('stringCount:', header.stringCount)
header.styleCount = this.readU32()
this.debug && console.debug('styleCount:', header.styleCount)
header.flags = this.readU32()
this.debug && console.debug('flags:', header.flags)
header.stringsStart = this.readU32()
this.debug && console.debug('stringsStart:', header.stringsStart)
header.stylesStart = this.readU32()
this.debug && console.debug('stylesStart:', header.stylesStart)
if (header.chunkType !== ChunkType.STRING_POOL) {
throw new Error('Invalid string pool header')
}
const offsets = []
for (let i = 0, l = header.stringCount; i < l; ++i) {
this.debug && console.debug('offset:', i)
offsets.push(this.readU32())
}
const sorted = (header.flags & StringFlags.SORTED) === StringFlags.SORTED
this.debug && console.debug('sorted:', sorted)
const encoding = (header.flags & StringFlags.UTF8) === StringFlags.UTF8
? 'utf-8'
: 'ucs2'
this.debug && console.debug('encoding:', encoding)
const stringsStart = header.startOffset + header.stringsStart
this.cursor = stringsStart
for (let i = 0, l = header.stringCount; i < l; ++i) {
this.debug && console.debug('string:', i)
this.debug && console.debug('offset:', offsets[i])
this.cursor = stringsStart + offsets[i]
this.strings.push(this.readString(encoding))
}
// Skip styles
this.cursor = header.startOffset + header.chunkSize
this.debug && console.groupEnd()
return null
}
readResourceMap (header) {
this.debug && console.group('readResourceMap')
const count = Math.floor((header.chunkSize - header.headerSize) / 4)
for (let i = 0; i < count; ++i) {
this.resources.push(this.readU32())
}
this.debug && console.groupEnd()
return null
}
readXmlNamespaceStart (/* header */) {
this.debug && console.group('readXmlNamespaceStart')
/* const line = */ this.readU32()
/* const commentRef = */ this.readU32()
/* const prefixRef = */ this.readS32()
/* const uriRef = */ this.readS32()
// We don't currently care about the values, but they could
// be accessed like so:
//
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
this.debug && console.groupEnd()
return null
}
readXmlNamespaceEnd (/* header */) {
this.debug && console.group('readXmlNamespaceEnd')
/* const line = */ this.readU32()
/* const commentRef = */ this.readU32()
/* const prefixRef = */ this.readS32()
/* const uriRef = */ this.readS32()
// We don't currently care about the values, but they could
// be accessed like so:
//
// namespaceURI.prefix = this.strings[prefixRef] // if prefixRef > 0
// namespaceURI.uri = this.strings[uriRef] // if uriRef > 0
this.debug && console.groupEnd()
return null
}
readXmlElementStart (/* header */) {
this.debug && console.group('readXmlElementStart')
const node = {
namespaceURI: null,
nodeType: NodeType.ELEMENT_NODE,
nodeName: null,
attributes: [],
childNodes: []
}
/* const line = */ this.readU32()
/* const commentRef = */ this.readU32()
const nsRef = this.readS32()
const nameRef = this.readS32()
if (nsRef > 0) {
node.namespaceURI = this.strings[nsRef]
}
node.nodeName = this.strings[nameRef]
/* const attrStart = */ this.readU16()
/* const attrSize = */ this.readU16()
const attrCount = this.readU16()
/* const idIndex = */ this.readU16()
/* const classIndex = */ this.readU16()
/* const styleIndex = */ this.readU16()
for (let i = 0; i < attrCount; ++i) {
node.attributes.push(this.readXmlAttribute())
}
if (this.document) {
this.parent.childNodes.push(node)
this.parent = node
} else {
this.document = (this.parent = node)
}
this.stack.push(node)
this.debug && console.groupEnd()
return node
}
readXmlAttribute () {
this.debug && console.group('readXmlAttribute')
const attr = {
namespaceURI: null,
nodeType: NodeType.ATTRIBUTE_NODE,
nodeName: null,
name: null,
value: null,
typedValue: null
}
const nsRef = this.readS32()
const nameRef = this.readS32()
const valueRef = this.readS32()
if (nsRef > 0) {
attr.namespaceURI = this.strings[nsRef]
}
attr.nodeName = attr.name = this.strings[nameRef]
if (valueRef > 0) {
// some apk have versionName with special characters
if (attr.name === 'versionName') {
// only keep printable characters
// https://www.ascii-code.com/characters/printable-characters
this.strings[valueRef] = this.strings[valueRef].replace(/[^\x21-\x7E]/g, '')
}
attr.value = this.strings[valueRef]
}
attr.typedValue = this.readTypedValue()
this.debug && console.groupEnd()
return attr
}
readXmlElementEnd (/* header */) {
this.debug && console.group('readXmlCData')
/* const line = */ this.readU32()
/* const commentRef = */ this.readU32()
/* const nsRef = */ this.readS32()
/* const nameRef = */ this.readS32()
this.stack.pop()
this.parent = this.stack[this.stack.length - 1]
this.debug && console.groupEnd()
return null
}
readXmlCData (/* header */) {
this.debug && console.group('readXmlCData')
const cdata = {
namespaceURI: null,
nodeType: NodeType.CDATA_SECTION_NODE,
nodeName: '#cdata',
data: null,
typedValue: null
}
/* const line = */ this.readU32()
/* const commentRef = */ this.readU32()
const dataRef = this.readS32()
if (dataRef > 0) {
cdata.data = this.strings[dataRef]
}
cdata.typedValue = this.readTypedValue()
this.parent.childNodes.push(cdata)
this.debug && console.groupEnd()
return cdata
}
readNull (header) {
this.debug && console.group('readNull')
this.cursor += header.chunkSize - header.headerSize
this.debug && console.groupEnd()
return null
}
parse () {
this.debug && console.group('BinaryXmlParser.parse')
const xmlHeader = this.readChunkHeader()
if (xmlHeader.chunkType !== ChunkType.XML) {
throw new Error('Invalid XML header')
}
while (this.cursor < this.buffer.length) {
this.debug && console.group('chunk')
const start = this.cursor
const header = this.readChunkHeader()
switch (header.chunkType) {
case ChunkType.STRING_POOL:
this.readStringPool(header)
break
case ChunkType.XML_RESOURCE_MAP:
this.readResourceMap(header)
break
case ChunkType.XML_START_NAMESPACE:
this.readXmlNamespaceStart(header)
break
case ChunkType.XML_END_NAMESPACE:
this.readXmlNamespaceEnd(header)
break
case ChunkType.XML_START_ELEMENT:
this.readXmlElementStart(header)
break
case ChunkType.XML_END_ELEMENT:
this.readXmlElementEnd(header)
break
case ChunkType.XML_CDATA:
this.readXmlCData(header)
break
case ChunkType.NULL:
this.readNull(header)
break
default:
throw new Error(`Unsupported chunk type '${header.chunkType}'`)
}
// Ensure we consume the whole chunk
const end = start + header.chunkSize
if (this.cursor !== end) {
const diff = end - this.cursor
const type = header.chunkType.toString(16)
console.debug(`Cursor is off by ${diff} bytes at ${this.cursor} at supposed \
end of chunk of type 0x${type}. The chunk started at offset ${start} and is \
supposed to end at offset ${end}. Ignoring the rest of the chunk.`)
this.cursor = end
}
this.debug && console.groupEnd()
}
this.debug && console.groupEnd()
return this.document
}
}
module.exports = BinaryXmlParser

View File

@@ -0,0 +1,216 @@
// From https://github.com/openstf/adbkit-apkreader
const BinaryXmlParser = require('./binary')
const INTENT_MAIN = 'android.intent.action.MAIN'
const CATEGORY_LAUNCHER = 'android.intent.category.LAUNCHER'
class ManifestParser {
constructor (buffer, options = {}) {
this.buffer = buffer
this.xmlParser = new BinaryXmlParser(this.buffer, options)
}
collapseAttributes (element) {
const collapsed = Object.create(null)
for (let attr of Array.from(element.attributes)) {
collapsed[attr.name] = attr.typedValue.value
}
return collapsed
}
parseIntents (element, target) {
target.intentFilters = []
target.metaData = []
return element.childNodes.forEach(element => {
switch (element.nodeName) {
case 'intent-filter': {
const intentFilter = this.collapseAttributes(element)
intentFilter.actions = []
intentFilter.categories = []
intentFilter.data = []
element.childNodes.forEach(element => {
switch (element.nodeName) {
case 'action':
intentFilter.actions.push(this.collapseAttributes(element))
break
case 'category':
intentFilter.categories.push(this.collapseAttributes(element))
break
case 'data':
intentFilter.data.push(this.collapseAttributes(element))
break
}
})
target.intentFilters.push(intentFilter)
break
}
case 'meta-data':
target.metaData.push(this.collapseAttributes(element))
break
}
})
}
parseApplication (element) {
const app = this.collapseAttributes(element)
app.activities = []
app.activityAliases = []
app.launcherActivities = []
app.services = []
app.receivers = []
app.providers = []
app.usesLibraries = []
app.metaData = []
element.childNodes.forEach(element => {
switch (element.nodeName) {
case 'activity': {
const activity = this.collapseAttributes(element)
this.parseIntents(element, activity)
app.activities.push(activity)
if (this.isLauncherActivity(activity)) {
app.launcherActivities.push(activity)
}
break
}
case 'activity-alias': {
const activityAlias = this.collapseAttributes(element)
this.parseIntents(element, activityAlias)
app.activityAliases.push(activityAlias)
if (this.isLauncherActivity(activityAlias)) {
app.launcherActivities.push(activityAlias)
}
break
}
case 'service': {
const service = this.collapseAttributes(element)
this.parseIntents(element, service)
app.services.push(service)
break
}
case 'receiver': {
const receiver = this.collapseAttributes(element)
this.parseIntents(element, receiver)
app.receivers.push(receiver)
break
}
case 'provider': {
const provider = this.collapseAttributes(element)
provider.grantUriPermissions = []
provider.metaData = []
provider.pathPermissions = []
element.childNodes.forEach(element => {
switch (element.nodeName) {
case 'grant-uri-permission':
provider.grantUriPermissions.push(this.collapseAttributes(element))
break
case 'meta-data':
provider.metaData.push(this.collapseAttributes(element))
break
case 'path-permission':
provider.pathPermissions.push(this.collapseAttributes(element))
break
}
})
app.providers.push(provider)
break
}
case 'uses-library':
app.usesLibraries.push(this.collapseAttributes(element))
break
case 'meta-data':
app.metaData.push(this.collapseAttributes(element))
break
}
})
return app
}
isLauncherActivity (activity) {
return activity.intentFilters.some(function (filter) {
const hasMain = filter.actions.some(action => action.name === INTENT_MAIN)
if (!hasMain) {
return false
}
return filter.categories.some(category => category.name === CATEGORY_LAUNCHER)
})
}
parse () {
const document = this.xmlParser.parse()
const manifest = this.collapseAttributes(document)
manifest.usesPermissions = []
manifest.usesPermissionsSDK23 = []
manifest.permissions = []
manifest.permissionTrees = []
manifest.permissionGroups = []
manifest.instrumentation = null
manifest.usesSdk = null
manifest.usesConfiguration = null
manifest.usesFeatures = []
manifest.supportsScreens = null
manifest.compatibleScreens = []
manifest.supportsGlTextures = []
manifest.application = Object.create(null)
document.childNodes.forEach(element => {
switch (element.nodeName) {
case 'uses-permission':
manifest.usesPermissions.push(this.collapseAttributes(element))
break
case 'uses-permission-sdk-23':
manifest.usesPermissionsSDK23.push(this.collapseAttributes(element))
break
case 'permission':
manifest.permissions.push(this.collapseAttributes(element))
break
case 'permission-tree':
manifest.permissionTrees.push(this.collapseAttributes(element))
break
case 'permission-group':
manifest.permissionGroups.push(this.collapseAttributes(element))
break
case 'instrumentation':
manifest.instrumentation = this.collapseAttributes(element)
break
case 'uses-sdk':
manifest.usesSdk = this.collapseAttributes(element)
break
case 'uses-configuration':
manifest.usesConfiguration = this.collapseAttributes(element)
break
case 'uses-feature':
manifest.usesFeatures.push(this.collapseAttributes(element))
break
case 'supports-screens':
manifest.supportsScreens = this.collapseAttributes(element)
break
case 'compatible-screens':
element.childNodes.forEach(screen => {
return manifest.compatibleScreens.push(this.collapseAttributes(screen))
})
break
case 'supports-gl-texture':
manifest.supportsGlTextures.push(this.collapseAttributes(element))
break
case 'application':
manifest.application = this.parseApplication(element)
break
}
})
return manifest
}
}
module.exports = ManifestParser

View File

@@ -0,0 +1,66 @@
const Unzip = require('isomorphic-unzip');
const { isBrowser, decodeNullUnicode } = require('./utils');
import { enumZipEntries, readEntire } from '../../bundle';
class Zip {
constructor(file) {
if (isBrowser()) {
if (!(file instanceof window.Blob || typeof file.size !== 'undefined')) {
throw new Error(
'Param error: [file] must be an instance of Blob or File in browser.',
);
}
this.file = file;
} else {
if (typeof file !== 'string') {
throw new Error('Param error: [file] must be file path in Node.');
}
this.file = require('path').resolve(file);
}
this.unzip = new Unzip(this.file);
}
/**
* get entries by regexps, the return format is: { <filename>: <Buffer|Blob> }
* @param {Array} regexps // regexps for matching files
* @param {String} type // return type, can be buffer or blob, default buffer
*/
getEntries(regexps, type = 'buffer') {
regexps = regexps.map((regex) => decodeNullUnicode(regex));
return new Promise((resolve, reject) => {
this.unzip.getBuffer(regexps, { type }, (err, buffers) => {
err ? reject(err) : resolve(buffers);
});
});
}
/**
* get entry by regex, return an instance of Buffer or Blob
* @param {Regex} regex // regex for matching file
* @param {String} type // return type, can be buffer or blob, default buffer
*/
getEntry(regex, type = 'buffer') {
regex = decodeNullUnicode(regex);
return new Promise((resolve, reject) => {
this.unzip.getBuffer([regex], { type }, (err, buffers) => {
// console.log(buffers);
err ? reject(err) : resolve(buffers[regex]);
});
});
}
async getEntryFromHarmonyApp(regex) {
try {
let originSource;
await enumZipEntries(this.file, (entry, zipFile) => {
if (regex.test(entry.fileName)) {
return readEntire(entry, zipFile).then((v) => (originSource = v));
}
});
return originSource;
} catch (error) {
console.error('Error in getEntryFromHarmonyApp:', error);
}
}
}
module.exports = Zip;

28
src/utils/check-plugin.ts Normal file
View File

@@ -0,0 +1,28 @@
import { plugins } from './plugin-config';
interface BundleParams {
sentry: boolean;
sourcemap: boolean;
[key: string]: any;
}
export async function checkPlugins(): Promise<BundleParams> {
const params: BundleParams = {
sentry: false,
sourcemap: false,
};
for (const plugin of plugins) {
try {
const isEnabled = await plugin.detect();
if (isEnabled && plugin.bundleParams) {
Object.assign(params, plugin.bundleParams);
console.log(`检测到 ${plugin.name} 插件,应用相应打包配置`);
}
} catch (err) {
console.warn(`检测 ${plugin.name} 插件时出错:`, err);
}
}
return params;
}

View File

@@ -1,154 +0,0 @@
/**
* Created by tdzl2003 on 2/13/16.
*/
import fs from 'fs-extra';
import os from 'os';
import path from 'path';
const pkg = require('../../package.json');
const AppInfoParser = require('app-info-parser');
var read = require('read');
export function question(query, password) {
if (NO_INTERACTIVE) {
return Promise.resolve('');
}
return new Promise((resolve, reject) =>
read(
{
prompt: query,
silent: password,
replace: password ? '*' : undefined,
},
(err, result) => (err ? reject(err) : resolve(result)),
),
);
}
export function translateOptions(options) {
const ret = {};
for (let key in options) {
const v = options[key];
if (typeof v === 'string') {
ret[key] = v.replace(/\$\{(\w+)\}/g, function (v, n) {
return options[n] || process.env[n] || v;
});
} else {
ret[key] = v;
}
}
return ret;
}
export function getRNVersion() {
const version = JSON.parse(
fs.readFileSync(path.resolve('node_modules/react-native/package.json')),
).version;
// We only care about major and minor version.
const match = /^(\d+)\.(\d+)\./.exec(version);
return {
version,
major: match[1] | 0,
minor: match[2] | 0,
};
}
export async function getApkInfo(fn) {
const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntry(
/assets\/index.android.bundle/,
);
if (!bundleFile) {
throw new Error(
'找不到bundle文件。请确保此apk为release版本且bundle文件名为默认的index.android.bundle',
);
}
const updateJsonFile = await appInfoParser.parser.getEntry(
/res\/raw\/update.json/,
);
let appCredential = {};
if (updateJsonFile) {
appCredential = JSON.parse(updateJsonFile.toString()).android;
}
const { versionName, application } = await appInfoParser.parse();
let buildTime = 0;
if (Array.isArray(application.metaData)) {
for (const meta of application.metaData) {
if (meta.name === 'pushy_build_time') {
buildTime = meta.value[0];
}
}
}
if (buildTime == 0) {
throw new Error(
'无法获取此包的编译时间戳。请更新react-native-update到最新版本后重新打包上传。',
);
}
return { versionName, buildTime, ...appCredential };
}
export async function getIpaInfo(fn) {
const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/main.jsbundle/,
);
if (!bundleFile) {
throw new Error(
'找不到bundle文件。请确保此ipa为release版本且bundle文件名为默认的main.jsbundle',
);
}
const updateJsonFile = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/assets\/update.json/,
);
let appCredential = {};
if (updateJsonFile) {
appCredential = JSON.parse(updateJsonFile.toString()).ios;
}
const {
CFBundleShortVersionString: versionName,
} = await appInfoParser.parse();
let buildTimeTxtBuffer = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/pushy_build_time.txt/,
);
if (!buildTimeTxtBuffer) {
// Not in root bundle when use `use_frameworks`
buildTimeTxtBuffer = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/frameworks\/react_native_update.framework\/pushy_build_time.txt/,
);
}
if (!buildTimeTxtBuffer) {
throw new Error(
'无法获取此包的编译时间戳。请更新react-native-update到最新版本后重新打包上传。',
);
}
const buildTime = buildTimeTxtBuffer.toString().replace('\n', '');
return { versionName, buildTime, ...appCredential };
}
const localDir = path.resolve(os.homedir(), '.pushy');
fs.ensureDirSync(localDir);
export function saveToLocal(originPath, destName) {
// TODO
// const destPath = path.join(localDir, destName);
// fs.ensureDirSync(path.dirname(destPath));
// fs.copyFileSync(originPath, destPath);
}
export function printVersionCommand() {
console.log('react-native-update-cli: ' + pkg.version);
try {
const PACKAGE_JSON_PATH = path.resolve(
process.cwd(),
'node_modules',
'react-native-update',
'package.json',
);
console.log('react-native-update: ' + require(PACKAGE_JSON_PATH).version);
} catch (e) {
console.log('react-native-update: 无法获取版本号,请在项目目录中运行命令');
}
}
export const pricingPageUrl = 'https://pushy.reactnative.cn/pricing.html';

230
src/utils/index.ts Normal file
View File

@@ -0,0 +1,230 @@
import fs from 'fs-extra';
import os from 'node:os';
import path from 'node:path';
import pkg from '../../package.json';
import AppInfoParser from './app-info-parser';
import semverSatisfies from 'semver/functions/satisfies';
import chalk from 'chalk';
import latestVersion from '@badisi/latest-version';
import { checkPlugins } from './check-plugin';
import { read } from 'read';
export async function question(query, password) {
if (NO_INTERACTIVE) {
return '';
}
return read({
prompt: query,
silent: password,
replace: password ? '*' : undefined,
});
}
export function translateOptions(options) {
const ret = {};
for (const key in options) {
const v = options[key];
if (typeof v === 'string') {
ret[key] = v.replace(
/\$\{(\w+)\}/g,
(v, n) => options[n] || process.env[n] || v,
);
} else {
ret[key] = v;
}
}
return ret;
}
export function getRNVersion() {
const version = JSON.parse(
fs.readFileSync(
require.resolve('react-native/package.json', {
paths: [process.cwd()],
}),
),
).version;
// We only care about major and minor version.
const match = /^(\d+)\.(\d+)\./.exec(version);
return {
version,
major: match[1] | 0,
minor: match[2] | 0,
};
}
export async function getApkInfo(fn: string) {
const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntry(
/assets\/index.android.bundle/,
);
if (!bundleFile) {
throw new Error(
'找不到bundle文件。请确保此apk为release版本且bundle文件名为默认的index.android.bundle',
);
}
const updateJsonFile = await appInfoParser.parser.getEntry(
/res\/raw\/update.json/,
);
let appCredential = {};
if (updateJsonFile) {
appCredential = JSON.parse(updateJsonFile.toString()).android;
}
const { versionName, application } = await appInfoParser.parse();
let buildTime = 0;
if (Array.isArray(application.metaData)) {
for (const meta of application.metaData) {
if (meta.name === 'pushy_build_time') {
buildTime = meta.value[0];
}
}
}
if (buildTime == 0) {
throw new Error(
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
}
return { versionName, buildTime, ...appCredential };
}
export async function getAppInfo(fn) {
const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntryFromHarmonyApp(
/rawfile\/bundle.harmony.js/,
);
if (!bundleFile) {
throw new Error(
'找不到bundle文件。请确保此app为release版本且bundle文件名为默认的bundle.harmony.js',
);
}
const updateJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp(
/rawfile\/update.json/,
);
let appCredential = {};
if (updateJsonFile) {
appCredential = JSON.parse(updateJsonFile.toString()).harmony;
}
const metaJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp(
/rawfile\/meta.json/,
);
let metaData = {};
if (metaJsonFile) {
metaData = JSON.parse(metaJsonFile.toString());
}
const { versionName, pushy_build_time } = metaData;
let buildTime = 0;
if (pushy_build_time) {
buildTime = pushy_build_time;
}
if (buildTime == 0) {
throw new Error(
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
}
return { versionName, buildTime, ...appCredential };
}
export async function getIpaInfo(fn: string) {
const appInfoParser = new AppInfoParser(fn);
const bundleFile = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/main.jsbundle/,
);
if (!bundleFile) {
throw new Error(
'找不到bundle文件。请确保此ipa为release版本且bundle文件名为默认的main.jsbundle',
);
}
const updateJsonFile = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/assets\/update.json/,
);
let appCredential = {};
if (updateJsonFile) {
appCredential = JSON.parse(updateJsonFile.toString()).ios;
}
const { CFBundleShortVersionString: versionName } =
await appInfoParser.parse();
let buildTimeTxtBuffer = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/pushy_build_time.txt/,
);
if (!buildTimeTxtBuffer) {
// Not in root bundle when use `use_frameworks`
buildTimeTxtBuffer = await appInfoParser.parser.getEntry(
/payload\/.+?\.app\/frameworks\/react_native_update.framework\/pushy_build_time.txt/,
);
}
if (!buildTimeTxtBuffer) {
throw new Error(
'无法获取此包的编译时间戳。请更新 react-native-update 到最新版本后重新打包上传。',
);
}
const buildTime = buildTimeTxtBuffer.toString().replace('\n', '');
return { versionName, buildTime, ...appCredential };
}
const localDir = path.resolve(os.homedir(), '.pushy');
fs.ensureDirSync(localDir);
export function saveToLocal(originPath, destName) {
// TODO
// const destPath = path.join(localDir, destName);
// fs.ensureDirSync(path.dirname(destPath));
// fs.copyFileSync(originPath, destPath);
}
async function getLatestVersion(pkgName) {
return Promise.race([
latestVersion(pkgName)
.then((p) => p.latest)
.catch(() => ''),
new Promise((resolve) => setTimeout(() => resolve(''), 2000)),
]);
}
export async function printVersionCommand() {
let latestPushyCliVersion = await getLatestVersion('react-native-update-cli');
latestPushyCliVersion = latestPushyCliVersion
? ` (最新:${chalk.green(latestPushyCliVersion)}`
: '';
console.log(
`react-native-update-cli: ${pkg.version}${latestPushyCliVersion}`,
);
let pushyVersion = '';
try {
const PACKAGE_JSON_PATH = require.resolve(
'react-native-update/package.json',
{
paths: [process.cwd()],
},
);
pushyVersion = require(PACKAGE_JSON_PATH).version;
let latestPushyVersion = await getLatestVersion('react-native-update');
latestPushyVersion = latestPushyVersion
? ` (最新:${chalk.green(latestPushyVersion)}`
: '';
console.log(`react-native-update: ${pushyVersion}${latestPushyVersion}`);
} catch (e) {
console.log('react-native-update: 无法获取版本号,请在项目目录中运行命令');
}
if (pushyVersion) {
if (semverSatisfies(pushyVersion, '<8.5.2')) {
console.warn(
`当前版本已不再支持,请至少升级到 v8 的最新小版本后重新打包(代码无需改动): npm i react-native-update@8 .
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
);
} else if (semverSatisfies(pushyVersion, '9.0.0 - 9.2.1')) {
console.warn(
`当前版本已不再支持,请至少升级到 v9 的最新小版本后重新打包(代码无需改动,可直接热更): npm i react-native-update@9 .
如有使用安装 apk 的功能,请注意添加所需权限 https://pushy.reactnative.cn/docs/api#async-function-downloadandinstallapkurl`,
);
} else if (semverSatisfies(pushyVersion, '10.0.0 - 10.17.0')) {
console.warn(
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10',
);
}
}
}
export const pricingPageUrl = 'https://pushy.reactnative.cn/pricing.html';
export { checkPlugins };

View File

@@ -0,0 +1,32 @@
import fs from 'fs-extra';
interface PluginConfig {
name: string;
bundleParams?: {
[key: string]: any;
};
detect: () => Promise<boolean>;
}
export const plugins: PluginConfig[] = [
{
name: 'sentry',
bundleParams: {
sentry: true,
sourcemap: true,
},
detect: async () => {
try {
await fs.access('ios/sentry.properties');
return true;
} catch {
try {
await fs.access('android/sentry.properties');
return true;
} catch {
return false;
}
}
}
}
];

View File

@@ -1,33 +1,32 @@
/**
* Created by tdzl2003 on 4/2/16.
*/
const {
get,
post,
put,
uploadFile,
} = require('./api');
import { get, post, put, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { checkPlatform, getSelectedApp } from './app';
import { choosePackage } from './package';
import { compare } from 'compare-versions';
async function showVersion(appId, offset) {
const { data, count } = await get(`/app/${appId}/version/list`);
console.log(`Offset ${offset}`);
for (const version of data) {
let packageInfo = version.packages.slice(0, 3).map(v=>v.name).join(', ');
let packageInfo = version.packages
.slice(0, 3)
.map((v) => v.name)
.join(', ');
const count = version.packages.length;
if (count > 3) {
packageInfo += `...and ${count-3} more`;
packageInfo += `...and ${count - 3} more`;
}
if (count === 0) {
packageInfo = `(no package)`;
} else {
packageInfo = `[${packageInfo}]`;
}
console.log(`${version.id}) ${version.hash.slice(0, 8)} ${version.name} ${packageInfo}`);
console.log(
`${version.id}) ${version.hash.slice(0, 8)} ${
version.name
} ${packageInfo}`,
);
}
return data;
}
@@ -38,10 +37,17 @@ async function listVersions(appId) {
await showVersion(appId, offset);
const cmd = await question('page Up/page Down/Begin/Quit(U/D/B/Q)');
switch (cmd.toLowerCase()) {
case 'u': offset = Math.max(0, offset - 10); break;
case 'd': offset += 10; break;
case 'b': offset = 0; break;
case 'q': return;
case 'u':
offset = Math.max(0, offset - 10);
break;
case 'd':
offset += 10;
break;
case 'b':
offset = 0;
break;
case 'q':
return;
}
}
}
@@ -50,14 +56,21 @@ async function chooseVersion(appId) {
let offset = 0;
while (true) {
const data = await showVersion(appId, offset);
const cmd = await question('Enter versionId or page Up/page Down/Begin(U/D/B)');
const cmd = await question(
'Enter versionId or page Up/page Down/Begin(U/D/B)',
);
switch (cmd.toLowerCase()) {
case 'U': offset = Math.max(0, offset - 10); break;
case 'D': offset += 10; break;
case 'B': offset = 0; break;
default:
{
const v = data.find(v=>v.id === (cmd | 0));
case 'U':
offset = Math.max(0, offset - 10);
break;
case 'D':
offset += 10;
break;
case 'B':
offset = 0;
break;
default: {
const v = data.find((v) => v.id === (cmd | 0));
if (v) {
return v;
}
@@ -67,47 +80,199 @@ async function chooseVersion(appId) {
}
export const commands = {
publish: async function({args, options}) {
publish: async function ({ args, options }) {
const fn = args[0];
const {name, description, metaInfo } = options;
const { name, description, metaInfo } = options;
if (!fn || !fn.endsWith('.ppk')) {
throw new Error('Usage: pushy publish <ppkFile> --platform ios|android');
throw new Error(
'使用方法: pushy publish ppk后缀文件 --platform ios|android|harmony',
);
}
const platform = checkPlatform(options.platform || await question('Platform(ios/android):'));
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { appId } = await getSelectedApp(platform);
const { hash } = await uploadFile(fn);
const versionName = name || (await question('输入版本名称: ')) || '(未命名)';
const { id } = await post(`/app/${appId}/version/create`, {
name: name || await question('Enter version name:') || '(未命名)',
name: versionName,
hash,
description: description || await question('Enter description:'),
metaInfo: metaInfo || await question('Enter meta info:'),
description: description || (await question('输入版本描述:')),
metaInfo: metaInfo || (await question('输入自定义的 meta info:')),
});
// TODO local diff
saveToLocal(fn, `${appId}/ppk/${id}.ppk`);
console.log(`Version published: ${id}`);
console.log(`已成功上传新热更包id: ${id}`);
const v = await question('Would you like to bind packages to this version?(Y/N)');
const v = await question('是否现在将此热更应用到原生包上?(Y/N)');
if (v.toLowerCase() === 'y') {
await this.update({args:[], options:{versionId: id, platform}});
await this.update({ args: [], options: { versionId: id, platform } });
}
return versionName;
},
versions: async function({options}) {
const platform = checkPlatform(options.platform || await question('Platform(ios/android):'));
versions: async ({ options }) => {
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { appId } = await getSelectedApp(platform);
await listVersions(appId);
},
update: async function({args, options}) {
const platform = checkPlatform(options.platform || await question('Platform(ios/android):'));
update: async ({ args, options }) => {
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { appId } = await getSelectedApp(platform);
const versionId = options.versionId || (await chooseVersion(appId)).id;
const pkgId = options.packageId || (await choosePackage(appId)).id;
let versionId = options.versionId || (await chooseVersion(appId)).id;
if (versionId === 'null') {
versionId = null;
}
let pkgId;
let pkgVersion = options.packageVersion;
let minPkgVersion = options.minPackageVersion;
let maxPkgVersion = options.maxPackageVersion;
let rollout = options.rollout;
if (rollout === undefined) {
rollout = null;
} else {
try {
rollout = Number.parseInt(rollout);
} catch (e) {
throw new Error('rollout 必须是 1-100 的整数');
}
if (rollout < 1 || rollout > 100) {
throw new Error('rollout 必须是 1-100 的整数');
}
}
if (minPkgVersion) {
minPkgVersion = String(minPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((d) => compare(d.name, minPkgVersion, '>='));
if (pkgs.length === 0) {
throw new Error(`未查询到 >= ${minPkgVersion} 的原生版本`);
}
if (rollout) {
const rolloutConfig = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`已在原生版本 ${pkgs
.map((p) => p.name)
.join(', ')} 上设置灰度发布 ${rollout}% 热更版本 ${versionId}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`已将热更版本 ${versionId} 绑定到原生版本 ${pkg.name} (id: ${pkg.id})`,
);
}
console.log(`操作完成,共已绑定 ${pkgs.length} 个原生版本`);
return;
}
if (maxPkgVersion) {
maxPkgVersion = String(maxPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((d) => compare(d.name, maxPkgVersion, '<='));
if (pkgs.length === 0) {
throw new Error(`未查询到 <= ${maxPkgVersion} 的原生版本`);
}
if (rollout) {
const rolloutConfig = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`已在原生版本 ${pkgs
.map((p) => p.name)
.join(', ')} 上设置灰度发布 ${rollout}% 热更版本 ${versionId}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`已将热更版本 ${versionId} 绑定到原生版本 ${pkg.name} (id: ${pkg.id})`,
);
}
console.log(`操作完成,共已绑定 ${pkgs.length} 个原生版本`);
return;
}
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
if (pkgVersion) {
pkgVersion = pkgVersion.trim();
const pkg = data.find((d) => d.name === pkgVersion);
if (pkg) {
pkgId = pkg.id;
} else {
throw new Error(`未查询到匹配原生版本:${pkgVersion}`);
}
}
if (!pkgId) {
pkgId = options.packageId || (await choosePackage(appId)).id;
}
if (!pkgId) {
throw new Error('请提供 packageId 或 packageVersion 参数');
}
if (!pkgVersion) {
const pkg = data.find((d) => d.id === pkgId);
if (pkg) {
pkgVersion = pkg.name;
}
}
if (rollout) {
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: {
[pkgVersion]: rollout,
},
},
});
console.log(
`已将在原生版本 ${pkgVersion} (id: ${pkgId}) 上设置灰度发布 ${rollout}% 热更版本 ${versionId} `,
);
}
await put(`/app/${appId}/package/${pkgId}`, {
versionId,
});
console.log('Ok.');
}
console.log(
`已将热更版本 ${versionId} 绑定到原生版本 ${pkgVersion} (id: ${pkgId})`,
);
},
updateVersionInfo: async ({ args, options }) => {
const platform = checkPlatform(
options.platform || (await question('平台(ios/android/harmony):')),
);
const { appId } = await getSelectedApp(platform);
const versionId = options.versionId || (await chooseVersion(appId)).id;
const updateParams = {};
options.name && (updateParams.name = options.name);
options.description && (updateParams.description = options.description);
options.metaInfo && (updateParams.metaInfo = options.metaInfo);
await put(`/app/${appId}/version/${versionId}`, updateParams);
console.log('操作成功');
},
};

75
tsconfig.json Normal file
View File

@@ -0,0 +1,75 @@
{
"compilerOptions": {
/* Basic Options */
"target": "ESNext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */,
"module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
"lib": [
"ESNext"
] /* Specify library files to be included in the compilation. */,
"allowJs": true /* Allow javascript files to be compiled. */,
// "checkJs": true /* Report errors in .js files. */,
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "lib" /* Redirect output structure to the directory. */,
// "rootDir": "src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
"noEmit": true /* Do not emit outputs. */,
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
"isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */,
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"strictNullChecks": true /* Enable strict null checks. */,
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true /* Report errors on unused locals. */,
// "noUnusedParameters": true /* Report errors on unused parameters. */,
"noImplicitReturns": false /* Report error when not all code paths in function return a value. */,
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./src" /* Base directory to resolve non-absolute module names. */,
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [
// "src",
// "db",
// "config",
// "models"
// ] /* List of root folders whose combined content represents the structure of the project at runtime. */,
"typeRoots": [
"src/types"
] /* List of folders to include type definitions from. */,
// "types": [], /* Type declaration files to be included in compilation. */
"allowSyntheticDefaultImports": true /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */,
// "paths": {
// "@/*": ["src/*"]
// },
"resolveJsonModule": true,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
"skipLibCheck": true,
"incremental": true
},
"exclude": ["node_modules", "lib"]
}

4224
yarn.lock

File diff suppressed because it is too large Load Diff