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

Compare commits

...

14 Commits

Author SHA1 Message Date
sunnylqm
91a602979d Refactor command exports to use specific command groups for app, bundle, package, user, and version modules 2025-06-23 11:30:36 +08:00
sunnylqm
2cfe451db5 one in all command 2025-06-20 20:32:06 +08:00
Sunny Luo
c7d0aadbf2 Update package.json 2025-06-15 18:19:17 +08:00
波仔糕
2e37d6f1c7 add logic to support SENTRY_PROPERTIES parameter (#14) 2025-06-15 10:10:04 +08:00
sunnylqm
6e7d5de82e Update version to 1.45.5, clean up imports in package.ts, and enhance localization for rollout and version messages in English and Chinese locales 2025-05-16 10:36:59 +08:00
sunnylqm
3266f09644 Update version to 1.45.4, add dryRun option in cli.json and versions.ts, and enhance localization for dryRun messages 2025-05-16 09:32:46 +08:00
sunnylqm
848f528625 Rename semverRange to packageVersionRange in cli.json and versions.ts for consistency 2025-05-15 22:48:15 +08:00
sunnylqm
18d772b1bc fix version compare 2025-05-15 22:45:08 +08:00
sunnylqm
bf0cea66b9 Update version to 1.45.1 and add semverRange property in cli.json 2025-05-15 22:29:57 +08:00
sunnylqm
8c31ee5762 semver range 2025-05-15 22:13:42 +08:00
sunnylqm
002e8662d6 Update version to 1.44.7 and modify import in zip.js to use readEntry instead of readEntire 2025-05-15 11:58:36 +08:00
sunnylqm
ebfb9dd4b9 Update version to 1.44.6, add Node.js import protocol setting, and clean up import statements across multiple files 2025-05-14 16:08:27 +08:00
sunnylqm
59c5be2719 inline latest version code 2025-05-07 14:51:32 +08:00
sunnylqm
2e8e242e75 fix latestverion timeout 2025-05-07 13:20:56 +08:00
22 changed files with 1349 additions and 350 deletions

View File

@@ -12,7 +12,8 @@
"noDoubleEquals": "off"
},
"style": {
"noNonNullAssertion": "off"
"noNonNullAssertion": "off",
"useNodejsImportProtocol": "off"
},
"a11y": {
"useValidAnchor": "off"

102
bun.lock
View File

@@ -3,7 +3,7 @@
"workspaces": {
"": {
"dependencies": {
"@badisi/latest-version": "^7.0.13",
"@colors/colors": "^1.6.0",
"bplist-parser": "^0.3.2",
"bytebuffer": "^5.0.1",
"cgbi-to-png": "^1.0.7",
@@ -14,6 +14,7 @@
"filesize-parser": "^1.5.1",
"form-data": "^4.0.2",
"fs-extra": "8",
"global-dirs": "^4.0.0",
"gradle-to-js": "^2.0.1",
"i18next": "^24.2.3",
"isomorphic-git": "^1.30.1",
@@ -23,7 +24,8 @@
"progress": "^2.0.3",
"properties": "^1.2.1",
"read": "^4.1.0",
"semver": "^7.7.1",
"registry-auth-token": "^5.1.0",
"semver": "^7.7.2",
"tcp-ping": "^0.1.1",
"tty-table": "4.2",
"yauzl": "^3.2.0",
@@ -31,11 +33,11 @@
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "^0.7.2",
"@swc/core": "^1.11.21",
"@swc/cli": "0.7.7",
"@swc/core": "^1.11.24",
"@types/filesize-parser": "^1.5.3",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.14.1",
"@types/node": "^22.15.18",
"@types/node-fetch": "^2.6.12",
"@types/progress": "^2.0.7",
"@types/semver": "^7.7.0",
@@ -53,8 +55,6 @@
"packages": {
"@babel/runtime": ["@babel/runtime@7.26.10", "", { "dependencies": { "regenerator-runtime": "^0.14.0" } }, "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw=="],
"@badisi/latest-version": ["@badisi/latest-version@7.0.13", "", { "dependencies": { "@colors/colors": "^1.6.0", "global-dirs": "3.0.1", "ora": "^8.2.0", "registry-auth-token": "^5.1.0", "semver": "^7.7.1" }, "bin": { "latest-version": "bin/latest-version", "lv": "bin/latest-version" } }, "sha512-iie68SUX7vUt6Ap9tVeb5tGE/Oj1wUAzAMhzY6mqOSy81jO9FrhRdGa8c3A7QJX3KSedn281pZ/ZZDgtsaFI6g=="],
"@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=="],
@@ -125,29 +125,29 @@
"@sindresorhus/is": ["@sindresorhus/is@5.6.0", "", {}, "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g=="],
"@swc/cli": ["@swc/cli@0.7.2", "", { "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.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-B73b2Orrd0tauaX3Jct9MxkAI79U3OMHzRB++x2wfyq+JPjgC6foJK6zyY2JI0vsTlaTbGpx9+hsowTQ8RtQFA=="],
"@swc/cli": ["@swc/cli@0.7.7", "", { "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.1", "semver": "^7.3.8", "slash": "3.0.0", "source-map": "^0.7.3" }, "peerDependencies": { "@swc/core": "^1.2.66", "chokidar": "^4.0.1" }, "optionalPeers": ["chokidar"], "bin": { "swc": "bin/swc.js", "swcx": "bin/swcx.js", "spack": "bin/spack.js" } }, "sha512-j4yYm9bx3pxWofaJKX1BFwj/3ngUDynN4UIQ2Xd2h0h/7Gt7zkReBTpDN7g5S13mgAYxacaTHTOUsz18097E8w=="],
"@swc/core": ["@swc/core@1.11.21", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.21" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.21", "@swc/core-darwin-x64": "1.11.21", "@swc/core-linux-arm-gnueabihf": "1.11.21", "@swc/core-linux-arm64-gnu": "1.11.21", "@swc/core-linux-arm64-musl": "1.11.21", "@swc/core-linux-x64-gnu": "1.11.21", "@swc/core-linux-x64-musl": "1.11.21", "@swc/core-win32-arm64-msvc": "1.11.21", "@swc/core-win32-ia32-msvc": "1.11.21", "@swc/core-win32-x64-msvc": "1.11.21" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-/Y3BJLcwd40pExmdar8MH2UGGvCBrqNN7hauOMckrEX2Ivcbv3IMhrbGX4od1dnF880Ed8y/E9aStZCIQi0EGw=="],
"@swc/core": ["@swc/core@1.11.24", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.21" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.11.24", "@swc/core-darwin-x64": "1.11.24", "@swc/core-linux-arm-gnueabihf": "1.11.24", "@swc/core-linux-arm64-gnu": "1.11.24", "@swc/core-linux-arm64-musl": "1.11.24", "@swc/core-linux-x64-gnu": "1.11.24", "@swc/core-linux-x64-musl": "1.11.24", "@swc/core-win32-arm64-msvc": "1.11.24", "@swc/core-win32-ia32-msvc": "1.11.24", "@swc/core-win32-x64-msvc": "1.11.24" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg=="],
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.21", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v6gjw9YFWvKulCw3ZA1dY+LGMafYzJksm1mD4UZFZ9b36CyHFowYVYug1ajYRIRqEvvfIhHUNV660zTLoVFR8g=="],
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.11.24", "", { "os": "darwin", "cpu": "arm64" }, "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA=="],
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.21", "", { "os": "darwin", "cpu": "x64" }, "sha512-CUiTiqKlzskwswrx9Ve5NhNoab30L1/ScOfQwr1duvNlFvarC8fvQSgdtpw2Zh3MfnfNPpyLZnYg7ah4kbT9JQ=="],
"@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.11.24", "", { "os": "darwin", "cpu": "x64" }, "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ=="],
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.21", "", { "os": "linux", "cpu": "arm" }, "sha512-YyBTAFM/QPqt1PscD8hDmCLnqPGKmUZpqeE25HXY8OLjl2MUs8+O4KjwPZZ+OGxpdTbwuWFyMoxjcLy80JODvg=="],
"@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.11.24", "", { "os": "linux", "cpu": "arm" }, "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw=="],
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.21", "", { "os": "linux", "cpu": "arm64" }, "sha512-DQD+ooJmwpNsh4acrftdkuwl5LNxxg8U4+C/RJNDd7m5FP9Wo4c0URi5U0a9Vk/6sQNh9aSGcYChDpqCDWEcBw=="],
"@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg=="],
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.21", "", { "os": "linux", "cpu": "arm64" }, "sha512-y1L49+snt1a1gLTYPY641slqy55QotPdtRK9Y6jMi4JBQyZwxC8swWYlQWb+MyILwxA614fi62SCNZNznB3XSA=="],
"@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.11.24", "", { "os": "linux", "cpu": "arm64" }, "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw=="],
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.21", "", { "os": "linux", "cpu": "x64" }, "sha512-NesdBXv4CvVEaFUlqKj+GA4jJMNUzK2NtKOrUNEtTbXaVyNiXjFCSaDajMTedEB0jTAd9ybB0aBvwhgkJUWkWA=="],
"@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.11.24", "", { "os": "linux", "cpu": "x64" }, "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg=="],
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.21", "", { "os": "linux", "cpu": "x64" }, "sha512-qFV60pwpKVOdmX67wqQzgtSrUGWX9Cibnp1CXyqZ9Mmt8UyYGvmGu7p6PMbTyX7vdpVUvWVRf8DzrW2//wmVHg=="],
"@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.11.24", "", { "os": "linux", "cpu": "x64" }, "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw=="],
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.21", "", { "os": "win32", "cpu": "arm64" }, "sha512-DJJe9k6gXR/15ZZVLv1SKhXkFst8lYCeZRNHH99SlBodvu4slhh/MKQ6YCixINRhCwliHrpXPym8/5fOq8b7Ig=="],
"@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.11.24", "", { "os": "win32", "cpu": "arm64" }, "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ=="],
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.21", "", { "os": "win32", "cpu": "ia32" }, "sha512-TqEXuy6wedId7bMwLIr9byds+mKsaXVHctTN88R1UIBPwJA92Pdk0uxDgip0pEFzHB/ugU27g6d8cwUH3h2eIw=="],
"@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.11.24", "", { "os": "win32", "cpu": "ia32" }, "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ=="],
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.21", "", { "os": "win32", "cpu": "x64" }, "sha512-BT9BNNbMxdpUM1PPAkYtviaV0A8QcXttjs2MDtOeSqqvSJaPtyM+Fof2/+xSwQDmDEFzbGCcn75M5+xy3lGqpA=="],
"@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.11.24", "", { "os": "win32", "cpu": "x64" }, "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w=="],
"@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
@@ -165,7 +165,7 @@
"@types/jsonfile": ["@types/jsonfile@6.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ=="],
"@types/node": ["@types/node@22.14.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw=="],
"@types/node": ["@types/node@22.15.18", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg=="],
"@types/node-fetch": ["@types/node-fetch@2.6.12", "", { "dependencies": { "@types/node": "*", "form-data": "^4.0.0" } }, "sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA=="],
@@ -267,10 +267,6 @@
"cli-arguments": ["cli-arguments@0.2.1", "", {}, "sha512-vaoTjiREjxKlpTNMiaJUkQnYRhgui8r+huhB6mMHcGQyz5F7Hd1o1jsW9C/wRKjlNYQ6fTvODLtZe7DxfEIz8g=="],
"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=="],
@@ -327,7 +323,7 @@
"dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
"emoji-regex": ["emoji-regex@10.4.0", "", {}, "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw=="],
"emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"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=="],
@@ -389,8 +385,6 @@
"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.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
"get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
@@ -401,7 +395,7 @@
"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=="],
"global-dirs": ["global-dirs@4.0.0", "", { "dependencies": { "ini": "2.0.0" } }, "sha512-PJ0OjGf/kVuu9gh5IPgAyssfJne5PsU9+ICxfWiRYDUnYq8ob+Y2nSWAEUNEHRj+gowyzI+wg5/nWkvcjcyLwg=="],
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
@@ -467,8 +461,6 @@
"is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
"is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
@@ -489,8 +481,6 @@
"is-typed-array": ["is-typed-array@1.1.13", "", { "dependencies": { "which-typed-array": "^1.1.14" } }, "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw=="],
"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=="],
"isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
@@ -515,8 +505,6 @@
"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=="],
@@ -537,8 +525,6 @@
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
"mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
"mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
@@ -567,8 +553,6 @@
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
"ora": ["ora@8.2.0", "", { "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-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="],
"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=="],
@@ -629,8 +613,6 @@
"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=="],
@@ -643,7 +625,7 @@
"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.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
"semver-regex": ["semver-regex@4.0.5", "", {}, "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw=="],
@@ -679,8 +661,6 @@
"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=="],
@@ -691,7 +671,7 @@
"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-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=="],
"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=="],
@@ -809,8 +789,6 @@
"call-bind/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=="],
"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=="],
"define-data-property/es-define-property": ["es-define-property@1.0.0", "", { "dependencies": { "get-intrinsic": "^1.2.4" } }, "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ=="],
@@ -845,22 +823,10 @@
"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@7.6.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A=="],
"object.assign/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"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=="],
"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=="],
"safe-array-concat/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=="],
"safe-array-concat/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
@@ -877,8 +843,6 @@
"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=="],
"string.prototype.trim/es-object-atoms": ["es-object-atoms@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw=="],
"string.prototype.trimend/es-object-atoms": ["es-object-atoms@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw=="],
@@ -895,10 +859,6 @@
"which-typed-array/gopd": ["gopd@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.1.3" } }, "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA=="],
"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=="],
"@types/fs-extra/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
@@ -917,8 +877,6 @@
"call-bind/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"define-data-property/es-define-property/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=="],
"define-data-property/gopd/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=="],
@@ -933,22 +891,16 @@
"is-array-buffer/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"ora/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"set-function-length/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"side-channel/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"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=="],
"typed-array-byte-length/gopd/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=="],
"typed-array-byte-offset/gopd/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=="],
@@ -957,10 +909,6 @@
"which-typed-array/gopd/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=="],
"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=="],
"define-data-property/es-define-property/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"define-data-property/gopd/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
@@ -971,8 +919,6 @@
"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=="],
"typed-array-byte-length/gopd/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],
"typed-array-byte-offset/gopd/get-intrinsic/has-symbols": ["has-symbols@1.0.3", "", {}, "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="],

