@dee-wan/cache 1.1.0 → 2.0.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.
Files changed (36) hide show
  1. package/README.md +31 -1
  2. package/dist/{chunk-MOJBHU3S.js → chunk-LAXBP5DQ.js} +72 -173
  3. package/dist/chunk-LAXBP5DQ.js.map +1 -0
  4. package/dist/{chunk-ZREX7LLC.js → chunk-M4UOCIDQ.js} +18 -6
  5. package/dist/chunk-M4UOCIDQ.js.map +1 -0
  6. package/dist/chunk-NFBMWKY5.js +54 -0
  7. package/dist/chunk-NFBMWKY5.js.map +1 -0
  8. package/dist/{chunk-HGAUU4EU.js → chunk-O3KHMFHX.js} +51 -14
  9. package/dist/chunk-O3KHMFHX.js.map +1 -0
  10. package/dist/chunk-WJNCFFF3.js +637 -0
  11. package/dist/chunk-WJNCFFF3.js.map +1 -0
  12. package/dist/{chunk-OOPPXK7Q.js → chunk-WKZ7TKGM.js} +3 -54
  13. package/dist/chunk-WKZ7TKGM.js.map +1 -0
  14. package/dist/chunk-ZBYAKDNZ.js +45 -0
  15. package/dist/chunk-ZBYAKDNZ.js.map +1 -0
  16. package/dist/client.d.ts +14 -1
  17. package/dist/client.js +37 -1
  18. package/dist/client.js.map +1 -1
  19. package/dist/cloudflare/index.d.ts +1 -1
  20. package/dist/cloudflare/index.js +3 -3
  21. package/dist/d1/index.d.ts +18 -2
  22. package/dist/d1/index.js +33 -11
  23. package/dist/d1/index.js.map +1 -1
  24. package/dist/d1/response-lease.js +10 -8
  25. package/dist/d1/response-lease.js.map +1 -1
  26. package/dist/index.d.ts +2 -2
  27. package/dist/index.js +1 -1
  28. package/dist/response-lease.js +7 -2
  29. package/dist/{types-D-Gd11to.d.ts → types-CtErcz2a.d.ts} +13 -1
  30. package/package.json +1 -1
  31. package/dist/chunk-D2EESWMC.js +0 -19
  32. package/dist/chunk-D2EESWMC.js.map +0 -1
  33. package/dist/chunk-HGAUU4EU.js.map +0 -1
  34. package/dist/chunk-MOJBHU3S.js.map +0 -1
  35. package/dist/chunk-OOPPXK7Q.js.map +0 -1
  36. package/dist/chunk-ZREX7LLC.js.map +0 -1
package/README.md CHANGED
@@ -194,7 +194,7 @@ Models that reference the target through a foreign key are invalidated too. Unkn
194
194
 
195
195
  ## Runtime requirements
196
196
 
197
- - Cloudflare Workers with a SQLite-backed Durable Object and D1. No `nodejs_compat` needed.
197
+ - Cloudflare Workers with a SQLite-backed Durable Object and D1. The core and Cloudflare entries do not require `nodejs_compat`; Workers importing `@dee-wan/cache/d1` require it.
198
198
  - Prisma 6.19.3 or newer 6.x with `@prisma/adapter-d1` (tested with 6.19.3).
199
199
  - Generator: Node 20 or newer (CI runs it on 20, 22 and 24). Wrangler 4 and Miniflare need Node 22.
200
200
 
@@ -348,3 +348,33 @@ Defaults are 48 targets per batch, 4 concurrent requests across all warmup batch
348
348
  `createIntentWarmup(cooldownMs?, now?)` warms reads on navigation intent, without storing response values. Call `setScope(siteAndActor)` before use and `warm(key, async isCurrent => ...)` on mouse hover or keyboard focus. One task runs; only the latest waiting intent remains. Check `isCurrent()` between sequential reads. Successful tasks cool for 60 seconds by default. Scope changes and `invalidate()` clear waiting tasks and cooldowns; old completions cannot warm a new scope. Use silent, bounded, read-only requests with the same URL, credentials and headers as normal reads. Do not adopt results into active editor stores or start a startup fanout.
349
349
 
350
350
  `cacheReadValue` from `@dee-wan/cache/scoped-read` provides a Cache API value cache without D1 or a Durable Object. Pass a nonempty `namespace`, a bounded structured `key`, and a `validate` type guard with the source loader. Include every authorization and result-varying scope in the key; do not put credentials in cached values. `ttlMs` defaults to 5000 and cannot exceed 5000. `maxBytes` defaults to 1,500,000 and can be lowered. Optional `cache` and `now` allow a Cache API implementation and clock to be supplied. Cache failures, invalid values, and expired entries fall back to the loader; loader errors propagate. Expiry starts before the loader runs.
351
+
352
+ ### D1 bookmark client transport
353
+
354
+ `createD1BookmarkFetch(fetch)` wraps a fetch implementation and remembers valid
355
+ `X-Dee-Wan-D1-Bookmarks` response headers. Later requests include the greatest
356
+ bookmark seen for each physical database. Create one wrapper per independent
357
+ client context. Bookmark maps are bounded to 64 database UUIDs and 8192
358
+ characters; invalid maps are ignored. Pass `{ storage }` as the second argument to persist per-origin maps in a `getItem`/`setItem` store such as sessionStorage. Storage errors fall back to memory.
359
+
360
+ ### D1 sessions
361
+
362
+ Cloudflare Workers importing `@dee-wan/cache/d1` require the `nodejs_compat`
363
+ compatibility flag, including when D1 sessions are not enabled.
364
+
365
+ Wrap HTTP handlers with `wrapD1ReadSessionHandler(handler, options)` outside
366
+ `wrapD1Handler`. Set `bindingNames`, `bindingPrefixes`, `databaseIdsEnv`, and
367
+ optionally `primaryBindings`, `freshnessHeader`, and `ignoreRequestCacheControl`. The named environment variable contains a JSON
368
+ map from each configured binding name to its physical D1 UUID. Bindings that
369
+ share a UUID share a request session. If the variable is absent, bindings keep
370
+ their original behavior. Invalid maps fail configuration; invalid bookmark
371
+ headers return HTTP 400.
372
+
373
+ For a reusable Prisma D1 adapter, pass `prismaD1SessionDatabase(database)` to
374
+ `PrismaD1` and run every Prisma operation through
375
+ `runD1SessionOperation(database, operation)`, including scheduled operations.
376
+ Admission waits at most 30 seconds for an earlier operation on the same physical database. Apply `sessionD1Env(env, options)` before cache wrapping scheduled bindings so
377
+ those operations use the same facades. Ordinary D1 calls use the regular
378
+ binding. Allow and expose
379
+ `X-Dee-Wan-D1-Bookmarks` in CORS configuration where browser clients need it.
380
+ D1 cache source fills start on the primary; cache hits reuse source bookmarks. Generic Prisma caches must set `sessionCache: d1SessionCacheHooks(database)`. Queries started after streaming response headers are sent cannot advance those headers. WebSocket upgrades bypass sessions.
@@ -1,148 +1,12 @@
1
- import { createCacheExtension, readTargets, CacheUnavailableError } from './chunk-ZREX7LLC.js';
2
- import { boundedD1Store, createDurableObjectStore } from './chunk-OOPPXK7Q.js';
3
- import { MAX_VALUE_BYTES } from './chunk-OQRNVGQE.js';
4
- import { isD1BindingName } from './chunk-AENVFT2S.js';
1
+ import { createDurableObjectStore } from './chunk-NFBMWKY5.js';
2
+ import { fenceD1Writes, registerD1SessionAlias, d1SessionBookmarkFloor, unwrapD1SessionCacheValue, advanceD1SessionBookmarks, trackD1SessionSource, runPrimaryD1SessionSource, wrapD1SessionCacheValue } from './chunk-WJNCFFF3.js';
5
3
  import { limitRegionalDataUntil } from './chunk-LHOK33GI.js';
4
+ import { createCacheExtension, readTargets } from './chunk-M4UOCIDQ.js';
5
+ import { boundedD1Store } from './chunk-WKZ7TKGM.js';
6
6
  import { boundedValue, regionalKey, regionalRead, regionalWrite } from './chunk-E6OZZ5UX.js';
7
+ import { MAX_VALUE_BYTES } from './chunk-OQRNVGQE.js';
7
8
  import { sha256Hex, stableStringify, decode, encode } from './chunk-ZCMZJKGN.js';
