keyv-github 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.releaserc.json +14 -0
- package/README.md +44 -8
- package/bun.lock +86 -19
- package/dist/index.d.mts +11 -3
- package/dist/index.mjs +57 -33
- package/package.json +2 -1
- package/src/index.test.ts +34 -1
- package/src/index.ts +89 -36
package/.releaserc.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"plugins": [
|
|
3
|
+
"@semantic-release/commit-analyzer",
|
|
4
|
+
"@semantic-release/release-notes-generator",
|
|
5
|
+
"@semantic-release/npm",
|
|
6
|
+
[
|
|
7
|
+
"@semantic-release/git",
|
|
8
|
+
{
|
|
9
|
+
"message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"@semantic-release/github"
|
|
13
|
+
]
|
|
14
|
+
}
|
package/README.md
CHANGED
|
@@ -45,11 +45,38 @@ await kv.delete("data/hello.txt");
|
|
|
45
45
|
new KeyvGithub(repoUrl, options?)
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
| Option
|
|
49
|
-
|
|
50
|
-
| `branch` | `string`
|
|
51
|
-
| `client` | `Octokit`
|
|
52
|
-
| `msg`
|
|
48
|
+
| Option | Type | Default | Description |
|
|
49
|
+
| -------- | ------------------------ | ----------------------------------- | -------------------------------------------------------- |
|
|
50
|
+
| `branch` | `string` | parsed from URL or `"main"` | Target branch |
|
|
51
|
+
| `client` | `Octokit` | `new Octokit()` | Authenticated Octokit instance |
|
|
52
|
+
| `msg` | `(key, value) => string` | `"update <key>"` / `"delete <key>"` | Customize commit messages; `value` is `null` for deletes |
|
|
53
|
+
| `prefix` | `string` | `""` | Path prefix prepended to every key (e.g. `"data/"`) |
|
|
54
|
+
| `suffix` | `string` | `""` | Path suffix appended to every key (e.g. `".json"`) |
|
|
55
|
+
|
|
56
|
+
### Store limitations
|
|
57
|
+
|
|
58
|
+
When using `KeyvGithub` directly (without wrapping in `Keyv`):
|
|
59
|
+
|
|
60
|
+
- **Values must be strings** — objects, arrays, and numbers will throw an error
|
|
61
|
+
- **TTL is not supported** — passing a TTL parameter throws an error
|
|
62
|
+
|
|
63
|
+
To store non-string values or use TTL, wrap the store with `new Keyv(store)`:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// Direct usage: strings only, no TTL
|
|
67
|
+
await store.set("key", "string value"); // ✓
|
|
68
|
+
await store.set("key", { obj: true }); // ✗ throws error
|
|
69
|
+
await store.set("key", "value", 1000); // ✗ throws error
|
|
70
|
+
|
|
71
|
+
// With Keyv wrapper: any serializable value, TTL supported
|
|
72
|
+
const kv = new Keyv({ store });
|
|
73
|
+
await kv.set("key", { obj: true }); // ✓ serialized automatically
|
|
74
|
+
await kv.set("key", "value", 1000); // ✓ TTL handled by Keyv
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### TTL
|
|
78
|
+
|
|
79
|
+
TTL is **not enforced at the adapter level** — GitHub has no native file expiry. If you pass a `ttl` to `new Keyv({ store, ttl })`, Keyv handles it by wrapping values as `{"value":…,"expires":…}` and filtering on read. Expired files remain in the repo as inert files until overwritten or deleted. This adapter is best suited for long-lived or permanent storage.
|
|
53
80
|
|
|
54
81
|
### URL formats accepted
|
|
55
82
|
|
|
@@ -66,9 +93,7 @@ owner/repo/tree/my-branch
|
|
|
66
93
|
```ts
|
|
67
94
|
const store = new KeyvGithub("owner/repo", {
|
|
68
95
|
msg: (key, value) =>
|
|
69
|
-
value === null
|
|
70
|
-
? `chore: delete ${key}`
|
|
71
|
-
: `chore: update ${key} → ${value.slice(0, 40)}`,
|
|
96
|
+
value === null ? `chore: delete ${key}` : `chore: update ${key} → ${value.slice(0, 40)}`,
|
|
72
97
|
});
|
|
73
98
|
```
|
|
74
99
|
|
|
@@ -84,6 +109,17 @@ Keys must be valid relative file paths:
|
|
|
84
109
|
|
|
85
110
|
Invalid keys throw synchronously before any API request.
|
|
86
111
|
|
|
112
|
+
## See Also
|
|
113
|
+
|
|
114
|
+
Other Keyv storage adapters by the same author:
|
|
115
|
+
|
|
116
|
+
- [keyv-sqlite](https://github.com/snomiao/keyv-sqlite) — SQLite storage adapter
|
|
117
|
+
- [keyv-mongodb-store](https://github.com/snomiao/keyv-mongodb-store) — MongoDB storage adapter
|
|
118
|
+
- [keyv-nedb-store](https://github.com/snomiao/keyv-nedb-store) — NeDB embedded file-based adapter
|
|
119
|
+
- [keyv-dir-store](https://github.com/snomiao/keyv-dir-store) — file-per-key directory adapter with TTL via mtime
|
|
120
|
+
- [keyv-cache-proxy](https://github.com/snomiao/keyv-cache-proxy) — transparent caching proxy that wraps any object
|
|
121
|
+
- [keyv-nest](https://github.com/snomiao/keyv-nest) — hierarchical multi-layer caching adapter
|
|
122
|
+
|
|
87
123
|
## License
|
|
88
124
|
|
|
89
125
|
MIT
|
package/bun.lock
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"octokit": "^5.0.5",
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
|
+
"@semantic-release/git": "^10.0.1",
|
|
12
13
|
"@types/bun": "latest",
|
|
13
14
|
"semantic-release": "^25.0.3",
|
|
14
15
|
"tsdown": "^0.20.3",
|
|
@@ -149,7 +150,9 @@
|
|
|
149
150
|
|
|
150
151
|
"@semantic-release/commit-analyzer": ["@semantic-release/commit-analyzer@13.0.1", "", { "dependencies": { "conventional-changelog-angular": "^8.0.0", "conventional-changelog-writer": "^8.0.0", "conventional-commits-filter": "^5.0.0", "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", "import-from-esm": "^2.0.0", "lodash-es": "^4.17.21", "micromatch": "^4.0.2" }, "peerDependencies": { "semantic-release": ">=20.1.0" } }, "sha512-wdnBPHKkr9HhNhXOhZD5a2LNl91+hs8CC2vsAVYxtZH3y0dV3wKn+uZSN61rdJQZ8EGxzWB3inWocBHV9+u/CQ=="],
|
|
151
152
|
|
|
152
|
-
"@semantic-release/error": ["@semantic-release/error@
|
|
153
|
+
"@semantic-release/error": ["@semantic-release/error@3.0.0", "", {}, "sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw=="],
|
|
154
|
+
|
|
155
|
+
"@semantic-release/git": ["@semantic-release/git@10.0.1", "", { "dependencies": { "@semantic-release/error": "^3.0.0", "aggregate-error": "^3.0.0", "debug": "^4.0.0", "dir-glob": "^3.0.0", "execa": "^5.0.0", "lodash": "^4.17.4", "micromatch": "^4.0.0", "p-reduce": "^2.0.0" }, "peerDependencies": { "semantic-release": ">=18.0.0" } }, "sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w=="],
|
|
153
156
|
|
|
154
157
|
"@semantic-release/github": ["@semantic-release/github@12.0.6", "", { "dependencies": { "@octokit/core": "^7.0.0", "@octokit/plugin-paginate-rest": "^14.0.0", "@octokit/plugin-retry": "^8.0.0", "@octokit/plugin-throttling": "^11.0.0", "@semantic-release/error": "^4.0.0", "aggregate-error": "^5.0.0", "debug": "^4.3.4", "dir-glob": "^3.0.1", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "issue-parser": "^7.0.0", "lodash-es": "^4.17.21", "mime": "^4.0.0", "p-filter": "^4.0.0", "tinyglobby": "^0.2.14", "undici": "^7.0.0", "url-join": "^5.0.0" }, "peerDependencies": { "semantic-release": ">=24.1.0" } }, "sha512-aYYFkwHW3c6YtHwQF0t0+lAjlU+87NFOZuH2CvWFD0Ylivc7MwhZMiHOJ0FMpIgPpCVib/VUAcOwvrW0KnxQtA=="],
|
|
155
158
|
|
|
@@ -193,7 +196,7 @@
|
|
|
193
196
|
|
|
194
197
|
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
|
195
198
|
|
|
196
|
-
"aggregate-error": ["aggregate-error@
|
|
199
|
+
"aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="],
|
|
197
200
|
|
|
198
201
|
"ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
|
|
199
202
|
|
|
@@ -231,7 +234,7 @@
|
|
|
231
234
|
|
|
232
235
|
"char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
|
|
233
236
|
|
|
234
|
-
"clean-stack": ["clean-stack@
|
|
237
|
+
"clean-stack": ["clean-stack@2.2.0", "", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="],
|
|
235
238
|
|
|
236
239
|
"cli-highlight": ["cli-highlight@2.1.11", "", { "dependencies": { "chalk": "^4.0.0", "highlight.js": "^10.7.1", "mz": "^2.4.0", "parse5": "^5.1.1", "parse5-htmlparser2-tree-adapter": "^6.0.0", "yargs": "^16.0.0" }, "bin": { "highlight": "bin/highlight" } }, "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg=="],
|
|
237
240
|
|
|
@@ -299,7 +302,7 @@
|
|
|
299
302
|
|
|
300
303
|
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
|
301
304
|
|
|
302
|
-
"execa": ["execa@
|
|
305
|
+
"execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="],
|
|
303
306
|
|
|
304
307
|
"fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="],
|
|
305
308
|
|
|
@@ -349,7 +352,7 @@
|
|
|
349
352
|
|
|
350
353
|
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
|
351
354
|
|
|
352
|
-
"human-signals": ["human-signals@
|
|
355
|
+
"human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="],
|
|
353
356
|
|
|
354
357
|
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
|
|
355
358
|
|
|
@@ -359,7 +362,7 @@
|
|
|
359
362
|
|
|
360
363
|
"import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="],
|
|
361
364
|
|
|
362
|
-
"indent-string": ["indent-string@
|
|
365
|
+
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
|
|
363
366
|
|
|
364
367
|
"index-to-position": ["index-to-position@1.2.0", "", {}, "sha512-Yg7+ztRkqslMAS2iFaU+Oa4KTSidr63OsFGlOrJoW981kIYO3CGCS3wA95P1mUi/IVSJkn0D479KTJpVpvFNuw=="],
|
|
365
368
|
|
|
@@ -379,7 +382,7 @@
|
|
|
379
382
|
|
|
380
383
|
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
|
|
381
384
|
|
|
382
|
-
"is-stream": ["is-stream@
|
|
385
|
+
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
|
383
386
|
|
|
384
387
|
"is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
|
|
385
388
|
|
|
@@ -411,6 +414,8 @@
|
|
|
411
414
|
|
|
412
415
|
"locate-path": ["locate-path@2.0.0", "", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA=="],
|
|
413
416
|
|
|
417
|
+
"lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
|
|
418
|
+
|
|
414
419
|
"lodash-es": ["lodash-es@4.17.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
|
|
415
420
|
|
|
416
421
|
"lodash.capitalize": ["lodash.capitalize@4.2.1", "", {}, "sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw=="],
|
|
@@ -439,7 +444,7 @@
|
|
|
439
444
|
|
|
440
445
|
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
|
|
441
446
|
|
|
442
|
-
"mimic-fn": ["mimic-fn@
|
|
447
|
+
"mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="],
|
|
443
448
|
|
|
444
449
|
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
|
|
445
450
|
|
|
@@ -459,7 +464,7 @@
|
|
|
459
464
|
|
|
460
465
|
"npm": ["npm@11.10.0", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/arborist": "^9.3.0", "@npmcli/config": "^10.7.0", "@npmcli/fs": "^5.0.0", "@npmcli/map-workspaces": "^5.0.3", "@npmcli/metavuln-calculator": "^9.0.3", "@npmcli/package-json": "^7.0.4", "@npmcli/promise-spawn": "^9.0.1", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.3", "@sigstore/tuf": "^4.0.1", "abbrev": "^4.0.0", "archy": "~1.0.0", "cacache": "^20.0.3", "chalk": "^5.6.2", "ci-info": "^4.4.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", "glob": "^13.0.2", "graceful-fs": "^4.2.11", "hosted-git-info": "^9.0.2", "ini": "^6.0.0", "init-package-json": "^8.2.4", "is-cidr": "^6.0.3", "json-parse-even-better-errors": "^5.0.0", "libnpmaccess": "^10.0.3", "libnpmdiff": "^8.1.1", "libnpmexec": "^10.2.1", "libnpmfund": "^7.0.15", "libnpmorg": "^8.0.1", "libnpmpack": "^9.1.1", "libnpmpublish": "^11.1.3", "libnpmsearch": "^9.0.1", "libnpmteam": "^8.0.2", "libnpmversion": "^8.0.3", "make-fetch-happen": "^15.0.3", "minimatch": "^10.1.1", "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", "node-gyp": "^12.2.0", "nopt": "^9.0.0", "npm-audit-report": "^7.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.2", "npm-pick-manifest": "^11.0.3", "npm-profile": "^12.0.1", "npm-registry-fetch": "^19.1.1", "npm-user-validate": "^4.0.0", "p-map": "^7.0.4", "pacote": "^21.3.1", "parse-conflict-json": "^5.0.1", "proc-log": "^6.1.0", "qrcode-terminal": "^0.12.0", "read": "^5.0.1", "semver": "^7.7.4", "spdx-expression-parse": "^4.0.0", "ssri": "^13.0.1", "supports-color": "^10.2.2", "tar": "^7.5.7", "text-table": "~0.2.0", "tiny-relative-date": "^2.0.2", "treeverse": "^3.0.0", "validate-npm-package-name": "^7.0.2", "which": "^6.0.1" }, "bin": { "npm": "bin/npm-cli.js", "npx": "bin/npx-cli.js" } }, "sha512-i8hE43iSIAMFuYVi8TxsEISdELM4fIza600aLjJ0ankGPLqd0oTPKMJqAcO/QWm307MbSlWGzJcNZ0lGMQgHPA=="],
|
|
461
466
|
|
|
462
|
-
"npm-run-path": ["npm-run-path@
|
|
467
|
+
"npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="],
|
|
463
468
|
|
|
464
469
|
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
|
465
470
|
|
|
@@ -467,7 +472,7 @@
|
|
|
467
472
|
|
|
468
473
|
"octokit": ["octokit@5.0.5", "", { "dependencies": { "@octokit/app": "^16.1.2", "@octokit/core": "^7.0.6", "@octokit/oauth-app": "^8.0.3", "@octokit/plugin-paginate-graphql": "^6.0.0", "@octokit/plugin-paginate-rest": "^14.0.0", "@octokit/plugin-rest-endpoint-methods": "^17.0.0", "@octokit/plugin-retry": "^8.0.3", "@octokit/plugin-throttling": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "@octokit/webhooks": "^14.0.0" } }, "sha512-4+/OFSqOjoyULo7eN7EA97DE0Xydj/PW5aIckxqQIoFjFwqXKuFCvXUJObyJfBF9Khu4RL/jlDRI9FPaMGfPnw=="],
|
|
469
474
|
|
|
470
|
-
"onetime": ["onetime@
|
|
475
|
+
"onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="],
|
|
471
476
|
|
|
472
477
|
"p-each-series": ["p-each-series@3.0.0", "", {}, "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw=="],
|
|
473
478
|
|
|
@@ -483,7 +488,7 @@
|
|
|
483
488
|
|
|
484
489
|
"p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="],
|
|
485
490
|
|
|
486
|
-
"p-reduce": ["p-reduce@
|
|
491
|
+
"p-reduce": ["p-reduce@2.1.0", "", {}, "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw=="],
|
|
487
492
|
|
|
488
493
|
"p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="],
|
|
489
494
|
|
|
@@ -555,7 +560,7 @@
|
|
|
555
560
|
|
|
556
561
|
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
|
557
562
|
|
|
558
|
-
"signal-exit": ["signal-exit@
|
|
563
|
+
"signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="],
|
|
559
564
|
|
|
560
565
|
"signale": ["signale@1.4.0", "", { "dependencies": { "chalk": "^2.3.2", "figures": "^2.0.0", "pkg-conf": "^2.1.0" } }, "sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w=="],
|
|
561
566
|
|
|
@@ -585,7 +590,7 @@
|
|
|
585
590
|
|
|
586
591
|
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
|
|
587
592
|
|
|
588
|
-
"strip-final-newline": ["strip-final-newline@
|
|
593
|
+
"strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="],
|
|
589
594
|
|
|
590
595
|
"strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
|
|
591
596
|
|
|
@@ -683,6 +688,16 @@
|
|
|
683
688
|
|
|
684
689
|
"@pnpm/network.ca-file/graceful-fs": ["graceful-fs@4.2.10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
|
|
685
690
|
|
|
691
|
+
"@semantic-release/github/@semantic-release/error": ["@semantic-release/error@4.0.0", "", {}, "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ=="],
|
|
692
|
+
|
|
693
|
+
"@semantic-release/github/aggregate-error": ["aggregate-error@5.0.0", "", { "dependencies": { "clean-stack": "^5.2.0", "indent-string": "^5.0.0" } }, "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw=="],
|
|
694
|
+
|
|
695
|
+
"@semantic-release/npm/@semantic-release/error": ["@semantic-release/error@4.0.0", "", {}, "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ=="],
|
|
696
|
+
|
|
697
|
+
"@semantic-release/npm/aggregate-error": ["aggregate-error@5.0.0", "", { "dependencies": { "clean-stack": "^5.2.0", "indent-string": "^5.0.0" } }, "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw=="],
|
|
698
|
+
|
|
699
|
+
"@semantic-release/npm/execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="],
|
|
700
|
+
|
|
686
701
|
"@semantic-release/release-notes-generator/get-stream": ["get-stream@7.0.1", "", {}, "sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ=="],
|
|
687
702
|
|
|
688
703
|
"@semantic-release/release-notes-generator/read-package-up": ["read-package-up@11.0.0", "", { "dependencies": { "find-up-simple": "^1.0.0", "read-pkg": "^9.0.0", "type-fest": "^4.6.0" } }, "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ=="],
|
|
@@ -697,8 +712,6 @@
|
|
|
697
712
|
|
|
698
713
|
"env-ci/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
|
699
714
|
|
|
700
|
-
"execa/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
|
701
|
-
|
|
702
715
|
"import-fresh/resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
|
|
703
716
|
|
|
704
717
|
"load-json-file/parse-json": ["parse-json@4.0.0", "", { "dependencies": { "error-ex": "^1.3.1", "json-parse-better-errors": "^1.0.1" } }, "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw=="],
|
|
@@ -1015,14 +1028,18 @@
|
|
|
1015
1028
|
|
|
1016
1029
|
"npm/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
|
1017
1030
|
|
|
1018
|
-
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
|
1019
|
-
|
|
1020
|
-
"npm-run-path/unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
|
1021
|
-
|
|
1022
1031
|
"parse5-htmlparser2-tree-adapter/parse5": ["parse5@6.0.1", "", {}, "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="],
|
|
1023
1032
|
|
|
1024
1033
|
"read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
|
|
1025
1034
|
|
|
1035
|
+
"semantic-release/@semantic-release/error": ["@semantic-release/error@4.0.0", "", {}, "sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ=="],
|
|
1036
|
+
|
|
1037
|
+
"semantic-release/aggregate-error": ["aggregate-error@5.0.0", "", { "dependencies": { "clean-stack": "^5.2.0", "indent-string": "^5.0.0" } }, "sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw=="],
|
|
1038
|
+
|
|
1039
|
+
"semantic-release/execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="],
|
|
1040
|
+
|
|
1041
|
+
"semantic-release/p-reduce": ["p-reduce@3.0.0", "", {}, "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q=="],
|
|
1042
|
+
|
|
1026
1043
|
"signale/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
|
1027
1044
|
|
|
1028
1045
|
"signale/figures": ["figures@2.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA=="],
|
|
@@ -1033,6 +1050,26 @@
|
|
|
1033
1050
|
|
|
1034
1051
|
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
|
1035
1052
|
|
|
1053
|
+
"@semantic-release/github/aggregate-error/clean-stack": ["clean-stack@5.3.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg=="],
|
|
1054
|
+
|
|
1055
|
+
"@semantic-release/github/aggregate-error/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
|
1056
|
+
|
|
1057
|
+
"@semantic-release/npm/aggregate-error/clean-stack": ["clean-stack@5.3.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg=="],
|
|
1058
|
+
|
|
1059
|
+
"@semantic-release/npm/aggregate-error/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
|
1060
|
+
|
|
1061
|
+
"@semantic-release/npm/execa/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
|
1062
|
+
|
|
1063
|
+
"@semantic-release/npm/execa/human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
|
|
1064
|
+
|
|
1065
|
+
"@semantic-release/npm/execa/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
|
|
1066
|
+
|
|
1067
|
+
"@semantic-release/npm/execa/npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
|
|
1068
|
+
|
|
1069
|
+
"@semantic-release/npm/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
1070
|
+
|
|
1071
|
+
"@semantic-release/npm/execa/strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],
|
|
1072
|
+
|
|
1036
1073
|
"@semantic-release/release-notes-generator/read-package-up/read-pkg": ["read-pkg@9.0.1", "", { "dependencies": { "@types/normalize-package-data": "^2.4.3", "normalize-package-data": "^6.0.0", "parse-json": "^8.0.0", "type-fest": "^4.6.0", "unicorn-magic": "^0.1.0" } }, "sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA=="],
|
|
1037
1074
|
|
|
1038
1075
|
"@semantic-release/release-notes-generator/read-package-up/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
@@ -1057,6 +1094,10 @@
|
|
|
1057
1094
|
|
|
1058
1095
|
"env-ci/execa/npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
|
1059
1096
|
|
|
1097
|
+
"env-ci/execa/onetime": ["onetime@6.0.0", "", { "dependencies": { "mimic-fn": "^4.0.0" } }, "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ=="],
|
|
1098
|
+
|
|
1099
|
+
"env-ci/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
1100
|
+
|
|
1060
1101
|
"env-ci/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
|
1061
1102
|
|
|
1062
1103
|
"npm/minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
|
@@ -1069,12 +1110,32 @@
|
|
|
1069
1110
|
|
|
1070
1111
|
"read-pkg/parse-json/type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="],
|
|
1071
1112
|
|
|
1113
|
+
"semantic-release/aggregate-error/clean-stack": ["clean-stack@5.3.0", "", { "dependencies": { "escape-string-regexp": "5.0.0" } }, "sha512-9ngPTOhYGQqNVSfeJkYXHmF7AGWp4/nN5D/QqNQs3Dvxd1Kk/WpjHfNujKHYUQ/5CoGyOyFNoWSPk5afzP0QVg=="],
|
|
1114
|
+
|
|
1115
|
+
"semantic-release/aggregate-error/indent-string": ["indent-string@5.0.0", "", {}, "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg=="],
|
|
1116
|
+
|
|
1117
|
+
"semantic-release/execa/get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
|
1118
|
+
|
|
1119
|
+
"semantic-release/execa/human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="],
|
|
1120
|
+
|
|
1121
|
+
"semantic-release/execa/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
|
|
1122
|
+
|
|
1123
|
+
"semantic-release/execa/npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
|
|
1124
|
+
|
|
1125
|
+
"semantic-release/execa/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
|
1126
|
+
|
|
1127
|
+
"semantic-release/execa/strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],
|
|
1128
|
+
|
|
1072
1129
|
"signale/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
|
1073
1130
|
|
|
1074
1131
|
"signale/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
|
1075
1132
|
|
|
1076
1133
|
"signale/figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
|
1077
1134
|
|
|
1135
|
+
"@semantic-release/npm/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
|
1136
|
+
|
|
1137
|
+
"@semantic-release/npm/execa/npm-run-path/unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
|
1138
|
+
|
|
1078
1139
|
"@semantic-release/release-notes-generator/read-package-up/read-pkg/normalize-package-data": ["normalize-package-data@6.0.2", "", { "dependencies": { "hosted-git-info": "^7.0.0", "semver": "^7.3.5", "validate-npm-package-license": "^3.0.4" } }, "sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g=="],
|
|
1079
1140
|
|
|
1080
1141
|
"@semantic-release/release-notes-generator/read-package-up/read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
|
|
@@ -1095,10 +1156,16 @@
|
|
|
1095
1156
|
|
|
1096
1157
|
"env-ci/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
|
1097
1158
|
|
|
1159
|
+
"env-ci/execa/onetime/mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
|
1160
|
+
|
|
1098
1161
|
"npm/minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
|
1099
1162
|
|
|
1100
1163
|
"npm/minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
|
1101
1164
|
|
|
1165
|
+
"semantic-release/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
|
1166
|
+
|
|
1167
|
+
"semantic-release/execa/npm-run-path/unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
|
1168
|
+
|
|
1102
1169
|
"signale/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
|
1103
1170
|
|
|
1104
1171
|
"@semantic-release/release-notes-generator/read-package-up/read-pkg/normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w=="],
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,11 @@ import { Octokit } from "octokit";
|
|
|
3
3
|
import { KeyvStoreAdapter, StoredData } from "keyv";
|
|
4
4
|
|
|
5
5
|
//#region src/index.d.ts
|
|
6
|
+
/** Minimal Map-like interface for SHA caching. */
|
|
7
|
+
interface ShaMap {
|
|
8
|
+
get(key: string): string | null | undefined;
|
|
9
|
+
set(key: string, value: string | null): void;
|
|
10
|
+
}
|
|
6
11
|
interface KeyvGithubOptions {
|
|
7
12
|
url: string;
|
|
8
13
|
branch?: string;
|
|
@@ -15,6 +20,8 @@ interface KeyvGithubOptions {
|
|
|
15
20
|
prefix?: string;
|
|
16
21
|
/** Path suffix appended to every key (e.g. '.json'). Defaults to ''. */
|
|
17
22
|
suffix?: string;
|
|
23
|
+
/** SHA cache map. Defaults to new Map(). Pass any keyv-like object with get/set. */
|
|
24
|
+
shaMap?: ShaMap;
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
27
|
* Keyv storage adapter backed by a GitHub repository.
|
|
@@ -35,6 +42,8 @@ declare class KeyvGithub extends EventEmitter implements KeyvStoreAdapter {
|
|
|
35
42
|
readonly enableClear: boolean;
|
|
36
43
|
readonly prefix: string;
|
|
37
44
|
readonly suffix: string;
|
|
45
|
+
/** SHA cache: key → sha (string), null (file doesn't exist), undefined (unknown). */
|
|
46
|
+
readonly shaMap: ShaMap;
|
|
38
47
|
constructor(url: string, options?: Omit<KeyvGithubOptions, "url">);
|
|
39
48
|
/** Converts a user key to the GitHub file path. */
|
|
40
49
|
private toPath;
|
|
@@ -46,7 +55,7 @@ declare class KeyvGithub extends EventEmitter implements KeyvStoreAdapter {
|
|
|
46
55
|
private static isHttpError;
|
|
47
56
|
private validatePath;
|
|
48
57
|
get<Value>(key: string): Promise<StoredData<Value> | undefined>;
|
|
49
|
-
set(key: string, value: any,
|
|
58
|
+
set(key: string, value: any, ttl?: number): Promise<void>;
|
|
50
59
|
delete(key: string): Promise<boolean>;
|
|
51
60
|
has(key: string): Promise<boolean>;
|
|
52
61
|
/**
|
|
@@ -59,7 +68,6 @@ declare class KeyvGithub extends EventEmitter implements KeyvStoreAdapter {
|
|
|
59
68
|
setMany(values: Array<{
|
|
60
69
|
key: string;
|
|
61
70
|
value: any;
|
|
62
|
-
ttl?: number;
|
|
63
71
|
}>): Promise<void>;
|
|
64
72
|
/**
|
|
65
73
|
* Keyv batch-delete: deletes multiple keys in a single commit (7 API calls total).
|
|
@@ -70,4 +78,4 @@ declare class KeyvGithub extends EventEmitter implements KeyvStoreAdapter {
|
|
|
70
78
|
iterator<Value>(prefix?: string): AsyncGenerator<[string, Value | undefined]>;
|
|
71
79
|
}
|
|
72
80
|
//#endregion
|
|
73
|
-
export { KeyvGithubOptions, KeyvGithub as default };
|
|
81
|
+
export { KeyvGithubOptions, ShaMap, KeyvGithub as default };
|
package/dist/index.mjs
CHANGED
|
@@ -23,6 +23,8 @@ var KeyvGithub = class KeyvGithub extends EventEmitter {
|
|
|
23
23
|
enableClear;
|
|
24
24
|
prefix;
|
|
25
25
|
suffix;
|
|
26
|
+
/** SHA cache: key → sha (string), null (file doesn't exist), undefined (unknown). */
|
|
27
|
+
shaMap;
|
|
26
28
|
constructor(url, options = {}) {
|
|
27
29
|
super();
|
|
28
30
|
const match = url.match(/(?:.*github\.com[/:])?([^/:]+)\/([^/]+?)(?:\.git)?(?:\/tree\/([^?#]+))?(?:[?#].*)?$/);
|
|
@@ -39,6 +41,7 @@ var KeyvGithub = class KeyvGithub extends EventEmitter {
|
|
|
39
41
|
this.enableClear = options.enableClear ?? false;
|
|
40
42
|
this.prefix = options.prefix ?? "";
|
|
41
43
|
this.suffix = options.suffix ?? "";
|
|
44
|
+
this.shaMap = options.shaMap ?? /* @__PURE__ */ new Map();
|
|
42
45
|
}
|
|
43
46
|
/** Converts a user key to the GitHub file path. */
|
|
44
47
|
toPath(key) {
|
|
@@ -65,37 +68,41 @@ var KeyvGithub = class KeyvGithub extends EventEmitter {
|
|
|
65
68
|
if (path.split("/").some((seg) => seg === ".." || seg === ".")) throw new Error(`Path must not contain '.' or '..' segments: ${path}`);
|
|
66
69
|
}
|
|
67
70
|
async get(key) {
|
|
68
|
-
this.
|
|
71
|
+
const path = this.toPath(key);
|
|
72
|
+
this.validatePath(path);
|
|
69
73
|
try {
|
|
70
74
|
const { data } = await this.rest.repos.getContent({
|
|
71
75
|
owner: this.owner,
|
|
72
76
|
repo: this.repo,
|
|
73
|
-
path
|
|
77
|
+
path,
|
|
74
78
|
ref: this.ref
|
|
75
79
|
});
|
|
76
|
-
if (Array.isArray(data) || data.type !== "file")
|
|
80
|
+
if (Array.isArray(data) || data.type !== "file") {
|
|
81
|
+
this.shaMap.set(path, null);
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
this.shaMap.set(path, data.sha);
|
|
77
85
|
return Buffer.from(data.content, "base64").toString("utf-8");
|
|
78
86
|
} catch (e) {
|
|
79
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
87
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
88
|
+
this.shaMap.set(path, null);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
80
91
|
throw e;
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
|
-
async set(key, value,
|
|
84
|
-
|
|
94
|
+
async set(key, value, ttl) {
|
|
95
|
+
if (ttl !== void 0) throw new Error("TTL is not supported natively by keyv-github. Use new Keyv(store) which handles TTL via value expiration metadata.");
|
|
96
|
+
if (typeof value !== "string") throw new Error("keyv-github only supports string values natively. Use new Keyv(store) which serializes values automatically.");
|
|
85
97
|
const path = this.toPath(key);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
path,
|
|
92
|
-
ref: this.ref
|
|
93
|
-
});
|
|
94
|
-
if (!Array.isArray(data) && data.type === "file") sha = data.sha;
|
|
95
|
-
} catch (e) {
|
|
96
|
-
if (!KeyvGithub.isHttpError(e) || e.status !== 404) throw e;
|
|
98
|
+
this.validatePath(path);
|
|
99
|
+
let cachedSha = this.shaMap.get(path);
|
|
100
|
+
if (cachedSha === void 0) {
|
|
101
|
+
await this.get(key);
|
|
102
|
+
cachedSha = this.shaMap.get(path);
|
|
97
103
|
}
|
|
98
|
-
|
|
104
|
+
const sha = cachedSha ?? void 0;
|
|
105
|
+
const { data } = await this.rest.repos.createOrUpdateFileContents({
|
|
99
106
|
owner: this.owner,
|
|
100
107
|
repo: this.repo,
|
|
101
108
|
path,
|
|
@@ -104,44 +111,58 @@ var KeyvGithub = class KeyvGithub extends EventEmitter {
|
|
|
104
111
|
sha,
|
|
105
112
|
branch: this.ref
|
|
106
113
|
});
|
|
114
|
+
this.shaMap.set(path, data.content?.sha ?? null);
|
|
107
115
|
}
|
|
108
116
|
async delete(key) {
|
|
109
|
-
this.validatePath(this.toPath(key));
|
|
110
117
|
const path = this.toPath(key);
|
|
118
|
+
this.validatePath(path);
|
|
119
|
+
let cachedSha = this.shaMap.get(path);
|
|
120
|
+
if (cachedSha === void 0) {
|
|
121
|
+
await this.get(key);
|
|
122
|
+
cachedSha = this.shaMap.get(path);
|
|
123
|
+
}
|
|
124
|
+
if (!cachedSha) return false;
|
|
125
|
+
const sha = cachedSha;
|
|
111
126
|
try {
|
|
112
|
-
const { data } = await this.rest.repos.getContent({
|
|
113
|
-
owner: this.owner,
|
|
114
|
-
repo: this.repo,
|
|
115
|
-
path,
|
|
116
|
-
ref: this.ref
|
|
117
|
-
});
|
|
118
|
-
if (Array.isArray(data) || data.type !== "file") return false;
|
|
119
127
|
await this.rest.repos.deleteFile({
|
|
120
128
|
owner: this.owner,
|
|
121
129
|
repo: this.repo,
|
|
122
130
|
path,
|
|
123
131
|
message: this.msg(path, null),
|
|
124
|
-
sha
|
|
132
|
+
sha,
|
|
125
133
|
branch: this.ref
|
|
126
134
|
});
|
|
135
|
+
this.shaMap.set(path, null);
|
|
127
136
|
return true;
|
|
128
137
|
} catch (e) {
|
|
129
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
138
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
139
|
+
this.shaMap.set(path, null);
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
130
142
|
throw e;
|
|
131
143
|
}
|
|
132
144
|
}
|
|
133
145
|
async has(key) {
|
|
134
|
-
this.
|
|
146
|
+
const path = this.toPath(key);
|
|
147
|
+
this.validatePath(path);
|
|
135
148
|
try {
|
|
136
149
|
const { data } = await this.rest.repos.getContent({
|
|
137
150
|
owner: this.owner,
|
|
138
151
|
repo: this.repo,
|
|
139
|
-
path
|
|
152
|
+
path,
|
|
140
153
|
ref: this.ref
|
|
141
154
|
});
|
|
142
|
-
|
|
155
|
+
if (Array.isArray(data) || data.type !== "file") {
|
|
156
|
+
this.shaMap.set(path, null);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
this.shaMap.set(path, data.sha);
|
|
160
|
+
return true;
|
|
143
161
|
} catch (e) {
|
|
144
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
162
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
163
|
+
this.shaMap.set(path, null);
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
145
166
|
throw e;
|
|
146
167
|
}
|
|
147
168
|
}
|
|
@@ -197,7 +218,10 @@ var KeyvGithub = class KeyvGithub extends EventEmitter {
|
|
|
197
218
|
/** Keyv batch-set: writes multiple keys in a single commit (5 API calls total). */
|
|
198
219
|
async setMany(values) {
|
|
199
220
|
if (values.length === 0) return;
|
|
200
|
-
for (const { key } of values)
|
|
221
|
+
for (const { key, value } of values) {
|
|
222
|
+
if (typeof value !== "string") throw new Error("keyv-github only supports string values natively. Use new Keyv(store) which serializes values automatically.");
|
|
223
|
+
this.validatePath(this.toPath(key));
|
|
224
|
+
}
|
|
201
225
|
const entries = values.map(({ key, value }) => [this.toPath(key), String(value)]);
|
|
202
226
|
const message = entries.length === 1 ? this.msg(entries[0][0], entries[0][1]) : `batch update ${entries.length} files`;
|
|
203
227
|
await this._batchCommit({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keyv-github",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"module": "src/index.ts",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"types": "dist/index.d.mts",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"octokit": "^5.0.5"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
+
"@semantic-release/git": "^10.0.1",
|
|
23
24
|
"@types/bun": "latest",
|
|
24
25
|
"semantic-release": "^25.0.3",
|
|
25
26
|
"tsdown": "^0.20.3",
|
package/src/index.test.ts
CHANGED
|
@@ -204,7 +204,9 @@ describe("KeyvGithub constructor", () => {
|
|
|
204
204
|
const client = makeMockClient();
|
|
205
205
|
const store = new KeyvGithub(
|
|
206
206
|
"https://github.com/owner/repo/tree/feature/my-branch",
|
|
207
|
-
{
|
|
207
|
+
{
|
|
208
|
+
client: client.rest as unknown as Octokit["rest"],
|
|
209
|
+
},
|
|
208
210
|
);
|
|
209
211
|
expect(store.branch).toBe("feature/my-branch");
|
|
210
212
|
});
|
|
@@ -294,6 +296,26 @@ describe("set", () => {
|
|
|
294
296
|
await store.set("unicode", "日本語テスト 🎉");
|
|
295
297
|
expect(mockFiles.get("unicode")?.content).toBe("日本語テスト 🎉");
|
|
296
298
|
});
|
|
299
|
+
|
|
300
|
+
test("throws when TTL is provided (not supported natively)", async () => {
|
|
301
|
+
const { store } = makeStore();
|
|
302
|
+
expect(store.set("key", "value", 1000)).rejects.toThrow(
|
|
303
|
+
"TTL is not supported natively",
|
|
304
|
+
);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
test("throws when value is not a string", async () => {
|
|
308
|
+
const { store } = makeStore();
|
|
309
|
+
expect(store.set("key", { obj: true })).rejects.toThrow(
|
|
310
|
+
"only supports string values",
|
|
311
|
+
);
|
|
312
|
+
expect(store.set("key", 123)).rejects.toThrow(
|
|
313
|
+
"only supports string values",
|
|
314
|
+
);
|
|
315
|
+
expect(store.set("key", ["array"])).rejects.toThrow(
|
|
316
|
+
"only supports string values",
|
|
317
|
+
);
|
|
318
|
+
});
|
|
297
319
|
});
|
|
298
320
|
|
|
299
321
|
describe("delete", () => {
|
|
@@ -391,6 +413,17 @@ describe("setMany", () => {
|
|
|
391
413
|
).rejects.toThrow();
|
|
392
414
|
expect(mockFiles.size).toBe(0);
|
|
393
415
|
});
|
|
416
|
+
|
|
417
|
+
test("throws when any value is not a string", async () => {
|
|
418
|
+
const { store, mockFiles } = makeStore();
|
|
419
|
+
expect(
|
|
420
|
+
store.setMany([
|
|
421
|
+
{ key: "a", value: "ok" },
|
|
422
|
+
{ key: "b", value: { obj: true } },
|
|
423
|
+
]),
|
|
424
|
+
).rejects.toThrow("only supports string values");
|
|
425
|
+
expect(mockFiles.size).toBe(0);
|
|
426
|
+
});
|
|
394
427
|
});
|
|
395
428
|
|
|
396
429
|
describe("deleteMany", () => {
|
package/src/index.ts
CHANGED
|
@@ -2,6 +2,12 @@ import { EventEmitter } from "events";
|
|
|
2
2
|
import type { KeyvStoreAdapter, StoredData } from "keyv";
|
|
3
3
|
import { Octokit } from "octokit";
|
|
4
4
|
|
|
5
|
+
/** Minimal Map-like interface for SHA caching. */
|
|
6
|
+
export interface ShaMap {
|
|
7
|
+
get(key: string): string | null | undefined;
|
|
8
|
+
set(key: string, value: string | null): void;
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
export interface KeyvGithubOptions {
|
|
6
12
|
url: string;
|
|
7
13
|
branch?: string;
|
|
@@ -14,6 +20,8 @@ export interface KeyvGithubOptions {
|
|
|
14
20
|
prefix?: string;
|
|
15
21
|
/** Path suffix appended to every key (e.g. '.json'). Defaults to ''. */
|
|
16
22
|
suffix?: string;
|
|
23
|
+
/** SHA cache map. Defaults to new Map(). Pass any keyv-like object with get/set. */
|
|
24
|
+
shaMap?: ShaMap;
|
|
17
25
|
}
|
|
18
26
|
|
|
19
27
|
/**
|
|
@@ -41,6 +49,8 @@ export default class KeyvGithub
|
|
|
41
49
|
readonly enableClear: boolean;
|
|
42
50
|
readonly prefix: string;
|
|
43
51
|
readonly suffix: string;
|
|
52
|
+
/** SHA cache: key → sha (string), null (file doesn't exist), undefined (unknown). */
|
|
53
|
+
readonly shaMap: ShaMap;
|
|
44
54
|
|
|
45
55
|
constructor(url: string, options: Omit<KeyvGithubOptions, "url"> = {}) {
|
|
46
56
|
super();
|
|
@@ -64,6 +74,7 @@ export default class KeyvGithub
|
|
|
64
74
|
this.enableClear = options.enableClear ?? false;
|
|
65
75
|
this.prefix = options.prefix ?? "";
|
|
66
76
|
this.suffix = options.suffix ?? "";
|
|
77
|
+
this.shaMap = options.shaMap ?? new Map<string, string | null>();
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
/** Converts a user key to the GitHub file path. */
|
|
@@ -106,41 +117,58 @@ export default class KeyvGithub
|
|
|
106
117
|
}
|
|
107
118
|
|
|
108
119
|
async get<Value>(key: string): Promise<StoredData<Value> | undefined> {
|
|
109
|
-
this.
|
|
120
|
+
const path = this.toPath(key);
|
|
121
|
+
this.validatePath(path);
|
|
110
122
|
try {
|
|
111
123
|
const { data } = await this.rest.repos.getContent({
|
|
112
124
|
owner: this.owner,
|
|
113
125
|
repo: this.repo,
|
|
114
|
-
path
|
|
126
|
+
path,
|
|
115
127
|
ref: this.ref,
|
|
116
128
|
});
|
|
117
|
-
if (Array.isArray(data) || data.type !== "file")
|
|
129
|
+
if (Array.isArray(data) || data.type !== "file") {
|
|
130
|
+
this.shaMap.set(path, null);
|
|
131
|
+
return undefined;
|
|
132
|
+
}
|
|
133
|
+
this.shaMap.set(path, data.sha);
|
|
118
134
|
return Buffer.from(data.content, "base64").toString(
|
|
119
135
|
"utf-8",
|
|
120
136
|
) as StoredData<Value>;
|
|
121
137
|
} catch (e: unknown) {
|
|
122
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
138
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
139
|
+
this.shaMap.set(path, null);
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
123
142
|
throw e;
|
|
124
143
|
}
|
|
125
144
|
}
|
|
126
145
|
|
|
127
|
-
async set(key: string, value: any,
|
|
128
|
-
|
|
146
|
+
async set(key: string, value: any, ttl?: number): Promise<void> {
|
|
147
|
+
if (ttl !== undefined) {
|
|
148
|
+
throw new Error(
|
|
149
|
+
"TTL is not supported natively by keyv-github. " +
|
|
150
|
+
"Use new Keyv(store) which handles TTL via value expiration metadata.",
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
if (typeof value !== "string") {
|
|
154
|
+
throw new Error(
|
|
155
|
+
"keyv-github only supports string values natively. " +
|
|
156
|
+
"Use new Keyv(store) which serializes values automatically.",
|
|
157
|
+
);
|
|
158
|
+
}
|
|
129
159
|
const path = this.toPath(key);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
});
|
|
138
|
-
if (!Array.isArray(data) && data.type === "file") sha = data.sha;
|
|
139
|
-
} catch (e: unknown) {
|
|
140
|
-
if (!KeyvGithub.isHttpError(e) || e.status !== 404) throw e;
|
|
160
|
+
this.validatePath(path);
|
|
161
|
+
|
|
162
|
+
// Check shaMap first; if unknown (undefined), fetch to populate it
|
|
163
|
+
let cachedSha = this.shaMap.get(path);
|
|
164
|
+
if (cachedSha === undefined) {
|
|
165
|
+
await this.get(key); // populates shaMap
|
|
166
|
+
cachedSha = this.shaMap.get(path);
|
|
141
167
|
}
|
|
168
|
+
// cachedSha is now string (existing file) or null (doesn't exist)
|
|
169
|
+
const sha = cachedSha ?? undefined;
|
|
142
170
|
|
|
143
|
-
await this.rest.repos.createOrUpdateFileContents({
|
|
171
|
+
const { data } = await this.rest.repos.createOrUpdateFileContents({
|
|
144
172
|
owner: this.owner,
|
|
145
173
|
repo: this.repo,
|
|
146
174
|
path,
|
|
@@ -149,46 +177,65 @@ export default class KeyvGithub
|
|
|
149
177
|
sha,
|
|
150
178
|
branch: this.ref,
|
|
151
179
|
});
|
|
180
|
+
// Update shaMap with new sha from response
|
|
181
|
+
this.shaMap.set(path, data.content?.sha ?? null);
|
|
152
182
|
}
|
|
153
183
|
|
|
154
184
|
async delete(key: string): Promise<boolean> {
|
|
155
|
-
this.validatePath(this.toPath(key));
|
|
156
185
|
const path = this.toPath(key);
|
|
186
|
+
this.validatePath(path);
|
|
187
|
+
|
|
188
|
+
// Check shaMap first; if unknown (undefined), fetch to populate it
|
|
189
|
+
let cachedSha = this.shaMap.get(path);
|
|
190
|
+
if (cachedSha === undefined) {
|
|
191
|
+
await this.get(key); // populates shaMap
|
|
192
|
+
cachedSha = this.shaMap.get(path);
|
|
193
|
+
}
|
|
194
|
+
// If null or still undefined, file doesn't exist
|
|
195
|
+
if (!cachedSha) return false;
|
|
196
|
+
|
|
197
|
+
const sha = cachedSha; // narrow to string for TypeScript
|
|
157
198
|
try {
|
|
158
|
-
const { data } = await this.rest.repos.getContent({
|
|
159
|
-
owner: this.owner,
|
|
160
|
-
repo: this.repo,
|
|
161
|
-
path,
|
|
162
|
-
ref: this.ref,
|
|
163
|
-
});
|
|
164
|
-
if (Array.isArray(data) || data.type !== "file") return false;
|
|
165
199
|
await this.rest.repos.deleteFile({
|
|
166
200
|
owner: this.owner,
|
|
167
201
|
repo: this.repo,
|
|
168
202
|
path,
|
|
169
203
|
message: this.msg(path, null),
|
|
170
|
-
sha
|
|
204
|
+
sha,
|
|
171
205
|
branch: this.ref,
|
|
172
206
|
});
|
|
207
|
+
this.shaMap.set(path, null);
|
|
173
208
|
return true;
|
|
174
209
|
} catch (e: unknown) {
|
|
175
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
210
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
211
|
+
this.shaMap.set(path, null);
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
176
214
|
throw e;
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
217
|
|
|
180
218
|
async has(key: string): Promise<boolean> {
|
|
181
|
-
this.
|
|
219
|
+
const path = this.toPath(key);
|
|
220
|
+
this.validatePath(path);
|
|
182
221
|
try {
|
|
183
222
|
const { data } = await this.rest.repos.getContent({
|
|
184
223
|
owner: this.owner,
|
|
185
224
|
repo: this.repo,
|
|
186
|
-
path
|
|
225
|
+
path,
|
|
187
226
|
ref: this.ref,
|
|
188
227
|
});
|
|
189
|
-
|
|
228
|
+
if (Array.isArray(data) || data.type !== "file") {
|
|
229
|
+
this.shaMap.set(path, null);
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
this.shaMap.set(path, data.sha);
|
|
233
|
+
return true;
|
|
190
234
|
} catch (e: unknown) {
|
|
191
|
-
if (KeyvGithub.isHttpError(e) && e.status === 404)
|
|
235
|
+
if (KeyvGithub.isHttpError(e) && e.status === 404) {
|
|
236
|
+
this.shaMap.set(path, null);
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
192
239
|
throw e;
|
|
193
240
|
}
|
|
194
241
|
}
|
|
@@ -257,11 +304,17 @@ export default class KeyvGithub
|
|
|
257
304
|
}
|
|
258
305
|
|
|
259
306
|
/** Keyv batch-set: writes multiple keys in a single commit (5 API calls total). */
|
|
260
|
-
async setMany(
|
|
261
|
-
values: Array<{ key: string; value: any; ttl?: number }>,
|
|
262
|
-
): Promise<void> {
|
|
307
|
+
async setMany(values: Array<{ key: string; value: any }>): Promise<void> {
|
|
263
308
|
if (values.length === 0) return;
|
|
264
|
-
for (const { key } of values)
|
|
309
|
+
for (const { key, value } of values) {
|
|
310
|
+
if (typeof value !== "string") {
|
|
311
|
+
throw new Error(
|
|
312
|
+
"keyv-github only supports string values natively. " +
|
|
313
|
+
"Use new Keyv(store) which serializes values automatically.",
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
this.validatePath(this.toPath(key));
|
|
317
|
+
}
|
|
265
318
|
const entries: [string, string][] = values.map(({ key, value }) => [
|
|
266
319
|
this.toPath(key),
|
|
267
320
|
String(value),
|