@dee-wan/cache 1.1.0 → 2.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.
Files changed (40) hide show
  1. package/README.md +31 -1
  2. package/dist/chunk-2V6MG4YX.js +652 -0
  3. package/dist/chunk-2V6MG4YX.js.map +1 -0
  4. package/dist/{chunk-MOJBHU3S.js → chunk-6VWIKYUQ.js} +72 -173
  5. package/dist/chunk-6VWIKYUQ.js.map +1 -0
  6. package/dist/{chunk-HGAUU4EU.js → chunk-7OWX6SH5.js} +52 -15
  7. package/dist/chunk-7OWX6SH5.js.map +1 -0
  8. package/dist/{chunk-A4WV6RY4.js → chunk-GGSQ6C6X.js} +8 -3
  9. package/dist/chunk-GGSQ6C6X.js.map +1 -0
  10. package/dist/{chunk-ZREX7LLC.js → chunk-M4UOCIDQ.js} +18 -6
  11. package/dist/chunk-M4UOCIDQ.js.map +1 -0
  12. package/dist/chunk-NFBMWKY5.js +54 -0
  13. package/dist/chunk-NFBMWKY5.js.map +1 -0
  14. package/dist/{chunk-OOPPXK7Q.js → chunk-WKZ7TKGM.js} +3 -54
  15. package/dist/chunk-WKZ7TKGM.js.map +1 -0
  16. package/dist/chunk-ZBYAKDNZ.js +45 -0
  17. package/dist/chunk-ZBYAKDNZ.js.map +1 -0
  18. package/dist/client.d.ts +14 -1
  19. package/dist/client.js +37 -1
  20. package/dist/client.js.map +1 -1
  21. package/dist/cloudflare/index.d.ts +1 -1
  22. package/dist/cloudflare/index.js +4 -4
  23. package/dist/d1/index.d.ts +18 -2
  24. package/dist/d1/index.js +33 -11
  25. package/dist/d1/index.js.map +1 -1
  26. package/dist/d1/response-lease.js +11 -9
  27. package/dist/d1/response-lease.js.map +1 -1
  28. package/dist/index.d.ts +2 -2
  29. package/dist/index.js +1 -1
  30. package/dist/response-lease.js +8 -3
  31. package/dist/{types-D-Gd11to.d.ts → types-CtErcz2a.d.ts} +13 -1
  32. package/docs/cache-contract.md +2 -0
  33. package/package.json +1 -1
  34. package/dist/chunk-A4WV6RY4.js.map +0 -1
  35. package/dist/chunk-D2EESWMC.js +0 -19
  36. package/dist/chunk-D2EESWMC.js.map +0 -1
  37. package/dist/chunk-HGAUU4EU.js.map +0 -1
  38. package/dist/chunk-MOJBHU3S.js.map +0 -1
  39. package/dist/chunk-OOPPXK7Q.js.map +0 -1
  40. package/dist/chunk-ZREX7LLC.js.map +0 -1
@@ -0,0 +1,54 @@
1
+ // src/cloudflare/retry.ts
2
+ var BASE_BACKOFF_MS = 50;
3
+ var isRetryable = (error) => !!error && typeof error === "object" && Reflect.get(error, "retryable") === true && Reflect.get(error, "overloaded") !== true;
4
+ async function retryTransient(call, attempts, sleep) {
5
+ for (let attempt = 0; ; attempt++) {
6
+ try {
7
+ return await call();
8
+ } catch (error) {
9
+ if (attempt + 1 >= attempts || !isRetryable(error)) throw error;
10
+ await sleep(BASE_BACKOFF_MS * Math.random() * 2 ** attempt);
11
+ }
12
+ }
13
+ }
14
+
15
+ // src/cloudflare/store-options.ts
16
+ var WRITE_PATH_ATTEMPTS = 3;
17
+ var MAX_COORDINATOR_NAME_LENGTH = 256;
18
+ var LOCATION_HINTS = ["wnam", "enam", "sam", "weur", "eeur", "apac", "oc", "afr", "me"];
19
+ var isLocationHint = (value) => LOCATION_HINTS.some((hint) => hint === value);
20
+ function resolveStoreOptions(options) {
21
+ const { attempts = WRITE_PATH_ATTEMPTS, locationHint, name } = options;
22
+ const problems = [
23
+ !(typeof name === "string" && name.length > 0 && name.length <= MAX_COORDINATOR_NAME_LENGTH) && `name must be 1..${MAX_COORDINATOR_NAME_LENGTH} characters and identify one D1 database`,
24
+ !(Number.isInteger(attempts) && attempts >= 1 && attempts <= 10) && "attempts must be an integer in 1..10",
25
+ locationHint !== void 0 && !isLocationHint(locationHint) && `locationHint must be one of ${LOCATION_HINTS.join(", ")}`
26
+ ].filter((problem) => typeof problem === "string");
27
+ if (problems.length > 0) throw new TypeError(`cache store: ${problems.join("; ")}`);
28
+ return {
29
+ attempts,
30
+ name,
31
+ sleep: options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
32
+ ...locationHint ? { locationHint } : {}
33
+ };
34
+ }
35
+
36
+ // src/cloudflare/store.ts
37
+ function createDurableObjectStore(namespace, options) {
38
+ const { attempts, locationHint, name, sleep } = resolveStoreOptions(options);
39
+ const stub = () => namespace.get(namespace.idFromName(name), locationHint ? { locationHint } : void 0);
40
+ const withRetry = (call) => retryTransient(() => call(stub()), attempts, sleep);
41
+ return {
42
+ inspectFences: async (request) => stub().inspectFences(request),
43
+ beginWrite: (request) => withRetry(async (coordinator) => void await coordinator.beginWrite(request)),
44
+ endWrite: (request) => withRetry(async (coordinator) => void await coordinator.endWrite(request)),
45
+ invalidate: (fences) => withRetry(async (coordinator) => void await coordinator.invalidate(fences)),
46
+ read: async (request) => stub().read(request),
47
+ release: async (request) => void await stub().release(request),
48
+ write: async (request) => stub().write(request)
49
+ };
50
+ }
51
+
52
+ export { createDurableObjectStore };
53
+ //# sourceMappingURL=chunk-NFBMWKY5.js.map
54
+ //# sourceMappingURL=chunk-NFBMWKY5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cloudflare/retry.ts","../src/cloudflare/store-options.ts","../src/cloudflare/store.ts"],"names":[],"mappings":"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","file":"chunk-NFBMWKY5.js","sourcesContent":["const BASE_BACKOFF_MS = 50;\n\nexport const isRetryable = (error: unknown): boolean =>\n !!error && typeof error === \"object\" && Reflect.get(error, \"retryable\") === true && Reflect.get(error, \"overloaded\") !== true;\n\nexport async function retryTransient<T>(call: () => Promise<T>, attempts: number, sleep: (ms: number) => Promise<void>): Promise<T> {\n for (let attempt = 0; ; attempt++) {\n try {\n return await call();\n } catch (error) {\n if (attempt + 1 >= attempts || !isRetryable(error)) throw error;\n await sleep(BASE_BACKOFF_MS * Math.random() * 2 ** attempt);\n }\n }\n}\n","export const WRITE_PATH_ATTEMPTS = 3;\nexport const MAX_COORDINATOR_NAME_LENGTH = 256;\n\nexport const LOCATION_HINTS = [\"wnam\", \"enam\", \"sam\", \"weur\", \"eeur\", \"apac\", \"oc\", \"afr\", \"me\"] as const;\n\nexport type CoordinatorLocationHint = (typeof LOCATION_HINTS)[number];\n\nexport interface DurableObjectStoreOptions {\n attempts?: number;\n locationHint?: CoordinatorLocationHint;\n name: string;\n sleep?: (ms: number) => Promise<void>;\n}\n\nexport interface ResolvedStoreOptions {\n attempts: number;\n locationHint?: CoordinatorLocationHint;\n name: string;\n sleep: (ms: number) => Promise<void>;\n}\n\nconst isLocationHint = (value: unknown): value is CoordinatorLocationHint =>\n LOCATION_HINTS.some((hint) => hint === value);\n\nexport function resolveStoreOptions(options: DurableObjectStoreOptions): ResolvedStoreOptions {\n const { attempts = WRITE_PATH_ATTEMPTS, locationHint, name } = options;\n const problems = [\n !(typeof name === \"string\" && name.length > 0 && name.length <= MAX_COORDINATOR_NAME_LENGTH) &&\n `name must be 1..${MAX_COORDINATOR_NAME_LENGTH} characters and identify one D1 database`,\n !(Number.isInteger(attempts) && attempts >= 1 && attempts <= 10) && \"attempts must be an integer in 1..10\",\n locationHint !== undefined && !isLocationHint(locationHint) && `locationHint must be one of ${LOCATION_HINTS.join(\", \")}`,\n ].filter((problem): problem is string => typeof problem === \"string\");\n if (problems.length > 0) throw new TypeError(`cache store: ${problems.join(\"; \")}`);\n return {\n attempts,\n name,\n sleep: options.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms))),\n ...(locationHint ? { locationHint } : {}),\n };\n}\n","import type { CacheStore } from \"../core/types\";\nimport type { CacheCoordinator } from \"./coordinator\";\n\nimport { retryTransient } from \"./retry\";\nimport { type DurableObjectStoreOptions, resolveStoreOptions } from \"./store-options\";\n\nexport function createDurableObjectStore<Env>(\n namespace: DurableObjectNamespace<CacheCoordinator<Env>>,\n options: DurableObjectStoreOptions,\n): CacheStore {\n const { attempts, locationHint, name, sleep } = resolveStoreOptions(options);\n const stub = () => namespace.get(namespace.idFromName(name), locationHint ? { locationHint } : undefined);\n const withRetry = <T>(call: (coordinator: ReturnType<typeof stub>) => Promise<T>): Promise<T> =>\n retryTransient(() => call(stub()), attempts, sleep);\n\n return {\n inspectFences: async (request) => stub().inspectFences(request),\n beginWrite: (request) => withRetry(async (coordinator) => void (await coordinator.beginWrite(request))),\n endWrite: (request) => withRetry(async (coordinator) => void (await coordinator.endWrite(request))),\n invalidate: (fences) => withRetry(async (coordinator) => void (await coordinator.invalidate(fences))),\n read: async (request) => stub().read(request),\n release: async (request) => void (await stub().release(request)),\n write: async (request) => stub().write(request),\n };\n}\n"]}
@@ -1,54 +1,3 @@
1
- // src/cloudflare/retry.ts
2
- var BASE_BACKOFF_MS = 50;
3
- var isRetryable = (error) => !!error && typeof error === "object" && Reflect.get(error, "retryable") === true && Reflect.get(error, "overloaded") !== true;
4
- async function retryTransient(call, attempts, sleep) {
5
- for (let attempt = 0; ; attempt++) {
6
- try {
7
- return await call();
8
- } catch (error) {
9
- if (attempt + 1 >= attempts || !isRetryable(error)) throw error;
10
- await sleep(BASE_BACKOFF_MS * Math.random() * 2 ** attempt);
11
- }
12
- }
13
- }
14
-
15
- // src/cloudflare/store-options.ts
16
- var WRITE_PATH_ATTEMPTS = 3;
17
- var MAX_COORDINATOR_NAME_LENGTH = 256;
18
- var LOCATION_HINTS = ["wnam", "enam", "sam", "weur", "eeur", "apac", "oc", "afr", "me"];
19
- var isLocationHint = (value) => LOCATION_HINTS.some((hint) => hint === value);
20
- function resolveStoreOptions(options) {
21
- const { attempts = WRITE_PATH_ATTEMPTS, locationHint, name } = options;
22
- const problems = [
23
- !(typeof name === "string" && name.length > 0 && name.length <= MAX_COORDINATOR_NAME_LENGTH) && `name must be 1..${MAX_COORDINATOR_NAME_LENGTH} characters and identify one D1 database`,
24
- !(Number.isInteger(attempts) && attempts >= 1 && attempts <= 10) && "attempts must be an integer in 1..10",
25
- locationHint !== void 0 && !isLocationHint(locationHint) && `locationHint must be one of ${LOCATION_HINTS.join(", ")}`
26
- ].filter((problem) => typeof problem === "string");
27
- if (problems.length > 0) throw new TypeError(`cache store: ${problems.join("; ")}`);
28
- return {
29
- attempts,
30
- name,
31
- sleep: options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))),
32
- ...locationHint ? { locationHint } : {}
33
- };
34
- }
35
-
36
- // src/cloudflare/store.ts
37
- function createDurableObjectStore(namespace, options) {
38
- const { attempts, locationHint, name, sleep } = resolveStoreOptions(options);
39
- const stub = () => namespace.get(namespace.idFromName(name), locationHint ? { locationHint } : void 0);
40
- const withRetry = (call) => retryTransient(() => call(stub()), attempts, sleep);
41
- return {
42
- inspectFences: async (request) => stub().inspectFences(request),
43
- beginWrite: (request) => withRetry(async (coordinator) => void await coordinator.beginWrite(request)),
44
- endWrite: (request) => withRetry(async (coordinator) => void await coordinator.endWrite(request)),
45
- invalidate: (fences) => withRetry(async (coordinator) => void await coordinator.invalidate(fences)),
46
- read: async (request) => stub().read(request),
47
- release: async (request) => void await stub().release(request),
48
- write: async (request) => stub().write(request)
49
- };
50
- }
51
-
52
1
  // src/d1/deadline.ts
