mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-21 06:26:26 +00:00
feat(sdk): add update verification
This commit is contained in:
@@ -152,4 +152,33 @@ bin if you install the package):
|
||||
- `release [dir] --repo o/n --tag vX [--sign [key]] [--merge f]` — pack → GitHub release → entry, in one go.
|
||||
- `publish [dir] --repo o/n --tag vX [--sign [key]] [--no-preflight]` — **the lot**: pack → tag + release → preflight → open the PR.
|
||||
|
||||
## Update notice
|
||||
|
||||
Both CLIs (`trek-plugin` and `create-trek-plugin`) tell you when a newer SDK has been
|
||||
published. This matters more than the usual "you're on an old version" nag: the
|
||||
registry entry format, the manifest rules and the permission catalog all move with the
|
||||
TREK host, so a stale SDK can `pack` and `submit` an entry that today's registry CI
|
||||
rejects.
|
||||
|
||||
It is powered by [`update-notifier`](https://github.com/sindresorhus/update-notifier),
|
||||
the standard for npm CLIs:
|
||||
|
||||
- At most **once every 24 hours**, a detached background process asks
|
||||
`registry.npmjs.org` for this package's `latest` version and caches the answer under
|
||||
`$XDG_CONFIG_HOME/configstore/` (or `~/.config/…`).
|
||||
- Your command **never waits for it** — the notice is printed from that cache, so a
|
||||
fresh install learns about an update on a later run.
|
||||
- The notice goes to **stderr**, so `pack --json` and `entry` keep piping clean JSON.
|
||||
|
||||
The request is an unauthenticated GET for a public package — the same one `npm install`
|
||||
makes (npm's servers see your IP, as for any download). TREK has no telemetry, and this
|
||||
isn't any. To turn it off:
|
||||
|
||||
```bash
|
||||
export NO_UPDATE_NOTIFIER=1
|
||||
```
|
||||
|
||||
It is already silent in CI (any `CI` env var), under `NODE_ENV=test`, and whenever
|
||||
stdout isn't a terminal (i.e. when piped or redirected).
|
||||
|
||||
The SDK tooling in this repo is MIT. Your plugin is your own code under your own license.
|
||||
|
||||
Generated
+768
-3
@@ -1,16 +1,17 @@
|
||||
{
|
||||
"name": "trek-plugin-sdk",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "trek-plugin-sdk",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.7.0",
|
||||
"semver": "^7.7.4"
|
||||
"semver": "^7.7.4",
|
||||
"update-notifier": "^7.3.1"
|
||||
},
|
||||
"bin": {
|
||||
"create-trek-plugin": "dist/cli/create.js",
|
||||
@@ -20,6 +21,7 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.20.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/update-notifier": "^6.0.8",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.1.9"
|
||||
},
|
||||
@@ -125,6 +127,47 @@
|
||||
"url": "https://github.com/sponsors/Boshen"
|
||||
}
|
||||
},
|
||||
"node_modules/@pnpm/config.env-replace": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz",
|
||||
"integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pnpm/network.ca-file": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz",
|
||||
"integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "4.2.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": {
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@pnpm/npm-conf": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-3.0.3.tgz",
|
||||
"integrity": "sha512-//0sR/cow/s4ICQaYoAobOl4aU8cjU6x/V24V7XkKotb9+O+3zySIYp146vpaobYHnxa4pZX8NkV54Z5AwbDKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pnpm/config.env-replace": "^1.1.0",
|
||||
"@pnpm/network.ca-file": "^1.0.1",
|
||||
"config-chain": "^1.1.11"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@rolldown/binding-android-arm64": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.4.tgz",
|
||||
@@ -418,6 +461,13 @@
|
||||
"assertion-error": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/configstore": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/configstore/-/configstore-6.0.2.tgz",
|
||||
"integrity": "sha512-OS//b51j9uyR3zvwD04Kfs5kHpve2qalQ18JhY/ho3voGYUTPLEG90/ocfKPI48hyHH8T04f7KEEbK6Ue60oZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/deep-eql": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
|
||||
@@ -449,6 +499,125 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/update-notifier": {
|
||||
"version": "6.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/update-notifier/-/update-notifier-6.0.8.tgz",
|
||||
"integrity": "sha512-IlDFnfSVfYQD+cKIg63DEXn3RFmd7W1iYtKQsJodcHK9R1yr8aKbKaPKfBxzPpcHCq2DU8zUq4PIPmy19Thjfg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/configstore": "*",
|
||||
"boxen": "^7.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/boxen": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz",
|
||||
"integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-align": "^3.0.1",
|
||||
"camelcase": "^7.0.1",
|
||||
"chalk": "^5.2.0",
|
||||
"cli-boxes": "^3.0.0",
|
||||
"string-width": "^5.1.2",
|
||||
"type-fest": "^2.13.0",
|
||||
"widest-line": "^4.0.1",
|
||||
"wrap-ansi": "^8.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/camelcase": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz",
|
||||
"integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/type-fest": {
|
||||
"version": "2.19.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/widest-line": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz",
|
||||
"integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"string-width": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/update-notifier/node_modules/wrap-ansi": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
"strip-ansi": "^7.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/@vitest/expect": {
|
||||
"version": "4.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.9.tgz",
|
||||
@@ -562,6 +731,80 @@
|
||||
"url": "https://opencollective.com/vitest"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-align": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
|
||||
"integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-align/node_modules/ansi-regex": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-align/node_modules/emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/ansi-align/node_modules/string-width": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-align/node_modules/strip-ansi": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-regex": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
|
||||
"integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-styles": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
|
||||
"integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/assertion-error": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
|
||||
@@ -572,6 +815,50 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/atomically": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/atomically/-/atomically-2.1.1.tgz",
|
||||
"integrity": "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"stubborn-fs": "^2.0.0",
|
||||
"when-exit": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/boxen": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz",
|
||||
"integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-align": "^3.0.1",
|
||||
"camelcase": "^8.0.0",
|
||||
"chalk": "^5.3.0",
|
||||
"cli-boxes": "^3.0.0",
|
||||
"string-width": "^7.2.0",
|
||||
"type-fest": "^4.21.0",
|
||||
"widest-line": "^5.0.0",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/camelcase": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz",
|
||||
"integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/chai": {
|
||||
"version": "6.2.2",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
|
||||
@@ -582,6 +869,64 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/chalk": {
|
||||
"version": "5.6.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
|
||||
"integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-boxes": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz",
|
||||
"integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/config-chain": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
|
||||
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ini": "^1.3.4",
|
||||
"proto-list": "~1.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/config-chain/node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/configstore": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/configstore/-/configstore-7.1.0.tgz",
|
||||
"integrity": "sha512-N4oog6YJWbR9kGyXvS7jEykLDXIE2C0ILYqNBZBp9iwiJpoCBWYsuAdW6PPFn6w06jjnC+3JstVvWHO4cZqvRg==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"atomically": "^2.0.3",
|
||||
"dot-prop": "^9.0.0",
|
||||
"graceful-fs": "^4.2.11",
|
||||
"xdg-basedir": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/convert-source-map": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
|
||||
@@ -589,6 +934,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-libc": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
@@ -599,6 +953,34 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-prop": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-9.0.0.tgz",
|
||||
"integrity": "sha512-1gxPBJpI/pcjQhKgIU91II6Wkay+dLcN3M6rf2uwP8hRur3HtQXjVrdAK3sjC0piaEuxzMwjXChcETiJl47lAQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"type-fest": "^4.18.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
|
||||
"integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/es-module-lexer": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.0.tgz",
|
||||
@@ -606,6 +988,18 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escape-goat": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz",
|
||||
"integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/estree-walker": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
|
||||
@@ -683,6 +1077,139 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-east-asian-width": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
|
||||
"integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/global-directory": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
|
||||
"integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ini": "4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ini": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
|
||||
"integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-in-ci": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-in-ci/-/is-in-ci-1.0.0.tgz",
|
||||
"integrity": "sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"is-in-ci": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-installed-globally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-1.0.0.tgz",
|
||||
"integrity": "sha512-K55T22lfpQ63N4KEN57jZUAaAYqYHEe8veb/TycJRk9DdSCLLcovXz/mL6mOnhQaZsQGwPhuFopdQIlqGSEjiQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"global-directory": "^4.0.1",
|
||||
"is-path-inside": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-npm": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.1.0.tgz",
|
||||
"integrity": "sha512-O2z4/kNgyjhQwVR1Wpkbfc19JIhggF97NZNCpWTnjH7kVcZMUrnut9XSN7txI7VdyIYk5ZatOq3zvSuWpU8hoA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/is-path-inside": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-4.0.0.tgz",
|
||||
"integrity": "sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/ky": {
|
||||
"version": "1.14.3",
|
||||
"resolved": "https://registry.npmjs.org/ky/-/ky-1.14.3.tgz",
|
||||
"integrity": "sha512-9zy9lkjac+TR1c2tG+mkNSVlyOpInnWdSMiue4F+kq8TwJSgv6o8jhLRg8Ho6SnZ9wOYUq/yozts9qQCfk7bIw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/ky?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/latest-version": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/latest-version/-/latest-version-9.0.0.tgz",
|
||||
"integrity": "sha512-7W0vV3rqv5tokqkBAFV1LbR7HPOWzXQDpDgEuib/aJ1jsZZx6x3c2mBI+TJhJzOhkGeaLbCKEHXEXLfirtG2JA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"package-json": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.32.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz",
|
||||
@@ -954,6 +1481,15 @@
|
||||
"@jridgewell/sourcemap-codec": "^1.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/minimist": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.3.15",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
|
||||
@@ -987,6 +1523,24 @@
|
||||
"node": ">=12.20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/package-json": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/package-json/-/package-json-10.0.1.tgz",
|
||||
"integrity": "sha512-ua1L4OgXSBdsu1FPb7F3tYH0F48a6kxvod4pLUlGY9COeJAJQNX/sNH2IiEmsxw7lqYiAwrdHMjz1FctOsyDQg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ky": "^1.2.0",
|
||||
"registry-auth-token": "^5.0.2",
|
||||
"registry-url": "^6.0.1",
|
||||
"semver": "^7.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
|
||||
@@ -1043,6 +1597,75 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/proto-list": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/pupa": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pupa/-/pupa-3.3.0.tgz",
|
||||
"integrity": "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"escape-goat": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/rc": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"rc": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/rc/node_modules/ini": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/registry-auth-token": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.1.tgz",
|
||||
"integrity": "sha512-P7B4+jq8DeD2nMsAcdfaqHbssgHtZ7Z5+++a5ask90fvmJ8p5je4mOa+wzu+DB4vQ5tdJV/xywY+UnVFeQLV5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pnpm/npm-conf": "^3.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/registry-url": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz",
|
||||
"integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"rc": "1.2.8"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/rolldown": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.4.tgz",
|
||||
@@ -1126,6 +1749,62 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/string-width": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^10.3.0",
|
||||
"get-east-asian-width": "^1.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz",
|
||||
"integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/stubborn-fs": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-2.0.0.tgz",
|
||||
"integrity": "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"stubborn-utils": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/stubborn-utils": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/stubborn-utils/-/stubborn-utils-1.0.2.tgz",
|
||||
"integrity": "sha512-zOh9jPYI+xrNOyisSelgym4tolKTJCQd5GBhK0+0xJvcYDcwlOoxF/rnFKQ2KRZknXSG9jWAp66fwP6AxN9STg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tinybench": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||
@@ -1178,6 +1857,18 @@
|
||||
"license": "0BSD",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/type-fest": {
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
|
||||
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
@@ -1199,6 +1890,30 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/update-notifier": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-7.3.1.tgz",
|
||||
"integrity": "sha512-+dwUY4L35XFYEzE+OAL3sarJdUioVovq+8f7lcIJ7wnmnYQV5UD1Y/lcwaMSyaQ6Bj3JMj1XSTjZbNLHn/19yA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"boxen": "^8.0.1",
|
||||
"chalk": "^5.3.0",
|
||||
"configstore": "^7.0.0",
|
||||
"is-in-ci": "^1.0.0",
|
||||
"is-installed-globally": "^1.0.0",
|
||||
"is-npm": "^6.0.0",
|
||||
"latest-version": "^9.0.0",
|
||||
"pupa": "^3.1.0",
|
||||
"semver": "^7.6.3",
|
||||
"xdg-basedir": "^5.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/yeoman/update-notifier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "8.1.3",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-8.1.3.tgz",
|
||||
@@ -1367,6 +2082,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/when-exit": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.5.tgz",
|
||||
"integrity": "sha512-VGkKJ564kzt6Ms1dbgPP/yuIoQCrsFAnRbptpC5wOEsDaNsbCB2bnfnaA8i/vRs5tjUSEOtIuvl9/MyVsvQZCg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/why-is-node-running": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
|
||||
@@ -1383,6 +2104,50 @@
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/widest-line": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz",
|
||||
"integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"string-width": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/wrap-ansi": {
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
|
||||
"integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.2.1",
|
||||
"string-width": "^7.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/xdg-basedir": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz",
|
||||
"integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,8 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@clack/prompts": "^1.7.0",
|
||||
"semver": "^7.7.4"
|
||||
"semver": "^7.7.4",
|
||||
"update-notifier": "^7.3.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node scripts/finish-cjs.mjs",
|
||||
@@ -75,6 +76,7 @@
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.20.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"@types/update-notifier": "^6.0.8",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^4.1.9"
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
PERMISSION_CATALOG,
|
||||
} from './ui.js';
|
||||
import { KNOWN_ADDONS } from '../manifest.js';
|
||||
import { notifySdkUpdate } from './update-notice.js';
|
||||
|
||||
/** This package's own version, for the scaffold's devDependency range. */
|
||||
function sdkVersionRange(): string {
|
||||
@@ -491,6 +492,7 @@ export async function interactiveScaffold(defaultDir: string, presetName?: strin
|
||||
|
||||
// CLI entry
|
||||
if (process.argv[1] && process.argv[1].endsWith('create.js')) {
|
||||
notifySdkUpdate();
|
||||
const args = process.argv.slice(2);
|
||||
const name = args.find((a: string) => !a.startsWith('-'));
|
||||
const typeIdx = args.indexOf('--type');
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
promptText, promptConfirm, clackLogSink, missingArgs,
|
||||
} from './ui.js';
|
||||
import { runMenu } from './menu.js';
|
||||
import { notifySdkUpdate } from './update-notice.js';
|
||||
|
||||
const [cmd, ...args] = process.argv.slice(2);
|
||||
|
||||
@@ -159,6 +160,9 @@ The goal: create -> dev -> publish, and never hand-compute sha256/size/commitSha
|
||||
or hand-write the registry JSON.`;
|
||||
|
||||
async function main(): Promise<void> {
|
||||
// Advisory only (update-notifier): prints from cache on stderr, refreshes in the
|
||||
// background, never blocks. `dev` never returns, so this runs up front.
|
||||
notifySdkUpdate();
|
||||
// Before dispatch, so assertKnownFlags never sees `--help` and rejects it as unknown.
|
||||
// Help is not an error: it goes to stdout and exits 0.
|
||||
if (cmd === 'help' || cmd === '--help' || cmd === '-h' || flags.help) {
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* The background half of the update notice (#plugins) — see update-check.ts.
|
||||
*
|
||||
* Spawned detached and unref'd, so nothing is waiting on it: it asks npm for the
|
||||
* `latest` dist-tag, writes the cache the NEXT command will read, and exits. It
|
||||
* prints nothing, ever, and every failure (offline, DNS, 404, timeout, read-only
|
||||
* cache dir) is a silent no-op — the author is not debugging our update check.
|
||||
*/
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import { PACKAGE_NAME, cachePath, type UpdateCache } from './update-check.js';
|
||||
|
||||
const REGISTRY = 'https://registry.npmjs.org';
|
||||
/** Generous: nobody is waiting on this process. */
|
||||
const TIMEOUT_MS = 3000;
|
||||
|
||||
/** Ask the registry for the `latest` dist-tag. `null` on any failure. */
|
||||
export async function fetchLatest(registry: string = REGISTRY): Promise<string | null> {
|
||||
try {
|
||||
const res = await fetch(`${registry}/${PACKAGE_NAME}/latest`, {
|
||||
signal: AbortSignal.timeout(TIMEOUT_MS),
|
||||
headers: { accept: 'application/json' },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
const body = (await res.json()) as { version?: unknown };
|
||||
return typeof body?.version === 'string' ? body.version : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** Write the cache the next command reads. Silently gives up if it can't. */
|
||||
export function writeCache(file: string, cache: UpdateCache): void {
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(file), { recursive: true });
|
||||
fs.writeFileSync(file, JSON.stringify(cache));
|
||||
} catch {
|
||||
// A cache we can't write just means we check again next time.
|
||||
}
|
||||
}
|
||||
|
||||
/** Fetch → cache. Exported whole so the tests can drive it with a stubbed `fetch`. */
|
||||
export async function refresh(file: string = cachePath(), now: number = Date.now()): Promise<void> {
|
||||
const latest = await fetchLatest();
|
||||
if (latest) writeCache(file, { lastCheck: now, latest });
|
||||
}
|
||||
|
||||
// Bin entry. Never throws, never prints, always exits 0.
|
||||
if (process.argv[1] && process.argv[1].endsWith('update-check-worker.js')) {
|
||||
refresh().catch(() => {}).finally(() => process.exit(0));
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* "Your SDK is out of date" — the advisory update notice (#plugins).
|
||||
*
|
||||
* A stale SDK is not a cosmetic problem: the registry-entry format, the manifest
|
||||
* validator and the permission catalog all move with the host, so an author on an
|
||||
* old SDK can happily `pack` and `submit` an entry that today's registry CI rejects.
|
||||
*
|
||||
* Three rules keep this safe to call from the top of every command:
|
||||
* 1. ZERO added latency. The command only ever prints from a cache file; the
|
||||
* refresh runs in a DETACHED child (see update-check-worker.ts). An un-awaited
|
||||
* in-process fetch() would NOT do — Node keeps the socket alive and won't exit
|
||||
* until it resolves, so every command would pay ~300ms.
|
||||
* 2. STDERR only. stdout is a pure data channel (`entry`, `pack --json`, PR URLs) —
|
||||
* see the contract in ui.ts.
|
||||
* 3. It CANNOT fail a command. Every path is wrapped; a broken cache, a missing
|
||||
* worker or an offline machine are all silently indistinguishable from "no news".
|
||||
*/
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import os from 'node:os';
|
||||
import { spawn } from 'node:child_process';
|
||||
import { createRequire } from 'node:module';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import semver from 'semver';
|
||||
|
||||
export const PACKAGE_NAME = 'trek-plugin-sdk';
|
||||
export const CACHE_FILE = 'update-check.json';
|
||||
export const TTL_MS = 24 * 60 * 60 * 1000;
|
||||
|
||||
export interface UpdateCache {
|
||||
/** Epoch ms of the last successful registry read. */
|
||||
lastCheck: number;
|
||||
/** The `latest` dist-tag as of `lastCheck`. */
|
||||
latest: string;
|
||||
}
|
||||
|
||||
/** This package's own version — the thing we compare the registry against. */
|
||||
export function sdkVersion(): string {
|
||||
try {
|
||||
const pkg = createRequire(import.meta.url)('../../package.json') as { version?: string };
|
||||
return pkg.version ?? '0.0.0';
|
||||
} catch {
|
||||
return '0.0.0';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Where the cache lives. Takes its inputs as arguments (rather than reading the
|
||||
* environment itself) so tests can point it at a temp dir without touching $HOME.
|
||||
*/
|
||||
export function cachePath(env: NodeJS.ProcessEnv = process.env, homedir = os.homedir(), tmpdir = os.tmpdir()): string {
|
||||
const base = env.XDG_CACHE_HOME || (homedir ? path.join(homedir, '.cache') : tmpdir);
|
||||
return path.join(base, PACKAGE_NAME, CACHE_FILE);
|
||||
}
|
||||
|
||||
/** Missing, unreadable, corrupt, or wrong-shaped — all are simply "no news". Never throws. */
|
||||
export function readCache(file: string): UpdateCache | null {
|
||||
try {
|
||||
const raw = JSON.parse(fs.readFileSync(file, 'utf8')) as Partial<UpdateCache>;
|
||||
if (typeof raw?.lastCheck !== 'number' || typeof raw?.latest !== 'string') return null;
|
||||
return { lastCheck: raw.lastCheck, latest: raw.latest };
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** An absent cache is stale — that is what triggers the very first refresh. */
|
||||
export function isStale(cache: UpdateCache | null, now: number, ttlMs: number = TTL_MS): boolean {
|
||||
return !cache || now - cache.lastCheck >= ttlMs;
|
||||
}
|
||||
|
||||
/**
|
||||
* The notice is for humans at a terminal, and for nobody else: not CI logs, not
|
||||
* pipes, and not authors who have opted out.
|
||||
*/
|
||||
export function isSilenced(env: NodeJS.ProcessEnv = process.env, isTTY: boolean = Boolean(process.stderr.isTTY)): boolean {
|
||||
if (env.TREK_SDK_NO_UPDATE_CHECK || env.NO_UPDATE_NOTIFIER || env.CI) return true;
|
||||
return !isTTY;
|
||||
}
|
||||
|
||||
/** The notice itself — `null` when there is nothing to say (same version, or ahead of it). */
|
||||
export function banner(current: string, latest: string): string | null {
|
||||
if (!semver.valid(current) || !semver.valid(latest) || !semver.gt(latest, current)) return null;
|
||||
const dim = (s: string): string => `\x1b[2m${s}\x1b[0m`;
|
||||
return dim(`\n Update available ${current} → ${latest} · npm i -g ${PACKAGE_NAME}@latest\n`);
|
||||
}
|
||||
|
||||
/** Detached + unref'd, so the parent process exits the instant its own work is done. */
|
||||
function spawnRefresh(): void {
|
||||
const worker = fileURLToPath(new URL('./update-check-worker.js', import.meta.url));
|
||||
spawn(process.execPath, [worker], { detached: true, stdio: 'ignore' }).unref();
|
||||
}
|
||||
|
||||
/**
|
||||
* The one entry point. Call it at the top of a command; it returns immediately.
|
||||
* Prints from cache, and refreshes that cache in the background for the NEXT run —
|
||||
* which is why a brand-new install learns about an update one run late. That is the
|
||||
* price of never making an author wait on the network.
|
||||
*/
|
||||
export function maybeNotify(now: number = Date.now()): void {
|
||||
try {
|
||||
if (isSilenced()) return;
|
||||
const cache = readCache(cachePath());
|
||||
if (cache) {
|
||||
const msg = banner(sdkVersion(), cache.latest);
|
||||
if (msg) process.stderr.write(msg);
|
||||
}
|
||||
if (isStale(cache, now)) spawnRefresh();
|
||||
} catch {
|
||||
// An update notice is never worth failing a command over.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* "Your SDK is out of date" — the advisory update notice (#plugins).
|
||||
*
|
||||
* A stale SDK is not cosmetic: the registry-entry format, the manifest validator and
|
||||
* the permission catalog all move with the host, so an author on an old SDK can `pack`
|
||||
* and `submit` an entry that today's registry CI rejects.
|
||||
*
|
||||
* This is a thin wrapper over `update-notifier` (the de-facto standard for npm CLIs):
|
||||
* a detached background process checks the registry at most once a day, the notice is
|
||||
* printed from cache on stderr, and CI / non-TTY / `NO_UPDATE_NOTIFIER` all silence it.
|
||||
* We hand it off rather than hand-roll the same detached-child + cache dance ourselves.
|
||||
*/
|
||||
import updateNotifier from 'update-notifier';
|
||||
import { createRequire } from 'node:module';
|
||||
|
||||
export function notifySdkUpdate(): void {
|
||||
try {
|
||||
// `../../package.json` resolves to the package root from dist/cli/ (prod) and
|
||||
// src/cli/ (tests) alike. createRequire keeps it working on every Node >=18,
|
||||
// unlike `import ... with { type: 'json' }`, which Node 18 does not accept.
|
||||
const pkg = createRequire(import.meta.url)('../../package.json') as { name: string; version: string };
|
||||
updateNotifier({ pkg }).notify();
|
||||
} catch {
|
||||
// An update notice is never worth disturbing a command over.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
||||
import fs from 'node:fs';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
const spawn = vi.hoisted(() => vi.fn(() => ({ unref: vi.fn() })));
|
||||
vi.mock('node:child_process', async (orig) => ({
|
||||
...(await orig<typeof import('node:child_process')>()),
|
||||
spawn,
|
||||
}));
|
||||
|
||||
const {
|
||||
banner, cachePath, readCache, isStale, isSilenced, maybeNotify, sdkVersion, PACKAGE_NAME, TTL_MS,
|
||||
} = await import('../src/cli/update-check.js');
|
||||
const { fetchLatest, writeCache, refresh } = await import('../src/cli/update-check-worker.js');
|
||||
|
||||
let tmp: string;
|
||||
beforeEach(() => {
|
||||
tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'update-check-'));
|
||||
spawn.mockClear();
|
||||
});
|
||||
afterEach(() => {
|
||||
fs.rmSync(tmp, { recursive: true, force: true });
|
||||
vi.unstubAllEnvs();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe('banner', () => {
|
||||
it('announces only a strictly newer version', () => {
|
||||
expect(banner('1.2.0', '1.5.0')).toContain('1.2.0 → 1.5.0');
|
||||
expect(banner('1.5.0', '1.5.0')).toBeNull();
|
||||
expect(banner('1.6.0', '1.5.0')).toBeNull();
|
||||
});
|
||||
|
||||
it('says nothing when either version is unparseable', () => {
|
||||
expect(banner('not-a-version', '1.5.0')).toBeNull();
|
||||
expect(banner('1.2.0', 'garbage')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('sdkVersion', () => {
|
||||
it("reads this package's real version", () => {
|
||||
const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
||||
expect(sdkVersion()).toBe(pkg.version);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cachePath', () => {
|
||||
it('prefers XDG_CACHE_HOME, else ~/.cache', () => {
|
||||
expect(cachePath({ XDG_CACHE_HOME: '/xdg' }, '/home/a', '/tmp'))
|
||||
.toBe(path.join('/xdg', PACKAGE_NAME, 'update-check.json'));
|
||||
expect(cachePath({}, '/home/a', '/tmp'))
|
||||
.toBe(path.join('/home/a', '.cache', PACKAGE_NAME, 'update-check.json'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('readCache', () => {
|
||||
it('reads a well-formed cache', () => {
|
||||
const f = path.join(tmp, 'c.json');
|
||||
fs.writeFileSync(f, JSON.stringify({ lastCheck: 42, latest: '9.9.9' }));
|
||||
expect(readCache(f)).toEqual({ lastCheck: 42, latest: '9.9.9' });
|
||||
});
|
||||
|
||||
it('returns null — never throws — for missing, corrupt or wrong-shaped files', () => {
|
||||
expect(readCache(path.join(tmp, 'nope.json'))).toBeNull();
|
||||
|
||||
const corrupt = path.join(tmp, 'corrupt.json');
|
||||
fs.writeFileSync(corrupt, '{not json');
|
||||
expect(readCache(corrupt)).toBeNull();
|
||||
|
||||
const wrong = path.join(tmp, 'wrong.json');
|
||||
fs.writeFileSync(wrong, JSON.stringify({ latest: 5 }));
|
||||
expect(readCache(wrong)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isStale', () => {
|
||||
it('treats an absent cache as stale, and expires at the TTL boundary', () => {
|
||||
expect(isStale(null, 1_000_000)).toBe(true);
|
||||
expect(isStale({ lastCheck: 1000, latest: '1.0.0' }, 1000 + TTL_MS - 1)).toBe(false);
|
||||
expect(isStale({ lastCheck: 1000, latest: '1.0.0' }, 1000 + TTL_MS)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSilenced', () => {
|
||||
it('is silent in CI, when opted out, and when stderr is not a TTY', () => {
|
||||
expect(isSilenced({ CI: '1' }, true)).toBe(true);
|
||||
expect(isSilenced({ NO_UPDATE_NOTIFIER: '1' }, true)).toBe(true);
|
||||
expect(isSilenced({ TREK_SDK_NO_UPDATE_CHECK: '1' }, true)).toBe(true);
|
||||
expect(isSilenced({}, false)).toBe(true);
|
||||
expect(isSilenced({}, true)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('maybeNotify', () => {
|
||||
/** A human at a terminal, with $XDG_CACHE_HOME pointed at the temp dir. */
|
||||
function asHuman(): ReturnType<typeof vi.spyOn> {
|
||||
vi.stubEnv('CI', '');
|
||||
vi.stubEnv('NO_UPDATE_NOTIFIER', '');
|
||||
vi.stubEnv('TREK_SDK_NO_UPDATE_CHECK', '');
|
||||
vi.stubEnv('XDG_CACHE_HOME', tmp);
|
||||
vi.spyOn(process.stderr, 'isTTY', 'get').mockReturnValue(true);
|
||||
return vi.spyOn(process.stderr, 'write').mockReturnValue(true);
|
||||
}
|
||||
|
||||
function seedCache(cache: { lastCheck: number; latest: string }): void {
|
||||
const f = path.join(tmp, PACKAGE_NAME, 'update-check.json');
|
||||
fs.mkdirSync(path.dirname(f), { recursive: true });
|
||||
fs.writeFileSync(f, JSON.stringify(cache));
|
||||
}
|
||||
|
||||
it('prints the notice when a fresh cache holds a newer version', () => {
|
||||
const write = asHuman();
|
||||
seedCache({ lastCheck: Date.now(), latest: '999.0.0' });
|
||||
|
||||
maybeNotify();
|
||||
|
||||
expect(write).toHaveBeenCalledOnce();
|
||||
expect(String(write.mock.calls[0][0])).toContain(`999.0.0 · npm i -g ${PACKAGE_NAME}@latest`);
|
||||
expect(spawn).not.toHaveBeenCalled(); // fresh cache — no refresh
|
||||
});
|
||||
|
||||
it('prints nothing when the cached version is the one we are running', () => {
|
||||
const write = asHuman();
|
||||
seedCache({ lastCheck: Date.now(), latest: sdkVersion() });
|
||||
|
||||
maybeNotify();
|
||||
|
||||
expect(write).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('is silent on a cold cache, but spawns the background refresh for next time', () => {
|
||||
const write = asHuman();
|
||||
|
||||
maybeNotify();
|
||||
|
||||
expect(write).not.toHaveBeenCalled();
|
||||
expect(spawn).toHaveBeenCalledOnce();
|
||||
const [, args, opts] = spawn.mock.calls[0] as unknown as [string, string[], Record<string, unknown>];
|
||||
expect(args[0]).toMatch(/update-check-worker\.js$/);
|
||||
expect(opts).toMatchObject({ detached: true, stdio: 'ignore' });
|
||||
});
|
||||
|
||||
it('refreshes a stale cache while still printing what it knows', () => {
|
||||
const write = asHuman();
|
||||
seedCache({ lastCheck: Date.now() - TTL_MS - 1, latest: '999.0.0' });
|
||||
|
||||
maybeNotify();
|
||||
|
||||
expect(write).toHaveBeenCalledOnce();
|
||||
expect(spawn).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
it('does nothing at all — no print, no spawn — when silenced', () => {
|
||||
const write = asHuman();
|
||||
vi.stubEnv('CI', '1');
|
||||
seedCache({ lastCheck: Date.now(), latest: '999.0.0' });
|
||||
|
||||
maybeNotify();
|
||||
|
||||
expect(write).not.toHaveBeenCalled();
|
||||
expect(spawn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('survives a corrupt cache without throwing', () => {
|
||||
const write = asHuman();
|
||||
const f = path.join(tmp, PACKAGE_NAME, 'update-check.json');
|
||||
fs.mkdirSync(path.dirname(f), { recursive: true });
|
||||
fs.writeFileSync(f, 'not json at all');
|
||||
|
||||
expect(() => maybeNotify()).not.toThrow();
|
||||
expect(write).not.toHaveBeenCalled();
|
||||
expect(spawn).toHaveBeenCalledOnce(); // unreadable == no news == refresh
|
||||
});
|
||||
});
|
||||
|
||||
describe('worker', () => {
|
||||
it('returns the latest dist-tag version', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn(async () => new Response(JSON.stringify({ version: '2.0.0' }))));
|
||||
await expect(fetchLatest()).resolves.toBe('2.0.0');
|
||||
});
|
||||
|
||||
it('returns null on a non-200, a malformed body, or a network failure', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn(async () => new Response('nope', { status: 404 })));
|
||||
await expect(fetchLatest()).resolves.toBeNull();
|
||||
|
||||
vi.stubGlobal('fetch', vi.fn(async () => new Response(JSON.stringify({ version: 42 }))));
|
||||
await expect(fetchLatest()).resolves.toBeNull();
|
||||
|
||||
vi.stubGlobal('fetch', vi.fn(async () => { throw new Error('ENOTFOUND'); }));
|
||||
await expect(fetchLatest()).resolves.toBeNull();
|
||||
});
|
||||
|
||||
it('writes the cache only when the fetch succeeded', async () => {
|
||||
const f = path.join(tmp, 'sub', 'update-check.json');
|
||||
|
||||
vi.stubGlobal('fetch', vi.fn(async () => { throw new Error('offline'); }));
|
||||
await refresh(f, 123);
|
||||
expect(fs.existsSync(f)).toBe(false);
|
||||
|
||||
vi.stubGlobal('fetch', vi.fn(async () => new Response(JSON.stringify({ version: '3.1.0' }))));
|
||||
await refresh(f, 123);
|
||||
expect(readCache(f)).toEqual({ lastCheck: 123, latest: '3.1.0' });
|
||||
});
|
||||
|
||||
it('gives up silently when the cache is unwritable', () => {
|
||||
expect(() => writeCache('/proc/definitely/not/writable.json', { lastCheck: 1, latest: '1.0.0' })).not.toThrow();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user