View File

@@ -57,6 +57,27 @@
},
"metaInfo": {
"hasValue": true
},
"packageId": {
"hasValue": true
},
"packageVersion": {
"hasValue": true
},
"minPackageVersion": {
"hasValue": true
},
"maxPackageVersion": {
"hasValue": true
},
"packageVersionRange": {
"hasValue": true
},
"rollout": {
"hasValue": true
},
"dryRun": {
"default": false
}
}
},
@@ -87,8 +108,14 @@
"maxPackageVersion": {
"hasValue": true
},
"packageVersionRange": {
"hasValue": true
},
"rollout": {
"hasValue": true
},
"dryRun": {
"default": false
}
}
},
@@ -169,6 +196,27 @@
"metaInfo": {
"hasValue": true,
"description": "Meta information for publishing"
},
"packageId": {
"hasValue": true
},
"packageVersion": {
"hasValue": true
},
"minPackageVersion": {
"hasValue": true
},
"maxPackageVersion": {
"hasValue": true
},
"packageVersionRange": {
"hasValue": true
},
"rollout": {
"hasValue": true
},
"dryRun": {
"default": false
}
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-update-cli",
"version": "1.44.2",
"version": "1.46.1",
"description": "command line tool for react-native-update (remote updates for react native)",
"main": "index.js",
"bin": {
@@ -14,7 +14,7 @@
],
"scripts": {
"build": "swc src -d lib --strip-leading-paths",
"prepare": "npm run build && chmod +x lib/index.js",
"prepublishOnly": "npm run build && chmod +x lib/index.js",
"lint": "tsc --noEmit & biome check --write ."
},
"repository": {
@@ -35,7 +35,7 @@
},
"homepage": "https://github.com/reactnativecn/react-native-pushy/tree/master/react-native-pushy-cli",
"dependencies": {
"@badisi/latest-version": "^7.0.13",
"@colors/colors": "^1.6.0",
"bplist-parser": "^0.3.2",
"bytebuffer": "^5.0.1",
"cgbi-to-png": "^1.0.7",
@@ -46,6 +46,7 @@
"filesize-parser": "^1.5.1",
"form-data": "^4.0.2",
"fs-extra": "8",
"global-dirs": "^4.0.0",
"gradle-to-js": "^2.0.1",
"i18next": "^24.2.3",
"isomorphic-git": "^1.30.1",
@@ -55,7 +56,8 @@
"progress": "^2.0.3",
"properties": "^1.2.1",
"read": "^4.1.0",
"semver": "^7.7.1",
"registry-auth-token": "^5.1.0",
"semver": "^7.7.2",
"tcp-ping": "^0.1.1",
"tty-table": "4.2",
"yauzl": "^3.2.0",
@@ -66,11 +68,11 @@
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@swc/cli": "^0.7.2",
"@swc/core": "^1.11.21",
"@swc/cli": "0.7.7",
"@swc/core": "^1.11.24",
"@types/filesize-parser": "^1.5.3",
"@types/fs-extra": "^11.0.4",
"@types/node": "^22.14.1",
"@types/node": "^22.15.18",
"@types/node-fetch": "^2.6.12",
"@types/progress": "^2.0.7",
"@types/semver": "^7.7.0",

View File

@@ -1,7 +1,7 @@
import fetch from 'node-fetch';
import fs from 'node:fs';
import util from 'node:util';
import path from 'node:path';
import fs from 'fs';
import util from 'util';
import path from 'path';
import ProgressBar from 'progress';
import packageJson from '../package.json';
import tcpp from 'tcp-ping';
@@ -11,7 +11,7 @@ import {
credentialFile,
defaultEndpoint,
} from './utils/constants';
import type { Session } from 'types';
import type { Session, Package } from 'types';
import FormData from 'form-data';
import { t } from './utils/i18n';
@@ -177,3 +177,8 @@ export async function uploadFile(fn: string, key?: string) {
// const body = await response.json();
return { hash: key || formData.key };
}
export const getAllPackages = async (appId: string) => {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
return data as Package[] | undefined | null;
};

View File

@@ -1,5 +1,5 @@
import { question } from './utils';
import fs from 'node:fs';
import fs from 'fs';
import Table from 'tty-table';
import { post, get, doDelete } from './api';
@@ -8,8 +8,13 @@ import { t } from './utils/i18n';
const validPlatforms = ['ios', 'android', 'harmony'];
export async function getPlatform(platform?: string) {
return assertPlatform(
platform || (await question(t('platformQuestion'))),
) as Platform;
}
export function checkPlatform(platform: Platform) {
export function assertPlatform(platform: string) {
if (!validPlatforms.includes(platform)) {
throw new Error(t('unsupportedPlatform', { platform }));
}
@@ -17,7 +22,7 @@ export function checkPlatform(platform: Platform) {
}
export function getSelectedApp(platform: Platform) {
checkPlatform(platform);
assertPlatform(platform);
if (!fs.existsSync('update.json')) {
throw new Error(t('appNotSelected', { platform }));
@@ -61,7 +66,7 @@ export async function chooseApp(platform: Platform) {
}
}
export const commands = {
export const appCommands = {
createApp: async function ({
options,
}: {
@@ -69,9 +74,7 @@ export const commands = {
}) {
const name = options.name || (await question(t('appNameQuestion')));
const { downloadUrl } = options;
const platform = checkPlatform(
options.platform || (await question(t('platformQuestion'))),
);
const platform = await getPlatform(options.platform);
const { id } = await post('/app/create', { name, platform, downloadUrl });
console.log(t('createAppSuccess', { id }));
await this.selectApp({
@@ -79,7 +82,13 @@ export const commands = {
options: { platform },
});
},
deleteApp: async ({ args, options }: { args: string[]; options: { platform: Platform } }) => {
deleteApp: async ({
args,
options,
}: {
args: string[];
options: { platform: Platform };
}) => {
const { platform } = options;
const id = args[0] || chooseApp(platform);
if (!id) {
@@ -92,15 +101,21 @@ export const commands = {
const { platform } = options;
listApp(platform);
},
selectApp: async ({ args, options }: { args: string[]; options: { platform: Platform } }) => {
const platform = checkPlatform(
options.platform || (await question(t('platformQuestion'))),
);
selectApp: async ({
args,
options,
}: {
args: string[];
options: { platform: Platform };
}) => {
const platform = await getPlatform(options.platform);
const id = args[0]
? Number.parseInt(args[0])
: (await chooseApp(platform)).id;
let updateInfo: Partial<Record<Platform, { appId: number; appKey: string }>> = {};
let updateInfo: Partial<
Record<Platform, { appId: number; appKey: string }>
> = {};
if (fs.existsSync('update.json')) {
try {
updateInfo = JSON.parse(fs.readFileSync('update.json', 'utf8'));

View File

@@ -1,4 +1,4 @@
import path from 'node:path';
import path from 'path';
import { translateOptions } from './utils';
import * as fs from 'fs-extra';
import { ZipFile as YazlZipFile } from 'yazl';
@@ -8,18 +8,18 @@ import {
type ZipFile as YauzlZipFile,
} from 'yauzl';
import { question, checkPlugins } from './utils';
import { checkPlatform } from './app';
import { spawn, spawnSync } from 'node:child_process';
import semverSatisfies from 'semver/functions/satisfies';
import { getPlatform } from './app';
import { spawn, spawnSync } from 'child_process';
import { satisfies } from 'compare-versions';
const g2js = require('gradle-to-js/lib/parser');
import os from 'node:os';
import os from 'os';
const properties = require('properties');
import { depVersions } from './utils/dep-versions';
import { t } from './utils/i18n';
import { tempDir } from './utils/constants';
import { checkLockFiles } from './utils/check-lockfile';
import { addGitIgnore } from './utils/add-gitignore';
import { commands as versionCommands } from './versions';
import { versionCommands } from './versions';
type Diff = (oldSource?: Buffer, newSource?: Buffer) => Buffer;
@@ -101,7 +101,7 @@ async function runReactNativeBundleCommand({
.toString(),
).version;
// expo cli 0.10.17 (expo 49) 开始支持 bundle:embed
if (semverSatisfies(expoCliVersion, '>= 0.10.17')) {
if (satisfies(expoCliVersion, '>= 0.10.17')) {
usingExpo = true;
} else {
cliPath = undefined;
@@ -149,6 +149,14 @@ async function runReactNativeBundleCommand({
const bundleParams = await checkPlugins();
const isSentry = bundleParams.sentry;
if (isSentry) {
if (platform === 'ios') {
process.env.SENTRY_PROPERTIES = 'ios/sentry.properties';
} else if (platform === 'android') {
process.env.SENTRY_PROPERTIES = 'android/sentry.properties';
}
}
let bundleCommand = 'bundle';
if (usingExpo) {
bundleCommand = 'export:embed';
@@ -900,11 +908,9 @@ function diffArgsCheck(args: string[], options: any, diffFn: string) {
};
}
export const commands = {
bundle: async function ({ options }) {
const platform = checkPlatform(
options.platform || (await question(t('platformPrompt'))),
);
export const bundleCommands = {
bundle: async ({ options }) => {
const platform = await getPlatform(options.platform);
const {
bundleName,
@@ -920,6 +926,13 @@ export const commands = {
name,
description,
metaInfo,
packageId,
packageVersion,
minPackageVersion,
maxPackageVersion,
packageVersionRange,
rollout,
dryRun,
} = translateOptions({
...options,
tempDir,
@@ -968,6 +981,13 @@ export const commands = {
name,
description,
metaInfo,
packageId,
packageVersion,
minPackageVersion,
maxPackageVersion,
packageVersionRange,
rollout,
dryRun: Boolean(dryRun),
},
});
@@ -990,7 +1010,11 @@ export const commands = {
},
});
if (isSentry) {
await copyDebugidForSentry(bundleName, intermediaDir, sourcemapOutput);
await copyDebugidForSentry(
bundleName,
intermediaDir,
sourcemapOutput,
);
await uploadSourcemapForSentry(
bundleName,
intermediaDir,

View File

@@ -3,6 +3,11 @@
import { loadSession } from './api';
import { printVersionCommand } from './utils';
import { t } from './utils/i18n';
import { bundleCommands } from './bundle';
import { versionCommands } from './versions';
import { userCommands } from './user';
import { appCommands } from './app';
import { packageCommands } from './package';
function printUsage() {
// const commandName = args[0];
@@ -15,11 +20,11 @@ function printUsage() {
}
const commands = {
...require('./user').commands,
...require('./bundle').commands,
...require('./app').commands,
...require('./package').commands,
...require('./versions').commands,
...userCommands,
...bundleCommands,
...appCommands,
...packageCommands,
...versionCommands,
help: printUsage,
};

View File

@@ -73,9 +73,11 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
'Multiple lock files detected ({{- lockFiles}}), which may cause inconsistent dependencies and hot-updating issues.',
nativePackageId: 'Native Package ID',
nativeVersion: 'Native Version',
nativeVersionNotFound: 'No native version found >= {{version}}',
nativeVersionNotFoundLess: 'No native version found <= {{version}}',
nativeVersionNotFoundGte: 'No native version found >= {{version}}',
nativeVersionNotFoundLte: 'No native version found <= {{version}}',
nativeVersionNotFoundMatch: 'No matching native version found: {{version}}',
nativePackageIdNotFound: 'No native package id found: {{id}}',
noPackagesFound: 'No packages found. (appId: {{appId}})',
offset: 'Offset {{offset}}',
operationComplete: 'Operation complete, bound to {{count}} native versions',
operationSuccess: 'Operation successful',
@@ -99,7 +101,7 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
rnuVersionNotFound:
'react-native-update: Cannot get the version number. Please run the command in the project directory',
rolloutConfigSet:
'Set {{rollout}}% rollout for version {{version}} on native version(s) {{versions}}',
'Set {{rollout}}% rollout for OTA update {{version}} on native version(s) {{versions}}',
rolloutRangeError: 'rollout must be an integer between 1-100',
runningHermesc: 'Running hermesc: {{- command}} {{- args}}',
sentryCliNotFound:
@@ -120,6 +122,12 @@ This can reduce the risk of inconsistent dependencies and supply chain attacks.
usageUploadApp: 'Usage: cresc uploadApp <app file>',
usageUploadIpa: 'Usage: cresc uploadIpa <ipa file>',
versionBind:
'Bound version {{version}} to native version {{nativeVersion}} (id: {{id}})',
'Bound hot update {{version}} to native version {{nativeVersion}} (id: {{id}})',
welcomeMessage: 'Welcome to Cresc hot update service, {{name}}.',
versionNameQuestion: 'Enter OTA update name:',
versionDescriptionQuestion: 'Enter OTA update description:',
versionMetaInfoQuestion: 'Enter custom meta info:',
updateNativePackageQuestion: 'Bind to native package now?(Y/N)',
unnamed: '(Unnamed)',
dryRun: 'Below is the dry-run result, no actual operation will be performed:',
};

View File

@@ -69,9 +69,11 @@ export default {
'检测到多种不同格式的锁文件({{- lockFiles}}),这可能导致依赖关系不一致而使热更异常。',
nativePackageId: '原生包 Id',
nativeVersion: '原生版本',
nativeVersionNotFound: '未查询到 >= {{version}} 的原生版本',
nativeVersionNotFoundLess: '未查询到 <= {{version}} 的原生版本',
nativeVersionNotFoundGte: '未查询到 >= {{version}} 的原生版本',
nativeVersionNotFoundLte: '未查询到 <= {{version}} 的原生版本',
nativeVersionNotFoundMatch: '未查询到匹配原生版本:{{version}}',
nativePackageIdNotFound: '未查询到原生包 id: {{id}}',
noPackagesFound: '未查询到任何原生包appId: {{appId}}',
offset: '偏移量 {{offset}}',
operationComplete: '操作完成,共已绑定 {{count}} 个原生版本',
operationSuccess: '操作成功',
@@ -94,7 +96,7 @@ export default {
rnuVersionNotFound:
'react-native-update: 无法获取版本号。请在项目目录中运行命令',
rolloutConfigSet:
'已在原生版本 {{versions}} 上设置灰度发布 {{rollout}}% 热更版本 {{version}}',
'已在原生版本 {{versions}} 上设置灰度发布 {{rollout}}% 热更 {{version}}',
rolloutRangeError: 'rollout 必须是 1-100 的整数',
runningHermesc: '运行 hermesc{{- command}} {{- args}}',
sentryCliNotFound: '无法找到 Sentry CLI 工具,请确保已正确安装 @sentry/cli',
@@ -113,6 +115,12 @@ export default {
usageUploadApp: '使用方法: pushy uploadApp app后缀文件',
usageUploadIpa: '使用方法: pushy uploadIpa ipa后缀文件',
versionBind:
'已将热更版本 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
'已将热更 {{version}} 绑定到原生版本 {{nativeVersion}} (id: {{id}})',
welcomeMessage: '欢迎使用 pushy 热更新服务,{{name}}。',
versionNameQuestion: '输入版本名称:',
versionDescriptionQuestion: '输入版本描述:',
versionMetaInfoQuestion: '输入自定义的 meta info:',
updateNativePackageQuestion: '是否现在将此热更应用到原生包上?(Y/N)',
unnamed: '(未命名)',
dryRun: '以下是 dry-run 模拟运行结果,不会实际执行任何操作:',
};

View File

@@ -1,8 +1,8 @@
import { get, post, uploadFile } from './api';
import { get, getAllPackages, post, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { t } from './utils/i18n';
import { checkPlatform, getSelectedApp } from './app';
import { getPlatform, getSelectedApp } from './app';
import { getApkInfo, getIpaInfo, getAppInfo } from './utils';
import Table from 'tty-table';
@@ -11,14 +11,14 @@ import { getCommitInfo } from './utils/git';
import type { Platform } from 'types';
export async function listPackage(appId: string) {
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const allPkgs = await getAllPackages(appId);
const header = [
{ value: t('nativePackageId') },
{ value: t('nativeVersion') },
];
const rows = [];
for (const pkg of data) {
for (const pkg of allPkgs) {
const { version } = pkg;
let versionInfo = '';
if (version) {
@@ -36,8 +36,8 @@ export async function listPackage(appId: string) {
}
console.log(Table(header, rows).render());
console.log(t('totalPackages', { count: data.length }));
return data;
console.log(t('totalPackages', { count: allPkgs.length }));
return allPkgs;
}
export async function choosePackage(appId: string) {
@@ -52,7 +52,7 @@ export async function choosePackage(appId: string) {
}
}
export const commands = {
export const packageCommands = {
uploadIpa: async ({ args }: { args: string[] }) => {
const fn = args[0];
if (!fn || !fn.endsWith('.ipa')) {
@@ -174,9 +174,7 @@ export const commands = {
console.log(await getApkInfo(fn));
},
packages: async ({ options }: { options: { platform: Platform } }) => {
const platform = checkPlatform(
options.platform || (await question(t('platformPrompt'))),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
await listPackage(appId);
},

View File

@@ -8,3 +8,15 @@ export interface Session {
}
export type Platform = 'ios' | 'android' | 'harmony';
export interface Package {
id: string;
name: string;
}
export interface Version {
id: string;
hash: string;
name: string;
packages?: Package[];
}

View File

@@ -1,13 +1,13 @@
import { question } from './utils';
import { post, get, replaceSession, saveSession, closeSession } from './api';
import crypto from 'node:crypto';
import crypto from 'crypto';
import { t } from './utils/i18n';
function md5(str: string) {
return crypto.createHash('md5').update(str).digest('hex');
}
export const commands = {
export const userCommands = {
login: async ({ args }: { args: string[] }) => {
const email = args[0] || (await question('email:'));
const pwd = args[1] || (await question('password:', true));

View File

@@ -1,5 +1,5 @@
import fs from 'node:fs';
// import path from 'node:path';
import fs from 'fs';
// import path from 'path';
import { credentialFile, tempDir } from './constants';
import { t } from './i18n';

View File

@@ -1,6 +1,6 @@
const Unzip = require('isomorphic-unzip');
const { isBrowser, decodeNullUnicode } = require('./utils');
import { enumZipEntries, readEntire } from '../../bundle';
import { enumZipEntries, readEntry } from '../../bundle';
class Zip {
constructor(file) {
@@ -53,7 +53,7 @@ class Zip {
let originSource;
await enumZipEntries(this.file, (entry, zipFile) => {
if (regex.test(entry.fileName)) {
return readEntire(entry, zipFile).then((v) => (originSource = v));
return readEntry(entry, zipFile).then((v) => (originSource = v));
}
});
return originSource;

View File

@@ -1,5 +1,5 @@
import fs from 'node:fs';
import path from 'node:path';
import fs from 'fs';
import path from 'path';
import { t } from './i18n';
const lockFiles = [

View File

@@ -1,4 +1,4 @@
import path from 'node:path';
import path from 'path';
const scriptName = path.basename(process.argv[1]) as 'cresc' | 'pushy';
export const IS_CRESC = scriptName === 'cresc';

View File

@@ -1,6 +1,6 @@
import git from 'isomorphic-git';
import fs from 'node:fs';
import path from 'node:path';
import fs from 'fs';
import path from 'path';
export interface CommitInfo {
hash: string;

View File

@@ -1,11 +1,11 @@
import fs from 'fs-extra';
import os from 'node:os';
import path from 'node:path';
import os from 'os';
import path from 'path';
import pkg from '../../package.json';
import AppInfoParser from './app-info-parser';
import semverSatisfies from 'semver/functions/satisfies';
import { satisfies } from 'compare-versions';
import chalk from 'chalk';
import latestVersion from '@badisi/latest-version';
import latestVersion from '../utils/latest-version';
import { checkPlugins } from './check-plugin';
import { read } from 'read';
@@ -98,7 +98,7 @@ export async function getAppInfo(fn: string) {
const metaJsonFile = await appInfoParser.parser.getEntryFromHarmonyApp(
/rawfile\/meta.json/,
);
let metaData = {};
let metaData: Record<string, any> = {};
if (metaJsonFile) {
metaData = JSON.parse(metaJsonFile.toString());
}
@@ -181,35 +181,32 @@ export async function printVersionCommand() {
version: chalk.green(latestRnuCliVersion),
})}`
: '';
console.log(
`react-native-update-cli: ${pkg.version}${latestRnuCliVersion}`,
);
let rnuVersion = '';
rnuVersion = depVersions['react-native-update'];
latestRnuVersion = latestRnuVersion
? ` ${t('latestVersionTag', { version: chalk.green(latestRnuVersion) })}`
: '';
console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
console.log(`react-native-update-cli: ${pkg.version}${latestRnuCliVersion}`);
const rnuVersion = depVersions['react-native-update'];
if (rnuVersion) {
latestRnuVersion = latestRnuVersion
? ` ${t('latestVersionTag', { version: chalk.green(latestRnuVersion) })}`
: '';
console.log(`react-native-update: ${rnuVersion}${latestRnuVersion}`);
if (IS_CRESC) {
if (semverSatisfies(rnuVersion, '<10.27.0')) {
if (satisfies(rnuVersion, '<10.27.0')) {
console.error(
'Unsupported version, please update to the latest version: npm i react-native-update@latest',
);
process.exit(1);
}
} else {
if (semverSatisfies(rnuVersion, '<8.5.2')) {
if (satisfies(rnuVersion, '<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(rnuVersion, '9.0.0 - 9.2.1')) {
} else if (satisfies(rnuVersion, '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(rnuVersion, '10.0.0 - 10.17.0')) {
} else if (satisfies(rnuVersion, '10.0.0 - 10.17.0')) {
console.warn(
'当前版本已不再支持,请升级到 v10 的最新小版本(代码无需改动,可直接热更): npm i react-native-update@10',
);

View File

@@ -0,0 +1,443 @@
import {
blue,
bold,
cyan,
gray,
green,
italic,
magenta,
red,
reset,
strip,
underline,
yellow,
} from '@colors/colors/safe';
import { existsSync, readFileSync } from 'fs';
import { dirname } from 'path';
import latestVersion, {
type Package,
type PackageJson,
type LatestVersionPackage,
type LatestVersionOptions,
} from '.';
import semverMajor from 'semver/functions/major';
import semverDiff from 'semver/functions/diff';
interface TableColumn {
label: string;
attrName: keyof TableRow;
align: 'left' | 'center' | 'right';
maxLength: number;
items: string[];
}
type TableRowGroup =
| 'patch'
| 'minor'
| 'major'
| 'majorVersionZero'
| 'unknown';
interface TableRow {
name: string;
location: string;
installed: string;
tagOrRange: string;
separator: string;
wanted: string;
latest: string;
group: TableRowGroup;
}
const colorizeDiff = (from: string, to: string): string => {
const toParts = to.split('.');
const diffIndex = from.split('.').findIndex((part, i) => part !== toParts[i]);
if (diffIndex !== -1) {
let color = magenta;
if (toParts[0] !== '0') {
color = diffIndex === 0 ? red : diffIndex === 1 ? cyan : green;
}
const start = toParts.slice(0, diffIndex).join('.');
const mid = diffIndex === 0 ? '' : '.';
const end = color(toParts.slice(diffIndex).join('.'));
return `${start}${mid}${end}`;
}
return to;
};
const columnCellRenderer = (column: TableColumn, row: TableRow): string => {
let text = row[column.attrName];
const gap =
text.length < column.maxLength
? ' '.repeat(column.maxLength - text.length)
: '';
switch (column.attrName) {
case 'name':
text = yellow(text);
break;
case 'installed':
case 'separator':
text = blue(text);
break;
case 'location':
case 'tagOrRange':
text = gray(text);
break;
case 'wanted':
text = colorizeDiff(row.installed, text);
break;
case 'latest':
if (text !== row.wanted) {
text = colorizeDiff(row.installed, text);
}
break;
default:
break;
}
return column.align === 'right' ? `${gap}${text}` : `${text}${gap}`;
};
const columnHeaderRenderer = (column: TableColumn): string => {
const text = column.label;
const gap =
text.length < column.maxLength
? ' '.repeat(column.maxLength - text.length)
: '';
return column.align === 'right'
? `${gap}${underline(text)}`
: `${underline(text)}${gap}`;
};
const drawBox = (
lines: string[],
color = yellow,
horizontalPadding = 3,
): void => {
const maxLineWidth = lines.reduce(
(max, row) => Math.max(max, strip(row).length),
0,
);
console.log(color(`${'─'.repeat(maxLineWidth + horizontalPadding * 2)}`));
lines.forEach((row) => {
const padding = ' '.repeat(horizontalPadding);
const fullRow = `${row}${' '.repeat(maxLineWidth - strip(row).length)}`;
console.log(
`${color('│')}${padding}${reset(fullRow)}${padding}${color('│')}`,
);
});
console.log(color(`${'─'.repeat(maxLineWidth + horizontalPadding * 2)}`));
};
const getTableColumns = (rows: TableRow[]): TableColumn[] => {
const columns: TableColumn[] = [
{
label: 'Package',
attrName: 'name',
align: 'left',
maxLength: 0,
items: [],
},
{
label: 'Location',
attrName: 'location',
align: 'left',
maxLength: 0,
items: [],
},
{
label: 'Installed',
attrName: 'installed',
align: 'right',
maxLength: 0,
items: [],
},
{
label: '',
attrName: 'separator',
align: 'center',
maxLength: 0,
items: [],
},
{
label: 'Range',
attrName: 'tagOrRange',
align: 'right',
maxLength: 0,
items: [],
},
{
label: '',
attrName: 'separator',
align: 'center',
maxLength: 0,
items: [],
},
{
label: 'Wanted',
attrName: 'wanted',
align: 'right',
maxLength: 0,
items: [],
},
{
label: 'Latest',
attrName: 'latest',
align: 'right',
maxLength: 0,
items: [],
},
];
rows.forEach((row) => {
columns.forEach((column) => {
column.maxLength = Math.max(
column.label.length,
column.maxLength,
row[column.attrName].length || 0,
);
});
});
return columns;
};
const getTableRows = (updates: LatestVersionPackage[]): TableRow[] => {
return updates.reduce<TableRow[]>((all, pkg) => {
const {
name,
latest,
local,
globalNpm,
globalYarn,
wantedTagOrRange,
updatesAvailable,
} = pkg;
const getGroup = (a?: string, b?: string): TableRowGroup => {
if (b && semverMajor(b) === 0) {
return 'majorVersionZero';
} else if (a && b) {
const releaseType = semverDiff(a, b) ?? '';
if (['major', 'premajor', 'prerelease'].includes(releaseType)) {
return 'major';
} else if (['minor', 'preminor'].includes(releaseType)) {
return 'minor';
} else if (['patch', 'prepatch'].includes(releaseType)) {
return 'patch';
}
}
return 'unknown';
};
const add = (
group: TableRowGroup,
location: string,
installed?: string,
wanted?: string,
) =>
all.push({
name: ' ' + name,
location,
installed: installed ?? 'unknown',
latest: latest ?? 'unknown',
tagOrRange: wantedTagOrRange ?? 'unknown',
separator: '→',
wanted: wanted ?? 'unknown',
group,
});
if (updatesAvailable) {
if (updatesAvailable.local) {
add(
getGroup(local, updatesAvailable.local),
'local',
local,
updatesAvailable.local,
);
}
if (updatesAvailable.globalNpm) {
add(
getGroup(globalNpm, updatesAvailable.globalNpm),
'NPM global',
globalNpm,
updatesAvailable.globalNpm,
);
}
if (updatesAvailable.globalYarn) {
add(
getGroup(globalYarn, updatesAvailable.globalYarn),
'YARN global',
globalYarn,
updatesAvailable.globalYarn,
);
}
} else {
if (local && local !== latest) {
add(getGroup(local, latest), 'local', local, pkg.wanted);
}
if (globalNpm && globalNpm !== latest) {
add(getGroup(globalNpm, latest), 'NPM global', globalNpm, pkg.wanted);
}
if (globalYarn && globalYarn !== latest) {
add(
getGroup(globalYarn, latest),
'YARN global',
globalYarn,
pkg.wanted,
);
}
if (!local && !globalNpm && !globalYarn) {
add('unknown', 'unknown', 'unknown', pkg.wanted);
}
}
return all;
}, []);
};
const displayTable = (latestVersionPackages: LatestVersionPackage[]): void => {
const updates = latestVersionPackages.filter((pkg) => pkg.updatesAvailable);
if (updates.length) {
const rows = getTableRows(updates);
const hasUpdates = rows.some((row) => row.installed !== 'unknown');
const columns = getTableColumns(rows);
const columnGap = 2;
const getGroupLines = (
groupType: TableRowGroup,
color: (str: string) => string,
title: string,
description?: string,
): string[] => {
const items = rows
.filter((row) => row.group === groupType)
.sort((a, b) => (a.name > b.name ? 1 : -1));
return !items.length
? []
: [
'',
color(`${bold(title)} ${italic(`(${description})`)}`),
...items.map((row) =>
columns
.map((column) => columnCellRenderer(column, row))
.join(' '.repeat(columnGap)),
),
];
};
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
drawBox(
[
'',
hasUpdates ? yellow('Important updates are available.') : undefined,
hasUpdates ? '' : undefined,
columns.map(columnHeaderRenderer).join(' '.repeat(columnGap)),
...getGroupLines(
'patch',
green,
'Patch',
'backwards-compatible bug fixes',
),
...getGroupLines(
'minor',
cyan,
'Minor',
'backwards-compatible features',
),
...getGroupLines(
'major',
red,
'Major',
'potentially breaking API changes',
),
...getGroupLines(
'majorVersionZero',
magenta,
'Major version zero',
'not stable, anything may change',
),
...getGroupLines('unknown', blue, 'Missing', 'not installed'),
'',
].filter((line) => line !== undefined) as string[],
);
} else {
console.log(green('🎉 Packages are up-to-date'));
}
};
const checkVersions = async (
packages: Package | Package[] | PackageJson,
skipMissing: boolean,
options: LatestVersionOptions = { useCache: true },
): Promise<void> => {
const ora = (await import('ora')).default;
const spinner = ora({ text: cyan('Checking versions...') });
spinner.start();
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
let latestVersionPackages: LatestVersionPackage[] = await latestVersion(
packages,
options,
);
if (skipMissing) {
latestVersionPackages = latestVersionPackages.filter(
(pkg) => pkg.local ?? pkg.globalNpm ?? pkg.globalYarn,
);
}
spinner.stop();
displayTable(latestVersionPackages);
};
void (async () => {
let args = process.argv.slice(2);
const skipMissing = args.includes('--skip-missing');
// Remove any options from the arguments
args = args.filter((arg) => !arg.startsWith('-'));
// If argument is a package.json file
if (args.length === 1 && args[0].endsWith('package.json')) {
if (existsSync(args[0])) {
process.chdir(dirname(args[0]));
await checkVersions(
JSON.parse(readFileSync(args[0]).toString()) as PackageJson,
skipMissing,
);
} else {
console.log(cyan('No package.json file were found'));
}
}
// else..
else {
// Check if a local package.json file exists
let localPkgJson: PackageJson | undefined;
if (existsSync('package.json')) {
localPkgJson = JSON.parse(readFileSync('package.json').toString());
}
// Check given arguments
if (args.length) {
// Map arguments with any range that could be found in local package.json
args = args.map((arg) => {
if (localPkgJson?.dependencies?.[arg]) {
return `${arg}@${localPkgJson.dependencies?.[arg]}`;
}
if (localPkgJson?.devDependencies?.[arg]) {
return `${arg}@${localPkgJson.devDependencies?.[arg]}`;
}
if (localPkgJson?.peerDependencies?.[arg]) {
return `${arg}@${localPkgJson.peerDependencies?.[arg]}`;
}
return arg;
});
await checkVersions(args, skipMissing);
}
// ...else check the local package.json if any
else if (localPkgJson) {
await checkVersions(localPkgJson, skipMissing);
}
// ...else do nothing
else {
console.log(cyan('No packages were found'));
}
}
})();

View File

@@ -0,0 +1,497 @@
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
import type {
RequestOptions as HttpRequestOptions,
Agent,
IncomingMessage,
} from 'http';
import type { RequestOptions as HttpsRequestOptions } from 'https';
import { join, dirname, resolve as pathResolve, parse } from 'path';
import { npm, yarn } from 'global-dirs';
import { homedir } from 'os';
import { URL } from 'url';
import getRegistryUrl from 'registry-auth-token/registry-url';
import registryAuthToken from 'registry-auth-token';
import maxSatisfying from 'semver/ranges/max-satisfying';
import gt from 'semver/functions/gt';
interface RegistryVersions {
/**
* The latest version of the package found on the registry (if found).
*/
latest?: string;
/**
* The next version of the package found on the registry (if found).
*/
next?: string;
/**
* The latest version of the package found on the registry and satisfied by the wanted tag or version range.
*/
wanted?: string;
}
interface InstalledVersions {
/**
* The current local installed version of the package (if installed).
*/
local?: string;
/**
* The current npm global installed version of the package (if installed).
*/
globalNpm?: string;
/**
* The current yarn global installed version of the package (if installed).
*/
globalYarn?: string;
}
interface LatestVersionPackage extends InstalledVersions, RegistryVersions {
/**
* The name of the package.
*/
name: string;
/**
* The tag or version range that was provided (if provided).
* @default "latest"
*/
wantedTagOrRange?: string;
/**
* Whether the local or global installed versions (if any) could be upgraded or not, based on the wanted version.
*/
updatesAvailable:
| {
local: string | false;
globalNpm: string | false;
globalYarn: string | false;
}
| false;
/**
* Any error that might have occurred during the process.
*/
error?: Error;
}
interface RequestOptions {
readonly ca?: string | Buffer | Array<string | Buffer>;
readonly rejectUnauthorized?: boolean;
readonly agent?: Agent | boolean;
readonly timeout?: number;
}
interface LatestVersionOptions {
/**
* Awaiting the api to return might take time, depending on the network, and might impact your package loading performance.
* You can use the cache mechanism to improve load performance and reduce unnecessary network requests.
* If `useCache` is not supplied, the api will always check for updates and wait for every requests to return before returning itself.
* If `useCache` is used, the api will always returned immediately, with either (for each provided packages):
* 1) a latest/next version available if a cache was found
* 2) no latest/next version available if no cache was found - in such case updates will be fetched in the background and a cache will
* be created for each provided packages and made available for the next call to the api.
* @default false
*/
readonly useCache?: boolean;
/**
* How long the cache for the provided packages should be used before being refreshed (in milliseconds).
* If `useCache` is not supplied, this option has no effect.
* If `0` is used, this will force the cache to refresh immediately:
* 1) The api will returned immediately (without any latest nor next version available for the provided packages)
* 2) New updates will be fetched in the background
* 3) The cache for each provided packages will be refreshed and made available for the next call to the api
* @default ONE_DAY
*/
readonly cacheMaxAge?: number;
/**
* A JavaScript package registry url that implements the CommonJS Package Registry specification.
* @default "Looks at any registry urls in the .npmrc file or fallback to the default npm registry instead"
* @example <caption>.npmrc</caption>
* registry = 'https://custom-registry.com/'
* @pkgscope:registry = 'https://custom-registry.com/'
*/
readonly registryUrl?: string;
/**
* Set of options to be passed down to Node.js http/https request.
* @example <caption>Behind a proxy with self-signed certificate</caption>
* { ca: [ fs.readFileSync('proxy-cert.pem') ] }
* @example <caption>Bypassing certificate validation</caption>
* { rejectUnauthorized: false }
*/
readonly requestOptions?: RequestOptions;
}
interface LatestVersion {
/**
* Get latest versions of packages from of a package json like object.
* @param {PackageJson} item - A package json like object (with dependencies, devDependencies and peerDependencies attributes).
* @example { dependencies: { 'npm': 'latest' }, devDependencies: { 'npm': '1.3.2' }, peerDependencies: { '@scope/name': '^5.0.2' } }
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
* If `useCache` is not supplied, the default of `false` is used.
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the `npm registry url` instead.
* @returns {Promise<LatestVersionPackage[]>}
*/
(item: PackageJson, options?: LatestVersionOptions): Promise<
LatestVersionPackage[]
>;
/**
* Get latest version of a single package.
* @param {Package} item - A single package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
* @example 'npm', 'npm@1.3.2', '@scope/name@^5.0.2'
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
* If `useCache` is not supplied, the default of `false` is used.
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
* @returns {Promise<LatestVersionPackage>}
*/
(
item: Package,
options?: LatestVersionOptions,
): Promise<LatestVersionPackage>;
/**
* Get latest versions of a collection of packages.
* @param {Package[]} items - A collection of package object (represented by a string that should match the following format: `${'@' | ''}${string}@${string}`)
* @example ['npm', 'npm@1.3.2', '@scope/name@^5.0.2']
* @param {LatestVersionOptions} [options] - An object optionally specifying the use of the cache, the max age of the cache, the registry url and the http or https options.
* If `useCache` is not supplied, the default of `false` is used.
* If `cacheMaxAge` is not supplied, the default of `one day` is used.
* If `registryUrl` is not supplied, the default from `.npmrc` is used or a fallback to the npm registry url instead.
* @returns {Promise<LatestVersionPackage[]>}
*/
(items: Package[], options?: LatestVersionOptions): Promise<
LatestVersionPackage[]
>; // eslint-disable-line @typescript-eslint/unified-signatures
}
type PackageRange = `${'@' | ''}${string}@${string}`;
type Package = PackageRange | string; // eslint-disable-line @typescript-eslint/no-redundant-type-constituents
type PackageJsonDependencies = Record<string, string>;
type PackageJson = Record<string, any> &
(
| {
dependencies: PackageJsonDependencies;
}
| {
devDependencies: PackageJsonDependencies;
}
| {
peerDependencies: PackageJsonDependencies;
}
);
/**
* @internal
*/
interface PackageMetadata {
name: string;
lastUpdateDate: number;
versions: string[];
distTags: Record<string, string>;
}
export const ONE_DAY = 1000 * 60 * 60 * 24; // eslint-disable-line @typescript-eslint/naming-convention
const isPackageJson = (obj: any): obj is PackageJson => {
return (
(obj as PackageJson).dependencies !== undefined ||
(obj as PackageJson).devDependencies !== undefined ||
(obj as PackageJson).peerDependencies !== undefined
);
};
const downloadMetadata = (
pkgName: string,
options?: LatestVersionOptions,
): Promise<PackageMetadata> => {
return new Promise((resolve, reject) => {
const i = pkgName.indexOf('/');
const pkgScope = i !== -1 ? pkgName.slice(0, i) : '';
const registryUrl = options?.registryUrl ?? getRegistryUrl(pkgScope);
const pkgUrl = new URL(
encodeURIComponent(pkgName).replace(/^%40/, '@'),
registryUrl,
);
let requestOptions: HttpRequestOptions | HttpsRequestOptions = {
headers: {
accept:
'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*',
},
host: pkgUrl.hostname,
path: pkgUrl.pathname,
port: pkgUrl.port,
};
const authInfo = registryAuthToken(pkgUrl.toString(), { recursive: true });
if (authInfo && requestOptions.headers) {
requestOptions.headers.authorization = `${authInfo.type} ${authInfo.token}`;
}
if (options?.requestOptions) {
requestOptions = { ...requestOptions, ...options.requestOptions };
}
const { get } = require(pkgUrl.protocol === 'https:' ? 'https' : 'http');
const request = get(requestOptions, (res: IncomingMessage) => {
if (res.statusCode === 200) {
let rawData = '';
res.setEncoding('utf8');
res.on('data', (chunk: string) => (rawData += chunk));
res.once('error', (err) => {
res.removeAllListeners();
reject(`Request error (${err.message}): ${pkgUrl}`);
});
res.once('end', () => {
res.removeAllListeners();
try {
const pkgMetadata = JSON.parse(rawData);
resolve({
name: pkgName,
lastUpdateDate: Date.now(),
versions: Object.keys(pkgMetadata.versions as string[]),
distTags: pkgMetadata['dist-tags'],
});
return;
} catch (err) {
reject(err);
return;
}
});
} else {
res.removeAllListeners();
res.resume(); // consume response data to free up memory
reject(`Request error (${res.statusCode}): ${pkgUrl}`);
return;
}
});
const abort = (error: Error | string): void => {
request.destroy();
reject(error);
};
request.once('timeout', () => {
abort(`Request timed out: ${pkgUrl}`);
});
request.once('error', (err: Error) => {
abort(err);
});
request.on('close', () => {
request.removeAllListeners();
});
});
};
const getCacheDir = (name = '@badisi/latest-version'): string => {
const homeDir = homedir();
switch (process.platform) {
case 'darwin':
return join(homeDir, 'Library', 'Caches', name);
case 'win32':
return join(
process.env.LOCALAPPDATA ?? join(homeDir, 'AppData', 'Local'),
name,
'Cache',
);
default:
return join(process.env.XDG_CACHE_HOME ?? join(homeDir, '.cache'), name);
}
};
const saveMetadataToCache = (pkg: PackageMetadata): void => {
const filePath = join(getCacheDir(), `${pkg.name}.json`);
if (!existsSync(dirname(filePath))) {
mkdirSync(dirname(filePath), { recursive: true });
}
writeFileSync(filePath, JSON.stringify(pkg));
};
const getMetadataFromCache = (
pkgName: string,
options?: LatestVersionOptions,
): PackageMetadata | undefined => {
const maxAge = options?.cacheMaxAge ?? ONE_DAY;
if (maxAge !== 0) {
const pkgCacheFilePath = join(getCacheDir(), `${pkgName}.json`);
if (existsSync(pkgCacheFilePath)) {
const pkg = JSON.parse(
readFileSync(pkgCacheFilePath).toString(),
) as PackageMetadata;
if (Date.now() - pkg.lastUpdateDate < maxAge) {
return pkg;
}
}
}
return undefined; // invalidates cache
};
const getRegistryVersions = async (
pkgName: string,
tagOrRange?: string,
options?: LatestVersionOptions,
): Promise<RegistryVersions> => {
let pkgMetadata: PackageMetadata | undefined;
if (pkgName.length && options?.useCache) {
pkgMetadata = getMetadataFromCache(pkgName, options);
if (!pkgMetadata) {
pkgMetadata = await downloadMetadata(pkgName, options);
saveMetadataToCache(pkgMetadata);
}
} else if (pkgName.length) {
pkgMetadata = await downloadMetadata(pkgName, options);
}
const versions: RegistryVersions = {
latest: pkgMetadata?.distTags.latest,
next: pkgMetadata?.distTags.next,
};
if (tagOrRange && pkgMetadata?.distTags[tagOrRange]) {
versions.wanted = pkgMetadata.distTags[tagOrRange];
} else if (tagOrRange && pkgMetadata?.versions.length) {
versions.wanted =
maxSatisfying(pkgMetadata.versions, tagOrRange) ?? undefined;
}
return versions;
};
const getInstalledVersion = (
pkgName: string,
location: keyof InstalledVersions = 'local',
): string | undefined => {
try {
if (location === 'globalNpm') {
return require(join(npm.packages, pkgName, 'package.json'))
?.version as string;
} else if (location === 'globalYarn') {
// Make sure package is globally installed by Yarn
const yarnGlobalPkg = require(pathResolve(
yarn.packages,
'..',
'package.json',
));
if (!yarnGlobalPkg?.dependencies?.[pkgName]) {
return undefined;
}
return require(join(yarn.packages, pkgName, 'package.json'))
?.version as string;
} else {
/**
* Compute the local paths manually as require.resolve() and require.resolve.paths()
* cannot be trusted anymore.
* @see https://github.com/nodejs/node/issues/33460
* @see https://github.com/nodejs/loaders/issues/26
*/
const { root } = parse(process.cwd());
let path = process.cwd();
const localPaths = [join(path, 'node_modules')];
while (path !== root) {
path = dirname(path);
localPaths.push(join(path, 'node_modules'));
}
for (const localPath of localPaths) {
const pkgPath = join(localPath, pkgName, 'package.json');
if (existsSync(pkgPath)) {
return require(pkgPath)?.version as string;
}
}
}
return undefined;
} catch {
return undefined;
}
};
const getInfo = async (
pkg: Package,
options?: LatestVersionOptions,
): Promise<LatestVersionPackage> => {
const i = pkg.lastIndexOf('@');
let pkgInfo: LatestVersionPackage = {
name: i > 1 ? pkg.slice(0, i) : pkg,
wantedTagOrRange: i > 1 ? pkg.slice(i + 1) : 'latest',
updatesAvailable: false,
};
try {
pkgInfo = {
...pkgInfo,
local: getInstalledVersion(pkgInfo.name, 'local'),
globalNpm: getInstalledVersion(pkgInfo.name, 'globalNpm'),
globalYarn: getInstalledVersion(pkgInfo.name, 'globalYarn'),
...(await getRegistryVersions(
pkgInfo.name,
pkgInfo.wantedTagOrRange,
options,
)),
};
const local =
pkgInfo.local && pkgInfo.wanted
? gt(pkgInfo.wanted, pkgInfo.local)
? pkgInfo.wanted
: false
: false;
const globalNpm =
pkgInfo.globalNpm && pkgInfo.wanted
? gt(pkgInfo.wanted, pkgInfo.globalNpm)
? pkgInfo.wanted
: false
: false;
const globalYarn =
pkgInfo.globalYarn && pkgInfo.wanted
? gt(pkgInfo.wanted, pkgInfo.globalYarn)
? pkgInfo.wanted
: false
: false;
pkgInfo.updatesAvailable =
local || globalNpm || globalYarn
? { local, globalNpm, globalYarn }
: false;
} catch (err: any) {
pkgInfo.error = err?.message ?? err;
}
return pkgInfo;
};
const latestVersion: LatestVersion = async (
arg: Package | Package[] | PackageJson,
options?: LatestVersionOptions,
): Promise<any> => {
const pkgs: Package[] = [];
if (typeof arg === 'string') {
pkgs.push(arg);
} else if (Array.isArray(arg)) {
pkgs.push(...arg);
} else if (isPackageJson(arg)) {
const addDeps = (deps?: PackageJsonDependencies): void => {
if (deps) {
pkgs.push(
...Object.keys(deps).map((key: string) => `${key}@${deps[key]}`),
);
}
};
addDeps(arg.dependencies as PackageJsonDependencies | undefined);
addDeps(arg.devDependencies as PackageJsonDependencies | undefined);
addDeps(arg.peerDependencies as PackageJsonDependencies | undefined);
}
const jobs = await Promise.allSettled(
pkgs.map((pkg) => getInfo(pkg, options)),
);
const results = jobs.map(
(jobResult: PromiseSettledResult<LatestVersionPackage>) =>
(jobResult as PromiseFulfilledResult<LatestVersionPackage>).value,
);
return typeof arg === 'string' ? results[0] : results;
};
export type {
LatestVersion,
Package,
PackageRange,
PackageJson,
PackageJsonDependencies,
RegistryVersions,
LatestVersionPackage,
RequestOptions,
LatestVersionOptions,
};
export default latestVersion;

View File

@@ -1,27 +1,17 @@
import { get, post, put, uploadFile } from './api';
import { get, getAllPackages, post, put, uploadFile } from './api';
import { question, saveToLocal } from './utils';
import { t } from './utils/i18n';
import { checkPlatform, getSelectedApp } from './app';
import { getPlatform, getSelectedApp } from './app';
import { choosePackage } from './package';
import { compare } from 'compare-versions';
import { depVersions } from './utils/dep-versions';
import { getCommitInfo } from './utils/git';
import type { Platform } from 'types';
import type { Package, Platform, Version } from 'types';
import { satisfies } from 'compare-versions';
import chalk from 'chalk';
interface Package {
id: string;
name: string;
}
interface Version {
id: string;
hash: string;
name: string;
packages?: Package[];
}
interface CommandOptions {
interface VersionCommandOptions {
appId?: string;
name?: string;
description?: string;
metaInfo?: string;
@@ -31,7 +21,9 @@ interface CommandOptions {
packageVersion?: string;
minPackageVersion?: string;
maxPackageVersion?: string;
packageVersionRange?: string;
rollout?: string;
dryRun?: boolean;
}
async function showVersion(appId: string, offset: number) {
@@ -113,13 +105,65 @@ async function chooseVersion(appId: string) {
}
}
export const commands = {
export const bindVersionToPackages = async ({
appId,
versionId,
pkgs,
rollout,
dryRun,
}: {
appId: string;
versionId: string;
pkgs: Package[];
rollout?: number;
dryRun?: boolean;
}) => {
if (dryRun) {
console.log(chalk.yellow(t('dryRun')));
}
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
if (!dryRun) {
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
}
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
if (!dryRun) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
}
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
};
export const versionCommands = {
publish: async function ({
args,
options,
}: {
args: string[];
options: CommandOptions;
options: VersionCommandOptions;
}) {
const fn = args[0];
const { name, description, metaInfo } = options;
@@ -128,21 +172,19 @@ export const commands = {
throw new Error(t('publishUsage'));
}
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
const { hash } = await uploadFile(fn);
const versionName =
name || (await question('输入版本名称: ')) || '(未命名)';
name || (await question(t('versionNameQuestion'))) || t('unnamed');
const { id } = await post(`/app/${appId}/version/create`, {
name: versionName,
hash,
description: description || (await question('输入版本描述:')),
metaInfo: metaInfo || (await question('输入自定义的 meta info:')),
description:
description || (await question(t('versionDescriptionQuestion'))),
metaInfo: metaInfo || (await question(t('versionMetaInfoQuestion'))),
deps: depVersions,
commit: await getCommitInfo(),
});
@@ -150,41 +192,62 @@ export const commands = {
saveToLocal(fn, `${appId}/ppk/${id}.ppk`);
console.log(t('packageUploadSuccess', { id }));
const v = await question('是否现在将此热更应用到原生包上?(Y/N)');
if (v.toLowerCase() === 'y') {
await this.update({ args: [], options: { versionId: id, platform } });
const {
packageId,
packageVersion,
packageVersionRange,
minPackageVersion,
maxPackageVersion,
rollout,
dryRun,
} = options;
if (
packageId ||
packageVersion ||
packageVersionRange ||
minPackageVersion ||
maxPackageVersion
) {
await this.update({
options: {
versionId: id,
platform,
packageId,
packageVersion,
packageVersionRange,
minPackageVersion,
maxPackageVersion,
rollout,
dryRun,
},
});
} else {
const q = await question(t('updateNativePackageQuestion'));
if (q.toLowerCase() === 'y') {
await this.update({ options: { versionId: id, platform } });
}
}
return versionName;
},
versions: async ({ options }: { options: CommandOptions }) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
versions: async ({ options }: { options: VersionCommandOptions }) => {
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
await listVersions(appId);
},
update: async ({
args,
options,
}: {
args: string[];
options: CommandOptions;
}) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const { appId } = await getSelectedApp(platform);
update: async ({ options }: { options: VersionCommandOptions }) => {
const platform = await getPlatform(options.platform);
const appId = options.appId || (await getSelectedApp(platform)).appId;
let versionId = options.versionId || (await chooseVersion(appId)).id;
if (versionId === 'null') {
versionId = undefined;
}
let pkgId: string | undefined;
let pkgId = options.packageId;
let pkgVersion = options.packageVersion;
let minPkgVersion = options.minPackageVersion;
let maxPkgVersion = options.maxPackageVersion;
let packageVersionRange = options.packageVersionRange;
let rollout: number | undefined = undefined;
if (options.rollout !== undefined) {
@@ -198,159 +261,86 @@ export const commands = {
}
}
if (minPkgVersion) {
minPkgVersion = String(minPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((pkg: Package) =>
compare(pkg.name, minPkgVersion!, '>='),
);
if (pkgs.length === 0) {
throw new Error(t('nativeVersionNotFound', { version: minPkgVersion }));
}
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
return;
}
if (maxPkgVersion) {
maxPkgVersion = String(maxPkgVersion).trim();
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
const pkgs = data.filter((pkg: Package) =>
compare(pkg.name, maxPkgVersion!, '<='),
);
if (pkgs.length === 0) {
throw new Error(
t('nativeVersionNotFoundLess', { version: maxPkgVersion }),
);
}
if (rollout !== undefined) {
const rolloutConfig: Record<string, number> = {};
for (const pkg of pkgs) {
rolloutConfig[pkg.name] = rollout;
}
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: rolloutConfig,
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgs.map((pkg: Package) => pkg.name).join(', '),
rollout: rollout,
})}`,
);
}
for (const pkg of pkgs) {
await put(`/app/${appId}/package/${pkg.id}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkg.name,
id: pkg.id,
})}`,
);
}
console.log(t('operationComplete', { count: pkgs.length }));
return;
const allPkgs = await getAllPackages(appId);
if (!allPkgs) {
throw new Error(t('noPackagesFound', { appId }));
}
const { data } = await get(`/app/${appId}/package/list?limit=1000`);
if (pkgVersion) {
let pkgsToBind: Package[] = [];
if (minPkgVersion) {
minPkgVersion = String(minPkgVersion).trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, `>=${minPkgVersion}`),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundGte', { version: minPkgVersion }),
);
}
} else if (maxPkgVersion) {
maxPkgVersion = String(maxPkgVersion).trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, `<=${maxPkgVersion}`),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundLte', { version: maxPkgVersion }),
);
}
} else if (pkgVersion) {
pkgVersion = pkgVersion.trim();
const pkg = data.find((pkg: Package) => pkg.name === pkgVersion);
const pkg = allPkgs.find((pkg: Package) => pkg.name === pkgVersion);
if (pkg) {
pkgId = pkg.id;
pkgsToBind = [pkg];
} else {
throw new Error(
t('nativeVersionNotFoundMatch', { version: pkgVersion }),
);
}
}
if (!pkgId) {
pkgId = options.packageId || (await choosePackage(appId)).id;
}
} else if (packageVersionRange) {
packageVersionRange = packageVersionRange.trim();
pkgsToBind = allPkgs.filter((pkg: Package) =>
satisfies(pkg.name, packageVersionRange!),
);
if (pkgsToBind.length === 0) {
throw new Error(
t('nativeVersionNotFoundMatch', { version: packageVersionRange }),
);
}
} else {
if (!pkgId) {
pkgId = (await choosePackage(appId)).id;
}
if (!pkgId) {
throw new Error(t('packageIdRequired'));
}
if (!pkgVersion) {
const pkg = data.find((pkg: Package) => String(pkg.id) === String(pkgId));
if (!pkgId) {
throw new Error(t('packageIdRequired'));
}
const pkg = allPkgs.find(
(pkg: Package) => String(pkg.id) === String(pkgId),
);
if (pkg) {
pkgVersion = pkg.name;
pkgsToBind = [pkg];
} else {
throw new Error(t('nativePackageIdNotFound', { id: pkgId }));
}
}
if (rollout !== undefined && pkgVersion) {
await put(`/app/${appId}/version/${versionId}`, {
config: {
rollout: {
[pkgVersion]: rollout,
},
},
});
console.log(
`${t('rolloutConfigSet', {
versions: pkgVersion,
rollout: rollout,
})}`,
);
}
if (versionId !== undefined) {
await put(`/app/${appId}/package/${pkgId}`, {
versionId,
});
console.log(
`${t('versionBind', {
version: versionId,
nativeVersion: pkgVersion,
id: pkgId,
})}`,
);
}
console.log(t('operationSuccess'));
await bindVersionToPackages({
appId,
versionId,
pkgs: pkgsToBind,
rollout,
dryRun: options.dryRun,
});
},
updateVersionInfo: async ({
args,
options,
}: {
args: string[];
options: CommandOptions;
options: VersionCommandOptions;
}) => {
const platform = checkPlatform(
options.platform ||
((await question('平台(ios/android/harmony):')) as Platform),
);
const platform = await getPlatform(options.platform);
const { appId } = await getSelectedApp(platform);
const versionId = options.versionId || (await chooseVersion(appId)).id;