keyv-github 1.3.0 → 1.5.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/README.md +60 -0
- package/bun.lock +347 -17
- package/demo-best-practice.ts +100 -0
- package/dist/index.d.mts +19 -1
- package/dist/index.mjs +16 -4
- package/package.json +3 -1
- package/src/index.test.ts +5 -5
- package/src/index.ts +35 -5
package/README.md
CHANGED
|
@@ -15,6 +15,50 @@ Every `set` costs **2 API calls** (read SHA + write), every `delete` costs **2**
|
|
|
15
15
|
|
|
16
16
|
Use a [GitHub App](https://docs.github.com/en/developers/apps) token or a fine-grained PAT with `contents: write` permission to maximise your quota.
|
|
17
17
|
|
|
18
|
+
### Best Practice: Use cache layers
|
|
19
|
+
|
|
20
|
+
To reduce API calls, chain memory and file caches before keyv-github using [keyv-nest](https://github.com/snomiao/keyv-nest) and [keyv-dir-store](https://github.com/snomiao/keyv-dir-store):
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import Keyv from "keyv";
|
|
24
|
+
import KeyvNest from "keyv-nest";
|
|
25
|
+
import { KeyvDirStore } from "keyv-dir-store";
|
|
26
|
+
import KeyvGithub from "keyv-github";
|
|
27
|
+
|
|
28
|
+
// Simple memory store (avoids Keyv namespace prefix issues)
|
|
29
|
+
const memoryStore = {
|
|
30
|
+
cache: new Map<string, any>(),
|
|
31
|
+
opts: { url: "", dialect: "map" },
|
|
32
|
+
get(key: string) { return this.cache.get(key); },
|
|
33
|
+
set(key: string, value: any) { this.cache.set(key, value); },
|
|
34
|
+
delete(key: string) { return this.cache.delete(key); },
|
|
35
|
+
clear() { this.cache.clear(); },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Use same prefix/suffix so local cache mirrors GitHub paths
|
|
39
|
+
const prefix = "data/";
|
|
40
|
+
const suffix = ".json";
|
|
41
|
+
|
|
42
|
+
const store = KeyvNest(
|
|
43
|
+
memoryStore, // L1: Memory (fastest)
|
|
44
|
+
new KeyvDirStore("./cache", { // L2: Local files (fast)
|
|
45
|
+
prefix,
|
|
46
|
+
suffix,
|
|
47
|
+
filename: (k) => k, // use key as-is, no hashing
|
|
48
|
+
}),
|
|
49
|
+
new KeyvGithub("owner/repo/tree/main", { client, prefix, suffix }) // L3: GitHub
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Wrap with Keyv (use empty namespace to preserve keys)
|
|
53
|
+
(store as any).opts = { url: "", dialect: "keyv-nest" };
|
|
54
|
+
const kv = new Keyv({ store, namespace: "" });
|
|
55
|
+
// key "foo" -> ./cache/data/foo.json (local) and data/foo.json (GitHub)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
See [demo-best-practice.ts](./demo-best-practice.ts) for a runnable example.
|
|
59
|
+
|
|
60
|
+
Reads check L1 → L2 → L3, with automatic backfill to faster layers on cache miss.
|
|
61
|
+
|
|
18
62
|
## Install
|
|
19
63
|
|
|
20
64
|
```sh
|
|
@@ -99,6 +143,8 @@ const store = new KeyvGithub("owner/repo", {
|
|
|
99
143
|
|
|
100
144
|
## Key rules
|
|
101
145
|
|
|
146
|
+
⚠️ **Keys are validated but NOT sanitized.** You must sanitize keys yourself before passing them to this adapter. Invalid keys will throw an error.
|
|
147
|
+
|
|
102
148
|
Keys must be valid relative file paths:
|
|
103
149
|
|
|
104
150
|
- Non-empty
|
|
@@ -107,8 +153,22 @@ Keys must be valid relative file paths:
|
|
|
107
153
|
- No `.` or `..` segments
|
|
108
154
|
- No null bytes
|
|
109
155
|
|
|
156
|
+
**OS-specific characters** like `<>:"|?*\` (invalid on Windows) are NOT validated — you must sanitize these yourself if your keys might contain them.
|
|
157
|
+
|
|
110
158
|
Invalid keys throw synchronously before any API request.
|
|
111
159
|
|
|
160
|
+
```ts
|
|
161
|
+
// ✗ These will throw errors
|
|
162
|
+
await store.set("/absolute/path", "value"); // leading slash
|
|
163
|
+
await store.set("path/", "value"); // trailing slash
|
|
164
|
+
await store.set("path/../escape", "value"); // directory traversal
|
|
165
|
+
await store.set("path//double", "value"); // double slashes
|
|
166
|
+
|
|
167
|
+
// ✓ Valid keys
|
|
168
|
+
await store.set("data/file.txt", "value");
|
|
169
|
+
await store.set("nested/path/key.json", "value");
|
|
170
|
+
```
|
|
171
|
+
|
|
112
172
|
## See Also
|
|
113
173
|
|
|
114
174
|
Other Keyv storage adapters by the same author:
|