8
-
9
- // src/d1/adapter.ts
10
- var fence = ["g"];
11
- var lexemes = /\s+|--[^\n]*|\/\*[\s\S]*?(?:\*\/|$)|'(?:[^']|'')*'?|`(?:[^`]|``)*`?|"(?:[^"]|"")*"?|\[[^\]]*\]?|[A-Za-z_][A-Za-z0-9_$]*|[\s\S]/g;
12
- var safePragmas = /* @__PURE__ */ new Set(["database_list", "table_list", "table_info", "table_xinfo", "index_list", "index_info", "index_xinfo", "foreign_key_list"]);
13
- function operationOf(tokens, start = 0) {
14
- const word = (index2) => tokens[index2]?.toLowerCase();
15
- if (word(start) !== "with") return word(start);
16
- let index = start + 1;
17
- if (word(index) === "recursive") index++;
18
- const group = () => {
19
- if (tokens[index] !== "(") return false;
20
- let depth = 0;
21
- do {
22
- if (tokens[index] === "(") depth++;
23
- if (tokens[index] === ")") depth--;
24
- index++;
25
- } while (index < tokens.length && depth > 0);
26
- return depth === 0;
27
- };
28
- while (index < tokens.length) {
29
- if (!/^(?:[A-Za-z_][A-Za-z0-9_$]*|`[^`]+`|"[^"]+"|\[[^\]]+\])$/.test(tokens[index] ?? "")) return void 0;
30
- index++;
31
- if (tokens[index] === "(" && !group()) return void 0;
32
- if (word(index++) !== "as") return void 0;
33
- if (word(index) === "not") index++;
34
- if (word(index) === "materialized") index++;
35
- if (tokens[index] !== "(" || !["select", "with"].includes(word(index + 1) ?? "")) return void 0;
36
- if (!group()) return void 0;
37
- if (tokens[index] !== ",") return word(index);
38
- index++;
39
- }
40
- return void 0;
41
- }
42
- function isReadonly(sql) {
43
- const tokens = [...sql.matchAll(lexemes)].map(([token = ""]) => token).filter((token) => !/^(?:\s|--|\/\*)/.test(token));
44
- if (tokens.at(-1) === ";") tokens.pop();
45
- const first = tokens[0]?.toLowerCase();
46
- const pragmaName = first === "pragma" ? (tokens[2] === "." ? tokens[3] : tokens[1])?.toLowerCase() : void 0;
47
- const readonlyPragma = first === "pragma" && pragmaName !== void 0 && safePragmas.has(pragmaName) && !tokens.includes("=");
48
- return !tokens.includes(";") && (operationOf(tokens) === "select" || readonlyPragma);
49
- }
50
- function needsWriteFence(sql, unrelatedWrites) {
51
- const tokens = [...sql.matchAll(lexemes)].map(([token = ""]) => token).filter((token) => !/^(?:\s|--|\/\*)/.test(token));
52
- if (tokens.at(-1) === ";") tokens.pop();
53
- if (tokens.includes(";")) return true;
54
- let index = 0;
55
- const word = () => tokens[index]?.toLowerCase();
56
- const operation = word();
57
- if (operation !== "insert" && operation !== "update" && operation !== "delete") return true;
58
- index++;
59
- if ((operation === "insert" || operation === "update") && word() === "or") {
60
- index++;
61
- if (!["rollback", "abort", "replace", "fail", "ignore"].includes(word() ?? "")) return true;
62
- index++;
63
- }
64
- if (operation === "insert") {
65
- if (word() !== "into") return true;
66
- index++;
67
- }
68
- if (operation === "delete") {
69
- if (word() !== "from") return true;
70
- index++;
71
- }
72
- const identifier = (token) => {
73
- if (!token) return null;
74
- if (/^[A-Za-z_][A-Za-z0-9_$]*$/.test(token)) return token.toLowerCase();
75
- if (/^"[A-Za-z_][A-Za-z0-9_$]*"$/.test(token) || /^`[A-Za-z_][A-Za-z0-9_$]*`$/.test(token) || /^\[[A-Za-z_][A-Za-z0-9_$]*\]$/.test(token)) return token.slice(1, -1).toLowerCase();
76
- return null;
77
- };
78
- let target = identifier(tokens[index++]);
79
- if (tokens[index] === ".") {
80
- if (target !== "main") return true;
81
- index++;
82
- target = identifier(tokens[index++]);
83
- }
84
- if (!target || !unrelatedWrites.has(target)) return true;
85
- if (operation === "update" && word() !== "set") return true;
86
- if (operation === "delete" && !["where", "returning"].includes(word() ?? "") && index !== tokens.length) return true;
87
- return false;
88
- }
89
- function fenceD1Writes(db, options) {
90
- const { generation, policy } = options;
91
- const store = boundedD1Store(options.store);
92
- const unrelatedWrites = new Set(policy.unfencedWriteTables.map((name) => name.toLowerCase()));
93
- if (!generation) throw new TypeError("cache generation is required");
94
- const statements = /* @__PURE__ */ new WeakMap();
95
- const withWrite = async (operation) => {
96
- const token = crypto.randomUUID();
97
- try {
98
- await store.beginWrite({ fences: fence, generation, leaseMs: 6e5, token });
99
- } catch (error) {
100
- await store.endWrite({ fences: fence, token }).catch(() => void 0);
101
- throw new CacheUnavailableError(error);
102
- }
103
- try {
104
- return await operation();
105
- } finally {
106
- await store.endWrite({ fences: fence, token }).catch(() => void 0);
107
- }
108
- };
109
- const wrapStatement = (raw, sql) => {
110
- const requiresFence = !isReadonly(sql) && needsWriteFence(sql, unrelatedWrites);
111
- const execute = (operation) => requiresFence ? withWrite(operation) : operation();
112
- function rawRows(rawOptions) {
113
- return execute(() => rawOptions?.columnNames === true ? raw.raw({ columnNames: true }) : raw.raw(rawOptions?.columnNames === false ? { columnNames: false } : void 0));
114
- }
115
- const wrapped2 = {
116
- bind: (...next) => wrapStatement(raw.bind(...next), sql),
117
- first: (column) => execute(() => column === void 0 ? raw.first() : raw.first(column)),
118
- all: () => execute(() => raw.all()),
119
- run: () => execute(() => raw.run()),
120
- raw: rawRows
121
- };
122
- statements.set(wrapped2, { raw, fence: requiresFence });
123
- return wrapped2;
124
- };
125
- const batch = (target, items) => {
126
- const resolved = items.map((item) => statements.get(item));
127
- const raw = items.map((item, index) => resolved[index]?.raw ?? item);
128
- const operation = () => target.batch(raw);
129
- return resolved.every((item) => item !== void 0 && !item.fence) ? operation() : withWrite(operation);
130
- };
131
- return {
132
- prepare: (sql) => wrapStatement(db.prepare(sql), sql),
133
- batch: (items) => batch(db, items),
134
- exec: (sql) => isReadonly(sql) || !needsWriteFence(sql, unrelatedWrites) ? db.exec(sql) : withWrite(() => db.exec(sql)),
135
- dump: () => db.dump(),
136
- withSession: (constraint) => {
137
- const session = db.withSession(constraint);
138
- return {
139
- prepare: (sql) => wrapStatement(session.prepare(sql), sql),
140
- batch: (items) => batch(session, items),
141
- getBookmark: () => session.getBookmark()
142
- };
143
- }
144
- };
145
- }
9
+ import { isD1BindingName } from './chunk-AENVFT2S.js';
146
10
 
147
11
  // src/d1/env.ts
148
12
  var uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
@@ -154,6 +18,7 @@ function createD1CacheRuntime(database, options) {
154
18
  const { generation, databaseId, profile, readsEnabled = true } = options;
155
19
  const store = boundedD1Store(options.store);
156
20
  const fenced = fenceD1Writes(database, { store, generation, policy: profile });
21
+ registerD1SessionAlias(fenced, database);
157
22
  runtimes.set(fenced, { store, generation, databaseId, readsEnabled, readModels: profile.readModels, coordinatorIdentity: options.coordinatorIdentity ?? options.store, coordinatorName: options.coordinatorName ?? "", regionalIdentity: options.regionalIdentity });
158
23
  return fenced;
159
24
  }
@@ -225,8 +90,10 @@ function d1PrismaCacheExtension(database, config, optionsOrDecimal, decimalArg)
225
90
  const scopedConfig = { ...config, cacheableByModel: Object.fromEntries(Object.entries(config.cacheableByModel).map(([model, enabled]) => [model, enabled && allowed.has(model)])) };
226
91
  const common = { config: scopedConfig, store: runtime.store, generation: runtime.generation, coordinationGeneration: runtime.generation, ...decimal ? { decimal } : {}, ...options?.keyArgs ? { keyArgs: options.keyArgs } : {} };
227
92
  const base = createCacheExtension({ ...common, scope: runtime.databaseId });
228
- if (!options) return base;
229
93
  const operation = base.query.$allModels.$allOperations;
94
+ if (!options) return { ...base, query: { $allModels: { $allOperations(params) {
95
+ return d1SessionBookmarkFloor() ? params.query(params.args) : operation(params);
96
+ } } } };
230
97
  return {
231
98
  ...base,
232
99
  query: { $allModels: { async $allOperations(params) {
@@ -249,50 +116,72 @@ function d1PrismaCacheExtension(database, config, optionsOrDecimal, decimalArg)
249
116
  normalizedArgs = options.keyArgs ? options.keyArgs(params.args) : params.args;
250
117
  normalized = true;
251
118
  const configDigest = await sha256Hex(stableStringify(config));
252
- regional = await regionalKey(options.regionalTtlMs, ["prisma", options.regionalTtlMs, identities, configDigest, options.scope, params.model, params.operation, dataPath, normalizedArgs ?? null]);
119
+ regional = await regionalKey(options.regionalTtlMs, ["prisma", d1SessionBookmarkFloor() ? "session-v1" : null, options.regionalTtlMs, identities, configDigest, options.scope, params.model, params.operation, dataPath, normalizedArgs ?? null]);
253
120
  }
254
121
  } catch {
255
122
  }
256
123
  const hit = await regionalRead(regional, options.regionalTtlMs, decimal);
257
124
  if (hit) {
258
- limitRegionalDataUntil(hit.expires);
259
- return hit.value;
125
+ const cached = unwrapD1SessionCacheValue(hit.value, [runtime, ...dependencies].map((item) => item.databaseId));
126
+ if (cached) {
127
+ if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks);
128
+ limitRegionalDataUntil(hit.expires);
129
+ return cached.value;
130
+ }
260
131
  }
261
132
  let started = Date.now();
262
133
  const snapshot = await inspect(dependencies);
263
134
  if (!snapshot) return params.query(params.args);
264
135
  let scope;
265
136
  try {
266
- scope = stableStringify([runtime.databaseId, runtime.generation, options.scope, snapshot.map(({ runtime: dependency, epoch }) => [dependency.databaseId, dependency.generation, epoch])]);
137
+ scope = stableStringify([d1SessionBookmarkFloor() ? "session-v1" : null, runtime.databaseId, runtime.generation, options.scope, snapshot.map(({ runtime: dependency, epoch }) => [dependency.databaseId, dependency.generation, epoch])]);
267
138
  if (new TextEncoder().encode(scope).byteLength > 32768) return params.query(params.args);
268
139
  } catch {
269
140
  return params.query(params.args);
270
141
  }
271
142
  let verifiedHit = false;
143
+ let hitBookmarks;
272
144
  let verifiedWrite = false;
273
145
  let queried = false;
274
146
  const store = {
275
147
  ...runtime.store,
276
148
  async write(request) {
277
- const result = await runtime.store.write(request);
149
+ const value = d1SessionBookmarkFloor() ? JSON.stringify(wrapD1SessionCacheValue(request.value)) : request.value;
150
+ const result = await runtime.store.write({ ...request, value });
278
151
  verifiedWrite = result.ok;
279
152
  return result;
280
153
  },
281
154
  async read(request) {
282
155
  const result = await runtime.store.read(request);
283
156
  if (result.kind === "hit" && !sameSnapshots(snapshot, await inspect(dependencies))) return { kind: "miss", epochs: result.epochs, lockHeldForMs: null, lockToken: null, pending: true };
157
+ if (result.kind === "hit" && d1SessionBookmarkFloor()) {
158
+ let cached;
159
+ try {
160
+ cached = unwrapD1SessionCacheValue(JSON.parse(result.value), [runtime, ...dependencies].map((item) => item.databaseId));
161
+ } catch {
162
+ cached = null;
163
+ }
164
+ if (!cached || typeof cached.value !== "string") return { kind: "miss", epochs: result.epochs, lockHeldForMs: null, lockToken: null, pending: true };
165
+ hitBookmarks = cached.bookmarks;
166
+ verifiedHit = true;
167
+ return { ...result, value: cached.value };
168
+ }
284
169
  if (result.kind === "hit") verifiedHit = true;
285
170
  return result;
286
171
  }
287
172
  };
288
173
  const scoped = createCacheExtension({ ...common, store, scope, ...normalized ? { keyArgs: () => normalizedArgs } : {} });
289
- const value = await scoped.query.$allModels.$allOperations({ ...params, query: async (args) => {
290
- queried = true;
291
- started = Date.now();
292
- return params.query(args);
293
- } });
294
- if (regional && (!queried && verifiedHit || verifiedWrite) && sameSnapshots(snapshot, await inspect(dependencies))) await regionalWrite(regional, options.regionalTtlMs, started, value);
295
- return value;
174
+ const tracked = await trackD1SessionSource(async () => {
175
+ const value = await scoped.query.$allModels.$allOperations({ ...params, query: async (args) => {
176
+ queried = true;
177
+ started = Date.now();
178
+ return runPrimaryD1SessionSource(() => params.query(args));
179
+ } });
180
+ if (!queried && verifiedHit && hitBookmarks) advanceD1SessionBookmarks(hitBookmarks);
181
+ return value;
182
+ });
183
+ if (regional && (!queried && verifiedHit || verifiedWrite) && sameSnapshots(snapshot, await inspect(dependencies))) await regionalWrite(regional, options.regionalTtlMs, started, wrapD1SessionCacheValue(tracked.value, tracked.bookmarks));
184
+ return tracked.value;
296
185
  } } }
297
186
  };
298
187
  }
@@ -366,21 +255,26 @@ async function cacheD1Read(database, options, load) {
366
255
  const primary = d1CacheRuntime(database);
367
256
  const ttl = options.ttlMs ?? DEFAULT_TTL_MS;
368
257
  if (!primary || !primary.readsEnabled || !Number.isFinite(ttl) || ttl <= 0 || ttl > MAX_TTL_MS || options.scope === void 0 || options.scope === null || !boundedValue(options.scope, MAX_IDENTITY_BYTES, true) || !boundedValue(options.key, MAX_IDENTITY_BYTES, true)) return load();
258
+ const source = () => runPrimaryD1SessionSource(load);
369
259
  const runtimes2 = dependencyRuntimes(database, options.dependencies ?? []);
370
- if (!runtimes2) return load();
260
+ if (!runtimes2) return source();
371
261
  const regionalIdentities = [primary, ...runtimes2].map((runtime) => [runtime.databaseId, runtime.generation, runtime.coordinatorName, runtime.regionalIdentity]);
372
- const regional = regionalIdentities.every((identity) => identity[3]) ? await regionalKey(options.regionalTtlMs, ["d1-read", options.regionalTtlMs, regionalIdentities, options.scope, options.key]) : null;
262
+ const regional = regionalIdentities.every((identity) => identity[3]) ? await regionalKey(options.regionalTtlMs, ["d1-read", d1SessionBookmarkFloor() ? "session-v1" : null, options.regionalTtlMs, regionalIdentities, options.scope, options.key]) : null;
373
263
  const hit = await regionalRead(regional, options.regionalTtlMs);
374
264
  if (hit) {
375
- limitRegionalDataUntil(hit.expires);
376
- return hit.value;
265
+ const cached = unwrapD1SessionCacheValue(hit.value, [primary, ...runtimes2].map((runtime) => runtime.databaseId));
266
+ if (cached) {
267
+ if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks);
268
+ limitRegionalDataUntil(hit.expires);
269
+ return cached.value;
270
+ }
377
271
  }
378
272
  const started = Date.now();
379
273
  const snapshot = await inspect(runtimes2);
380
- if (!snapshot) return load();
274
+ if (!snapshot) return source();
381
275
  let key;
382
276
  try {
383
- const identity = stableStringify(["d1-read-v1", primary.databaseId, primary.generation, options.scope, options.key, snapshot.map(({ runtime, epoch }) => [runtime.databaseId, runtime.generation, epoch])]);
277
+ const identity = stableStringify(["d1-read-v1", d1SessionBookmarkFloor() ? "session-v1" : null, primary.databaseId, primary.generation, options.scope, options.key, snapshot.map(({ runtime, epoch }) => [runtime.databaseId, runtime.generation, epoch])]);
384
278
  if (new TextEncoder().encode(identity).byteLength > MAX_IDENTITY_BYTES) return load();
385
279
  key = `d1:${await sha256Hex(identity)}`;
386
280
  } catch {
@@ -390,29 +284,34 @@ async function cacheD1Read(database, options, load) {
390
284
  try {
391
285
  result = await primary.store.read({ key, fences: FENCES, generation: primary.generation, lockMs: 3e4, refresh: false });
392
286
  } catch {
393
- return load();
287
+ return source();
394
288
  }
395
289
  if (result.kind === "hit") {
396
290
  try {
397
- const value = decode(JSON.parse(result.value));
398
- if (boundedValue(value, MAX_VALUE_SIZE, false) && sameSnapshots(snapshot, await inspect(runtimes2))) {
399
- await regionalWrite(regional, options.regionalTtlMs, started, value);
291
+ const raw = decode(JSON.parse(result.value));
292
+ const cached = unwrapD1SessionCacheValue(raw, [primary, ...runtimes2].map((runtime) => runtime.databaseId));
293
+ const value = cached?.value;
294
+ if (cached && boundedValue(value, MAX_VALUE_SIZE, false) && sameSnapshots(snapshot, await inspect(runtimes2))) {
295
+ if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks);
296
+ await regionalWrite(regional, options.regionalTtlMs, started, raw);
400
297
  return value;
401
298
  }
402
299
  } catch {
403
300
  }
404
- return load();
301
+ return source();
405
302
  }
406
- if (!result.lockToken || result.pending) return load();
303
+ if (!result.lockToken || result.pending) return source();
407
304
  const lockToken = result.lockToken;
408
305
  try {
409
- const value = await load();
306
+ const tracked = await trackD1SessionSource(source);
307
+ const value = tracked.value;
410
308
  try {
411
309
  if (value !== null && value !== void 0 && boundedValue(value, MAX_VALUE_SIZE, false) && (options.cacheable?.(value) ?? true)) {
412
- const text = JSON.stringify(encode(value));
310
+ const cachedValue = wrapD1SessionCacheValue(value, tracked.bookmarks);
311
+ const text = JSON.stringify(encode(cachedValue));
413
312
  if (new TextEncoder().encode(text).byteLength <= MAX_VALUE_SIZE && sameSnapshots(snapshot, await inspect(runtimes2))) {
414
313
  const written = await primary.store.write({ key, lockToken, snapshot: result.epochs, ttlMs: ttl, softTtlMs: ttl, value: text });
415
- if (regional && written.ok && sameSnapshots(snapshot, await inspect(runtimes2))) await regionalWrite(regional, options.regionalTtlMs, started, value);
314
+ if (regional && written.ok && sameSnapshots(snapshot, await inspect(runtimes2))) await regionalWrite(regional, options.regionalTtlMs, started, cachedValue);
416
315
  }
417
316
  }
418
317
  } catch {
@@ -426,6 +325,6 @@ async function cacheD1Read(database, options, load) {
426
325
  }
427
326
  }
428
327
 
429
- export { cacheD1Env, cacheD1Read, createD1CacheRuntime, d1CacheEpoch, d1CacheRuntime, d1PrismaCacheExtension, fenceD1Writes, sameD1CacheDatabase, withD1PrismaCache, wrapD1Handler };
430
- //# sourceMappingURL=chunk-MOJBHU3S.js.map
431
- //# sourceMappingURL=chunk-MOJBHU3S.js.map
328
+ export { cacheD1Env, cacheD1Read, createD1CacheRuntime, d1CacheEpoch, d1CacheRuntime, d1PrismaCacheExtension, sameD1CacheDatabase, withD1PrismaCache, wrapD1Handler };
329
+ //# sourceMappingURL=chunk-LAXBP5DQ.js.map
330
+ //# sourceMappingURL=chunk-LAXBP5DQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/d1/env.ts","../src/d1/read.ts"],"names":["runtimes"],"mappings":";;;;;;;;;;;AAeA,IAAM,IAAA,GAAO,iEAAA;AACb,IAAM,KAAA,mBAAQ,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,MAAA,EAAQ,MAAA,EAAQ,IAAA,EAAM,KAAA,EAAO,IAAI,CAAC,CAAA;AACxF,IAAM,OAAA,uBAAc,OAAA,EAA8D;AAElF,IAAM,QAAA,uBAAe,OAAA,EAAgC;AAC9C,IAAM,cAAA,GAAiB,CAAC,QAAA,KAAiD,QAAA,CAAS,IAAI,QAAQ;AAC9F,SAAS,oBAAA,CAAqB,UAAsB,OAAA,EAAwN;AACjR,EAAA,MAAM,EAAE,UAAA,EAAY,UAAA,EAAY,OAAA,EAAS,YAAA,GAAe,MAAK,GAAI,OAAA;AACjE,EAAA,MAAM,KAAA,GAAQ,cAAA,CAAe,OAAA,CAAQ,KAAK,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,cAAc,QAAA,EAAU,EAAE,OAAO,UAAA,EAAY,MAAA,EAAQ,SAAS,CAAA;AAC7E,EAAA,sBAAA,CAAuB,QAAQ,QAAQ,CAAA;AACvC,EAAA,QAAA,CAAS,GAAA,CAAI,QAAQ,EAAE,KAAA,EAAO,YAAY,UAAA,EAAY,YAAA,EAAc,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,mBAAA,EAAqB,QAAQ,mBAAA,IAAuB,OAAA,CAAQ,OAAO,eAAA,EAAiB,OAAA,CAAQ,mBAAmB,EAAA,EAAI,gBAAA,EAAkB,OAAA,CAAQ,gBAAA,EAAkB,CAAA;AACnQ,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,UAAA,CAA6B,KAAQ,OAAA,EAA4B;AAC/E,EAAA,MAAM,KAAA,GAAQ,CAAC,MAAA,KAA4B,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAA;AAC5F,EAAA,MAAM,OAAA,GAAU,MAAM,SAAS,CAAA;AAC/B,EAAA,IAAI,OAAA,KAAY,MAAA,IAAa,OAAA,KAAY,OAAA,EAAS,OAAO,GAAA;AACzD,EAAA,IAAI,OAAA,KAAY,QAAQ,MAAM,IAAI,MAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,QAAA,CAAU,CAAA;AAC9E,EAAA,MAAM,KAAA,GAAQ,MAAM,eAAe,CAAA;AACnC,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,MAAA,IAAU,KAAA,KAAU,OAAA,EAAS,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,cAAA,CAAgB,CAAA;AAC9H,EAAA,MAAM,eAAe,KAAA,KAAU,OAAA;AAC/B,EAAA,MAAM,SAAA,GAAY,MAAM,aAAa,CAAA;AACrC,EAAA,MAAM,MAAA,GAAS,MAAM,cAAc,CAAA;AACnC,EAAA,MAAM,UAAA,GAAa,MAAM,YAAY,CAAA;AACrC,EAAA,IAAI,CAAC,SAAA,IAAa,OAAO,SAAA,KAAc,QAAA,IAAY,OAAO,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,YAAY,CAAA,KAAM,UAAA,IAAc,OAAO,OAAA,CAAQ,GAAA,CAAI,SAAA,EAAW,KAAK,CAAA,KAAM,UAAA,IAAc,OAAO,MAAA,KAAW,QAAA,IAAY,OAAO,UAAA,KAAe,QAAA,IAAY,CAAC,UAAA,CAAW,IAAA,EAAK;AACvP,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,OAAA,CAAQ,SAAS,CAAA,yDAAA,CAA2D,CAAA;AACjG,EAAA,IAAI,UAAA,CAAW,SAAS,GAAA,EAAK,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,WAAA,CAAa,CAAA;AACtF,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AAAE,IAAA,GAAA,GAAM,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,EAAG,CAAA,CAAA,MAAQ;AAAE,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,aAAA,CAAe,CAAA;AAAA,EAAG;AACxG,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,YAAY,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,QAAS,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,aAAA,CAAe,CAAA;AACtH,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA;AAC9B,EAAA,IAAI,GAAA,CAAI,IAAA,CAAK,CAAC,CAAC,GAAA,EAAK,EAAE,CAAA,KAAM,CAAC,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,IAAK,OAAO,EAAA,KAAO,QAAA,IAAY,CAAC,IAAA,CAAK,IAAA,CAAK,EAAE,CAAC,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,iCAAiC,CAAA;AAC1J,EAAA,MAAM,YAAA,GAAe,KAAA,CAAM,eAAe,CAAA,IAAK,MAAA;AAC/C,EAAA,IAAI,OAAO,YAAA,KAAiB,QAAA,IAAY,CAAC,MAAM,GAAA,CAAI,YAAY,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,OAAA,CAAQ,SAAS,CAAA,cAAA,CAAgB,CAAA;AAC9H,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,GAAG,CAAA;AAC9B,EAAA,MAAM,MAAA,GAAS,EAAE,GAAG,GAAA,EAAI;AACxB,EAAA,KAAA,MAAW,IAAA,IAAQ,OAAA,CAAQ,YAAA,EAAc,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,GAAA,EAAK,IAAI,GAAG,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,IAAI,CAAA,CAAE,CAAA;AACzH,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACjD,IAAA,IAAI,OAAA,CAAQ,gBAAgB,IAAA,CAAK,CAAC,WAAW,GAAA,CAAI,UAAA,CAAW,MAAM,CAAC,CAAA,IAAK,CAAC,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG,MAAM,IAAI,KAAA,CAAM,CAAA,uBAAA,EAA0B,GAAG,CAAA,CAAE,CAAA;AACvJ,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG;AACpC,IAAA,MAAM,EAAA,GAAK,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAC7B,IAAA,IAAI,OAAO,EAAA,KAAO,QAAA,IAAY,CAAC,YAAY,OAAO,QAAA,CAAS,OAAA,KAAY,UAAA,EAAY,MAAM,IAAI,KAAA,CAAM,CAAA,sCAAA,EAAyC,GAAG,CAAA,CAAE,CAAA;AACjJ,IAAA,MAAM,UAAA,GAAa,GAAG,WAAA,EAAY;AAClC,IAAA,MAAM,QAAA,GAAW,KAAK,SAAA,CAAU,CAAC,YAAY,UAAA,EAAY,YAAA,EAAc,YAAA,EAAc,OAAO,CAAC,CAAA;AAC7F,IAAA,IAAI,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA;AACrC,IAAA,IAAI,CAAC,SAAA,EAAW;AAAE,MAAA,SAAA,uBAAgB,OAAA,EAAQ;AAAG,MAAA,OAAA,CAAQ,GAAA,CAAI,WAAW,SAAS,CAAA;AAAA,IAAG;AAChF,IAAA,IAAI,QAAA,GAAW,SAAA,CAAU,GAAA,CAAI,QAAQ,CAAA;AACrC,IAAA,IAAI,CAAC,QAAA,EAAU;AAAE,MAAA,QAAA,uBAAe,GAAA,EAAI;AAAG,MAAA,SAAA,CAAU,GAAA,CAAI,UAAU,QAAQ,CAAA;AAAA,IAAG;AAC1E,IAAA,IAAI,MAAA,GAAS,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA;AAClC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,eAAA,GAAkB,CAAA,EAAG,OAAA,CAAQ,qBAAqB,GAAG,UAAU,CAAA,CAAA;AACrE,MAAA,MAAM,QAAQ,wBAAA,CAAyB,SAAA,EAAuD,EAAE,IAAA,EAAM,eAAA,EAAiB,cAAuD,CAAA;AAC9K,MAAA,MAAA,GAAS,qBAAqB,QAAA,EAAU,EAAE,OAAO,UAAA,EAAY,UAAA,EAAY,cAAc,OAAA,EAAS,mBAAA,EAAqB,SAAA,EAAW,eAAA,EAAiB,kBAAmB,SAAA,CAAuD,UAAA,CAAW,eAAe,CAAA,CAAE,QAAA,IAAY,CAAA;AACnQ,MAAA,QAAA,CAAS,GAAA,CAAI,UAAU,MAAM,CAAA;AAAA,IAC/B;AACA,IAAA,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,GAAA,EAAK,MAAM,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,aAAA,CAA0D,SAA+D,OAAA,EAA+E;AACtN,EAAA,OAAO,CAAC,KAAA,EAAO,GAAA,EAAK,OAAA,KAAY,OAAA,CAAQ,OAAO,UAAA,CAAW,GAAA,EAAK,OAAO,CAAA,EAAG,OAAO,CAAA;AAClF;AAUO,SAAS,sBAAA,CAAuB,QAAA,EAAkB,MAAA,EAA8B,gBAAA,EAA8D,UAAA,EAAsF;AACzO,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,GAAA,CAAI,QAAQ,CAAA;AACrC,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,CAAQ,cAAc,OAAO,MAAA;AAC9C,EAAA,MAAM,OAAA,GAAU,OAAO,gBAAA,KAAqB,UAAA,GAAa,MAAA,GAAY,gBAAA;AACrE,EAAA,MAAM,OAAA,GAAU,OAAO,gBAAA,KAAqB,UAAA,GAAa,gBAAA,GAAmB,UAAA;AAC5E,EAAA,MAAM,OAAA,GAAU,IAAI,GAAA,CAAI,OAAA,CAAQ,UAAU,CAAA;AAC1C,EAAA,MAAM,YAAA,GAAe,EAAE,GAAG,MAAA,EAAQ,gBAAA,EAAkB,MAAA,CAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,MAAA,CAAO,gBAAgB,CAAA,CAAE,GAAA,CAAI,CAAC,CAAC,KAAA,EAAO,OAAO,CAAA,KAAM,CAAC,KAAA,EAAO,OAAA,IAAW,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAC,CAAC,CAAC,CAAA,EAAE;AAClL,EAAA,MAAM,MAAA,GAAS,EAAE,MAAA,EAAQ,YAAA,EAAc,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,sBAAA,EAAwB,OAAA,CAAQ,UAAA,EAAY,GAAI,OAAA,GAAU,EAAE,OAAA,EAAQ,GAAI,EAAC,EAAI,GAAI,OAAA,EAAS,OAAA,GAAU,EAAE,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAQ,GAAI,EAAC,EAAG;AACpO,EAAA,MAAM,IAAA,GAAO,qBAAqB,EAAE,GAAG,QAAQ,KAAA,EAAO,OAAA,CAAQ,YAAY,CAAA;AAC1E,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,cAAA;AACxC,EAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,EAAE,UAAA,EAAY,EAAE,cAAA,CAAe,MAAA,EAAyC;AAC7G,IAAA,OAAO,sBAAA,KAA2B,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,CAAA,GAAI,UAAU,MAAM,CAAA;AAAA,EAChF,CAAA,IAAI,EAAE;AACN,EAAA,OAAO;AAAA,IACL,GAAG,IAAA;AAAA,IACH,OAAO,EAAE,UAAA,EAAY,EAAE,MAAM,eAAe,MAAA,EAAyC;AACnF,MAAA,IAAI,CAAC,MAAA,CAAO,KAAA,IAAS,CAAC,OAAA,CAAQ,GAAA,CAAI,MAAA,CAAO,KAAK,CAAA,IAAK,CAAC,CAAC,YAAA,EAAc,mBAAA,EAAqB,aAAa,kBAAA,EAAoB,UAAA,EAAY,OAAA,EAAS,WAAA,EAAa,SAAS,CAAA,CAAE,QAAA,CAAS,MAAA,CAAO,SAAS,CAAA,EAAG,OAAO,SAAA,CAAU,MAAM,CAAA;AACzN,MAAA,IAAI,OAAA,CAAQ,UAAU,IAAA,IAAQ,OAAA,CAAQ,UAAU,MAAA,IAAa,CAAC,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO,KAAA,EAAQ,IAAI,CAAA,IAAA,CAAM,OAAA,CAAQ,cAAc,MAAA,IAAU,CAAA,IAAK,IAAI,OAAO,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AACpL,MAAA,MAAM,eAAe,kBAAA,CAAmB,QAAA,EAAU,OAAA,CAAQ,YAAA,IAAgB,EAAE,CAAA;AAC5E,MAAA,IAAI,CAAC,YAAA,EAAc,OAAO,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,CAAA;AAClD,MAAA,MAAM,WAAW,MAAA,CAAO,gBAAA;AACxB,MAAA,MAAM,WAAW,QAAA,IAAY,OAAO,aAAa,QAAA,IAAY,KAAA,CAAM,QAAQ,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAU,UAAU,CAAC,CAAA,GAAI,OAAA,CAAQ,IAAI,QAAA,EAAU,UAAU,IAAI,EAAC;AACrJ,MAAA,MAAM,WAAA,GAAuB,YAAY,OAAO,QAAA,KAAa,WAAW,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAU,aAAa,CAAA,GAAI,MAAA;AAC/G,MAAA,MAAM,OAAA,GAAU,CAAC,CAAC,WAAA,IAAe,OAAO,WAAA,KAAgB,QAAA,IAAY,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAa,MAAM,CAAA,KAAM,OAAA;AACzG,MAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,MAAA,IAAI,cAAA;AACJ,MAAA,IAAI,UAAA,GAAa,KAAA;AACjB,MAAA,IAAI;AACF,QAAA,MAAM,aAAa,CAAC,OAAA,EAAS,GAAG,YAAY,CAAA,CAAE,IAAI,CAAC,IAAA,KAAS,CAAC,IAAA,CAAK,YAAY,IAAA,CAAK,UAAA,EAAY,KAAK,eAAA,EAAiB,IAAA,CAAK,gBAAgB,CAAC,CAAA;AAC3I,QAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,cAAA,GAAiB,WAAA,CAAY,MAAA,CAAO,eAAe,MAAA,CAAO,KAAA,EAAO,MAAA,CAAO,IAAI,CAAA,GAAI,KAAA,CAAA;AACxG,QAAA,MAAM,iBAAiB,CAAC,OAAA,CAAQ,kBAAmB,CAAC,CAAC,WAAW,CAAC,GAAG,QAAQ,MAAM,CAAA,CAAE,MAAM,CAAC,KAAA,KAAU,QAAQ,cAAA,EAAgB,QAAA,CAAS,KAAK,CAAC,CAAA;AAC5I,QAAA,IAAI,QAAQ,aAAA,IAAiB,OAAA,CAAQ,gBAAgB,CAAA,IAAK,OAAA,CAAQ,iBAAiB,GAAA,IAAQ,CAAC,OAAA,IAAW,cAAA,IAAkB,WAAW,KAAA,CAAM,CAAC,SAAS,IAAA,CAAK,CAAC,CAAC,CAAA,EAAG;AAC5J,UAAA,cAAA,GAAiB,QAAQ,OAAA,GAAU,OAAA,CAAQ,QAAQ,MAAA,CAAO,IAAI,IAAI,MAAA,CAAO,IAAA;AACzE,UAAA,UAAA,GAAa,IAAA;AACb,UAAA,MAAM,YAAA,GAAe,MAAM,SAAA,CAAU,eAAA,CAAgB,MAAM,CAAC,CAAA;AAC5D,UAAA,QAAA,GAAW,MAAM,YAAY,OAAA,CAAQ,aAAA,EAAe,CAAC,QAAA,EAAU,sBAAA,EAAuB,GAAI,YAAA,GAAe,IAAA,EAAM,OAAA,CAAQ,eAAe,UAAA,EAAY,YAAA,EAAc,OAAA,CAAQ,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,OAAO,SAAA,EAAW,QAAA,EAAU,cAAA,IAAkB,IAAI,CAAC,CAAA;AAAA,QAClP;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAAsD;AAC9D,MAAA,MAAM,MAAM,MAAM,YAAA,CAAa,QAAA,EAAU,OAAA,CAAQ,eAAe,OAAO,CAAA;AACvE,MAAA,IAAI,GAAA,EAAK;AACP,QAAA,MAAM,MAAA,GAAS,yBAAA,CAA0B,GAAA,CAAI,KAAA,EAAO,CAAC,OAAA,EAAS,GAAG,YAAY,CAAA,CAAE,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,UAAU,CAAC,CAAA;AAC7G,QAAA,IAAI,MAAA,EAAQ;AAAE,UAAA,IAAI,MAAA,CAAO,SAAA,EAAW,yBAAA,CAA0B,MAAA,CAAO,SAAS,CAAA;AAAG,UAAA,sBAAA,CAAuB,IAAI,OAAO,CAAA;AAAG,UAAA,OAAO,MAAA,CAAO,KAAA;AAAA,QAAO;AAAA,MAC7I;AACA,MAAA,IAAI,OAAA,GAAU,KAAK,GAAA,EAAI;AACvB,MAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,YAAY,CAAA;AAC3C,MAAA,IAAI,CAAC,QAAA,EAAU,OAAO,MAAA,CAAO,KAAA,CAAM,OAAO,IAAI,CAAA;AAC9C,MAAA,IAAI,KAAA;AACJ,MAAA,IAAI;AACF,QAAA,KAAA,GAAQ,eAAA,CAAgB,CAAC,sBAAA,EAAuB,GAAI,YAAA,GAAe,IAAA,EAAM,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,KAAA,EAAO,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,OAAA,EAAS,UAAA,EAAY,KAAA,EAAM,KAAM,CAAC,UAAA,CAAW,UAAA,EAAY,UAAA,CAAW,UAAA,EAAY,KAAK,CAAC,CAAC,CAAC,CAAA;AACxO,QAAA,IAAI,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,KAAK,CAAA,CAAE,UAAA,GAAa,KAAA,EAAQ,OAAO,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AAAA,MAC1F,CAAA,CAAA,MAAQ;AAAE,QAAA,OAAO,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,IAAI,CAAA;AAAA,MAAG;AAC5C,MAAA,IAAI,WAAA,GAAc,KAAA;AAClB,MAAA,IAAI,YAAA;AACJ,MAAA,IAAI,aAAA,GAAgB,KAAA;AACpB,MAAA,IAAI,OAAA,GAAU,KAAA;AACd,MAAA,MAAM,KAAA,GAAoB;AAAA,QAAE,GAAG,OAAA,CAAQ,KAAA;AAAA,QACrC,MAAM,MAAM,OAAA,EAAS;AACnB,UAAA,MAAM,KAAA,GAAQ,sBAAA,EAAuB,GAAI,IAAA,CAAK,SAAA,CAAU,wBAAwB,OAAA,CAAQ,KAAK,CAAC,CAAA,GAAI,OAAA,CAAQ,KAAA;AAC1G,UAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,MAAM,EAAE,GAAG,OAAA,EAAS,KAAA,EAAO,CAAA;AAC9D,UAAA,aAAA,GAAgB,MAAA,CAAO,EAAA;AACvB,UAAA,OAAO,MAAA;AAAA,QACT,CAAA;AAAA,QACA,MAAM,KAAK,OAAA,EAAS;AACpB,UAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,KAAK,OAAO,CAAA;AAC/C,UAAA,IAAI,MAAA,CAAO,SAAS,KAAA,IAAS,CAAC,cAAc,QAAA,EAAU,MAAM,OAAA,CAAQ,YAAY,CAAC,CAAA,SAAU,EAAE,IAAA,EAAM,MAAA,EAAQ,MAAA,EAAQ,MAAA,CAAO,MAAA,EAAQ,eAAe,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,IAAA,EAAK;AACtL,UAAA,IAAI,MAAA,CAAO,IAAA,KAAS,KAAA,IAAS,sBAAA,EAAuB,EAAG;AACrD,YAAA,IAAI,MAAA;AACJ,YAAA,IAAI;AAAE,cAAA,MAAA,GAAS,0BAA0B,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAK,GAAG,CAAC,OAAA,EAAS,GAAG,YAAY,EAAE,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,UAAU,CAAC,CAAA;AAAA,YAAG,CAAA,CAAA,MAAQ;AAAE,cAAA,MAAA,GAAS,IAAA;AAAA,YAAM;AACxJ,YAAA,IAAI,CAAC,MAAA,IAAU,OAAO,OAAO,KAAA,KAAU,QAAA,SAAiB,EAAE,IAAA,EAAK,MAAA,EAAQ,MAAA,EAAO,OAAO,MAAA,EAAQ,aAAA,EAAc,MAAM,SAAA,EAAU,IAAA,EAAM,SAAQ,IAAA,EAAK;AAC9I,YAAA,YAAA,GAAe,MAAA,CAAO,SAAA;AACtB,YAAA,WAAA,GAAc,IAAA;AACd,YAAA,OAAO,EAAE,GAAG,MAAA,EAAQ,KAAA,EAAM,OAAO,KAAA,EAAM;AAAA,UACzC;AACA,UAAA,IAAI,MAAA,CAAO,IAAA,KAAS,KAAA,EAAO,WAAA,GAAc,IAAA;AACzC,UAAA,OAAO,MAAA;AAAA,QACT;AAAA,OAAE;AACF,MAAA,MAAM,SAAS,oBAAA,CAAqB,EAAE,GAAG,MAAA,EAAQ,OAAO,KAAA,EAAO,GAAI,UAAA,GAAa,EAAE,SAAS,MAAM,cAAA,EAAe,GAAI,IAAK,CAAA;AACzH,MAAA,MAAM,OAAA,GAAU,MAAM,oBAAA,CAAqB,YAAY;AACrD,QAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,KAAA,CAAM,UAAA,CAAW,cAAA,CAAe,EAAE,GAAG,MAAA,EAAQ,KAAA,EAAO,OAAO,IAAA,KAAS;AAC7F,UAAA,OAAA,GAAU,IAAA;AACV,UAAA,OAAA,GAAU,KAAK,GAAA,EAAI;AACnB,UAAA,OAAO,yBAAA,CAA0B,MAAM,MAAA,CAAO,KAAA,CAAM,IAAI,CAAC,CAAA;AAAA,QAC3D,GAAG,CAAA;AACH,QAAA,IAAI,CAAC,OAAA,IAAW,WAAA,IAAe,YAAA,4BAAwC,YAAY,CAAA;AACnF,QAAA,OAAO,KAAA;AAAA,MACT,CAAC,CAAA;AACD,MAAA,IAAI,QAAA,KAAc,CAAC,OAAA,IAAW,WAAA,IAAgB,kBAAkB,aAAA,CAAc,QAAA,EAAU,MAAM,OAAA,CAAQ,YAAY,CAAC,GAAG,MAAM,aAAA,CAAc,QAAA,EAAU,OAAA,CAAQ,aAAA,EAAe,OAAA,EAAS,wBAAwB,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,SAAS,CAAC,CAAA;AAC7O,MAAA,OAAO,OAAA,CAAQ,KAAA;AAAA,IACjB,GAAE;AAAE,GACN;AACF;AAEO,SAAS,iBAAA,CAAyC,MAAA,EAAgB,QAAA,EAAkB,MAAA,EAA8B,kBAA8D,UAAA,EAAyC;AAC9N,EAAA,MAAM,SAAA,GAAY,sBAAA,CAAuB,QAAA,EAAU,MAAA,EAAQ,kBAAkB,UAAU,CAAA;AACvF,EAAA,IAAI,CAAC,WAAW,OAAO,MAAA;AACvB,EAAA,MAAM,MAAA,GAAkB,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,YAAY,MAAM,CAAA;AAC9D,EAAA,IAAI,OAAO,MAAA,KAAW,UAAA,EAAY,MAAM,IAAI,UAAU,qCAAqC,CAAA;AAC3F,EAAA,MAAM,WAAoB,OAAA,CAAQ,KAAA,CAAM,QAAQ,MAAA,EAAQ,CAAC,SAAS,CAAC,CAAA;AACnE,EAAA,IAAI,CAAC,YAAY,OAAO,QAAA,KAAa,UAAU,MAAM,IAAI,UAAU,qCAAqC,CAAA;AACxG,EAAA,OAAO,IAAI,MAAM,MAAA,EAAQ;AAAA,IACvB,GAAA,CAAI,QAAQ,QAAA,EAAU;AACpB,MAAA,MAAM,MAAA,GAAS,QAAA,KAAa,KAAA,GAAQ,MAAA,GAAS,QAAA;AAC7C,MAAA,MAAM,MAAA,GAAkB,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,UAAU,MAAM,CAAA;AAC5D,MAAA,OAAO,OAAO,MAAA,KAAW,UAAA,GAAa,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,GAAI,MAAA;AAAA,IAC9D;AAAA,GACD,CAAA;AACH;;;AC1LA,IAAM,MAAA,GAAS,CAAC,GAAG,CAAA;AACnB,IAAM,cAAA,GAAiB,GAAA;AACvB,IAAM,UAAA,GAAa,GAAA;AACnB,IAAM,kBAAA,GAAqB,KAAA;AAC3B,IAAM,cAAA,GAAiB,IAAA,CAAK,GAAA,CAAI,IAAA,EAAW,eAAe,CAAA;AAcnD,SAAS,mBAAA,CAAoB,MAAc,KAAA,EAAwB;AACxE,EAAA,MAAM,CAAA,GAAI,eAAe,IAAI,CAAA;AAC7B,EAAA,MAAM,CAAA,GAAI,eAAe,KAAK,CAAA;AAC9B,EAAA,OAAO,CAAC,CAAC,CAAA,IAAK,CAAC,CAAC,CAAA,IAAK,CAAA,CAAE,eAAe,CAAA,CAAE,UAAA,IAAc,EAAE,UAAA,KAAe,CAAA,CAAE,cAAc,CAAA,CAAE,mBAAA,KAAwB,EAAE,mBAAA,IAAuB,CAAA,CAAE,oBAAoB,CAAA,CAAE,eAAA;AACpK;AACA,eAAsB,aAAa,QAAA,EAA0C;AAC3E,EAAA,MAAM,OAAA,GAAU,eAAe,QAAQ,CAAA;AACvC,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,CAAQ,cAAc,OAAO,IAAA;AAC9C,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQ,CAAC,OAAO,CAAC,CAAA;AACxC,EAAA,IAAI,CAAC,QAAA,GAAW,CAAC,CAAA,EAAG,OAAO,IAAA;AAC3B,EAAA,OAAO,eAAA,CAAgB,CAAC,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,YAAY,QAAA,CAAS,CAAC,CAAA,CAAE,KAAK,CAAC,CAAA;AACpF;AACA,eAAsB,QAAQA,SAAAA,EAAiE;AAC7F,EAAA,IAAIA,SAAAA,CAAS,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AACnC,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,OAAA,CAAQ,IAAIA,SAAAA,CAAS,GAAA,CAAI,OAAO,OAAA,KAAY;AAC/D,MAAA,IAAI,CAAC,OAAA,CAAQ,KAAA,CAAM,aAAA,EAAe,OAAO,IAAA;AACzC,MAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,KAAA,CAAM,aAAA,CAAc,EAAE,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,CAAA;AAClG,MAAA,MAAM,KAAA,GAAQ,MAAM,MAAA,CAAO,CAAA;AAC3B,MAAA,IAAI,KAAA,CAAM,OAAA,KAAY,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,aAAA,CAAc,KAAK,CAAA,IAAK,KAAA,GAAQ,GAAG,OAAO,IAAA;AAC9G,MAAA,OAAO,EAAE,SAAS,KAAA,EAAM;AAAA,IAC1B,CAAC,CAAC,CAAA;AACF,IAAA,OAAO,MAAA,CAAO,IAAA,CAAK,CAAC,KAAA,KAAU,KAAA,KAAU,IAAI,CAAA,GAAI,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,CAAC,KAAA,KAA6B,UAAU,IAAI,CAAA;AAAA,EACnH,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,IAAA;AAAA,EAAM;AACzB;AAEO,IAAM,gBAAgB,CAAC,CAAA,EAAwB,CAAA,KACpD,CAAA,KAAM,QAAQ,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,IAAU,EAAE,KAAA,CAAM,CAAC,IAAA,EAAM,KAAA,KAAU,KAAK,OAAA,CAAQ,UAAA,KAAe,CAAA,CAAE,KAAK,GAAG,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,OAAA,CAAQ,eAAe,CAAA,CAAE,KAAK,CAAA,EAAG,OAAA,CAAQ,cAAc,IAAA,CAAK,KAAA,KAAU,CAAA,CAAE,KAAK,GAAG,KAAK,CAAA;AAEjN,SAAS,kBAAA,CAAmB,UAAkB,YAAA,EAA0D;AAC7G,EAAA,IAAI,YAAA,CAAa,MAAA,GAAS,EAAA,EAAI,OAAO,IAAA;AACrC,EAAA,MAAM,OAAA,GAAU,eAAe,QAAQ,CAAA;AACvC,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,CAAQ,cAAc,OAAO,IAAA;AAC9C,EAAA,MAAM,IAAA,uBAAW,GAAA,EAA4B;AAC7C,EAAA,KAAA,MAAW,cAAc,YAAA,EAAc;AACrC,IAAA,MAAM,OAAA,GAAU,eAAe,UAAU,CAAA;AACzC,IAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,CAAQ,cAAc,OAAO,IAAA;AAC9C,IAAA,MAAM,KAAA,GAAQ,QAAQ,UAAA,KAAe,OAAA,CAAQ,aAAa,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,UAAU,CAAA;AAC/F,IAAA,IAAI,KAAA,KAAU,KAAA,CAAM,UAAA,KAAe,OAAA,CAAQ,UAAA,IAAc,KAAA,CAAM,mBAAA,KAAwB,OAAA,CAAQ,mBAAA,IAAuB,KAAA,CAAM,eAAA,KAAoB,OAAA,CAAQ,kBAAkB,OAAO,IAAA;AACjL,IAAA,IAAI,OAAA,CAAQ,UAAA,KAAe,OAAA,CAAQ,UAAA,EAAY;AAC/C,IAAA,IAAI,CAAC,OAAA,CAAQ,KAAA,CAAM,aAAA,EAAe,OAAO,IAAA;AACzC,IAAA,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,UAAA,EAAY,KAAA,IAAS,OAAO,CAAA;AAAA,EAC/C;AACA,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,MAAA,EAAQ,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,UAAA,CAAW,aAAA,CAAc,CAAA,CAAE,UAAU,CAAC,CAAA;AACnF;AAEA,eAAsB,WAAA,CAAe,QAAA,EAAsB,OAAA,EAA2B,IAAA,EAAoC;AACxH,EAAA,MAAM,OAAA,GAAU,eAAe,QAAQ,CAAA;AACvC,EAAA,MAAM,GAAA,GAAM,QAAQ,KAAA,IAAS,cAAA;AAC7B,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,OAAA,CAAQ,gBAAgB,CAAC,MAAA,CAAO,QAAA,CAAS,GAAG,KAAK,GAAA,IAAO,CAAA,IAAK,GAAA,GAAM,UAAA,IAAc,QAAQ,KAAA,KAAU,MAAA,IAAa,OAAA,CAAQ,KAAA,KAAU,QAAQ,CAAC,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO,oBAAoB,IAAI,CAAA,IAAK,CAAC,YAAA,CAAa,QAAQ,GAAA,EAAK,kBAAA,EAAoB,IAAI,CAAA,SAAU,IAAA,EAAK;AACvR,EAAA,MAAM,MAAA,GAAS,MAAM,yBAAA,CAA0B,IAAI,CAAA;AACnD,EAAA,MAAMA,YAAW,kBAAA,CAAmB,QAAA,EAAU,OAAA,CAAQ,YAAA,IAAgB,EAAE,CAAA;AACxE,EAAA,IAAI,CAACA,SAAAA,EAAU,OAAO,MAAA,EAAO;AAC7B,EAAA,MAAM,qBAAqB,CAAC,OAAA,EAAS,GAAGA,SAAQ,CAAA,CAAE,IAAI,CAAC,OAAA,KAAY,CAAC,OAAA,CAAQ,YAAY,OAAA,CAAQ,UAAA,EAAY,QAAQ,eAAA,EAAiB,OAAA,CAAQ,gBAAgB,CAAC,CAAA;AAC9J,EAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,KAAA,CAAM,CAAC,QAAA,KAAa,QAAA,CAAS,CAAC,CAAC,CAAA,GAC/D,MAAM,WAAA,CAAY,OAAA,CAAQ,aAAA,EAAe,CAAC,SAAA,EAAW,sBAAA,EAAuB,GAAI,YAAA,GAAe,IAAA,EAAM,OAAA,CAAQ,aAAA,EAAe,kBAAA,EAAoB,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,GAAG,CAAC,CAAA,GAAI,IAAA;AACnL,EAAA,MAAM,GAAA,GAAM,MAAM,YAAA,CAAa,QAAA,EAAU,QAAQ,aAAa,CAAA;AAC9D,EAAA,IAAI,GAAA,EAAK;AACP,IAAA,MAAM,MAAA,GAAS,yBAAA,CAA0B,GAAA,CAAI,KAAA,EAAO,CAAC,OAAA,EAAS,GAAGA,SAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,OAAA,KAAY,OAAA,CAAQ,UAAU,CAAC,CAAA;AAC/G,IAAA,IAAI,MAAA,EAAQ;AAAE,MAAA,IAAI,MAAA,CAAO,SAAA,EAAW,yBAAA,CAA0B,MAAA,CAAO,SAAS,CAAA;AAAG,MAAA,sBAAA,CAAuB,IAAI,OAAO,CAAA;AAAG,MAAA,OAAO,MAAA,CAAO,KAAA;AAAA,IAAY;AAAA,EAClJ;AACA,EAAA,MAAM,OAAA,GAAU,KAAK,GAAA,EAAI;AACzB,EAAA,MAAM,QAAA,GAAW,MAAM,OAAA,CAAQA,SAAQ,CAAA;AACvC,EAAA,IAAI,CAAC,QAAA,EAAU,OAAO,MAAA,EAAO;AAC7B,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,eAAA,CAAgB,CAAC,YAAA,EAAc,sBAAA,EAAuB,GAAI,YAAA,GAAe,IAAA,EAAM,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,QAAQ,KAAA,EAAO,OAAA,CAAQ,GAAA,EAAK,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,OAAA,EAAS,OAAM,KAAM,CAAC,OAAA,CAAQ,UAAA,EAAY,OAAA,CAAQ,UAAA,EAAY,KAAK,CAAC,CAAC,CAAC,CAAA;AAC1P,IAAA,IAAI,IAAI,aAAY,CAAE,MAAA,CAAO,QAAQ,CAAA,CAAE,UAAA,GAAa,kBAAA,EAAoB,OAAO,IAAA,EAAK;AACpF,IAAA,GAAA,GAAM,CAAA,GAAA,EAAM,MAAM,SAAA,CAAU,QAAQ,CAAC,CAAA,CAAA;AAAA,EACvC,CAAA,CAAA,MAAQ;AAAE,IAAA,OAAO,IAAA,EAAK;AAAA,EAAG;AACzB,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI;AAAE,IAAA,MAAA,GAAS,MAAM,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,EAAE,GAAA,EAAK,MAAA,EAAQ,MAAA,EAAQ,UAAA,EAAY,QAAQ,UAAA,EAAY,MAAA,EAAQ,GAAA,EAAQ,OAAA,EAAS,OAAO,CAAA;AAAA,EAAG,CAAA,CAAA,MAC5H;AAAE,IAAA,OAAO,MAAA,EAAO;AAAA,EAAG;AACzB,EAAA,IAAI,MAAA,CAAO,SAAS,KAAA,EAAO;AACzB,IAAA,IAAI;AACF,MAAA,MAAM,MAAe,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC,CAAA;AACpD,MAAA,MAAM,MAAA,GAAS,yBAAA,CAA0B,GAAA,EAAK,CAAC,OAAA,EAAS,GAAGA,SAAQ,CAAA,CAAE,GAAA,CAAI,CAAC,OAAA,KAAY,OAAA,CAAQ,UAAU,CAAC,CAAA;AACzG,MAAA,MAAM,QAAQ,MAAA,EAAQ,KAAA;AACtB,MAAA,IAAI,MAAA,IAAU,YAAA,CAAa,KAAA,EAAO,cAAA,EAAgB,KAAK,CAAA,IAAK,aAAA,CAAc,QAAA,EAAU,MAAM,OAAA,CAAQA,SAAQ,CAAC,CAAA,EAAG;AAC5G,QAAA,IAAI,MAAA,CAAO,SAAA,EAAW,yBAAA,CAA0B,MAAA,CAAO,SAAS,CAAA;AAChE,QAAA,MAAM,aAAA,CAAc,QAAA,EAAU,OAAA,CAAQ,aAAA,EAAe,SAAS,GAAG,CAAA;AACjE,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAAwD;AAChE,IAAA,OAAO,MAAA,EAAO;AAAA,EAChB;AACA,EAAA,IAAI,CAAC,MAAA,CAAO,SAAA,IAAa,MAAA,CAAO,OAAA,SAAgB,MAAA,EAAO;AACvD,EAAA,MAAM,YAAY,MAAA,CAAO,SAAA;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAM,oBAAA,CAAqB,MAAM,CAAA;AACjD,IAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA;AACtB,IAAA,IAAI;AACF,MAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,KAAA,CAAA,IAAa,YAAA,CAAa,KAAA,EAAO,cAAA,EAAgB,KAAK,CAAA,KAAM,OAAA,CAAQ,SAAA,GAAY,KAAK,KAAK,IAAA,CAAA,EAAO;AAC/H,QAAA,MAAM,WAAA,GAAc,uBAAA,CAAwB,KAAA,EAAO,OAAA,CAAQ,SAAS,CAAA;AACpE,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,WAAW,CAAC,CAAA;AAC/C,QAAA,IAAI,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,IAAI,CAAA,CAAE,UAAA,IAAc,cAAA,IAAkB,aAAA,CAAc,QAAA,EAAU,MAAM,OAAA,CAAQA,SAAQ,CAAC,CAAA,EAAG;AACnH,UAAA,MAAM,UAAU,MAAM,OAAA,CAAQ,KAAA,CAAM,KAAA,CAAM,EAAE,GAAA,EAAK,SAAA,EAAW,QAAA,EAAU,MAAA,CAAO,QAAQ,KAAA,EAAO,GAAA,EAAK,WAAW,GAAA,EAAK,KAAA,EAAO,MAAM,CAAA;AAC9H,UAAA,IAAI,YAAY,OAAA,CAAQ,EAAA,IAAM,aAAA,CAAc,QAAA,EAAU,MAAM,OAAA,CAAQA,SAAQ,CAAC,CAAA,QAAS,aAAA,CAAc,QAAA,EAAU,OAAA,CAAQ,aAAA,EAAe,SAAS,WAAW,CAAA;AAAA,QAC3J;AAAA,MACF;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAAoE;AAC5E,IAAA,OAAO,KAAA;AAAA,EACT,CAAA,SAAE;AACA,IAAA,IAAI;AAAE,MAAA,MAAM,QAAQ,KAAA,CAAM,OAAA,CAAQ,EAAE,GAAA,EAAK,WAAW,CAAA;AAAA,IAAG,CAAA,CAAA,MAAQ;AAAA,IAA+D;AAAA,EAChI;AACF","file":"chunk-LAXBP5DQ.js","sourcesContent":["import { createDurableObjectStore } from '../cloudflare/store';\nimport type { CoordinatorLocationHint } from '../cloudflare/store-options';\nimport type { CacheCoordinator } from '../cloudflare/coordinator';\nimport { fenceD1Writes } from './adapter';\nimport { isD1BindingName, type D1CacheProfile } from './profile';\nimport { createCacheExtension } from '../core/extension';\nimport type { CacheStore, DecimalConstructor, GeneratedCacheConfig } from '../core/types';\nimport { sha256Hex, stableStringify } from '../core/codec';\nimport { boundedValue, dependencyRuntimes, inspect, sameSnapshots } from './read';\nimport { boundedD1Store } from './bounded-store';\nimport { regionalKey, regionalRead, regionalWrite } from './regional';\nimport { limitRegionalDataUntil } from './regional-deadline';\nimport { readTargets } from '../core/targets';\nimport { registerD1SessionAlias, d1SessionBookmarkFloor, wrapD1SessionCacheValue, unwrapD1SessionCacheValue, advanceD1SessionBookmarks, trackD1SessionSource, runPrimaryD1SessionSource } from './session';\n\nconst uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst hints = new Set(['wnam', 'enam', 'sam', 'weur', 'eeur', 'apac', 'oc', 'afr', 'me']);\nconst wrapped = new WeakMap<object, WeakMap<D1Database, Map<string, D1Database>>>();\nexport interface D1CacheRuntime { store: CacheStore; generation: string; databaseId: string; readsEnabled: boolean; readModels: readonly string[]; coordinatorIdentity: object; coordinatorName: string; regionalIdentity?: string }\nconst runtimes = new WeakMap<object, D1CacheRuntime>();\nexport const d1CacheRuntime = (database: object): D1CacheRuntime | undefined => runtimes.get(database);\nexport function createD1CacheRuntime(database: D1Database, options: { store: CacheStore; databaseId: string; generation: string; readsEnabled?: boolean; profile: D1CacheProfile; coordinatorIdentity?: object; coordinatorName?: string; regionalIdentity?: string }): D1Database {\n const { generation, databaseId, profile, readsEnabled = true } = options;\n const store = boundedD1Store(options.store);\n const fenced = fenceD1Writes(database, { store, generation, policy: profile });\n registerD1SessionAlias(fenced, database);\n runtimes.set(fenced, { store, generation, databaseId, readsEnabled, readModels: profile.readModels, coordinatorIdentity: options.coordinatorIdentity ?? options.store, coordinatorName: options.coordinatorName ?? '', regionalIdentity: options.regionalIdentity });\n return fenced;\n}\n\nexport function cacheD1Env<T extends object>(env: T, profile: D1CacheProfile): T {\n const value = (suffix: string): unknown => Reflect.get(env, `${profile.envPrefix}_${suffix}`);\n const enabled = value('ENABLED');\n if (enabled === undefined || enabled === 'false') return env;\n if (enabled !== 'true') throw new Error(`Invalid ${profile.envPrefix}_ENABLED`);\n const reads = value('READS_ENABLED');\n if (reads !== undefined && reads !== 'true' && reads !== 'false') throw new Error(`Invalid ${profile.envPrefix}_READS_ENABLED`);\n const readsEnabled = reads !== 'false';\n const namespace = value('COORDINATOR');\n const rawIds = value('DATABASE_IDS');\n const generation = value('GENERATION');\n if (!namespace || typeof namespace !== 'object' || typeof Reflect.get(namespace, 'idFromName') !== 'function' || typeof Reflect.get(namespace, 'get') !== 'function' || typeof rawIds !== 'string' || typeof generation !== 'string' || !generation.trim())\n throw new Error(`${profile.envPrefix} requires coordinator, database identities and generation`);\n if (generation.length > 256) throw new Error(`Invalid ${profile.envPrefix}_GENERATION`);\n let ids: unknown;\n try { ids = JSON.parse(rawIds); } catch { throw new Error(`Invalid ${profile.envPrefix}_DATABASE_IDS`); }\n if (!ids || typeof ids !== 'object' || Array.isArray(ids)) throw new Error(`Invalid ${profile.envPrefix}_DATABASE_IDS`);\n const map = Object.entries(ids);\n if (map.some(([key, id]) => !isD1BindingName(key, profile) || typeof id !== 'string' || !uuid.test(id))) throw new Error('Invalid cache database identity');\n const locationHint = value('LOCATION_HINT') ?? 'weur';\n if (typeof locationHint !== 'string' || !hints.has(locationHint)) throw new Error(`Invalid ${profile.envPrefix}_LOCATION_HINT`);\n const identities = new Map(map);\n const scoped = { ...env };\n for (const name of profile.bindingNames) if (!Reflect.has(env, name)) throw new Error(`Cache missing D1 binding: ${name}`);\n for (const [key, database] of Object.entries(env)) {\n if (profile.bindingPrefixes.some((prefix) => key.startsWith(prefix)) && !isD1BindingName(key, profile)) throw new Error(`Invalid cache binding: ${key}`);\n if (!isD1BindingName(key, profile)) continue;\n const id = identities.get(key);\n if (typeof id !== 'string' || !database || typeof database.prepare !== 'function') throw new Error(`Cache missing D1 identity or binding: ${key}`);\n const databaseId = id.toLowerCase();\n const cacheKey = JSON.stringify([databaseId, generation, locationHint, readsEnabled, profile]);\n let databases = wrapped.get(namespace);\n if (!databases) { databases = new WeakMap(); wrapped.set(namespace, databases); }\n let versions = databases.get(database);\n if (!versions) { versions = new Map(); databases.set(database, versions); }\n let cached = versions.get(cacheKey);\n if (!cached) {\n const coordinatorName = `${profile.coordinatorNamePrefix}${databaseId}`;\n const store = createDurableObjectStore(namespace as DurableObjectNamespace<CacheCoordinator>, { name: coordinatorName, locationHint: locationHint as CoordinatorLocationHint });\n cached = createD1CacheRuntime(database, { store, generation, databaseId, readsEnabled, profile, coordinatorIdentity: namespace, coordinatorName, regionalIdentity: (namespace as DurableObjectNamespace<CacheCoordinator>).idFromName(coordinatorName).toString() });\n versions.set(cacheKey, cached);\n }\n Reflect.set(scoped, key, cached);\n }\n return scoped;\n}\n\nexport function wrapD1Handler<Event, Env extends object, Context, Result>(handler: (event: Event, env: Env, context: Context) => Result, profile: D1CacheProfile): (event: Event, env: Env, context: Context) => Result {\n return (event, env, context) => handler(event, cacheD1Env(env, profile), context);\n}\n\nexport interface D1PrismaCacheOptions {\n scope: unknown;\n dependencies?: readonly D1Database[];\n keyArgs?: (args: unknown) => unknown;\n regionalTtlMs?: number;\n regionalModels?: readonly string[];\n}\n\nexport function d1PrismaCacheExtension(database: object, config: GeneratedCacheConfig, optionsOrDecimal?: D1PrismaCacheOptions | DecimalConstructor, decimalArg?: DecimalConstructor): ReturnType<typeof createCacheExtension> | undefined {\n const runtime = runtimes.get(database);\n if (!runtime || !runtime.readsEnabled) return undefined;\n const options = typeof optionsOrDecimal === 'function' ? undefined : optionsOrDecimal;\n const decimal = typeof optionsOrDecimal === 'function' ? optionsOrDecimal : decimalArg;\n const allowed = new Set(runtime.readModels);\n const scopedConfig = { ...config, cacheableByModel: Object.fromEntries(Object.entries(config.cacheableByModel).map(([model, enabled]) => [model, enabled && allowed.has(model)])) };\n const common = { config: scopedConfig, store: runtime.store, generation: runtime.generation, coordinationGeneration: runtime.generation, ...(decimal ? { decimal } : {}), ...(options?.keyArgs ? { keyArgs: options.keyArgs } : {}) };\n const base = createCacheExtension({ ...common, scope: runtime.databaseId });\n const operation = base.query.$allModels.$allOperations;\n if (!options) return { ...base, query: { $allModels: { $allOperations(params: Parameters<typeof operation>[0]) {\n return d1SessionBookmarkFloor() ? params.query(params.args) : operation(params);\n } } } };\n return {\n ...base,\n query: { $allModels: { async $allOperations(params: Parameters<typeof operation>[0]) {\n if (!params.model || !allowed.has(params.model) || !['findUnique', 'findUniqueOrThrow', 'findFirst', 'findFirstOrThrow', 'findMany', 'count', 'aggregate', 'groupBy'].includes(params.operation)) return operation(params);\n if (options.scope === null || options.scope === undefined || !boundedValue(options.scope, 32_768, true) || (options.dependencies?.length ?? 0) > 32) return params.query(params.args);\n const dependencies = dependencyRuntimes(database, options.dependencies ?? []);\n if (!dependencies) return params.query(params.args);\n const internal = params.__internalParams;\n const dataPath = internal && typeof internal === 'object' && Array.isArray(Reflect.get(internal, 'dataPath')) ? Reflect.get(internal, 'dataPath') : [];\n const transaction: unknown = internal && typeof internal === 'object' ? Reflect.get(internal, 'transaction') : undefined;\n const inBatch = !!transaction && typeof transaction === 'object' && Reflect.get(transaction, 'kind') === 'batch';\n let regional: string | null = null;\n let normalizedArgs: unknown;\n let normalized = false;\n try {\n const identities = [runtime, ...dependencies].map((item) => [item.databaseId, item.generation, item.coordinatorName, item.regionalIdentity]);\n const targets = options.regionalModels ? readTargets(config.relationGraph, params.model, params.args) : undefined;\n const allowedTargets = !options.regionalModels || (!!targets && [...targets.models].every((model) => options.regionalModels?.includes(model)));\n if (options.regionalTtlMs && options.regionalTtlMs > 0 && options.regionalTtlMs <= 5000 && !inBatch && allowedTargets && identities.every((item) => item[3])) {\n normalizedArgs = options.keyArgs ? options.keyArgs(params.args) : params.args;\n normalized = true;\n const configDigest = await sha256Hex(stableStringify(config));\n regional = await regionalKey(options.regionalTtlMs, ['prisma', d1SessionBookmarkFloor() ? 'session-v1' : null, options.regionalTtlMs, identities, configDigest, options.scope, params.model, params.operation, dataPath, normalizedArgs ?? null]);\n }\n } catch { /* Key callbacks use the strict path on failure. */ }\n const hit = await regionalRead(regional, options.regionalTtlMs, decimal);\n if (hit) {\n const cached = unwrapD1SessionCacheValue(hit.value, [runtime, ...dependencies].map((item) => item.databaseId));\n if (cached) { if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks); limitRegionalDataUntil(hit.expires); return cached.value; }\n }\n let started = Date.now();\n const snapshot = await inspect(dependencies);\n if (!snapshot) return params.query(params.args);\n let scope: string;\n try {\n scope = stableStringify([d1SessionBookmarkFloor() ? 'session-v1' : null, runtime.databaseId, runtime.generation, options.scope, snapshot.map(({ runtime: dependency, epoch }) => [dependency.databaseId, dependency.generation, epoch])]);\n if (new TextEncoder().encode(scope).byteLength > 32_768) return params.query(params.args);\n } catch { return params.query(params.args); }\n let verifiedHit = false;\n let hitBookmarks: Record<string, string> | undefined;\n let verifiedWrite = false;\n let queried = false;\n const store: CacheStore = { ...runtime.store,\n async write(request) {\n const value = d1SessionBookmarkFloor() ? JSON.stringify(wrapD1SessionCacheValue(request.value)) : request.value;\n const result = await runtime.store.write({ ...request, value });\n verifiedWrite = result.ok;\n return result;\n },\n async read(request) {\n const result = await runtime.store.read(request);\n if (result.kind === 'hit' && !sameSnapshots(snapshot, await inspect(dependencies))) return { kind: 'miss', epochs: result.epochs, lockHeldForMs: null, lockToken: null, pending: true };\n if (result.kind === 'hit' && d1SessionBookmarkFloor()) {\n let cached;\n try { cached = unwrapD1SessionCacheValue(JSON.parse(result.value), [runtime, ...dependencies].map((item) => item.databaseId)); } catch { cached = null; }\n if (!cached || typeof cached.value !== 'string') return { kind:'miss', epochs:result.epochs, lockHeldForMs:null, lockToken:null, pending:true };\n hitBookmarks = cached.bookmarks;\n verifiedHit = true;\n return { ...result, value:cached.value };\n }\n if (result.kind === 'hit') verifiedHit = true;\n return result;\n } };\n const scoped = createCacheExtension({ ...common, store, scope, ...(normalized ? { keyArgs: () => normalizedArgs } : {}) });\n const tracked = await trackD1SessionSource(async () => {\n const value = await scoped.query.$allModels.$allOperations({ ...params, query: async (args) => {\n queried = true;\n started = Date.now();\n return runPrimaryD1SessionSource(() => params.query(args));\n } });\n if (!queried && verifiedHit && hitBookmarks) advanceD1SessionBookmarks(hitBookmarks);\n return value;\n });\n if (regional && ((!queried && verifiedHit) || verifiedWrite) && sameSnapshots(snapshot, await inspect(dependencies))) await regionalWrite(regional, options.regionalTtlMs, started, wrapD1SessionCacheValue(tracked.value, tracked.bookmarks));\n return tracked.value;\n } } },\n };\n}\n\nexport function withD1PrismaCache<Client extends object>(client: Client, database: object, config: GeneratedCacheConfig, optionsOrDecimal?: D1PrismaCacheOptions | DecimalConstructor, decimalArg?: DecimalConstructor): Client {\n const extension = d1PrismaCacheExtension(database, config, optionsOrDecimal, decimalArg);\n if (!extension) return client;\n const extend: unknown = Reflect.get(client, '$extends', client);\n if (typeof extend !== 'function') throw new TypeError('Prisma client must support $extends');\n const extended: unknown = Reflect.apply(extend, client, [extension]);\n if (!extended || typeof extended !== 'object') throw new TypeError('Prisma extension returned no client');\n return new Proxy(client, {\n get(target, property) {\n const source = property === '$on' ? target : extended;\n const member: unknown = Reflect.get(source, property, source);\n return typeof member === 'function' ? member.bind(source) : member;\n },\n });\n}\n","import { boundedValue } from '../core/bounded-value';\nimport type { D1Database } from '@cloudflare/workers-types';\nimport { decode, encode, sha256Hex, stableStringify } from '../core/codec';\nimport { MAX_VALUE_BYTES } from '../core/limits';\nimport { d1CacheRuntime, type D1CacheRuntime } from './env';\nimport { regionalKey, regionalRead, regionalWrite } from './regional';\nimport { limitRegionalDataUntil } from './regional-deadline';\nimport { wrapD1SessionCacheValue, unwrapD1SessionCacheValue, advanceD1SessionBookmarks, d1SessionBookmarkFloor, trackD1SessionSource, runPrimaryD1SessionSource } from './session';\n\nconst FENCES = ['g'];\nconst DEFAULT_TTL_MS = 30_000;\nconst MAX_TTL_MS = 300_000;\nconst MAX_IDENTITY_BYTES = 32_768;\nconst MAX_VALUE_SIZE = Math.min(1_500_000, MAX_VALUE_BYTES);\n\nexport interface D1ReadOptions<T> {\n key: unknown;\n scope: unknown;\n dependencies?: readonly D1Database[];\n ttlMs?: number;\n regionalTtlMs?: number;\n cacheable?: (value: T) => boolean;\n}\n\nexport { boundedValue } from '../core/bounded-value';\n\nexport interface Snapshot { runtime: D1CacheRuntime; epoch: number }\nexport function sameD1CacheDatabase(left: object, right: object): boolean {\n const a = d1CacheRuntime(left);\n const b = d1CacheRuntime(right);\n return !!a && !!b && a.databaseId === b.databaseId && a.generation === b.generation && a.coordinatorIdentity === b.coordinatorIdentity && a.coordinatorName === b.coordinatorName;\n}\nexport async function d1CacheEpoch(database: object): Promise<string | null> {\n const runtime = d1CacheRuntime(database);\n if (!runtime || !runtime.readsEnabled) return null;\n const snapshot = await inspect([runtime]);\n if (!snapshot?.[0]) return null;\n return stableStringify([runtime.databaseId, runtime.generation, snapshot[0].epoch]);\n}\nexport async function inspect(runtimes: readonly D1CacheRuntime[]): Promise<Snapshot[] | null> {\n if (runtimes.length === 0) return [];\n try {\n const states = await Promise.all(runtimes.map(async (runtime) => {\n if (!runtime.store.inspectFences) return null;\n const state = await runtime.store.inspectFences({ fences: FENCES, generation: runtime.generation });\n const epoch = state.epochs.g;\n if (state.pending !== false || typeof epoch !== 'number' || !Number.isSafeInteger(epoch) || epoch < 0) return null;\n return { runtime, epoch };\n }));\n return states.some((state) => state === null) ? null : states.filter((state): state is Snapshot => state !== null);\n } catch { return null; }\n}\n\nexport const sameSnapshots = (a: readonly Snapshot[], b: readonly Snapshot[] | null): boolean =>\n b !== null && a.length === b.length && a.every((item, index) => item.runtime.databaseId === b[index]?.runtime.databaseId && item.runtime.generation === b[index]?.runtime.generation && item.epoch === b[index]?.epoch);\n\nexport function dependencyRuntimes(database: object, dependencies: readonly object[]): D1CacheRuntime[] | null {\n if (dependencies.length > 32) return null;\n const primary = d1CacheRuntime(database);\n if (!primary || !primary.readsEnabled) return null;\n const byId = new Map<string, D1CacheRuntime>();\n for (const dependency of dependencies) {\n const runtime = d1CacheRuntime(dependency);\n if (!runtime || !runtime.readsEnabled) return null;\n const prior = runtime.databaseId === primary.databaseId ? primary : byId.get(runtime.databaseId);\n if (prior && (prior.generation !== runtime.generation || prior.coordinatorIdentity !== runtime.coordinatorIdentity || prior.coordinatorName !== runtime.coordinatorName)) return null;\n if (runtime.databaseId === primary.databaseId) continue;\n if (!runtime.store.inspectFences) return null;\n byId.set(runtime.databaseId, prior ?? runtime);\n }\n return [...byId.values()].sort((a, b) => a.databaseId.localeCompare(b.databaseId));\n}\n\nexport async function cacheD1Read<T>(database: D1Database, options: D1ReadOptions<T>, load: () => Promise<T>): Promise<T> {\n const primary = d1CacheRuntime(database);\n const ttl = options.ttlMs ?? DEFAULT_TTL_MS;\n if (!primary || !primary.readsEnabled || !Number.isFinite(ttl) || ttl <= 0 || ttl > MAX_TTL_MS || options.scope === undefined || options.scope === null || !boundedValue(options.scope, MAX_IDENTITY_BYTES, true) || !boundedValue(options.key, MAX_IDENTITY_BYTES, true)) return load();\n const source = () => runPrimaryD1SessionSource(load);\n const runtimes = dependencyRuntimes(database, options.dependencies ?? []);\n if (!runtimes) return source();\n const regionalIdentities = [primary, ...runtimes].map((runtime) => [runtime.databaseId, runtime.generation, runtime.coordinatorName, runtime.regionalIdentity]);\n const regional = regionalIdentities.every((identity) => identity[3])\n ? await regionalKey(options.regionalTtlMs, ['d1-read', d1SessionBookmarkFloor() ? 'session-v1' : null, options.regionalTtlMs, regionalIdentities, options.scope, options.key]) : null;\n const hit = await regionalRead(regional, options.regionalTtlMs);\n if (hit) {\n const cached = unwrapD1SessionCacheValue(hit.value, [primary, ...runtimes].map((runtime) => runtime.databaseId));\n if (cached) { if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks); limitRegionalDataUntil(hit.expires); return cached.value as T; }\n }\n const started = Date.now();\n const snapshot = await inspect(runtimes);\n if (!snapshot) return source();\n let key: string;\n try {\n const identity = stableStringify(['d1-read-v1', d1SessionBookmarkFloor() ? 'session-v1' : null, primary.databaseId, primary.generation, options.scope, options.key, snapshot.map(({ runtime, epoch }) => [runtime.databaseId, runtime.generation, epoch])]);\n if (new TextEncoder().encode(identity).byteLength > MAX_IDENTITY_BYTES) return load();\n key = `d1:${await sha256Hex(identity)}`;\n } catch { return load(); }\n let result;\n try { result = await primary.store.read({ key, fences: FENCES, generation: primary.generation, lockMs: 30_000, refresh: false }); }\n catch { return source(); }\n if (result.kind === 'hit') {\n try {\n const raw: unknown = decode(JSON.parse(result.value));\n const cached = unwrapD1SessionCacheValue(raw, [primary, ...runtimes].map((runtime) => runtime.databaseId));\n const value = cached?.value;\n if (cached && boundedValue(value, MAX_VALUE_SIZE, false) && sameSnapshots(snapshot, await inspect(runtimes))) {\n if (cached.bookmarks) advanceD1SessionBookmarks(cached.bookmarks);\n await regionalWrite(regional, options.regionalTtlMs, started, raw);\n return value as T;\n }\n } catch { /* Invalid cached values are read from the source. */ }\n return source();\n }\n if (!result.lockToken || result.pending) return source();\n const lockToken = result.lockToken;\n try {\n const tracked = await trackD1SessionSource(source);\n const value = tracked.value;\n try {\n if (value !== null && value !== undefined && boundedValue(value, MAX_VALUE_SIZE, false) && (options.cacheable?.(value) ?? true)) {\n const cachedValue = wrapD1SessionCacheValue(value, tracked.bookmarks);\n const text = JSON.stringify(encode(cachedValue));\n if (new TextEncoder().encode(text).byteLength <= MAX_VALUE_SIZE && sameSnapshots(snapshot, await inspect(runtimes))) {\n const written = await primary.store.write({ key, lockToken, snapshot: result.epochs, ttlMs: ttl, softTtlMs: ttl, value: text });\n if (regional && written.ok && sameSnapshots(snapshot, await inspect(runtimes))) await regionalWrite(regional, options.regionalTtlMs, started, cachedValue);\n }\n }\n } catch { /* The source result remains authoritative when caching fails. */ }\n return value;\n } finally {\n try { await primary.store.release({ key, lockToken }); } catch { /* The lock expires if the coordinator cannot be reached. */ }\n }\n}\n"]}
@@ -409,14 +409,17 @@ function createCacheExtension(options) {
409
409
  }
410
410
  async function fill(ctx, lockToken, epochs) {
411
411
  let value;
412
+ let cached;
412
413
  try {
413
- value = await ctx.query(ctx.args);
414
+ const loaded = options.sessionCache ? await options.sessionCache.fill(() => ctx.query(ctx.args)) : { value: await ctx.query(ctx.args), cached: void 0 };
415
+ value = loaded.value;
416
+ cached = options.sessionCache ? loaded.cached : value;
414
417
  await hooks?.afterFillQuery?.();
415
418
  } catch (error) {
416
419
  await release(ctx.key, lockToken);
417
420
  throw error;
418
421
  }
419
- const serialized = serialize(value);
422
+ const serialized = serialize(cached);
420
423
  if (serialized === null) {
421
424
  await release(ctx.key, lockToken);
422
425
  return value;
@@ -446,7 +449,8 @@ function createCacheExtension(options) {
446
449
  if (!token) return;
447
450
  if (!options.waitUntil) return release(ctx.key, token);
448
451
  try {
449
- options.waitUntil(fill(ctx, token, response.epochs).catch((error) => report(error, "refresh")));
452
+ const refresh = () => fill(ctx, token, response.epochs).then(() => void 0);
453
+ options.waitUntil((options.sessionCache?.background ? options.sessionCache.background(refresh) : refresh()).catch((error) => report(error, "refresh")));
450
454
  } catch (error) {
451
455
  report(error, "waitUntil");
452
456
  await release(ctx.key, token);
@@ -455,7 +459,7 @@ function createCacheExtension(options) {
455
459
  async function handleRead(model, operation, args, query, dataPath) {
456
460
  let key;
457
461
  try {
458
- const identity = [PLANNER_VERSION, config.cacheVersion, scope, model, operation, dataPath, (options.keyArgs ? options.keyArgs(args) : args) ?? null];
462
+ const identity = [PLANNER_VERSION, config.cacheVersion, scope, ...options.sessionCache ? [options.sessionCache.key()] : [], model, operation, dataPath, (options.keyArgs ? options.keyArgs(args) : args) ?? null];
459
463
  key = `${model}:${await sha256Hex(stableStringify(identity))}`;
460
464
  } catch (error) {
461
465
  report(error, "key");
@@ -475,6 +479,14 @@ function createCacheExtension(options) {
475
479
  let value;
476
480
  try {
477
481
  value = decode(JSON.parse(response.value), options.decimal);
482
+ if (options.sessionCache) {
483
+ const cached = options.sessionCache.read(value);
484
+ if (!cached) {
485
+ if (response.refreshToken) await release(key, response.refreshToken);
486
+ return (await options.sessionCache.fill(() => query(args))).value;
487
+ }
488
+ value = cached.value;
489
+ }
478
490
  } catch (error) {
479
491
  report(error, "decode");
480
492
  if (response.refreshToken) await release(key, response.refreshToken);
@@ -541,5 +553,5 @@ function createCacheExtension(options) {
541
553
  }
542
554
 
543
555
  export { CacheUnavailableError, createCacheExtension, readTargets };
544
- //# sourceMappingURL=chunk-ZREX7LLC.js.map
545
- //# sourceMappingURL=chunk-ZREX7LLC.js.map
556
+ //# sourceMappingURL=chunk-M4UOCIDQ.js.map
557
+ //# sourceMappingURL=chunk-M4UOCIDQ.js.map