mirror of
https://gitcode.com/github-mirrors/react-native-update-cli.git
synced 2025-09-16 01:41:37 +08:00
inline latest version code
This commit is contained in:
69
bun.lock
69
bun.lock
@@ -3,7 +3,7 @@
|
||||
"workspaces": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@badisi/latest-version": "^7.0.14",
|
||||
"@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,6 +24,7 @@
|
||||
"progress": "^2.0.3",
|
||||
"properties": "^1.2.1",
|
||||
"read": "^4.1.0",
|
||||
"registry-auth-token": "^5.1.0",
|
||||
"semver": "^7.7.1",
|
||||
"tcp-ping": "^0.1.1",
|
||||
"tty-table": "4.2",
|
||||
@@ -50,14 +52,9 @@
|
||||
"@biomejs/biome",
|
||||
"@swc/core",
|
||||
],
|
||||
"patchedDependencies": {
|
||||
"@badisi/latest-version@7.0.14": "patches/@badisi%2Flatest-version@7.0.14.patch",
|
||||
},
|
||||
"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.14", "", { "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-/p+0uggyIiv8PkNIcRgUvm/CWWnclJHRSSeYry4iHzXF3m1IXRS6hXKR9dtEgpF3XsvNYEvlGGF/0MBvBACgQA=="],
|
||||
|
||||
"@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=="],
|
||||
@@ -270,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=="],
|
||||
@@ -330,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=="],
|
||||
|
||||
@@ -392,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=="],
|
||||
@@ -404,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=="],
|
||||
|
||||
@@ -470,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=="],
|
||||
@@ -492,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=="],
|
||||
@@ -518,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=="],
|
||||
@@ -540,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=="],
|
||||
@@ -570,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=="],
|
||||
@@ -632,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=="],
|
||||
@@ -682,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=="],
|
||||
@@ -694,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=="],
|
||||
|
||||
@@ -812,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=="],
|
||||
@@ -848,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=="],
|
||||
@@ -880,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=="],
|
||||
@@ -898,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=="],
|
||||
@@ -920,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=="],
|
||||
@@ -936,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=="],
|
||||
@@ -960,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=="],
|
||||
@@ -974,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=="],
|
||||
|
11
package.json
11
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "react-native-update-cli",
|
||||
"version": "1.44.3",
|
||||
"version": "1.44.5",
|
||||
"description": "command line tool for react-native-update (remote updates for react native)",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
@@ -35,7 +35,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/reactnativecn/react-native-pushy/tree/master/react-native-pushy-cli",
|
||||
"dependencies": {
|
||||
"@badisi/latest-version": "^7.0.14",
|
||||
"@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,6 +56,7 @@
|
||||
"progress": "^2.0.3",
|
||||
"properties": "^1.2.1",
|
||||
"read": "^4.1.0",
|
||||
"registry-auth-token": "^5.1.0",
|
||||
"semver": "^7.7.1",
|
||||
"tcp-ping": "^0.1.1",
|
||||
"tty-table": "4.2",
|
||||
@@ -82,8 +84,5 @@
|
||||
"trustedDependencies": [
|
||||
"@biomejs/biome",
|
||||
"@swc/core"
|
||||
],
|
||||
"patchedDependencies": {
|
||||
"@badisi/latest-version@7.0.14": "patches/@badisi%2Flatest-version@7.0.14.patch"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -1,23 +0,0 @@
|
||||
diff --git a/index.js b/index.js
|
||||
index a7af7990160fa54a549cbb6245017d55e6b150f5..74b3372c53b9c693af5b571722bafd97e448a34b 100644
|
||||
--- a/index.js
|
||||
+++ b/index.js
|
||||
@@ -100,7 +100,7 @@ var downloadMetadata = (pkgName, options) => {
|
||||
}
|
||||
});
|
||||
const abort = (error) => {
|
||||
- request.removeAllListeners();
|
||||
+ // request.removeAllListeners();
|
||||
request.destroy();
|
||||
reject(error);
|
||||
};
|
||||
@@ -110,6 +110,9 @@ var downloadMetadata = (pkgName, options) => {
|
||||
request.once("error", (err) => {
|
||||
abort(err);
|
||||
});
|
||||
+ request.on("close", () => {
|
||||
+ request.removeAllListeners();
|
||||
+ });
|
||||
});
|
||||
};
|
||||
var getCacheDir = (name = "@badisi/latest-version") => {
|
@@ -5,7 +5,7 @@ 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 latestVersion from '../utils/latest-version';
|
||||
import { checkPlugins } from './check-plugin';
|
||||
|
||||
import { read } from 'read';
|
||||
|
443
src/utils/latest-version/cli.ts
Normal file
443
src/utils/latest-version/cli.ts
Normal 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 'node:fs';
|
||||
import { dirname } from 'node: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'));
|
||||
}
|
||||
}
|
||||
})();
|
497
src/utils/latest-version/index.ts
Normal file
497
src/utils/latest-version/index.ts
Normal file
@@ -0,0 +1,497 @@
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import type {
|
||||
RequestOptions as HttpRequestOptions,
|
||||
Agent,
|
||||
IncomingMessage,
|
||||
} from 'node:http';
|
||||
import type { RequestOptions as HttpsRequestOptions } from 'node:https';
|
||||
import { join, dirname, resolve as pathResolve, parse } from 'node:path';
|
||||
import { npm, yarn } from 'global-dirs';
|
||||
import { homedir } from 'node:os';
|
||||
import { URL } from 'node: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;
|
Reference in New Issue
Block a user