53
2
  var COORDINATOR_TIMEOUT_MS = 2e3;
54
3
  async function withinCoordinatorDeadline(work) {
@@ -128,6 +77,6 @@ function boundedD1Store(store) {
128
77
  return bounded;
129
78
  }
130
79
 
131
- export { boundedD1Store, createDurableObjectStore, withinCoordinatorDeadline };
132
- //# sourceMappingURL=chunk-OOPPXK7Q.js.map
133
- //# sourceMappingURL=chunk-OOPPXK7Q.js.map
80
+ export { boundedD1Store, withinCoordinatorDeadline };
81
+ //# sourceMappingURL=chunk-WKZ7TKGM.js.map
82
+ //# sourceMappingURL=chunk-WKZ7TKGM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/d1/deadline.ts","../src/d1/bounded-store.ts"],"names":[],"mappings":"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","file":"chunk-WKZ7TKGM.js","sourcesContent":["const COORDINATOR_TIMEOUT_MS = 2_000;\n\nexport async function withinCoordinatorDeadline<T>(work: Promise<T>): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([work, new Promise<never>((_, reject) => { timer = setTimeout(() => reject(new Error('cache coordinator timeout')), COORDINATOR_TIMEOUT_MS); })]);\n } finally { if (timer !== undefined) clearTimeout(timer); }\n}\n","import type { CacheStore, EndWriteRequest } from '../core/types';\nimport { withinCoordinatorDeadline } from './deadline';\n\nconst boundedStores = new WeakMap<CacheStore, CacheStore>();\n\nexport function boundedD1Store(store: CacheStore): CacheStore {\n const existing = boundedStores.get(store);\n if (existing) return existing;\n const failedBegins = new Set<string>();\n const inspectFences = store.inspectFences;\n const endWrite = async (request: EndWriteRequest): Promise<void> => {\n let active = true;\n try {\n await withinCoordinatorDeadline((async () => {\n for (let attempt = 0; ; attempt++) {\n try { await store.endWrite(request); return; }\n catch (error) { if (!active || attempt === 1) throw error; }\n }\n })());\n } finally { active = false; }\n };\n const bounded: CacheStore = {\n ...store,\n ...(inspectFences ? { inspectFences: (request: Parameters<typeof inspectFences>[0]) => withinCoordinatorDeadline(Promise.resolve().then(() => inspectFences.call(store, request))) } : {}),\n async read(request) {\n const pending = Promise.resolve().then(() => store.read(request));\n try { return await withinCoordinatorDeadline(pending); }\n catch (error) {\n void pending.then((result) => {\n const token = result.kind === 'miss' ? result.lockToken : result.refreshToken;\n if (token) return bounded.release({ key: request.key, lockToken: token });\n return undefined;\n }).catch(() => undefined);\n throw error;\n }\n },\n write: (request) => withinCoordinatorDeadline(Promise.resolve().then(() => store.write(request))),\n release: (request) => withinCoordinatorDeadline(Promise.resolve().then(() => store.release(request))),\n async beginWrite(request) {\n const begin = Promise.resolve().then(() => store.beginWrite(request));\n try { await withinCoordinatorDeadline(begin); }\n catch (error) {\n failedBegins.add(request.token);\n void begin.then(\n () => endWrite({ fences: request.fences, token: request.token }),\n () => endWrite({ fences: request.fences, token: request.token }),\n ).catch(() => undefined);\n throw error;\n }\n },\n async endWrite(request) {\n if (failedBegins.delete(request.token)) return;\n await endWrite(request);\n },\n invalidate: (fences) => withinCoordinatorDeadline(Promise.resolve().then(() => store.invalidate(fences))),\n };\n boundedStores.set(store, bounded);\n boundedStores.set(bounded, bounded);\n return bounded;\n}\n"]}
@@ -0,0 +1,45 @@
1
+ // src/d1/bookmarks.ts
2
+ var D1_BOOKMARK_HEADER = "X-Dee-Wan-D1-Bookmarks";
3
+ var MAX_HEADER_LENGTH = 8192;
4
+ var MAX_DATABASES = 64;
5
+ var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
6
+ var BOOKMARK = /^(?!first-primary$|first-unconstrained$)[\x21-\x7e]{1,512}$/;
7
+ function decodeD1Bookmarks(value) {
8
+ if (value === null) return {};
9
+ if (!value || value.length > MAX_HEADER_LENGTH) return null;
10
+ try {
11
+ const parsed = JSON.parse(value);
12
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
13
+ const entries = Object.entries(parsed);
14
+ if (entries.length > MAX_DATABASES || entries.some(([id, bookmark]) => !UUID.test(id) || typeof bookmark !== "string" || !BOOKMARK.test(bookmark))) return null;
15
+ return Object.fromEntries(entries);
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function parseD1Bookmarks(value) {
21
+ return decodeD1Bookmarks(value) ?? {};
22
+ }
23
+ function mergeD1Bookmarks(target, incoming) {
24
+ for (const [id, bookmark] of Object.entries(incoming)) {
25
+ if (!UUID.test(id) || !BOOKMARK.test(bookmark) || target[id] && bookmark <= target[id]) continue;
26
+ const previous = target[id];
27
+ target[id] = bookmark;
28
+ if (serializeD1Bookmarks(target) === null) {
29
+ if (previous === void 0) delete target[id];
30
+ else target[id] = previous;
31
+ return false;
32
+ }
33
+ }
34
+ return true;
35
+ }
36
+ function serializeD1Bookmarks(bookmarks) {
37
+ const entries = Object.entries(bookmarks).sort(([a], [b]) => a.localeCompare(b));
38
+ if (entries.length > MAX_DATABASES || entries.some(([id, bookmark]) => !UUID.test(id) || !BOOKMARK.test(bookmark))) return null;
39
+ const result = JSON.stringify(Object.fromEntries(entries));
40
+ return result.length <= MAX_HEADER_LENGTH ? result : null;
41
+ }
42
+
43
+ export { D1_BOOKMARK_HEADER, decodeD1Bookmarks, mergeD1Bookmarks, parseD1Bookmarks, serializeD1Bookmarks };
44
+ //# sourceMappingURL=chunk-ZBYAKDNZ.js.map
45
+ //# sourceMappingURL=chunk-ZBYAKDNZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/d1/bookmarks.ts"],"names":[],"mappings":";AAAO,IAAM,kBAAA,GAAqB;AAClC,IAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAM,aAAA,GAAgB,EAAA;AACtB,IAAM,IAAA,GAAO,gEAAA;AACb,IAAM,QAAA,GAAW,6DAAA;AAIV,SAAS,kBAAkB,KAAA,EAA0C;AAC1E,EAAA,IAAI,KAAA,KAAU,IAAA,EAAM,OAAO,EAAC;AAC5B,EAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,GAAS,mBAAmB,OAAO,IAAA;AACvD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,KAAK,CAAA;AACxC,IAAA,IAAI,CAAC,UAAU,OAAO,MAAA,KAAW,YAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG,OAAO,IAAA;AAC3E,IAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA;AACrC,IAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,aAAA,IAAiB,OAAA,CAAQ,IAAA,CAAK,CAAC,CAAC,EAAA,EAAI,QAAQ,CAAA,KAAM,CAAC,IAAA,CAAK,KAAK,EAAE,CAAA,IAAK,OAAO,QAAA,KAAa,QAAA,IAAY,CAAC,SAAS,IAAA,CAAK,QAAQ,CAAC,CAAA,EAAG,OAAO,IAAA;AAC3J,IAAA,OAAO,MAAA,CAAO,YAAY,OAAO,CAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,IAAA;AAAA,EAAM;AACzB;AAEO,SAAS,iBAAiB,KAAA,EAAmC;AAClE,EAAA,OAAO,iBAAA,CAAkB,KAAK,CAAA,IAAK,EAAC;AACtC;AAEO,SAAS,gBAAA,CAAiB,QAAqB,QAAA,EAAgC;AACpF,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACrD,IAAA,IAAI,CAAC,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,IAAK,CAAC,QAAA,CAAS,IAAA,CAAK,QAAQ,CAAA,IAAM,OAAO,EAAE,CAAA,IAAK,QAAA,IAAY,MAAA,CAAO,EAAE,CAAA,EAAI;AAC1F,IAAA,MAAM,QAAA,GAAW,OAAO,EAAE,CAAA;AAC1B,IAAA,MAAA,CAAO,EAAE,CAAA,GAAI,QAAA;AACb,IAAA,IAAI,oBAAA,CAAqB,MAAM,CAAA,KAAM,IAAA,EAAM;AACzC,MAAA,IAAI,QAAA,KAAa,MAAA,EAAW,OAAO,MAAA,CAAO,EAAE,CAAA;AAAA,WACvC,MAAA,CAAO,EAAE,CAAA,GAAI,QAAA;AAClB,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEO,SAAS,qBAAqB,SAAA,EAAuC;AAC1E,EAAA,MAAM,UAAU,MAAA,CAAO,OAAA,CAAQ,SAAS,CAAA,CAAE,KAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA,KAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA;AAC/E,EAAA,IAAI,OAAA,CAAQ,SAAS,aAAA,IAAiB,OAAA,CAAQ,KAAK,CAAC,CAAC,IAAI,QAAQ,CAAA,KAAM,CAAC,IAAA,CAAK,IAAA,CAAK,EAAE,CAAA,IAAK,CAAC,SAAS,IAAA,CAAK,QAAQ,CAAC,CAAA,EAAG,OAAO,IAAA;AAC3H,EAAA,MAAM,SAAS,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,WAAA,CAAY,OAAO,CAAC,CAAA;AACzD,EAAA,OAAO,MAAA,CAAO,MAAA,IAAU,iBAAA,GAAoB,MAAA,GAAS,IAAA;AACvD","file":"chunk-ZBYAKDNZ.js","sourcesContent":["export const D1_BOOKMARK_HEADER = 'X-Dee-Wan-D1-Bookmarks';\nconst MAX_HEADER_LENGTH = 8192;\nconst MAX_DATABASES = 64;\nconst UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\nconst BOOKMARK = /^(?!first-primary$|first-unconstrained$)[\\x21-\\x7e]{1,512}$/;\n\nexport type D1Bookmarks = Record<string, string>;\n\nexport function decodeD1Bookmarks(value: string | null): D1Bookmarks | null {\n if (value === null) return {};\n if (!value || value.length > MAX_HEADER_LENGTH) return null;\n try {\n const parsed: unknown = JSON.parse(value);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;\n const entries = Object.entries(parsed);\n if (entries.length > MAX_DATABASES || entries.some(([id, bookmark]) => !UUID.test(id) || typeof bookmark !== 'string' || !BOOKMARK.test(bookmark))) return null;\n return Object.fromEntries(entries);\n } catch { return null; }\n}\n\nexport function parseD1Bookmarks(value: string | null): D1Bookmarks {\n return decodeD1Bookmarks(value) ?? {};\n}\n\nexport function mergeD1Bookmarks(target: D1Bookmarks, incoming: D1Bookmarks): boolean {\n for (const [id, bookmark] of Object.entries(incoming)) {\n if (!UUID.test(id) || !BOOKMARK.test(bookmark) || (target[id] && bookmark <= target[id])) continue;\n const previous = target[id];\n target[id] = bookmark;\n if (serializeD1Bookmarks(target) === null) {\n if (previous === undefined) delete target[id];\n else target[id] = previous;\n return false;\n }\n }\n return true;\n}\n\nexport function serializeD1Bookmarks(bookmarks: D1Bookmarks): string | null {\n const entries = Object.entries(bookmarks).sort(([a], [b]) => a.localeCompare(b));\n if (entries.length > MAX_DATABASES || entries.some(([id, bookmark]) => !UUID.test(id) || !BOOKMARK.test(bookmark))) return null;\n const result = JSON.stringify(Object.fromEntries(entries));\n return result.length <= MAX_HEADER_LENGTH ? result : null;\n}\n"]}
package/dist/client.d.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  import { D as D1CacheProfile } from './profile--LBtbQI_.js';
2
2
 
3
+ declare const D1_BOOKMARK_HEADER = "X-Dee-Wan-D1-Bookmarks";
4
+ type D1Bookmarks = Record<string, string>;
5
+ declare function parseD1Bookmarks(value: string | null): D1Bookmarks;
6
+ declare function serializeD1Bookmarks(bookmarks: D1Bookmarks): string | null;
7
+
3
8
  declare function createSingleFlight<Key, Value>(): {
4
9
  run(key: Key, load: () => Promise<Value>): Promise<Value>;
5
10
  forget(key: Key): void;
@@ -47,4 +52,12 @@ declare function createMutationInvalidation(policy: Pick<NonNullable<D1CacheProf
47
52
  dispose(): void;
48
53
  };
49
54
 
50
- export { type FreshnessTransport, type MutationInvalidationChannel, type MutationInvalidationEvent, createIntentWarmup, createMutationInvalidation, createReadFreshness, createRevalidationWindow, createSingleFlight };
55
+ interface D1BookmarkStorage {
56
+ getItem(key: string): string | null;
57
+ setItem(key: string, value: string): void;
58
+ }
59
+ declare function createD1BookmarkFetch(fetcher?: typeof fetch, options?: {
60
+ storage?: D1BookmarkStorage;
61
+ }): typeof fetch;
62
+
63
+ export { type D1BookmarkStorage, D1_BOOKMARK_HEADER, type FreshnessTransport, type MutationInvalidationChannel, type MutationInvalidationEvent, createD1BookmarkFetch, createIntentWarmup, createMutationInvalidation, createReadFreshness, createRevalidationWindow, createSingleFlight, parseD1Bookmarks, serializeD1Bookmarks };
package/dist/client.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { needsFreshness } from './chunk-JPK2AF7X.js';
2
+ import { mergeD1Bookmarks, parseD1Bookmarks, D1_BOOKMARK_HEADER, serializeD1Bookmarks } from './chunk-ZBYAKDNZ.js';
3
+ export { D1_BOOKMARK_HEADER, parseD1Bookmarks, serializeD1Bookmarks } from './chunk-ZBYAKDNZ.js';
2
4
 
3
5
  // src/client.ts
4
6
  function createSingleFlight() {
@@ -218,7 +220,41 @@ function createMutationInvalidation(policy, options = {}) {
218
220
  }
219
221
  };
220
222
  }
223
+ function createD1BookmarkFetch(fetcher = fetch, options = {}) {
224
+ const origins = /* @__PURE__ */ new Map();
225
+ return async (input, init) => {
226
+ const request = new Request(input, init);
227
+ const origin = new URL(request.url).origin;
228
+ const bookmarks = origins.get(origin) ?? {};
229
+ if (!origins.has(origin)) origins.set(origin, bookmarks);
230
+ const key = `dee-wan:d1-bookmarks:${origin}`;
231
+ const mergeStored = () => {
232
+ try {
233
+ const saved = parseD1Bookmarks(options.storage?.getItem(key) ?? null);
234
+ const combined = { ...bookmarks };
235
+ if (mergeD1Bookmarks(combined, saved)) Object.assign(bookmarks, combined);
236
+ } catch {
237
+ }
238
+ };
239
+ mergeStored();
240
+ const headers = new Headers(request.headers);
241
+ const outgoing = { ...bookmarks };
242
+ if (!mergeD1Bookmarks(outgoing, parseD1Bookmarks(headers.get(D1_BOOKMARK_HEADER)))) throw new RangeError("D1 bookmark capacity exceeded");
243
+ const encoded = serializeD1Bookmarks(outgoing);
244
+ if (encoded && encoded !== "{}") headers.set(D1_BOOKMARK_HEADER, encoded);
245
+ else headers.delete(D1_BOOKMARK_HEADER);
246
+ const response = await fetcher(new Request(request, { headers }));
247
+ mergeStored();
248
+ if (!mergeD1Bookmarks(bookmarks, parseD1Bookmarks(response.headers.get(D1_BOOKMARK_HEADER)))) throw new RangeError("D1 bookmark capacity exceeded");
249
+ try {
250
+ const value = serializeD1Bookmarks(bookmarks);
251
+ if (value && value !== "{}") options.storage?.setItem(key, value);
252
+ } catch {
253
+ }
254
+ return response;
255
+ };
256
+ }
221
257
 
222
- export { createIntentWarmup, createMutationInvalidation, createReadFreshness, createRevalidationWindow, createSingleFlight };
258
+ export { createD1BookmarkFetch, createIntentWarmup, createMutationInvalidation, createReadFreshness, createRevalidationWindow, createSingleFlight };
223
259
  //# sourceMappingURL=client.js.map
224
260
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"client.js","sourcesContent":["import type { D1CacheProfile } from './d1/profile';\nimport { needsFreshness } from './d1/read-freshness-policy';\n\nexport function createSingleFlight<Key, Value>() {\n const pending = new Map<Key, Promise<Value>>();\n return {\n run(key: Key, load: () => Promise<Value>): Promise<Value> {\n const existing = pending.get(key);\n if (existing) return existing;\n const promise = Promise.resolve().then(load);\n pending.set(key, promise);\n void promise.then(() => { if (pending.get(key) === promise) pending.delete(key); }, () => { if (pending.get(key) === promise) pending.delete(key); });\n return promise;\n },\n forget(key: Key): void { pending.delete(key); },\n };\n}\n\nexport function createIntentWarmup(cooldownMs = 60_000, now: () => number = monotonicNow) {\n const duration = Number.isFinite(cooldownMs) && cooldownMs > 0 ? cooldownMs : 60_000;\n const warmed = new Map<string, number>();\n let scope = '';\n let generation = 0;\n let running = false;\n let queued: { key: string; load: (isCurrent: () => boolean) => Promise<boolean>; generation: number } | undefined;\n const drain = () => {\n if (running || !queued) return;\n const task = queued;\n queued = undefined;\n if ((warmed.get(task.key) ?? 0) > now()) return;\n running = true;\n const isCurrent = () => task.generation === generation && scope !== '';\n void Promise.resolve().then(() => isCurrent() ? task.load(isCurrent) : false).then((ok) => {\n if (ok && task.generation === generation) warmed.set(task.key, now() + duration);\n }, () => {}).finally(() => { running = false; drain(); });\n };\n return {\n setScope(next: string): void {\n if (scope === next) return;\n scope = next;\n generation++;\n queued = undefined;\n warmed.clear();\n },\n invalidate(): void { generation++; queued = undefined; warmed.clear(); },\n warm(key: string, load: (isCurrent: () => boolean) => Promise<boolean>): void {\n if (!scope || !key || (warmed.get(key) ?? 0) > now()) return;\n queued = { key, load, generation };\n drain();\n },\n };\n}\n\ntype ReadLeasePolicy = Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'freshnessHeader' | 'freshnessCookieExcludedPaths' | 'maxSeconds' | 'freshnessCookieMode'> & Partial<Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'credentialHeaders'>>;\n\nexport interface FreshnessTransport { origin?: string; baseUrl?: string; withCredentials?: boolean }\n\nfunction usesGenerationCookie(policy: ReadLeasePolicy, url: string, transport?: FreshnessTransport): boolean {\n if (policy.freshnessCookieMode !== 'generation' || !policy.credentialHeaders?.some((name) => name.toLowerCase() === 'cookie') || transport?.withCredentials !== true || !transport.origin || transport.baseUrl === undefined) return false;\n try {\n const origin = new URL(transport.origin).origin;\n const base = new URL(transport.baseUrl, origin);\n return origin !== 'null' && new URL(url, base).origin === origin;\n } catch { return false; }\n}\n\nexport function createReadFreshness(policy: ReadLeasePolicy, now: () => number = Date.now) {\n const until = new Map<string, number>();\n const prune = (time: number) => { for (const [scope, deadline] of until) if (deadline <= time) until.delete(scope); };\n return {\n headers(scope: string, method: string): Record<string, string> {\n const time = now();\n prune(time);\n if (method.toUpperCase() !== 'GET' || !until.has(scope)) return {};\n return { 'Cache-Control':'no-cache', ...(policy.freshnessHeader ? { [policy.freshnessHeader]:'1' } : {}) };\n },\n observe(scope: string, method: string, url: string, transport?: FreshnessTransport): void {\n const time = now();\n prune(time);\n let pathname: string;\n try { pathname = new URL(url, 'https://cache.invalid').pathname; } catch { pathname = ''; }\n if (needsFreshness(method, pathname, policy.freshnessCookieExcludedPaths) && !usesGenerationCookie(policy, url, transport)) until.set(scope, time + (Number.isInteger(policy.maxSeconds) && policy.maxSeconds !== undefined && policy.maxSeconds >= 1 && policy.maxSeconds <= 300 ? policy.maxSeconds : 5) * 1000);\n },\n };\n}\n\nfunction monotonicNow(): number {\n const clock: unknown = Reflect.get(globalThis, 'performance');\n if (clock && typeof clock === 'object') {\n const read: unknown = Reflect.get(clock, 'now');\n if (typeof read === 'function') {\n const value: unknown = Reflect.apply(read, clock, []);\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n }\n }\n return Date.now();\n}\n\nexport function createRevalidationWindow(windowMs: number, now: () => number = monotonicNow) {\n const duration = Number.isFinite(windowMs) && windowMs > 0 ? windowMs : 300_000;\n const scopes = new Map<string, number>();\n return {\n remaining(scope: string): number {\n const time = now();\n let deadline = scopes.get(scope);\n if (deadline === undefined) { deadline = time + duration; scopes.set(scope, deadline); }\n return Math.max(0, deadline - time);\n },\n take(scope: string): boolean {\n const time = now();\n const deadline = scopes.get(scope);\n if (deadline !== undefined && time < deadline) return false;\n scopes.set(scope, time + duration);\n return true;\n },\n };\n}\n\nexport interface MutationInvalidationEvent {\n scope: string;\n method: string;\n pathname: string;\n}\n\nexport interface MutationInvalidationChannel {\n readonly name: string;\n postMessage(value: MutationInvalidationEvent): void;\n addEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n removeEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n close(): void;\n}\n\nconst mutationChannelName = 'dee-wan-cache-invalidation-v1';\nconst validScope = (scope: string): boolean => /^[A-Za-z0-9:_-]{1,256}$/.test(scope);\nconst validMethod = (method: string): boolean => /^[!#$%&'*+.^_`|~0-9A-Z-]{1,32}$/.test(method);\nconst validPathname = (pathname: string): boolean => pathname.startsWith('/') && pathname.length <= 2048 && ![...pathname].some((character) => character === '?' || character === '#' || character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127);\n\nfunction invalidationChannel(value: unknown): value is MutationInvalidationChannel {\n return !!value && typeof value === 'object' && Reflect.get(value, 'name') === mutationChannelName && ['postMessage', 'addEventListener', 'removeEventListener', 'close'].every((name) => typeof Reflect.get(value, name) === 'function');\n}\n\nfunction browserInvalidationChannel(): MutationInvalidationChannel | undefined {\n const document: unknown = Reflect.get(globalThis, 'document');\n if (!document || typeof document !== 'object') return undefined;\n const constructor: unknown = Reflect.get(globalThis, 'BroadcastChannel');\n if (typeof constructor !== 'function') return undefined;\n try { const channel: unknown = Reflect.construct(constructor, [mutationChannelName]); return invalidationChannel(channel) ? channel : undefined; } catch { return undefined; }\n}\n\nexport function createMutationInvalidation(policy: Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'freshnessCookieExcludedPaths'>, options: { channel?: MutationInvalidationChannel | null } = {}) {\n const supplied = options.channel === undefined ? browserInvalidationChannel() : options.channel;\n const channel = invalidationChannel(supplied) ? supplied : undefined;\n const listeners = new Map<string, Set<(event: MutationInvalidationEvent) => void>>();\n let disposed = false;\n const notify = (event: MutationInvalidationEvent) => {\n for (const listener of listeners.get(event.scope) ?? []) {\n try { listener({ ...event }); } catch { /* Subscribers are independent. */ }\n }\n };\n const receive = ({ data }: { data: unknown }) => {\n try {\n if (disposed || !data || typeof data !== 'object' || Object.keys(data).sort().join(',') !== 'method,pathname,scope') return;\n const scope: unknown = Reflect.get(data, 'scope');\n const method: unknown = Reflect.get(data, 'method');\n const pathname: unknown = Reflect.get(data, 'pathname');\n if (typeof scope !== 'string' || !validScope(scope) || typeof method !== 'string' || !validMethod(method) || typeof pathname !== 'string' || !validPathname(pathname) || !needsFreshness(method, pathname, policy.freshnessCookieExcludedPaths)) return;\n notify({ scope, method, pathname });\n } catch { /* Ignore malformed messages. */ }\n };\n channel?.addEventListener('message', receive);\n return {\n publish(scope: string, method: string, url: string): void {\n if (disposed || !validScope(scope)) return;\n const normalized = method.toUpperCase();\n if (!validMethod(normalized)) return;\n let pathname: string;\n try { pathname = new URL(url, 'https://cache.invalid').pathname; } catch { return; }\n if (!validPathname(pathname) || !needsFreshness(normalized, pathname, policy.freshnessCookieExcludedPaths)) return;\n const event = { scope, method:normalized, pathname };\n notify(event);\n try { channel?.postMessage({ scope, method:normalized, pathname }); } catch { /* Local notification remains available. */ }\n },\n subscribe(scope: string, listener: (event: MutationInvalidationEvent) => void): () => void {\n if (disposed || !validScope(scope)) return () => {};\n let group = listeners.get(scope);\n if (!group) { group = new Set(); listeners.set(scope, group); }\n group.add(listener);\n const subscribed = group;\n return () => { subscribed.delete(listener); if (subscribed.size === 0 && listeners.get(scope) === subscribed) listeners.delete(scope); };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n listeners.clear();\n channel?.removeEventListener('message', receive);\n channel?.close();\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":";;;;;AAGO,SAAS,kBAAA,GAAiC;AAC/C,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAyB;AAC7C,EAAA,OAAO;AAAA,IACL,GAAA,CAAI,KAAU,IAAA,EAA4C;AACxD,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA;AAChC,MAAA,IAAI,UAAU,OAAO,QAAA;AACrB,MAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,OAAA,EAAQ,CAAE,KAAK,IAAI,CAAA;AAC3C,MAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,OAAO,CAAA;AACxB,MAAA,KAAK,OAAA,CAAQ,KAAK,MAAM;AAAE,QAAA,IAAI,QAAQ,GAAA,CAAI,GAAG,MAAM,OAAA,EAAS,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,MAAG,GAAG,MAAM;AAAE,QAAA,IAAI,QAAQ,GAAA,CAAI,GAAG,MAAM,OAAA,EAAS,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,MAAG,CAAC,CAAA;AACpJ,MAAA,OAAO,OAAA;AAAA,IACT,CAAA;AAAA,IACA,OAAO,GAAA,EAAgB;AAAE,MAAA,OAAA,CAAQ,OAAO,GAAG,CAAA;AAAA,IAAG;AAAA,GAChD;AACF;AAEO,SAAS,kBAAA,CAAmB,UAAA,GAAa,GAAA,EAAQ,GAAA,GAAoB,YAAA,EAAc;AACxF,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,IAAK,UAAA,GAAa,IAAI,UAAA,GAAa,GAAA;AAC9E,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,IAAI,KAAA,GAAQ,EAAA;AACZ,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,IAAI,MAAA;AACJ,EAAA,MAAM,QAAQ,MAAM;AAClB,IAAA,IAAI,OAAA,IAAW,CAAC,MAAA,EAAQ;AACxB,IAAA,MAAM,IAAA,GAAO,MAAA;AACb,IAAA,MAAA,GAAS,MAAA;AACT,IAAA,IAAA,CAAK,OAAO,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA,IAAK,CAAA,IAAK,KAAI,EAAG;AACzC,IAAA,OAAA,GAAU,IAAA;AACV,IAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,UAAA,KAAe,cAAc,KAAA,KAAU,EAAA;AACpE,IAAA,KAAK,OAAA,CAAQ,OAAA,EAAQ,CAAE,IAAA,CAAK,MAAM,SAAA,EAAU,GAAI,IAAA,CAAK,IAAA,CAAK,SAAS,CAAA,GAAI,KAAK,CAAA,CAAE,IAAA,CAAK,CAAC,EAAA,KAAO;AACzF,MAAA,IAAI,EAAA,IAAM,IAAA,CAAK,UAAA,KAAe,UAAA,EAAY,MAAA,CAAO,IAAI,IAAA,CAAK,GAAA,EAAK,GAAA,EAAI,GAAI,QAAQ,CAAA;AAAA,IACjF,GAAG,MAAM;AAAA,IAAC,CAAC,CAAA,CAAE,OAAA,CAAQ,MAAM;AAAE,MAAA,OAAA,GAAU,KAAA;AAAO,MAAA,KAAA,EAAM;AAAA,IAAG,CAAC,CAAA;AAAA,EAC1D,CAAA;AACA,EAAA,OAAO;AAAA,IACL,SAAS,IAAA,EAAoB;AAC3B,MAAA,IAAI,UAAU,IAAA,EAAM;AACpB,MAAA,KAAA,GAAQ,IAAA;AACR,MAAA,UAAA,EAAA;AACA,MAAA,MAAA,GAAS,MAAA;AACT,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IACf,CAAA;AAAA,IACA,UAAA,GAAmB;AAAE,MAAA,UAAA,EAAA;AAAc,MAAA,MAAA,GAAS,MAAA;AAAW,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IAAG,CAAA;AAAA,IACvE,IAAA,CAAK,KAAa,IAAA,EAA4D;AAC5E,MAAA,IAAI,CAAC,KAAA,IAAS,CAAC,GAAA,IAAA,CAAQ,MAAA,CAAO,IAAI,GAAG,CAAA,IAAK,CAAA,IAAK,GAAA,EAAI,EAAG;AACtD,MAAA,MAAA,GAAS,EAAE,GAAA,EAAK,IAAA,EAAM,UAAA,EAAW;AACjC,MAAA,KAAA,EAAM;AAAA,IACR;AAAA,GACF;AACF;AAMA,SAAS,oBAAA,CAAqB,MAAA,EAAyB,GAAA,EAAa,SAAA,EAAyC;AAC3G,EAAA,IAAI,MAAA,CAAO,wBAAwB,YAAA,IAAgB,CAAC,OAAO,iBAAA,EAAmB,IAAA,CAAK,CAAC,IAAA,KAAS,IAAA,CAAK,WAAA,OAAkB,QAAQ,CAAA,IAAK,SAAA,EAAW,eAAA,KAAoB,IAAA,IAAQ,CAAC,UAAU,MAAA,IAAU,SAAA,CAAU,OAAA,KAAY,MAAA,EAAW,OAAO,KAAA;AACrO,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,SAAA,CAAU,MAAM,CAAA,CAAE,MAAA;AACzC,IAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,SAAA,CAAU,SAAS,MAAM,CAAA;AAC9C,IAAA,OAAO,WAAW,MAAA,IAAU,IAAI,IAAI,GAAA,EAAK,IAAI,EAAE,MAAA,KAAW,MAAA;AAAA,EAC5D,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,KAAA;AAAA,EAAO;AAC1B;AAEO,SAAS,mBAAA,CAAoB,MAAA,EAAyB,GAAA,GAAoB,IAAA,CAAK,GAAA,EAAK;AACzF,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAoB;AACtC,EAAA,MAAM,KAAA,GAAQ,CAAC,IAAA,KAAiB;AAAE,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,QAAQ,CAAA,IAAK,KAAA,MAAW,QAAA,IAAY,IAAA,EAAM,KAAA,CAAM,MAAA,CAAO,KAAK,CAAA;AAAA,EAAG,CAAA;AACpH,EAAA,OAAO;AAAA,IACL,OAAA,CAAQ,OAAe,MAAA,EAAwC;AAC7D,MAAA,MAAM,OAAO,GAAA,EAAI;AACjB,MAAA,KAAA,CAAM,IAAI,CAAA;AACV,MAAA,IAAI,MAAA,CAAO,WAAA,EAAY,KAAM,KAAA,IAAS,CAAC,MAAM,GAAA,CAAI,KAAK,CAAA,EAAG,OAAO,EAAC;AACjE,MAAA,OAAO,EAAE,eAAA,EAAgB,UAAA,EAAY,GAAI,OAAO,eAAA,GAAkB,EAAE,CAAC,MAAA,CAAO,eAAe,GAAE,GAAA,EAAI,GAAI,EAAC,EAAG;AAAA,IAC3G,CAAA;AAAA,IACA,OAAA,CAAQ,KAAA,EAAe,MAAA,EAAgB,GAAA,EAAa,SAAA,EAAsC;AACxF,MAAA,MAAM,OAAO,GAAA,EAAI;AACjB,MAAA,KAAA,CAAM,IAAI,CAAA;AACV,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AAAE,QAAA,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,EAAK,uBAAuB,CAAA,CAAE,QAAA;AAAA,MAAU,CAAA,CAAA,MAAQ;AAAE,QAAA,QAAA,GAAW,EAAA;AAAA,MAAI;AAC1F,MAAA,IAAI,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,MAAA,CAAO,4BAA4B,CAAA,IAAK,CAAC,oBAAA,CAAqB,MAAA,EAAQ,GAAA,EAAK,SAAS,CAAA,EAAG,KAAA,CAAM,IAAI,KAAA,EAAO,IAAA,GAAA,CAAQ,MAAA,CAAO,SAAA,CAAU,MAAA,CAAO,UAAU,CAAA,IAAK,MAAA,CAAO,eAAe,MAAA,IAAa,MAAA,CAAO,UAAA,IAAc,CAAA,IAAK,OAAO,UAAA,IAAc,GAAA,GAAM,MAAA,CAAO,UAAA,GAAa,KAAK,GAAI,CAAA;AAAA,IACnT;AAAA,GACF;AACF;AAEA,SAAS,YAAA,GAAuB;AAC9B,EAAA,MAAM,KAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,aAAa,CAAA;AAC5D,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,IAAA,MAAM,IAAA,GAAgB,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,KAAK,CAAA;AAC9C,IAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,MAAA,MAAM,QAAiB,OAAA,CAAQ,KAAA,CAAM,IAAA,EAAM,KAAA,EAAO,EAAE,CAAA;AACpD,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,OAAO,QAAA,CAAS,KAAK,GAAG,OAAO,KAAA;AAAA,IAClE;AAAA,EACF;AACA,EAAA,OAAO,KAAK,GAAA,EAAI;AAClB;AAEO,SAAS,wBAAA,CAAyB,QAAA,EAAkB,GAAA,GAAoB,YAAA,EAAc;AAC3F,EAAA,MAAM,WAAW,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,IAAK,QAAA,GAAW,IAAI,QAAA,GAAW,GAAA;AACxE,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,EAAA,OAAO;AAAA,IACL,UAAU,KAAA,EAAuB;AAC/B,MAAA,MAAM,OAAO,GAAA,EAAI;AACjB,MAAA,IAAI,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AAC/B,MAAA,IAAI,aAAa,MAAA,EAAW;AAAE,QAAA,QAAA,GAAW,IAAA,GAAO,QAAA;AAAU,QAAA,MAAA,CAAO,GAAA,CAAI,OAAO,QAAQ,CAAA;AAAA,MAAG;AACvF,MAAA,OAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAA,GAAW,IAAI,CAAA;AAAA,IACpC,CAAA;AAAA,IACA,KAAK,KAAA,EAAwB;AAC3B,MAAA,MAAM,OAAO,GAAA,EAAI;AACjB,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,CAAI,KAAK,CAAA;AACjC,MAAA,IAAI,QAAA,KAAa,MAAA,IAAa,IAAA,GAAO,QAAA,EAAU,OAAO,KAAA;AACtD,MAAA,MAAA,CAAO,GAAA,CAAI,KAAA,EAAO,IAAA,GAAO,QAAQ,CAAA;AACjC,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,GACF;AACF;AAgBA,IAAM,mBAAA,GAAsB,+BAAA;AAC5B,IAAM,UAAA,GAAa,CAAC,KAAA,KAA2B,yBAAA,CAA0B,KAAK,KAAK,CAAA;AACnF,IAAM,WAAA,GAAc,CAAC,MAAA,KAA4B,iCAAA,CAAkC,KAAK,MAAM,CAAA;AAC9F,IAAM,aAAA,GAAgB,CAAC,QAAA,KAA8B,QAAA,CAAS,UAAA,CAAW,GAAG,CAAA,IAAK,QAAA,CAAS,MAAA,IAAU,IAAA,IAAQ,CAAC,CAAC,GAAG,QAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,SAAA,KAAc,SAAA,KAAc,GAAA,IAAO,SAAA,KAAc,OAAO,SAAA,CAAU,UAAA,CAAW,CAAC,CAAA,GAAI,EAAA,IAAM,SAAA,CAAU,UAAA,CAAW,CAAC,MAAM,GAAG,CAAA;AAExP,SAAS,oBAAoB,KAAA,EAAsD;AACjF,EAAA,OAAO,CAAC,CAAC,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA,KAAM,mBAAA,IAAuB,CAAC,aAAA,EAAe,kBAAA,EAAoB,qBAAA,EAAuB,OAAO,CAAA,CAAE,KAAA,CAAM,CAAC,IAAA,KAAS,OAAO,OAAA,CAAQ,GAAA,CAAI,KAAA,EAAO,IAAI,CAAA,KAAM,UAAU,CAAA;AACzO;AAEA,SAAS,0BAAA,GAAsE;AAC7E,EAAA,MAAM,QAAA,GAAoB,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,UAAU,CAAA;AAC5D,EAAA,IAAI,CAAC,QAAA,IAAY,OAAO,QAAA,KAAa,UAAU,OAAO,MAAA;AACtD,EAAA,MAAM,WAAA,GAAuB,OAAA,CAAQ,GAAA,CAAI,UAAA,EAAY,kBAAkB,CAAA;AACvE,EAAA,IAAI,OAAO,WAAA,KAAgB,UAAA,EAAY,OAAO,MAAA;AAC9C,EAAA,IAAI;AAAE,IAAA,MAAM,UAAmB,OAAA,CAAQ,SAAA,CAAU,WAAA,EAAa,CAAC,mBAAmB,CAAC,CAAA;AAAG,IAAA,OAAO,mBAAA,CAAoB,OAAO,CAAA,GAAI,OAAA,GAAU,KAAA,CAAA;AAAA,EAAW,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,MAAA;AAAA,EAAW;AAC/K;AAEO,SAAS,0BAAA,CAA2B,MAAA,EAAgG,OAAA,GAA4D,EAAC,EAAG;AACzM,EAAA,MAAM,WAAW,OAAA,CAAQ,OAAA,KAAY,MAAA,GAAY,0BAAA,KAA+B,OAAA,CAAQ,OAAA;AACxF,EAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,QAAQ,CAAA,GAAI,QAAA,GAAW,MAAA;AAC3D,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAA6D;AACnF,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAAqC;AACnD,IAAA,KAAA,MAAW,YAAY,SAAA,CAAU,GAAA,CAAI,MAAM,KAAK,CAAA,IAAK,EAAC,EAAG;AACvD,MAAA,IAAI;AAAE,QAAA,QAAA,CAAS,EAAE,GAAG,KAAA,EAAO,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAAqC;AAAA,IAC7E;AAAA,EACF,CAAA;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,EAAE,IAAA,EAAK,KAAyB;AAC/C,IAAA,IAAI;AACF,MAAA,IAAI,QAAA,IAAY,CAAC,IAAA,IAAQ,OAAO,SAAS,QAAA,IAAY,MAAA,CAAO,IAAA,CAAK,IAAI,EAAE,IAAA,EAAK,CAAE,IAAA,CAAK,GAAG,MAAM,uBAAA,EAAyB;AACrH,MAAA,MAAM,KAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,OAAO,CAAA;AAChD,MAAA,MAAM,MAAA,GAAkB,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,QAAQ,CAAA;AAClD,MAAA,MAAM,QAAA,GAAoB,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,UAAU,CAAA;AACtD,MAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,UAAA,CAAW,KAAK,CAAA,IAAK,OAAO,MAAA,KAAW,QAAA,IAAY,CAAC,WAAA,CAAY,MAAM,CAAA,IAAK,OAAO,QAAA,KAAa,QAAA,IAAY,CAAC,aAAA,CAAc,QAAQ,CAAA,IAAK,CAAC,cAAA,CAAe,MAAA,EAAQ,QAAA,EAAU,MAAA,CAAO,4BAA4B,CAAA,EAAG;AACjP,MAAA,MAAA,CAAO,EAAE,KAAA,EAAO,MAAA,EAAQ,QAAA,EAAU,CAAA;AAAA,IACpC,CAAA,CAAA,MAAQ;AAAA,IAAmC;AAAA,EAC7C,CAAA;AACA,EAAA,OAAA,EAAS,gBAAA,CAAiB,WAAW,OAAO,CAAA;AAC5C,EAAA,OAAO;AAAA,IACL,OAAA,CAAQ,KAAA,EAAe,MAAA,EAAgB,GAAA,EAAmB;AACxD,MAAA,IAAI,QAAA,IAAY,CAAC,UAAA,CAAW,KAAK,CAAA,EAAG;AACpC,MAAA,MAAM,UAAA,GAAa,OAAO,WAAA,EAAY;AACtC,MAAA,IAAI,CAAC,WAAA,CAAY,UAAU,CAAA,EAAG;AAC9B,MAAA,IAAI,QAAA;AACJ,MAAA,IAAI;AAAE,QAAA,QAAA,GAAW,IAAI,GAAA,CAAI,GAAA,EAAK,uBAAuB,CAAA,CAAE,QAAA;AAAA,MAAU,CAAA,CAAA,MAAQ;AAAE,QAAA;AAAA,MAAQ;AACnF,MAAA,IAAI,CAAC,aAAA,CAAc,QAAQ,CAAA,IAAK,CAAC,eAAe,UAAA,EAAY,QAAA,EAAU,MAAA,CAAO,4BAA4B,CAAA,EAAG;AAC5G,MAAA,MAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,MAAA,EAAO,YAAY,QAAA,EAAS;AACnD,MAAA,MAAA,CAAO,KAAK,CAAA;AACZ,MAAA,IAAI;AAAE,QAAA,OAAA,EAAS,YAAY,EAAE,KAAA,EAAO,MAAA,EAAO,UAAA,EAAY,UAAU,CAAA;AAAA,MAAG,CAAA,CAAA,MAAQ;AAAA,MAA8C;AAAA,IAC5H,CAAA;AAAA,IACA,SAAA,CAAU,OAAe,QAAA,EAAkE;AACzF,MAAA,IAAI,YAAY,CAAC,UAAA,CAAW,KAAK,CAAA,SAAU,MAAM;AAAA,MAAC,CAAA;AAClD,MAAA,IAAI,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC/B,MAAA,IAAI,CAAC,KAAA,EAAO;AAAE,QAAA,KAAA,uBAAY,GAAA,EAAI;AAAG,QAAA,SAAA,CAAU,GAAA,CAAI,OAAO,KAAK,CAAA;AAAA,MAAG;AAC9D,MAAA,KAAA,CAAM,IAAI,QAAQ,CAAA;AAClB,MAAA,MAAM,UAAA,GAAa,KAAA;AACnB,MAAA,OAAO,MAAM;AAAE,QAAA,UAAA,CAAW,OAAO,QAAQ,CAAA;AAAG,QAAA,IAAI,UAAA,CAAW,IAAA,KAAS,CAAA,IAAK,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA,KAAM,UAAA,EAAY,SAAA,CAAU,MAAA,CAAO,KAAK,CAAA;AAAA,MAAG,CAAA;AAAA,IACzI,CAAA;AAAA,IACA,OAAA,GAAgB;AACd,MAAA,IAAI,QAAA,EAAU;AACd,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,SAAA,CAAU,KAAA,EAAM;AAChB,MAAA,OAAA,EAAS,mBAAA,CAAoB,WAAW,OAAO,CAAA;AAC/C,MAAA,OAAA,EAAS,KAAA,EAAM;AAAA,IACjB;AAAA,GACF;AACF;AAWO,SAAS,qBAAA,CAAsB,OAAA,GAAwB,KAAA,EAAO,OAAA,GAA2C,EAAC,EAAiB;AAChI,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAoC;AACxD,EAAA,OAAO,OAAO,OAAO,IAAA,KAAS;AAC5B,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,KAAA,EAAO,IAAI,CAAA;AACvC,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA;AACpC,IAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,MAAM,KAAK,EAAC;AAC1C,IAAA,IAAI,CAAC,QAAQ,GAAA,CAAI,MAAM,GAAG,OAAA,CAAQ,GAAA,CAAI,QAAQ,SAAS,CAAA;AACvD,IAAA,MAAM,GAAA,GAAM,wBAAwB,MAAM,CAAA,CAAA;AAC1C,IAAA,MAAM,cAAc,MAAM;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,QAAQ,gBAAA,CAAiB,OAAA,CAAQ,SAAS,OAAA,CAAQ,GAAG,KAAK,IAAI,CAAA;AACpE,QAAA,MAAM,QAAA,GAAW,EAAE,GAAG,SAAA,EAAU;AAChC,QAAA,IAAI,iBAAiB,QAAA,EAAU,KAAK,GAAG,MAAA,CAAO,MAAA,CAAO,WAAW,QAAQ,CAAA;AAAA,MAC1E,CAAA,CAAA,MAAQ;AAAA,MAA6B;AAAA,IACvC,CAAA;AACA,IAAA,WAAA,EAAY;AACZ,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,OAAA,CAAQ,OAAO,CAAA;AAC3C,IAAA,MAAM,QAAA,GAAW,EAAE,GAAG,SAAA,EAAU;AAChC,IAAA,IAAI,CAAC,gBAAA,CAAiB,QAAA,EAAU,gBAAA,CAAiB,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAC,CAAC,CAAA,EAAG,MAAM,IAAI,WAAW,+BAA+B,CAAA;AACxI,IAAA,MAAM,OAAA,GAAU,qBAAqB,QAAQ,CAAA;AAC7C,IAAA,IAAI,WAAW,OAAA,KAAY,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,oBAAoB,OAAO,CAAA;AAAA,SACnE,OAAA,CAAQ,OAAO,kBAAkB,CAAA;AACtC,IAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,IAAI,QAAQ,OAAA,EAAS,EAAE,OAAA,EAAS,CAAC,CAAA;AAChE,IAAA,WAAA,EAAY;AACZ,IAAA,IAAI,CAAC,gBAAA,CAAiB,SAAA,EAAW,gBAAA,CAAiB,SAAS,OAAA,CAAQ,GAAA,CAAI,kBAAkB,CAAC,CAAC,CAAA,EAAG,MAAM,IAAI,WAAW,+BAA+B,CAAA;AAClJ,IAAA,IAAI;AACF,MAAA,MAAM,KAAA,GAAQ,qBAAqB,SAAS,CAAA;AAC5C,MAAA,IAAI,SAAS,KAAA,KAAU,IAAA,UAAc,OAAA,EAAS,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,IAClE,CAAA,CAAA,MAAQ;AAAA,IAA6B;AACrC,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF","file":"client.js","sourcesContent":["import type { D1CacheProfile } from './d1/profile';\nimport { needsFreshness } from './d1/read-freshness-policy';\n\nexport function createSingleFlight<Key, Value>() {\n const pending = new Map<Key, Promise<Value>>();\n return {\n run(key: Key, load: () => Promise<Value>): Promise<Value> {\n const existing = pending.get(key);\n if (existing) return existing;\n const promise = Promise.resolve().then(load);\n pending.set(key, promise);\n void promise.then(() => { if (pending.get(key) === promise) pending.delete(key); }, () => { if (pending.get(key) === promise) pending.delete(key); });\n return promise;\n },\n forget(key: Key): void { pending.delete(key); },\n };\n}\n\nexport function createIntentWarmup(cooldownMs = 60_000, now: () => number = monotonicNow) {\n const duration = Number.isFinite(cooldownMs) && cooldownMs > 0 ? cooldownMs : 60_000;\n const warmed = new Map<string, number>();\n let scope = '';\n let generation = 0;\n let running = false;\n let queued: { key: string; load: (isCurrent: () => boolean) => Promise<boolean>; generation: number } | undefined;\n const drain = () => {\n if (running || !queued) return;\n const task = queued;\n queued = undefined;\n if ((warmed.get(task.key) ?? 0) > now()) return;\n running = true;\n const isCurrent = () => task.generation === generation && scope !== '';\n void Promise.resolve().then(() => isCurrent() ? task.load(isCurrent) : false).then((ok) => {\n if (ok && task.generation === generation) warmed.set(task.key, now() + duration);\n }, () => {}).finally(() => { running = false; drain(); });\n };\n return {\n setScope(next: string): void {\n if (scope === next) return;\n scope = next;\n generation++;\n queued = undefined;\n warmed.clear();\n },\n invalidate(): void { generation++; queued = undefined; warmed.clear(); },\n warm(key: string, load: (isCurrent: () => boolean) => Promise<boolean>): void {\n if (!scope || !key || (warmed.get(key) ?? 0) > now()) return;\n queued = { key, load, generation };\n drain();\n },\n };\n}\n\ntype ReadLeasePolicy = Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'freshnessHeader' | 'freshnessCookieExcludedPaths' | 'maxSeconds' | 'freshnessCookieMode'> & Partial<Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'credentialHeaders'>>;\n\nexport interface FreshnessTransport { origin?: string; baseUrl?: string; withCredentials?: boolean }\n\nfunction usesGenerationCookie(policy: ReadLeasePolicy, url: string, transport?: FreshnessTransport): boolean {\n if (policy.freshnessCookieMode !== 'generation' || !policy.credentialHeaders?.some((name) => name.toLowerCase() === 'cookie') || transport?.withCredentials !== true || !transport.origin || transport.baseUrl === undefined) return false;\n try {\n const origin = new URL(transport.origin).origin;\n const base = new URL(transport.baseUrl, origin);\n return origin !== 'null' && new URL(url, base).origin === origin;\n } catch { return false; }\n}\n\nexport function createReadFreshness(policy: ReadLeasePolicy, now: () => number = Date.now) {\n const until = new Map<string, number>();\n const prune = (time: number) => { for (const [scope, deadline] of until) if (deadline <= time) until.delete(scope); };\n return {\n headers(scope: string, method: string): Record<string, string> {\n const time = now();\n prune(time);\n if (method.toUpperCase() !== 'GET' || !until.has(scope)) return {};\n return { 'Cache-Control':'no-cache', ...(policy.freshnessHeader ? { [policy.freshnessHeader]:'1' } : {}) };\n },\n observe(scope: string, method: string, url: string, transport?: FreshnessTransport): void {\n const time = now();\n prune(time);\n let pathname: string;\n try { pathname = new URL(url, 'https://cache.invalid').pathname; } catch { pathname = ''; }\n if (needsFreshness(method, pathname, policy.freshnessCookieExcludedPaths) && !usesGenerationCookie(policy, url, transport)) until.set(scope, time + (Number.isInteger(policy.maxSeconds) && policy.maxSeconds !== undefined && policy.maxSeconds >= 1 && policy.maxSeconds <= 300 ? policy.maxSeconds : 5) * 1000);\n },\n };\n}\n\nfunction monotonicNow(): number {\n const clock: unknown = Reflect.get(globalThis, 'performance');\n if (clock && typeof clock === 'object') {\n const read: unknown = Reflect.get(clock, 'now');\n if (typeof read === 'function') {\n const value: unknown = Reflect.apply(read, clock, []);\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n }\n }\n return Date.now();\n}\n\nexport function createRevalidationWindow(windowMs: number, now: () => number = monotonicNow) {\n const duration = Number.isFinite(windowMs) && windowMs > 0 ? windowMs : 300_000;\n const scopes = new Map<string, number>();\n return {\n remaining(scope: string): number {\n const time = now();\n let deadline = scopes.get(scope);\n if (deadline === undefined) { deadline = time + duration; scopes.set(scope, deadline); }\n return Math.max(0, deadline - time);\n },\n take(scope: string): boolean {\n const time = now();\n const deadline = scopes.get(scope);\n if (deadline !== undefined && time < deadline) return false;\n scopes.set(scope, time + duration);\n return true;\n },\n };\n}\n\nexport interface MutationInvalidationEvent {\n scope: string;\n method: string;\n pathname: string;\n}\n\nexport interface MutationInvalidationChannel {\n readonly name: string;\n postMessage(value: MutationInvalidationEvent): void;\n addEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n removeEventListener(type: 'message', listener: (event: { data: unknown }) => void): void;\n close(): void;\n}\n\nconst mutationChannelName = 'dee-wan-cache-invalidation-v1';\nconst validScope = (scope: string): boolean => /^[A-Za-z0-9:_-]{1,256}$/.test(scope);\nconst validMethod = (method: string): boolean => /^[!#$%&'*+.^_`|~0-9A-Z-]{1,32}$/.test(method);\nconst validPathname = (pathname: string): boolean => pathname.startsWith('/') && pathname.length <= 2048 && ![...pathname].some((character) => character === '?' || character === '#' || character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127);\n\nfunction invalidationChannel(value: unknown): value is MutationInvalidationChannel {\n return !!value && typeof value === 'object' && Reflect.get(value, 'name') === mutationChannelName && ['postMessage', 'addEventListener', 'removeEventListener', 'close'].every((name) => typeof Reflect.get(value, name) === 'function');\n}\n\nfunction browserInvalidationChannel(): MutationInvalidationChannel | undefined {\n const document: unknown = Reflect.get(globalThis, 'document');\n if (!document || typeof document !== 'object') return undefined;\n const constructor: unknown = Reflect.get(globalThis, 'BroadcastChannel');\n if (typeof constructor !== 'function') return undefined;\n try { const channel: unknown = Reflect.construct(constructor, [mutationChannelName]); return invalidationChannel(channel) ? channel : undefined; } catch { return undefined; }\n}\n\nexport function createMutationInvalidation(policy: Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'freshnessCookieExcludedPaths'>, options: { channel?: MutationInvalidationChannel | null } = {}) {\n const supplied = options.channel === undefined ? browserInvalidationChannel() : options.channel;\n const channel = invalidationChannel(supplied) ? supplied : undefined;\n const listeners = new Map<string, Set<(event: MutationInvalidationEvent) => void>>();\n let disposed = false;\n const notify = (event: MutationInvalidationEvent) => {\n for (const listener of listeners.get(event.scope) ?? []) {\n try { listener({ ...event }); } catch { /* Subscribers are independent. */ }\n }\n };\n const receive = ({ data }: { data: unknown }) => {\n try {\n if (disposed || !data || typeof data !== 'object' || Object.keys(data).sort().join(',') !== 'method,pathname,scope') return;\n const scope: unknown = Reflect.get(data, 'scope');\n const method: unknown = Reflect.get(data, 'method');\n const pathname: unknown = Reflect.get(data, 'pathname');\n if (typeof scope !== 'string' || !validScope(scope) || typeof method !== 'string' || !validMethod(method) || typeof pathname !== 'string' || !validPathname(pathname) || !needsFreshness(method, pathname, policy.freshnessCookieExcludedPaths)) return;\n notify({ scope, method, pathname });\n } catch { /* Ignore malformed messages. */ }\n };\n channel?.addEventListener('message', receive);\n return {\n publish(scope: string, method: string, url: string): void {\n if (disposed || !validScope(scope)) return;\n const normalized = method.toUpperCase();\n if (!validMethod(normalized)) return;\n let pathname: string;\n try { pathname = new URL(url, 'https://cache.invalid').pathname; } catch { return; }\n if (!validPathname(pathname) || !needsFreshness(normalized, pathname, policy.freshnessCookieExcludedPaths)) return;\n const event = { scope, method:normalized, pathname };\n notify(event);\n try { channel?.postMessage({ scope, method:normalized, pathname }); } catch { /* Local notification remains available. */ }\n },\n subscribe(scope: string, listener: (event: MutationInvalidationEvent) => void): () => void {\n if (disposed || !validScope(scope)) return () => {};\n let group = listeners.get(scope);\n if (!group) { group = new Set(); listeners.set(scope, group); }\n group.add(listener);\n const subscribed = group;\n return () => { subscribed.delete(listener); if (subscribed.size === 0 && listeners.get(scope) === subscribed) listeners.delete(scope); };\n },\n dispose(): void {\n if (disposed) return;\n disposed = true;\n listeners.clear();\n channel?.removeEventListener('message', receive);\n channel?.close();\n },\n };\n}\n\nexport { D1_BOOKMARK_HEADER, parseD1Bookmarks, serializeD1Bookmarks } from './d1/bookmarks';\n\nimport { D1_BOOKMARK_HEADER, mergeD1Bookmarks, parseD1Bookmarks, serializeD1Bookmarks } from './d1/bookmarks';\n\nexport interface D1BookmarkStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nexport function createD1BookmarkFetch(fetcher: typeof fetch = fetch, options: { storage?: D1BookmarkStorage } = {}): typeof fetch {\n const origins = new Map<string, Record<string, string>>();\n return async (input, init) => {\n const request = new Request(input, init);\n const origin = new URL(request.url).origin;\n const bookmarks = origins.get(origin) ?? {};\n if (!origins.has(origin)) origins.set(origin, bookmarks);\n const key = `dee-wan:d1-bookmarks:${origin}`;\n const mergeStored = () => {\n try {\n const saved = parseD1Bookmarks(options.storage?.getItem(key) ?? null);\n const combined = { ...bookmarks };\n if (mergeD1Bookmarks(combined, saved)) Object.assign(bookmarks, combined);\n } catch { /* Storage is optional. */ }\n };\n mergeStored();\n const headers = new Headers(request.headers);\n const outgoing = { ...bookmarks };\n if (!mergeD1Bookmarks(outgoing, parseD1Bookmarks(headers.get(D1_BOOKMARK_HEADER)))) throw new RangeError('D1 bookmark capacity exceeded');\n const encoded = serializeD1Bookmarks(outgoing);\n if (encoded && encoded !== '{}') headers.set(D1_BOOKMARK_HEADER, encoded);\n else headers.delete(D1_BOOKMARK_HEADER);\n const response = await fetcher(new Request(request, { headers }));\n mergeStored();\n if (!mergeD1Bookmarks(bookmarks, parseD1Bookmarks(response.headers.get(D1_BOOKMARK_HEADER)))) throw new RangeError('D1 bookmark capacity exceeded');\n try {\n const value = serializeD1Bookmarks(bookmarks);\n if (value && value !== '{}') options.storage?.setItem(key, value);\n } catch { /* Storage is optional. */ }\n return response;\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { DurableObject } from 'cloudflare:workers';
2
- import { I as InspectFencesRequest, a as InspectFencesResponse, R as ReadRequest, b as ReadResponse, W as WriteRequest, c as WriteResult, d as ReleaseRequest, B as BeginWriteRequest, E as EndWriteRequest, C as CacheStore } from '../types-D-Gd11to.js';
2
+ import { I as InspectFencesRequest, a as InspectFencesResponse, R as ReadRequest, b as ReadResponse, W as WriteRequest, c as WriteResult, d as ReleaseRequest, B as BeginWriteRequest, E as EndWriteRequest, C as CacheStore } from '../types-CtErcz2a.js';
3
3
  export { a as ReadResponseWarmupContext, R as ReadResponseWarmupOptions, b as ReadResponseWarmupTarget, c as createResponseWarmup } from '../response-warmup-BWQvnT1G.js';
4
4
 
5
5
  declare class CacheCoordinator<Env = unknown> extends DurableObject<Env> {
@@ -1,8 +1,8 @@
1
- import { boundedD1Store, withinCoordinatorDeadline } from '../chunk-OOPPXK7Q.js';
2
- export { createDurableObjectStore } from '../chunk-OOPPXK7Q.js';
3
- import { GLOBAL_FENCE, MAX_TTL_MS, MAX_VALUE_BYTES, MAX_COORDINATOR_GENERATION_LENGTH, MAX_LEASE_MS, MAX_LOCK_MS } from '../chunk-OQRNVGQE.js';
4
- export { createResponseWarmup } from '../chunk-A4WV6RY4.js';
1
+ export { createDurableObjectStore } from '../chunk-NFBMWKY5.js';
2
+ export { createResponseWarmup } from '../chunk-GGSQ6C6X.js';
3
+ import { boundedD1Store, withinCoordinatorDeadline } from '../chunk-WKZ7TKGM.js';
5
4
  import { createRegionalCache } from '../chunk-E6OZZ5UX.js';
5
+ import { GLOBAL_FENCE, MAX_TTL_MS, MAX_VALUE_BYTES, MAX_COORDINATOR_GENERATION_LENGTH, MAX_LEASE_MS, MAX_LOCK_MS } from '../chunk-OQRNVGQE.js';
6
6
  import '../chunk-ZCMZJKGN.js';
7
7
  import { DurableObject } from 'cloudflare:workers';
8
8
 
@@ -1,4 +1,4 @@
1
- import { C as CacheStore, G as GeneratedCacheConfig, D as DecimalConstructor } from '../types-D-Gd11to.js';
1
+ import { C as CacheStore, G as GeneratedCacheConfig, D as DecimalConstructor, e as CacheSessionHooks } from '../types-CtErcz2a.js';
2
2
  import { a as D1WritePolicy, D as D1CacheProfile } from '../profile--LBtbQI_.js';
3
3
  export { i as isD1BindingName } from '../profile--LBtbQI_.js';
4
4
  import { D1Database as D1Database$1 } from '@cloudflare/workers-types';
@@ -61,4 +61,20 @@ declare function cacheRegionalResponse(request: Request, options: RegionalRespon
61
61
  type FreshnessPolicy = Pick<NonNullable<D1CacheProfile['readResponseLease']>, 'freshnessCookie' | 'freshnessHeader' | 'ignoreRequestCacheControl'>;
62
62
  declare function regionalD1MetadataTtl(request: Request, policy: FreshnessPolicy): 0 | 5000;
63
63
 
64
- export { D1CacheProfile, type D1JsonReadOptions, type D1PrismaCacheOptions, type D1ReadOptions, D1WritePolicy, type RegionalResponseOptions, cacheD1Env, cacheD1JsonRead, cacheD1Read, cacheRegionalResponse, createD1CacheRuntime, d1CacheEpoch, d1PrismaCacheExtension, fenceD1Writes, regionalD1MetadataTtl, sameD1CacheDatabase, withD1PrismaCache, wrapD1Handler };
64
+ interface D1ReadSessionOptions extends Pick<D1CacheProfile, 'bindingNames' | 'bindingPrefixes'> {
65
+ databaseIdsEnv: string;
66
+ primaryBindings?: readonly string[];
67
+ freshnessHeader?: string;
68
+ ignoreRequestCacheControl?: boolean;
69
+ }
70
+ declare function runPrimaryD1SessionSource<T>(operation: () => Promise<T>): Promise<T>;
71
+ declare function runD1PrismaScope<T>(operation: () => Promise<T>): Promise<T>;
72
+ declare function runD1SessionOperation<T>(database: object, operation: () => Promise<T>): Promise<T>;
73
+ declare function prismaD1SessionDatabase(database: D1Database$1): D1Database$1;
74
+ declare function runIsolatedD1Session<T>(request: Request, operation: () => Promise<T>): Promise<T>;
75
+ declare function d1SessionWarmupRequest(request: Request, response: Response): Request;
76
+ declare function d1SessionCacheHooks(database: object): CacheSessionHooks;
77
+ declare function sessionD1Env<Env extends object>(env: Env, options: D1ReadSessionOptions): Env;
78
+ declare function wrapD1ReadSessionHandler<Env extends object, Context>(handler: (request: Request, env: Env, context: Context) => Promise<Response>, options: D1ReadSessionOptions): (request: Request, env: Env, context: Context) => Promise<Response>;
79
+
80
+ export { D1CacheProfile, type D1JsonReadOptions, type D1PrismaCacheOptions, type D1ReadOptions, type D1ReadSessionOptions, D1WritePolicy, type RegionalResponseOptions, cacheD1Env, cacheD1JsonRead, cacheD1Read, cacheRegionalResponse, createD1CacheRuntime, d1CacheEpoch, d1PrismaCacheExtension, d1SessionCacheHooks, d1SessionWarmupRequest, fenceD1Writes, prismaD1SessionDatabase, regionalD1MetadataTtl, runD1PrismaScope, runD1SessionOperation, runIsolatedD1Session, runPrimaryD1SessionSource, sameD1CacheDatabase, sessionD1Env, withD1PrismaCache, wrapD1Handler, wrapD1ReadSessionHandler };
package/dist/d1/index.js CHANGED
@@ -1,13 +1,16 @@
1
- import { cacheD1Read } from '../chunk-MOJBHU3S.js';
2
- export { cacheD1Env, cacheD1Read, createD1CacheRuntime, d1CacheEpoch, d1PrismaCacheExtension, fenceD1Writes, sameD1CacheDatabase, withD1PrismaCache, wrapD1Handler } from '../chunk-MOJBHU3S.js';
3
- import '../chunk-ZREX7LLC.js';
4
- import '../chunk-OOPPXK7Q.js';
5
- import '../chunk-OQRNVGQE.js';
6
- export { isD1BindingName } from '../chunk-AENVFT2S.js';
7
- export { regionalD1MetadataTtl } from '../chunk-D2EESWMC.js';
1
+ import { cacheD1Read } from '../chunk-6VWIKYUQ.js';
2
+ export { cacheD1Env, cacheD1Read, createD1CacheRuntime, d1CacheEpoch, d1PrismaCacheExtension, sameD1CacheDatabase, withD1PrismaCache, wrapD1Handler } from '../chunk-6VWIKYUQ.js';
3
+ import '../chunk-NFBMWKY5.js';
4
+ import { d1SessionBookmarkFloor, advanceD1SessionBookmarks, trackD1SessionSource, runPrimaryD1SessionSource, responseD1SessionBookmarks, varyD1Bookmarks } from '../chunk-2V6MG4YX.js';
5
+ export { d1SessionCacheHooks, d1SessionWarmupRequest, fenceD1Writes, prismaD1SessionDatabase, regionalD1MetadataTtl, runD1PrismaScope, runD1SessionOperation, runIsolatedD1Session, runPrimaryD1SessionSource, sessionD1Env, wrapD1ReadSessionHandler } from '../chunk-2V6MG4YX.js';
8
6
  import '../chunk-LHOK33GI.js';
7
+ import '../chunk-M4UOCIDQ.js';
8
+ import { D1_BOOKMARK_HEADER, decodeD1Bookmarks, serializeD1Bookmarks } from '../chunk-ZBYAKDNZ.js';
9
+ import '../chunk-WKZ7TKGM.js';
9
10
  import { regionalKey, regionalRead, regionalWrite } from '../chunk-E6OZZ5UX.js';
11
+ import '../chunk-OQRNVGQE.js';
10
12
  import '../chunk-ZCMZJKGN.js';
13
+ export { isD1BindingName } from '../chunk-AENVFT2S.js';
11
14
 
12
15
  // src/d1/json-read.ts
13
16
  var MAX_BODY_BYTES = 1e6;
@@ -118,7 +121,7 @@ function identity(request) {
118
121
  const headers = [];
119
122
  for (const [name, value] of request.headers) {
120
123
  if (sensitive.test(name) || conditional.test(name) || /(?:^|[-_])(?:capability|preview)(?:[-_]|$)/i.test(name)) return null;
121
- if (!ephemeral.test(name)) headers.push([name, value]);
124
+ if (!ephemeral.test(name) && name.toLowerCase() !== D1_BOOKMARK_HEADER.toLowerCase()) headers.push([name, value]);
122
125
  }
123
126
  headers.sort(([a], [b]) => a.localeCompare(b));
124
127
  return [url.toString(), headers];
@@ -160,15 +163,34 @@ async function cacheRegionalResponse(request, options, load) {
160
163
  return load();
161
164
  }
162
165
  if (requestIdentity2 === null || typeof options.namespace !== "string" || !options.namespace.trim()) return load();
163
- const key = await regionalKey(options.ttlMs, ["http-response", options.namespace, options.ttlMs, requestIdentity2]);
166
+ const floor = d1SessionBookmarkFloor();
167
+ const key = await regionalKey(options.ttlMs, ["http-response", floor ? "session-v1" : null, options.namespace, options.ttlMs, requestIdentity2]);
164
168
  if (!key) return load();
165
169
  const cached = await regionalRead(key, options.ttlMs);
166
170
  if (cached) {
167
171
  const response2 = reconstruct(cached.value);
168
- if (response2) return response2;
172
+ if (response2) {
173
+ if (!floor) return response2;
174
+ const raw = response2.headers.get(D1_BOOKMARK_HEADER);
175
+ const source = decodeD1Bookmarks(raw);
176
+ if (raw && source && Object.entries(floor).every(([id, bookmark]) => source[id] && source[id] >= bookmark)) {
177
+ advanceD1SessionBookmarks(source);
178
+ return response2;
179
+ }
180
+ void response2.body?.cancel().catch(() => void 0);
181
+ }
169
182
  }
170
183
  const started = Date.now();
171
- const response = await load();
184
+ const tracked = await trackD1SessionSource(() => runPrimaryD1SessionSource(load));
185
+ let response = tracked.value;
186
+ const bookmarks = responseD1SessionBookmarks(response.headers, tracked.bookmarks);
187
+ if (bookmarks) {
188
+ const headers = new Headers(response.headers);
189
+ const encoded = serializeD1Bookmarks(bookmarks);
190
+ if (encoded) headers.set(D1_BOOKMARK_HEADER, encoded);
191
+ varyD1Bookmarks(headers);
192
+ response = new Response(response.body, { status: response.status, statusText: response.statusText, headers });
193
+ }
172
194
  if (!eligible(response.headers)) return response;
173
195
  let entry;
174
196
  try {