@vercel/kv2 0.0.1
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 +87 -0
- package/SKILL.md +65 -0
- package/dist/blob-format.d.ts +35 -0
- package/dist/blob-format.d.ts.map +1 -0
- package/dist/blob-format.js +91 -0
- package/dist/blob-format.js.map +1 -0
- package/dist/blob-store.d.ts +11 -0
- package/dist/blob-store.d.ts.map +1 -0
- package/dist/blob-store.js +32 -0
- package/dist/blob-store.js.map +1 -0
- package/dist/cache.d.ts +33 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +146 -0
- package/dist/cache.js.map +1 -0
- package/dist/cached-kv.d.ts +63 -0
- package/dist/cached-kv.d.ts.map +1 -0
- package/dist/cached-kv.js +891 -0
- package/dist/cached-kv.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +342 -0
- package/dist/cli.js.map +1 -0
- package/dist/create-kv.d.ts +86 -0
- package/dist/create-kv.d.ts.map +1 -0
- package/dist/create-kv.js +125 -0
- package/dist/create-kv.js.map +1 -0
- package/dist/disk-cache.d.ts.map +1 -0
- package/dist/disk-cache.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/indexed-kv.d.ts +44 -0
- package/dist/indexed-kv.d.ts.map +1 -0
- package/dist/indexed-kv.js +373 -0
- package/dist/indexed-kv.js.map +1 -0
- package/dist/manifest-log.d.ts +57 -0
- package/dist/manifest-log.d.ts.map +1 -0
- package/dist/manifest-log.js +128 -0
- package/dist/manifest-log.js.map +1 -0
- package/dist/memory-cache.d.ts +22 -0
- package/dist/memory-cache.d.ts.map +1 -0
- package/dist/memory-cache.js +90 -0
- package/dist/memory-cache.js.map +1 -0
- package/dist/proxy-cache.d.ts +40 -0
- package/dist/proxy-cache.d.ts.map +1 -0
- package/dist/proxy-cache.js +124 -0
- package/dist/proxy-cache.js.map +1 -0
- package/dist/readme.test.d.ts +9 -0
- package/dist/readme.test.d.ts.map +1 -0
- package/dist/readme.test.js +285 -0
- package/dist/readme.test.js.map +1 -0
- package/dist/schema/define-schema.d.ts +35 -0
- package/dist/schema/define-schema.d.ts.map +1 -0
- package/dist/schema/define-schema.js +70 -0
- package/dist/schema/define-schema.js.map +1 -0
- package/dist/schema/index.d.ts +4 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +5 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/key-builders.d.ts +40 -0
- package/dist/schema/key-builders.d.ts.map +1 -0
- package/dist/schema/key-builders.js +124 -0
- package/dist/schema/key-builders.js.map +1 -0
- package/dist/schema/schema-kv.d.ts +48 -0
- package/dist/schema/schema-kv.d.ts.map +1 -0
- package/dist/schema/schema-kv.js +96 -0
- package/dist/schema/schema-kv.js.map +1 -0
- package/dist/schema/tree.d.ts +14 -0
- package/dist/schema/tree.d.ts.map +1 -0
- package/dist/schema/tree.js +135 -0
- package/dist/schema/tree.js.map +1 -0
- package/dist/schema/types.d.ts +135 -0
- package/dist/schema/types.d.ts.map +1 -0
- package/dist/schema/types.js +2 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/testing/core-tests.d.ts +30 -0
- package/dist/testing/core-tests.d.ts.map +1 -0
- package/dist/testing/core-tests.js +383 -0
- package/dist/testing/core-tests.js.map +1 -0
- package/dist/testing/create-kv-test-setup.d.ts +21 -0
- package/dist/testing/create-kv-test-setup.d.ts.map +1 -0
- package/dist/testing/create-kv-test-setup.js +25 -0
- package/dist/testing/create-kv-test-setup.js.map +1 -0
- package/dist/testing/debug-manifest.d.ts +2 -0
- package/dist/testing/debug-manifest.d.ts.map +1 -0
- package/dist/testing/debug-manifest.js +14 -0
- package/dist/testing/debug-manifest.js.map +1 -0
- package/dist/testing/fake-blob-store.d.ts +23 -0
- package/dist/testing/fake-blob-store.d.ts.map +1 -0
- package/dist/testing/fake-blob-store.js +158 -0
- package/dist/testing/fake-blob-store.js.map +1 -0
- package/dist/testing/fake-cache.d.ts +54 -0
- package/dist/testing/fake-cache.d.ts.map +1 -0
- package/dist/testing/fake-cache.js +137 -0
- package/dist/testing/fake-cache.js.map +1 -0
- package/dist/testing/index.d.ts +34 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +101 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/manifest-test-setup.d.ts +22 -0
- package/dist/testing/manifest-test-setup.d.ts.map +1 -0
- package/dist/testing/manifest-test-setup.js +43 -0
- package/dist/testing/manifest-test-setup.js.map +1 -0
- package/dist/testing/perf-test.d.ts +13 -0
- package/dist/testing/perf-test.d.ts.map +1 -0
- package/dist/testing/perf-test.js +101 -0
- package/dist/testing/perf-test.js.map +1 -0
- package/dist/testing/run-tests.d.ts +2 -0
- package/dist/testing/run-tests.d.ts.map +1 -0
- package/dist/testing/run-tests.js +141 -0
- package/dist/testing/run-tests.js.map +1 -0
- package/dist/testing/setup.d.ts +2 -0
- package/dist/testing/setup.d.ts.map +1 -0
- package/dist/testing/setup.js +3 -0
- package/dist/testing/setup.js.map +1 -0
- package/dist/testing/test-index.d.ts +28 -0
- package/dist/testing/test-index.d.ts.map +1 -0
- package/dist/testing/test-index.js +35 -0
- package/dist/testing/test-index.js.map +1 -0
- package/dist/testing/test-setup.d.ts +32 -0
- package/dist/testing/test-setup.d.ts.map +1 -0
- package/dist/testing/test-setup.js +72 -0
- package/dist/testing/test-setup.js.map +1 -0
- package/dist/testing/upstream-kv-test-setup.d.ts +30 -0
- package/dist/testing/upstream-kv-test-setup.d.ts.map +1 -0
- package/dist/testing/upstream-kv-test-setup.js +66 -0
- package/dist/testing/upstream-kv-test-setup.js.map +1 -0
- package/dist/testing/vitest-compat.d.ts +92 -0
- package/dist/testing/vitest-compat.d.ts.map +1 -0
- package/dist/testing/vitest-compat.js +601 -0
- package/dist/testing/vitest-compat.js.map +1 -0
- package/dist/tracing.d.ts +71 -0
- package/dist/tracing.d.ts.map +1 -0
- package/dist/tracing.js +232 -0
- package/dist/tracing.js.map +1 -0
- package/dist/typed-kv.d.ts +120 -0
- package/dist/typed-kv.d.ts.map +1 -0
- package/dist/typed-kv.js +565 -0
- package/dist/typed-kv.js.map +1 -0
- package/dist/typed-upstream-kv.d.ts +17 -0
- package/dist/typed-upstream-kv.d.ts.map +1 -0
- package/dist/typed-upstream-kv.js +38 -0
- package/dist/typed-upstream-kv.js.map +1 -0
- package/dist/types.d.ts +199 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/dist/upstream-kv.d.ts +84 -0
- package/dist/upstream-kv.d.ts.map +1 -0
- package/dist/upstream-kv.js +375 -0
- package/dist/upstream-kv.js.map +1 -0
- package/docs/api-reference.md +222 -0
- package/docs/caching.md +60 -0
- package/docs/cli.md +123 -0
- package/docs/copy-on-write-branches.md +98 -0
- package/docs/getting-started.md +61 -0
- package/docs/indexes.md +122 -0
- package/docs/iterating-and-pagination.md +93 -0
- package/docs/metadata.md +82 -0
- package/docs/optimistic-locking.md +72 -0
- package/docs/schema-and-trees.md +222 -0
- package/docs/streaming.md +61 -0
- package/docs/testing-and-tracing.md +141 -0
- package/docs/typed-stores.md +68 -0
- package/package.json +63 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { KV2 } from "./cached-kv.js";
|
|
2
|
+
const MANIFEST_CACHE_KEY = "__manifest__";
|
|
3
|
+
/**
|
|
4
|
+
* Manifest for tracking key sources (local vs upstream vs tombstone).
|
|
5
|
+
*
|
|
6
|
+
* Individual entries stored in blob for persistence.
|
|
7
|
+
* Aggregated manifest cached as single entry for fast cross-instance reads.
|
|
8
|
+
*/
|
|
9
|
+
export class ManifestLog {
|
|
10
|
+
kv;
|
|
11
|
+
cache;
|
|
12
|
+
cacheKey;
|
|
13
|
+
constructor(blobStore, manifestPrefix, cache) {
|
|
14
|
+
this.kv = new KV2({
|
|
15
|
+
prefix: manifestPrefix,
|
|
16
|
+
blobStore,
|
|
17
|
+
// Pass same cache to inner KV for test isolation
|
|
18
|
+
// (avoids falling back to global Vercel runtime cache singleton)
|
|
19
|
+
cache,
|
|
20
|
+
});
|
|
21
|
+
this.cache = cache;
|
|
22
|
+
this.cacheKey = `manifest:${manifestPrefix}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the source for a specific key.
|
|
26
|
+
* Returns null if key is not in manifest (unknown).
|
|
27
|
+
*/
|
|
28
|
+
async getKeySource(key) {
|
|
29
|
+
const manifest = await this.loadManifest();
|
|
30
|
+
return manifest.get(key) ?? null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Record a key as local or upstream.
|
|
34
|
+
*/
|
|
35
|
+
async recordAdd(key, source) {
|
|
36
|
+
await this.kv.set(key, { source });
|
|
37
|
+
await this.invalidateCache();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Record a key deletion (tombstone).
|
|
41
|
+
*/
|
|
42
|
+
async recordDelete(key) {
|
|
43
|
+
await this.kv.set(key, { source: "tombstone" });
|
|
44
|
+
await this.invalidateCache();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Delete a manifest entry (for cleanup).
|
|
48
|
+
*/
|
|
49
|
+
async remove(key) {
|
|
50
|
+
await this.kv.delete(key);
|
|
51
|
+
await this.invalidateCache();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Delete all manifest entries.
|
|
55
|
+
*/
|
|
56
|
+
async destroy() {
|
|
57
|
+
for await (const key of this.kv.keys()) {
|
|
58
|
+
await this.kv.delete(key);
|
|
59
|
+
}
|
|
60
|
+
await this.invalidateCache();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Get all manifest entries.
|
|
64
|
+
*/
|
|
65
|
+
async getAll() {
|
|
66
|
+
return this.loadManifest();
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get manifest state with keys map.
|
|
70
|
+
*/
|
|
71
|
+
async getManifest() {
|
|
72
|
+
return { keys: await this.loadManifest() };
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Load manifest from cache or blob.
|
|
76
|
+
* Caches aggregated result for fast repeated reads.
|
|
77
|
+
*/
|
|
78
|
+
async loadManifest() {
|
|
79
|
+
// Try cache first
|
|
80
|
+
if (this.cache) {
|
|
81
|
+
try {
|
|
82
|
+
const cached = (await this.cache.get(this.cacheKey));
|
|
83
|
+
if (cached?.entries) {
|
|
84
|
+
return new Map(cached.entries);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
// Cache miss or error, fall through to blob
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Load from blob
|
|
92
|
+
const entries = new Map();
|
|
93
|
+
for await (const key of this.kv.keys()) {
|
|
94
|
+
const result = await this.kv.get(key);
|
|
95
|
+
if (result.exists) {
|
|
96
|
+
entries.set(key, await result.value);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Cache the aggregated result
|
|
100
|
+
if (this.cache) {
|
|
101
|
+
try {
|
|
102
|
+
const toCache = {
|
|
103
|
+
entries: Array.from(entries.entries()),
|
|
104
|
+
};
|
|
105
|
+
await this.cache.set(this.cacheKey, toCache, { ttl: 3600 });
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Cache write failed, continue without caching
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return entries;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Invalidate the cached manifest.
|
|
115
|
+
*/
|
|
116
|
+
async invalidateCache() {
|
|
117
|
+
if (this.cache) {
|
|
118
|
+
try {
|
|
119
|
+
// Use expireTag if available, otherwise set to empty
|
|
120
|
+
await this.cache.set(this.cacheKey, null, { ttl: 0 });
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Ignore cache invalidation errors
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=manifest-log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest-log.js","sourceRoot":"","sources":["../src/manifest-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory cache for local development.
|
|
3
|
+
* State is stored in globalThis to persist across HMR reloads.
|
|
4
|
+
*/
|
|
5
|
+
import type { CacheLike } from "./types.js";
|
|
6
|
+
export declare class MemoryCache implements CacheLike {
|
|
7
|
+
private state;
|
|
8
|
+
constructor();
|
|
9
|
+
get(key: string): Promise<unknown>;
|
|
10
|
+
set(key: string, value: unknown, options?: {
|
|
11
|
+
tags?: string[];
|
|
12
|
+
ttl?: number;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
expireTag(tag: string): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare function getMemoryCache(): MemoryCache;
|
|
17
|
+
/**
|
|
18
|
+
* Check if memory cache should be used.
|
|
19
|
+
* Returns true when running locally (not on Vercel) and not in integration test mode.
|
|
20
|
+
*/
|
|
21
|
+
export declare function shouldUseMemoryCache(): boolean;
|
|
22
|
+
//# sourceMappingURL=memory-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-cache.d.ts","sourceRoot":"","sources":["../src/memory-cache.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AA4B5C,qBAAa,WAAY,YAAW,SAAS;IAC5C,OAAO,CAAC,KAAK,CAAmB;;IAU1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAelC,GAAG,CACR,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GACzC,OAAO,CAAC,IAAI,CAAC;IAqBV,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAS3C;AAKD,wBAAgB,cAAc,IAAI,WAAW,CAM5C;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAW9C"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory cache for local development.
|
|
3
|
+
* State is stored in globalThis to persist across HMR reloads.
|
|
4
|
+
*/
|
|
5
|
+
const globalKey = Symbol.for("kv-memory-cache");
|
|
6
|
+
function getState() {
|
|
7
|
+
const g = globalThis;
|
|
8
|
+
if (!g[globalKey]) {
|
|
9
|
+
g[globalKey] = {
|
|
10
|
+
data: new Map(),
|
|
11
|
+
tags: new Map(),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
return g[globalKey];
|
|
15
|
+
}
|
|
16
|
+
let loggedUsage = false;
|
|
17
|
+
export class MemoryCache {
|
|
18
|
+
state;
|
|
19
|
+
constructor() {
|
|
20
|
+
this.state = getState();
|
|
21
|
+
if (!loggedUsage) {
|
|
22
|
+
console.log("[MemoryCache] Using in-memory cache for local development");
|
|
23
|
+
loggedUsage = true;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
async get(key) {
|
|
27
|
+
const entry = this.state.data.get(key);
|
|
28
|
+
if (!entry) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
// Check expiration
|
|
32
|
+
if (Date.now() > entry.expiresAt) {
|
|
33
|
+
this.state.data.delete(key);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return entry.value;
|
|
37
|
+
}
|
|
38
|
+
async set(key, value, options) {
|
|
39
|
+
const tags = options?.tags ?? [];
|
|
40
|
+
const ttl = options?.ttl ?? 3600;
|
|
41
|
+
const entry = {
|
|
42
|
+
value,
|
|
43
|
+
tags,
|
|
44
|
+
expiresAt: Date.now() + ttl * 1000,
|
|
45
|
+
};
|
|
46
|
+
this.state.data.set(key, entry);
|
|
47
|
+
// Track tags
|
|
48
|
+
for (const tag of tags) {
|
|
49
|
+
if (!this.state.tags.has(tag)) {
|
|
50
|
+
this.state.tags.set(tag, new Set());
|
|
51
|
+
}
|
|
52
|
+
this.state.tags.get(tag).add(key);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async expireTag(tag) {
|
|
56
|
+
const keys = this.state.tags.get(tag);
|
|
57
|
+
if (keys) {
|
|
58
|
+
for (const key of keys) {
|
|
59
|
+
this.state.data.delete(key);
|
|
60
|
+
}
|
|
61
|
+
this.state.tags.delete(tag);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Singleton instance (also stored in globalThis)
|
|
66
|
+
const instanceKey = Symbol.for("kv-memory-cache-instance");
|
|
67
|
+
export function getMemoryCache() {
|
|
68
|
+
const g = globalThis;
|
|
69
|
+
if (!g[instanceKey]) {
|
|
70
|
+
g[instanceKey] = new MemoryCache();
|
|
71
|
+
}
|
|
72
|
+
return g[instanceKey];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Check if memory cache should be used.
|
|
76
|
+
* Returns true when running locally (not on Vercel) and not in integration test mode.
|
|
77
|
+
*/
|
|
78
|
+
export function shouldUseMemoryCache() {
|
|
79
|
+
// Don't use on Vercel
|
|
80
|
+
if (process.env.VERCEL) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// Don't use during integration tests (they use proxy cache)
|
|
84
|
+
if (process.env.INTEGRATION_TEST === "1") {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
// Use memory cache for local development
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=memory-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-cache.js","sourceRoot":"","sources":["../src/memory-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProxyCache - A cache implementation that proxies to a deployed cache-proxy endpoint.
|
|
3
|
+
* This allows local development to use the real Vercel cache.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* // Set environment variables:
|
|
7
|
+
* // CACHE_PROXY_URL=https://cached-kv-poc.vercel.app/api/cache-proxy
|
|
8
|
+
* // PROTECTION_BYPASS=<your-bypass-token>
|
|
9
|
+
*
|
|
10
|
+
* import { getProxyCache } from "./proxy-cache.js";
|
|
11
|
+
* const cache = getProxyCache();
|
|
12
|
+
* await cache.set("key", { data: "value" }, { ttl: 3600 });
|
|
13
|
+
* const value = await cache.get("key");
|
|
14
|
+
*/
|
|
15
|
+
interface CacheSetOptions {
|
|
16
|
+
tags?: string[];
|
|
17
|
+
ttl?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface ProxyCache {
|
|
20
|
+
get(key: string): Promise<unknown>;
|
|
21
|
+
set(key: string, value: unknown, options?: CacheSetOptions): Promise<void>;
|
|
22
|
+
expireTag(tag: string): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface ProxyCacheOptions {
|
|
25
|
+
/** Base URL of the cache-proxy endpoint */
|
|
26
|
+
proxyUrl?: string;
|
|
27
|
+
/** Protection bypass token for Vercel deployment protection */
|
|
28
|
+
protectionBypass?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get a proxy cache instance for local development.
|
|
32
|
+
* Uses CACHE_PROXY_URL and PROTECTION_BYPASS environment variables.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getProxyCache(options?: ProxyCacheOptions): ProxyCache;
|
|
35
|
+
/**
|
|
36
|
+
* Check if we should use the proxy cache (running locally with integration tests).
|
|
37
|
+
*/
|
|
38
|
+
export declare function shouldUseProxyCache(): boolean;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=proxy-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-cache.d.ts","sourceRoot":"","sources":["../src/proxy-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,UAAU,eAAe;IACxB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,UAAU;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,iBAAiB;IACjC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AA6GD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,UAAU,CAKrE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAW7C"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProxyCache - A cache implementation that proxies to a deployed cache-proxy endpoint.
|
|
3
|
+
* This allows local development to use the real Vercel cache.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* // Set environment variables:
|
|
7
|
+
* // CACHE_PROXY_URL=https://cached-kv-poc.vercel.app/api/cache-proxy
|
|
8
|
+
* // PROTECTION_BYPASS=<your-bypass-token>
|
|
9
|
+
*
|
|
10
|
+
* import { getProxyCache } from "./proxy-cache.js";
|
|
11
|
+
* const cache = getProxyCache();
|
|
12
|
+
* await cache.set("key", { data: "value" }, { ttl: 3600 });
|
|
13
|
+
* const value = await cache.get("key");
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_CACHE_PROXY_URL = "https://cached-kv-poc.vercel.app/api/cache-proxy";
|
|
16
|
+
const REQUEST_TIMEOUT_MS = 10000; // 10 second timeout
|
|
17
|
+
class ProxyCacheImpl {
|
|
18
|
+
proxyUrl;
|
|
19
|
+
protectionBypass;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.proxyUrl =
|
|
22
|
+
options?.proxyUrl ??
|
|
23
|
+
process.env.CACHE_PROXY_URL ??
|
|
24
|
+
DEFAULT_CACHE_PROXY_URL;
|
|
25
|
+
this.protectionBypass =
|
|
26
|
+
options?.protectionBypass ?? process.env.PROTECTION_BYPASS;
|
|
27
|
+
}
|
|
28
|
+
getHeaders(contentType) {
|
|
29
|
+
const headers = {};
|
|
30
|
+
if (contentType) {
|
|
31
|
+
headers["Content-Type"] = contentType;
|
|
32
|
+
}
|
|
33
|
+
if (this.protectionBypass) {
|
|
34
|
+
headers["x-vercel-protection-bypass"] = this.protectionBypass;
|
|
35
|
+
}
|
|
36
|
+
return headers;
|
|
37
|
+
}
|
|
38
|
+
async fetchWithTimeout(url, options = {}) {
|
|
39
|
+
const controller = new AbortController();
|
|
40
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(url, {
|
|
43
|
+
...options,
|
|
44
|
+
signal: controller.signal,
|
|
45
|
+
});
|
|
46
|
+
return response;
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
clearTimeout(timeoutId);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async get(key) {
|
|
53
|
+
// Pass key in POST body to avoid URL encoding issues with unicode
|
|
54
|
+
const url = `${this.proxyUrl}?op=get`;
|
|
55
|
+
const response = await this.fetchWithTimeout(url, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: this.getHeaders("application/json"),
|
|
58
|
+
body: JSON.stringify({ key }),
|
|
59
|
+
});
|
|
60
|
+
const data = (await response.json());
|
|
61
|
+
if (data.error) {
|
|
62
|
+
throw new Error(data.error);
|
|
63
|
+
}
|
|
64
|
+
return data.value;
|
|
65
|
+
}
|
|
66
|
+
async set(key, value, options) {
|
|
67
|
+
// Pass key in POST body to avoid URL encoding issues with unicode
|
|
68
|
+
const url = `${this.proxyUrl}?op=set`;
|
|
69
|
+
const response = await this.fetchWithTimeout(url, {
|
|
70
|
+
method: "POST",
|
|
71
|
+
headers: this.getHeaders("application/json"),
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
key,
|
|
74
|
+
value,
|
|
75
|
+
tags: options?.tags,
|
|
76
|
+
ttl: options?.ttl,
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
const data = (await response.json());
|
|
80
|
+
if (data.error) {
|
|
81
|
+
throw new Error(data.error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async expireTag(tag) {
|
|
85
|
+
// Pass tag in POST body to avoid URL encoding issues with unicode
|
|
86
|
+
const url = `${this.proxyUrl}?op=expireTag`;
|
|
87
|
+
const response = await this.fetchWithTimeout(url, {
|
|
88
|
+
method: "POST",
|
|
89
|
+
headers: this.getHeaders("application/json"),
|
|
90
|
+
body: JSON.stringify({ tag }),
|
|
91
|
+
});
|
|
92
|
+
const data = (await response.json());
|
|
93
|
+
if (data.error) {
|
|
94
|
+
throw new Error(data.error);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
let proxyCacheInstance = null;
|
|
99
|
+
/**
|
|
100
|
+
* Get a proxy cache instance for local development.
|
|
101
|
+
* Uses CACHE_PROXY_URL and PROTECTION_BYPASS environment variables.
|
|
102
|
+
*/
|
|
103
|
+
export function getProxyCache(options) {
|
|
104
|
+
if (!proxyCacheInstance) {
|
|
105
|
+
proxyCacheInstance = new ProxyCacheImpl(options);
|
|
106
|
+
}
|
|
107
|
+
return proxyCacheInstance;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Check if we should use the proxy cache (running locally with integration tests).
|
|
111
|
+
*/
|
|
112
|
+
export function shouldUseProxyCache() {
|
|
113
|
+
// On Vercel, use the native cache
|
|
114
|
+
if (process.env.VERCEL) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
// Only use proxy for integration tests when PROTECTION_BYPASS is set
|
|
118
|
+
if (process.env.INTEGRATION_TEST !== "1") {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
// Use proxy if CACHE_PROXY_URL or PROTECTION_BYPASS is set
|
|
122
|
+
return !!(process.env.CACHE_PROXY_URL || process.env.PROTECTION_BYPASS);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=proxy-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy-cache.js","sourceRoot":"","sources":["../src/proxy-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* README and docs/ validation tests
|
|
3
|
+
*
|
|
4
|
+
* Ensures documentation stays in sync with the actual codebase:
|
|
5
|
+
* 1. TypeScript examples compile correctly
|
|
6
|
+
* 2. API documentation matches KVLike interface
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=readme.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readme.test.d.ts","sourceRoot":"","sources":["../src/readme.test.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|