@rocicorp/zero 0.19.2025040901 → 0.19.2025041102

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 (134) hide show
  1. package/out/advanced.js +1 -2
  2. package/out/analyze-query/src/bin-analyze.js +73 -13
  3. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  4. package/out/ast-to-zql/src/ast-to-zql.d.ts +1 -1
  5. package/out/ast-to-zql/src/ast-to-zql.js +2 -2
  6. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  7. package/out/{chunk-56G3QAI6.js → chunk-CW3J6ZJF.js} +38 -41
  8. package/out/{chunk-56G3QAI6.js.map → chunk-CW3J6ZJF.js.map} +2 -2
  9. package/out/{chunk-JW7AJ755.js → chunk-GTRWLUIW.js} +281 -3022
  10. package/out/chunk-GTRWLUIW.js.map +7 -0
  11. package/out/chunk-J3DNXL5V.js +2843 -0
  12. package/out/chunk-J3DNXL5V.js.map +7 -0
  13. package/out/{chunk-2NCGIK6G.js → chunk-SKR5JO2A.js} +21 -1
  14. package/out/{chunk-2NCGIK6G.js.map → chunk-SKR5JO2A.js.map} +1 -1
  15. package/out/{inspector-R2AXP2NY.js → inspector-YQC2D2E3.js} +9 -10
  16. package/out/inspector-YQC2D2E3.js.map +7 -0
  17. package/out/react.js +20 -9
  18. package/out/react.js.map +2 -2
  19. package/out/shared/src/options.d.ts +1 -0
  20. package/out/shared/src/options.d.ts.map +1 -1
  21. package/out/shared/src/options.js +12 -10
  22. package/out/shared/src/options.js.map +1 -1
  23. package/out/solid.js +31 -22
  24. package/out/solid.js.map +3 -3
  25. package/out/zero/src/cli.d.ts +1 -1
  26. package/out/zero/src/cli.d.ts.map +1 -1
  27. package/out/zero/src/cli.js +1 -1
  28. package/out/zero/src/cli.js.map +1 -1
  29. package/out/zero/src/server/runner/main.d.ts +2 -0
  30. package/out/zero/src/server/runner/main.d.ts.map +1 -0
  31. package/out/zero/src/server/runner/main.js +2 -0
  32. package/out/zero/src/server/runner/main.js.map +1 -0
  33. package/out/zero/src/zero-cache-dev.d.ts.map +1 -1
  34. package/out/zero/src/zero-cache-dev.js +1 -1
  35. package/out/zero/src/zero-cache-dev.js.map +1 -1
  36. package/out/zero-cache/src/config/zero-config.d.ts +7 -2
  37. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  38. package/out/zero-cache/src/config/zero-config.js +20 -4
  39. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  40. package/out/zero-cache/src/server/{multi → runner}/config.d.ts +7 -2
  41. package/out/zero-cache/src/server/runner/config.d.ts.map +1 -0
  42. package/out/zero-cache/src/server/{multi → runner}/config.js +2 -1
  43. package/out/zero-cache/src/server/runner/config.js.map +1 -0
  44. package/out/zero-cache/src/server/runner/main.d.ts.map +1 -0
  45. package/out/zero-cache/src/server/runner/main.js.map +1 -0
  46. package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -0
  47. package/out/zero-cache/src/server/{multi → runner}/run-worker.js +27 -17
  48. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -0
  49. package/out/zero-cache/src/server/runner/runtime.d.ts.map +1 -0
  50. package/out/zero-cache/src/server/runner/runtime.js.map +1 -0
  51. package/out/zero-cache/src/server/{multi/tenant-dispatcher.d.ts → runner/zero-dispatcher.d.ts} +4 -4
  52. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -0
  53. package/out/zero-cache/src/server/{multi/tenant-dispatcher.js → runner/zero-dispatcher.js} +25 -12
  54. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -0
  55. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  56. package/out/zero-cache/src/services/change-source/pg/change-source.js +15 -6
  57. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  58. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  59. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +17 -5
  60. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  61. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +1 -2
  62. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  63. package/out/zero-cache/src/services/change-source/pg/schema/init.js +1 -2
  64. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  65. package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts +10 -1
  66. package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts.map +1 -1
  67. package/out/zero-cache/src/services/dispatcher/websocket-handoff.js +15 -3
  68. package/out/zero-cache/src/services/dispatcher/websocket-handoff.js.map +1 -1
  69. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +1 -0
  70. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  71. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +9 -0
  72. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  73. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/view-syncer/view-syncer.js +66 -25
  75. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  76. package/out/zero-pg/src/query.d.ts +0 -2
  77. package/out/zero-pg/src/query.d.ts.map +1 -1
  78. package/out/zero-pg/src/query.js +0 -3
  79. package/out/zero-pg/src/query.js.map +1 -1
  80. package/out/zero-react/src/use-query.d.ts +3 -1
  81. package/out/zero-react/src/use-query.d.ts.map +1 -1
  82. package/out/zero-solid/src/create-query.d.ts +22 -0
  83. package/out/zero-solid/src/create-query.d.ts.map +1 -0
  84. package/out/zero-solid/src/mod.d.ts +1 -1
  85. package/out/zero-solid/src/mod.d.ts.map +1 -1
  86. package/out/zero-solid/src/solid-view.d.ts +4 -3
  87. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  88. package/out/zero.js +4 -5
  89. package/out/zql/src/ivm/array-view.d.ts +5 -1
  90. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  91. package/out/zql/src/ivm/array-view.js +8 -1
  92. package/out/zql/src/ivm/array-view.js.map +1 -1
  93. package/out/zql/src/ivm/view.d.ts +2 -1
  94. package/out/zql/src/ivm/view.d.ts.map +1 -1
  95. package/out/zql/src/query/query-impl.d.ts +5 -5
  96. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  97. package/out/zql/src/query/query-impl.js +15 -10
  98. package/out/zql/src/query/query-impl.js.map +1 -1
  99. package/out/zql/src/query/query.d.ts +8 -5
  100. package/out/zql/src/query/query.d.ts.map +1 -1
  101. package/out/zql/src/query/static-query.d.ts +0 -2
  102. package/out/zql/src/query/static-query.d.ts.map +1 -1
  103. package/out/zql/src/query/static-query.js +0 -3
  104. package/out/zql/src/query/static-query.js.map +1 -1
  105. package/out/zql/src/query/typed-view.d.ts +2 -0
  106. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  107. package/package.json +6 -2
  108. package/out/chunk-424PT5DM.js +0 -23
  109. package/out/chunk-424PT5DM.js.map +0 -7
  110. package/out/chunk-JW7AJ755.js.map +0 -7
  111. package/out/chunk-MB3DEFRC.js +0 -67
  112. package/out/chunk-MB3DEFRC.js.map +0 -7
  113. package/out/inspector-R2AXP2NY.js.map +0 -7
  114. package/out/zero/src/server/multi/main.d.ts +0 -2
  115. package/out/zero/src/server/multi/main.d.ts.map +0 -1
  116. package/out/zero/src/server/multi/main.js +0 -2
  117. package/out/zero/src/server/multi/main.js.map +0 -1
  118. package/out/zero-cache/src/server/multi/config.d.ts.map +0 -1
  119. package/out/zero-cache/src/server/multi/config.js.map +0 -1
  120. package/out/zero-cache/src/server/multi/main.d.ts.map +0 -1
  121. package/out/zero-cache/src/server/multi/main.js.map +0 -1
  122. package/out/zero-cache/src/server/multi/run-worker.d.ts.map +0 -1
  123. package/out/zero-cache/src/server/multi/run-worker.js.map +0 -1
  124. package/out/zero-cache/src/server/multi/runtime.d.ts.map +0 -1
  125. package/out/zero-cache/src/server/multi/runtime.js.map +0 -1
  126. package/out/zero-cache/src/server/multi/tenant-dispatcher.d.ts.map +0 -1
  127. package/out/zero-cache/src/server/multi/tenant-dispatcher.js.map +0 -1
  128. package/out/zero-solid/src/use-query.d.ts +0 -12
  129. package/out/zero-solid/src/use-query.d.ts.map +0 -1
  130. /package/out/zero-cache/src/server/{multi → runner}/main.d.ts +0 -0
  131. /package/out/zero-cache/src/server/{multi → runner}/main.js +0 -0
  132. /package/out/zero-cache/src/server/{multi → runner}/run-worker.d.ts +0 -0
  133. /package/out/zero-cache/src/server/{multi → runner}/runtime.d.ts +0 -0
  134. /package/out/zero-cache/src/server/{multi → runner}/runtime.js +0 -0
@@ -0,0 +1,2843 @@
1
+ import {
2
+ assert as assert2,
3
+ assertJSONObject,
4
+ assertJSONValue,
5
+ astSchema,
6
+ deepEqual,
7
+ h128,
8
+ hasOwn,
9
+ isProd,
10
+ joinIterables,
11
+ parse,
12
+ readonly,
13
+ readonlyArray,
14
+ readonlyObject,
15
+ readonlyRecord,
16
+ valita_exports
17
+ } from "./chunk-GTRWLUIW.js";
18
+ import {
19
+ assert,
20
+ assertArray,
21
+ assertBoolean,
22
+ assertNumber,
23
+ assertObject,
24
+ assertString,
25
+ throwInvalidType,
26
+ unreachable
27
+ } from "./chunk-SKR5JO2A.js";
28
+
29
+ // ../replicache/src/dag/store.ts
30
+ var ChunkNotFoundError = class extends Error {
31
+ name = "ChunkNotFoundError";
32
+ hash;
33
+ constructor(hash) {
34
+ super(`Chunk not found ${hash}`);
35
+ this.hash = hash;
36
+ }
37
+ };
38
+ async function mustGetChunk(store, hash) {
39
+ const chunk = await store.getChunk(hash);
40
+ if (chunk) {
41
+ return chunk;
42
+ }
43
+ throw new ChunkNotFoundError(hash);
44
+ }
45
+ async function mustGetHeadHash(name, store) {
46
+ const hash = await store.getHead(name);
47
+ assert(hash, `Missing head ${name}`);
48
+ return hash;
49
+ }
50
+
51
+ // ../replicache/src/format-version-enum.ts
52
+ var DD31 = 5;
53
+ var V6 = 6;
54
+ var V7 = 7;
55
+ var Latest = V7;
56
+
57
+ // ../shared/src/random-uint64.ts
58
+ function randomUint64() {
59
+ const high = Math.floor(Math.random() * 4294967295);
60
+ const low = Math.floor(Math.random() * 4294967295);
61
+ return BigInt(high) << 32n | BigInt(low);
62
+ }
63
+
64
+ // ../replicache/src/hash.ts
65
+ var STRING_LENGTH = 22;
66
+ var hashRe = /^[0-9a-v-]+$/;
67
+ var emptyUUID = "0".repeat(STRING_LENGTH);
68
+ var emptyHash = emptyUUID;
69
+ var newRandomHash = makeNewRandomHashFunctionInternal();
70
+ function toStringAndSlice(n, len) {
71
+ return n.toString(32).slice(-len).padStart(len, "0");
72
+ }
73
+ function makeNewRandomHashFunctionInternal() {
74
+ let base = "";
75
+ let i = 0;
76
+ return () => {
77
+ if (!base) {
78
+ base = toStringAndSlice(randomUint64(), 12);
79
+ }
80
+ const tail = toStringAndSlice(i++, 10);
81
+ return base + tail;
82
+ };
83
+ }
84
+ function isHash(value) {
85
+ return typeof value === "string" && hashRe.test(value);
86
+ }
87
+ function assertHash(value) {
88
+ assert2(value, hashSchema);
89
+ }
90
+ var hashSchema = valita_exports.string().assert(isHash, "Invalid hash");
91
+
92
+ // ../replicache/src/size-of-value.ts
93
+ var SIZE_TAG = 1;
94
+ var SIZE_INT32 = 4;
95
+ var SIZE_SMI = 5;
96
+ var SIZE_DOUBLE = 8;
97
+ function getSizeOfValue(value) {
98
+ switch (typeof value) {
99
+ case "string":
100
+ return SIZE_TAG + SIZE_INT32 + value.length;
101
+ case "number":
102
+ if (isSmi(value)) {
103
+ if (value <= -(2 ** 30) || value >= 2 ** 30 - 1) {
104
+ return SIZE_TAG + SIZE_SMI;
105
+ }
106
+ return SIZE_TAG + SIZE_INT32;
107
+ }
108
+ return SIZE_TAG + SIZE_DOUBLE;
109
+ case "boolean":
110
+ return SIZE_TAG;
111
+ case "object":
112
+ if (value === null) {
113
+ return SIZE_TAG;
114
+ }
115
+ if (Array.isArray(value)) {
116
+ let sum = 2 * SIZE_TAG + SIZE_INT32;
117
+ for (const element of value) {
118
+ sum += getSizeOfValue(element);
119
+ }
120
+ return sum;
121
+ }
122
+ {
123
+ const val = value;
124
+ let sum = 2 * SIZE_TAG + SIZE_INT32;
125
+ for (const k in val) {
126
+ if (hasOwn(val, k)) {
127
+ const propertyValue = val[k];
128
+ if (propertyValue !== void 0) {
129
+ sum += getSizeOfValue(k) + getSizeOfValue(propertyValue);
130
+ }
131
+ }
132
+ }
133
+ return sum;
134
+ }
135
+ }
136
+ throw new Error(`Invalid value. type: ${typeof value}, value: ${value}`);
137
+ }
138
+ function isSmi(value) {
139
+ return value === (value | 0);
140
+ }
141
+ var entryFixed = 2 * SIZE_TAG + SIZE_INT32 + SIZE_TAG + SIZE_INT32;
142
+ function getSizeOfEntry(key, value) {
143
+ return entryFixed + getSizeOfValue(key) + getSizeOfValue(value);
144
+ }
145
+
146
+ // ../replicache/src/btree/node.ts
147
+ import { compareUTF8 } from "compare-utf8";
148
+
149
+ // ../replicache/src/binary-search.ts
150
+ function binarySearch(high, compare) {
151
+ let low = 0;
152
+ while (low < high) {
153
+ const mid = low + (high - low >> 1);
154
+ const i = compare(mid);
155
+ if (i === 0) {
156
+ return mid;
157
+ }
158
+ if (i > 0) {
159
+ low = mid + 1;
160
+ } else {
161
+ high = mid;
162
+ }
163
+ }
164
+ return low;
165
+ }
166
+
167
+ // ../replicache/src/frozen-json.ts
168
+ var deepFrozenObjects = /* @__PURE__ */ new WeakSet();
169
+ function deepFreeze(v) {
170
+ if (isProd) {
171
+ return v;
172
+ }
173
+ deepFreezeInternal(v, []);
174
+ return v;
175
+ }
176
+ function deepFreezeInternal(v, seen) {
177
+ switch (typeof v) {
178
+ case "undefined":
179
+ throw new TypeError("Unexpected value undefined");
180
+ case "boolean":
181
+ case "number":
182
+ case "string":
183
+ return;
184
+ case "object": {
185
+ if (v === null) {
186
+ return;
187
+ }
188
+ if (deepFrozenObjects.has(v)) {
189
+ return;
190
+ }
191
+ deepFrozenObjects.add(v);
192
+ if (seen.includes(v)) {
193
+ throwInvalidType(v, "Cyclic JSON object");
194
+ }
195
+ seen.push(v);
196
+ Object.freeze(v);
197
+ if (Array.isArray(v)) {
198
+ deepFreezeArray(v, seen);
199
+ } else {
200
+ deepFreezeObject(v, seen);
201
+ }
202
+ seen.pop();
203
+ return;
204
+ }
205
+ default:
206
+ throwInvalidType(v, "JSON value");
207
+ }
208
+ }
209
+ function deepFreezeArray(v, seen) {
210
+ for (const item of v) {
211
+ deepFreezeInternal(item, seen);
212
+ }
213
+ }
214
+ function deepFreezeObject(v, seen) {
215
+ for (const k in v) {
216
+ if (hasOwn(v, k)) {
217
+ const value = v[k];
218
+ if (value !== void 0) {
219
+ deepFreezeInternal(value, seen);
220
+ }
221
+ }
222
+ }
223
+ }
224
+ function assertDeepFrozen(v) {
225
+ if (isProd) {
226
+ return;
227
+ }
228
+ if (!isDeepFrozen(v, [])) {
229
+ throw new Error("Expected frozen object");
230
+ }
231
+ }
232
+ function isDeepFrozen(v, seen) {
233
+ switch (typeof v) {
234
+ case "boolean":
235
+ case "number":
236
+ case "string":
237
+ return true;
238
+ case "object":
239
+ if (v === null) {
240
+ return true;
241
+ }
242
+ if (deepFrozenObjects.has(v)) {
243
+ return true;
244
+ }
245
+ if (!Object.isFrozen(v)) {
246
+ return false;
247
+ }
248
+ if (seen.includes(v)) {
249
+ throwInvalidType(v, "Cyclic JSON object");
250
+ }
251
+ seen.push(v);
252
+ if (Array.isArray(v)) {
253
+ for (const item of v) {
254
+ if (!isDeepFrozen(item, seen)) {
255
+ seen.pop();
256
+ return false;
257
+ }
258
+ }
259
+ } else {
260
+ for (const k in v) {
261
+ if (hasOwn(v, k)) {
262
+ const value = v[k];
263
+ if (value !== void 0 && !isDeepFrozen(value, seen)) {
264
+ seen.pop();
265
+ return false;
266
+ }
267
+ }
268
+ }
269
+ }
270
+ deepFrozenObjects.add(v);
271
+ seen.pop();
272
+ return true;
273
+ default:
274
+ throwInvalidType(v, "JSON value");
275
+ }
276
+ }
277
+ function deepFreezeAllowUndefined(v) {
278
+ if (v === void 0) {
279
+ return void 0;
280
+ }
281
+ return deepFreeze(v);
282
+ }
283
+
284
+ // ../replicache/src/btree/node.ts
285
+ var NODE_LEVEL = 0;
286
+ var NODE_ENTRIES = 1;
287
+ function makeNodeChunkData(level, entries, formatVersion) {
288
+ return deepFreeze([
289
+ level,
290
+ formatVersion >= V7 ? entries : entries.map((e) => e.slice(0, 2))
291
+ ]);
292
+ }
293
+ async function findLeaf(key, hash, source, expectedRootHash) {
294
+ const node = await source.getNode(hash);
295
+ if (expectedRootHash !== source.rootHash) {
296
+ return findLeaf(key, source.rootHash, source, source.rootHash);
297
+ }
298
+ if (isDataNodeImpl(node)) {
299
+ return node;
300
+ }
301
+ const { entries } = node;
302
+ let i = binarySearch2(key, entries);
303
+ if (i === entries.length) {
304
+ i--;
305
+ }
306
+ const entry = entries[i];
307
+ return findLeaf(key, entry[1], source, expectedRootHash);
308
+ }
309
+ function binarySearch2(key, entries) {
310
+ return binarySearch(
311
+ entries.length,
312
+ (i) => compareUTF8(key, entries[i][0])
313
+ );
314
+ }
315
+ function binarySearchFound(i, entries, key) {
316
+ return i !== entries.length && entries[i][0] === key;
317
+ }
318
+ function parseBTreeNode(v, formatVersion, getSizeOfEntry2) {
319
+ if (isProd && formatVersion >= V7) {
320
+ return v;
321
+ }
322
+ assertArray(v);
323
+ assertDeepFrozen(v);
324
+ assert(v.length >= 2);
325
+ const [level, entries] = v;
326
+ assertNumber(level);
327
+ assertArray(entries);
328
+ const f = level > 0 ? assertString : assertJSONValue;
329
+ if (formatVersion >= V7) {
330
+ for (const e of entries) {
331
+ assertEntry(e, f);
332
+ }
333
+ return v;
334
+ }
335
+ const newEntries = entries.map((e) => convertNonV7Entry(e, f, getSizeOfEntry2));
336
+ return [level, newEntries];
337
+ }
338
+ function assertEntry(entry, f) {
339
+ assertArray(entry);
340
+ assert(entry.length >= 3);
341
+ assertString(entry[0]);
342
+ f(entry[1]);
343
+ assertNumber(entry[2]);
344
+ }
345
+ function convertNonV7Entry(entry, f, getSizeOfEntry2) {
346
+ assertArray(entry);
347
+ assert(entry.length >= 2);
348
+ assertString(entry[0]);
349
+ f(entry[1]);
350
+ const entrySize = getSizeOfEntry2(entry[0], entry[1]);
351
+ return [entry[0], entry[1], entrySize];
352
+ }
353
+ var NodeImpl = class {
354
+ entries;
355
+ hash;
356
+ isMutable;
357
+ #childNodeSize = -1;
358
+ constructor(entries, hash, isMutable) {
359
+ this.entries = entries;
360
+ this.hash = hash;
361
+ this.isMutable = isMutable;
362
+ }
363
+ maxKey() {
364
+ return this.entries[this.entries.length - 1][0];
365
+ }
366
+ getChildNodeSize(tree) {
367
+ if (this.#childNodeSize !== -1) {
368
+ return this.#childNodeSize;
369
+ }
370
+ let sum = tree.chunkHeaderSize;
371
+ for (const entry of this.entries) {
372
+ sum += entry[2];
373
+ }
374
+ return this.#childNodeSize = sum;
375
+ }
376
+ _updateNode(tree) {
377
+ this.#childNodeSize = -1;
378
+ tree.updateNode(
379
+ this
380
+ );
381
+ }
382
+ };
383
+ function toChunkData(node, formatVersion) {
384
+ return makeNodeChunkData(node.level, node.entries, formatVersion);
385
+ }
386
+ var DataNodeImpl = class extends NodeImpl {
387
+ level = 0;
388
+ set(key, value, entrySize, tree) {
389
+ let deleteCount;
390
+ const i = binarySearch2(key, this.entries);
391
+ if (!binarySearchFound(i, this.entries, key)) {
392
+ deleteCount = 0;
393
+ } else {
394
+ deleteCount = 1;
395
+ }
396
+ return Promise.resolve(
397
+ this.#splice(tree, i, deleteCount, [key, value, entrySize])
398
+ );
399
+ }
400
+ #splice(tree, start, deleteCount, ...items) {
401
+ if (this.isMutable) {
402
+ this.entries.splice(start, deleteCount, ...items);
403
+ this._updateNode(tree);
404
+ return this;
405
+ }
406
+ const entries = readonlySplice(this.entries, start, deleteCount, ...items);
407
+ return tree.newDataNodeImpl(entries);
408
+ }
409
+ del(key, tree) {
410
+ const i = binarySearch2(key, this.entries);
411
+ if (!binarySearchFound(i, this.entries, key)) {
412
+ return Promise.resolve(this);
413
+ }
414
+ return Promise.resolve(this.#splice(tree, i, 1));
415
+ }
416
+ async *keys(_tree) {
417
+ for (const entry of this.entries) {
418
+ yield entry[0];
419
+ }
420
+ }
421
+ async *entriesIter(_tree) {
422
+ for (const entry of this.entries) {
423
+ yield entry;
424
+ }
425
+ }
426
+ };
427
+ function readonlySplice(array3, start, deleteCount, ...items) {
428
+ const arr = array3.slice(0, start);
429
+ for (let i = 0; i < items.length; i++) {
430
+ arr.push(items[i]);
431
+ }
432
+ for (let i = start + deleteCount; i < array3.length; i++) {
433
+ arr.push(array3[i]);
434
+ }
435
+ return arr;
436
+ }
437
+ var InternalNodeImpl = class _InternalNodeImpl extends NodeImpl {
438
+ level;
439
+ constructor(entries, hash, level, isMutable) {
440
+ super(entries, hash, isMutable);
441
+ this.level = level;
442
+ }
443
+ async set(key, value, entrySize, tree) {
444
+ let i = binarySearch2(key, this.entries);
445
+ if (i === this.entries.length) {
446
+ i--;
447
+ }
448
+ const childHash = this.entries[i][1];
449
+ const oldChildNode = await tree.getNode(childHash);
450
+ const childNode = await oldChildNode.set(key, value, entrySize, tree);
451
+ const childNodeSize = childNode.getChildNodeSize(tree);
452
+ if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {
453
+ return this.#mergeAndPartition(tree, i, childNode);
454
+ }
455
+ const newEntry = createNewInternalEntryForNode(
456
+ childNode,
457
+ tree.getEntrySize
458
+ );
459
+ return this.#replaceChild(tree, i, newEntry);
460
+ }
461
+ /**
462
+ * This merges the child node entries with previous or next sibling and then
463
+ * partitions the merged entries.
464
+ */
465
+ async #mergeAndPartition(tree, i, childNode) {
466
+ const level = this.level - 1;
467
+ const thisEntries = this.entries;
468
+ let values;
469
+ let startIndex;
470
+ let removeCount;
471
+ if (i > 0) {
472
+ const hash = thisEntries[i - 1][1];
473
+ const previousSibling = await tree.getNode(hash);
474
+ values = joinIterables(
475
+ previousSibling.entries,
476
+ childNode.entries
477
+ );
478
+ startIndex = i - 1;
479
+ removeCount = 2;
480
+ } else if (i < thisEntries.length - 1) {
481
+ const hash = thisEntries[i + 1][1];
482
+ const nextSibling = await tree.getNode(hash);
483
+ values = joinIterables(
484
+ childNode.entries,
485
+ nextSibling.entries
486
+ );
487
+ startIndex = i;
488
+ removeCount = 2;
489
+ } else {
490
+ values = childNode.entries;
491
+ startIndex = i;
492
+ removeCount = 1;
493
+ }
494
+ const partitions = partition(
495
+ values,
496
+ (value) => value[2],
497
+ tree.minSize - tree.chunkHeaderSize,
498
+ tree.maxSize - tree.chunkHeaderSize
499
+ );
500
+ const newEntries = [];
501
+ for (const entries2 of partitions) {
502
+ const node = tree.newNodeImpl(entries2, level);
503
+ const newHashEntry = createNewInternalEntryForNode(
504
+ node,
505
+ tree.getEntrySize
506
+ );
507
+ newEntries.push(newHashEntry);
508
+ }
509
+ if (this.isMutable) {
510
+ this.entries.splice(startIndex, removeCount, ...newEntries);
511
+ this._updateNode(tree);
512
+ return this;
513
+ }
514
+ const entries = readonlySplice(
515
+ thisEntries,
516
+ startIndex,
517
+ removeCount,
518
+ ...newEntries
519
+ );
520
+ return tree.newInternalNodeImpl(entries, this.level);
521
+ }
522
+ #replaceChild(tree, index, newEntry) {
523
+ if (this.isMutable) {
524
+ this.entries.splice(index, 1, newEntry);
525
+ this._updateNode(tree);
526
+ return this;
527
+ }
528
+ const entries = readonlySplice(this.entries, index, 1, newEntry);
529
+ return tree.newInternalNodeImpl(entries, this.level);
530
+ }
531
+ async del(key, tree) {
532
+ const i = binarySearch2(key, this.entries);
533
+ if (i === this.entries.length) {
534
+ return this;
535
+ }
536
+ const childHash = this.entries[i][1];
537
+ const oldChildNode = await tree.getNode(childHash);
538
+ const oldHash = oldChildNode.hash;
539
+ const childNode = await oldChildNode.del(key, tree);
540
+ if (childNode.hash === oldHash) {
541
+ return this;
542
+ }
543
+ if (childNode.entries.length === 0) {
544
+ const entries = readonlySplice(this.entries, i, 1);
545
+ return tree.newInternalNodeImpl(entries, this.level);
546
+ }
547
+ if (i === 0 && this.entries.length === 1) {
548
+ return childNode;
549
+ }
550
+ if (childNode.getChildNodeSize(tree) > tree.minSize) {
551
+ const entry = createNewInternalEntryForNode(childNode, tree.getEntrySize);
552
+ return this.#replaceChild(tree, i, entry);
553
+ }
554
+ return this.#mergeAndPartition(tree, i, childNode);
555
+ }
556
+ async *keys(tree) {
557
+ for (const entry of this.entries) {
558
+ const childNode = await tree.getNode(entry[1]);
559
+ yield* childNode.keys(tree);
560
+ }
561
+ }
562
+ async *entriesIter(tree) {
563
+ for (const entry of this.entries) {
564
+ const childNode = await tree.getNode(entry[1]);
565
+ yield* childNode.entriesIter(tree);
566
+ }
567
+ }
568
+ getChildren(start, length, tree) {
569
+ const ps = [];
570
+ for (let i = start; i < length && i < this.entries.length; i++) {
571
+ ps.push(tree.getNode(this.entries[i][1]));
572
+ }
573
+ return Promise.all(ps);
574
+ }
575
+ async getCompositeChildren(start, length, tree) {
576
+ const { level } = this;
577
+ if (length === 0) {
578
+ return new _InternalNodeImpl([], newRandomHash(), level - 1, true);
579
+ }
580
+ const output = await this.getChildren(start, start + length, tree);
581
+ if (level > 1) {
582
+ const entries2 = [];
583
+ for (const child of output) {
584
+ entries2.push(...child.entries);
585
+ }
586
+ return new _InternalNodeImpl(entries2, newRandomHash(), level - 1, true);
587
+ }
588
+ assert(level === 1);
589
+ const entries = [];
590
+ for (const child of output) {
591
+ entries.push(...child.entries);
592
+ }
593
+ return new DataNodeImpl(entries, newRandomHash(), true);
594
+ }
595
+ };
596
+ function newNodeImpl(entries, hash, level, isMutable) {
597
+ if (level === 0) {
598
+ return new DataNodeImpl(
599
+ entries,
600
+ hash,
601
+ isMutable
602
+ );
603
+ }
604
+ return new InternalNodeImpl(entries, hash, level, isMutable);
605
+ }
606
+ function isDataNodeImpl(node) {
607
+ return node.level === 0;
608
+ }
609
+ function partition(values, getSizeOfEntry2, min, max) {
610
+ const partitions = [];
611
+ const sizes = [];
612
+ let sum = 0;
613
+ let accum = [];
614
+ for (const value of values) {
615
+ const size = getSizeOfEntry2(value);
616
+ if (size >= max) {
617
+ if (accum.length > 0) {
618
+ partitions.push(accum);
619
+ sizes.push(sum);
620
+ }
621
+ partitions.push([value]);
622
+ sizes.push(size);
623
+ sum = 0;
624
+ accum = [];
625
+ } else if (sum + size >= min) {
626
+ accum.push(value);
627
+ partitions.push(accum);
628
+ sizes.push(sum + size);
629
+ sum = 0;
630
+ accum = [];
631
+ } else {
632
+ sum += size;
633
+ accum.push(value);
634
+ }
635
+ }
636
+ if (sum > 0) {
637
+ if (sizes.length > 0 && sum + sizes[sizes.length - 1] <= max) {
638
+ partitions[partitions.length - 1].push(...accum);
639
+ } else {
640
+ partitions.push(accum);
641
+ }
642
+ }
643
+ return partitions;
644
+ }
645
+ var emptyDataNode = makeNodeChunkData(
646
+ 0,
647
+ [],
648
+ Latest
649
+ );
650
+ var emptyDataNodeImpl = new DataNodeImpl([], emptyHash, false);
651
+ function createNewInternalEntryForNode(node, getSizeOfEntry2) {
652
+ const key = node.maxKey();
653
+ const value = node.hash;
654
+ const size = getSizeOfEntry2(key, value);
655
+ return [key, value, size];
656
+ }
657
+
658
+ // ../replicache/src/btree/splice.ts
659
+ var SPLICE_UNASSIGNED = -1;
660
+ var SPLICE_AT = 0;
661
+ var SPLICE_REMOVED = 1;
662
+ var SPLICE_ADDED = 2;
663
+ var SPLICE_FROM = 3;
664
+ var KEY = 0;
665
+ var VALUE = 1;
666
+ function* computeSplices(previous, current) {
667
+ let previousIndex = 0;
668
+ let currentIndex = 0;
669
+ let splice;
670
+ function ensureAssigned(splice2, index) {
671
+ if (splice2[SPLICE_FROM] === SPLICE_UNASSIGNED) {
672
+ splice2[SPLICE_FROM] = index;
673
+ }
674
+ }
675
+ function newSplice() {
676
+ return [previousIndex, 0, 0, SPLICE_UNASSIGNED];
677
+ }
678
+ while (previousIndex < previous.length && currentIndex < current.length) {
679
+ if (previous[previousIndex][KEY] === current[currentIndex][KEY]) {
680
+ if (deepEqual(
681
+ // These are really Hash | InternalValue
682
+ previous[previousIndex][VALUE],
683
+ current[currentIndex][VALUE]
684
+ )) {
685
+ if (splice) {
686
+ ensureAssigned(splice, 0);
687
+ yield splice;
688
+ splice = void 0;
689
+ }
690
+ } else {
691
+ if (!splice) {
692
+ splice = newSplice();
693
+ }
694
+ splice[SPLICE_ADDED]++;
695
+ splice[SPLICE_REMOVED]++;
696
+ ensureAssigned(splice, currentIndex);
697
+ }
698
+ previousIndex++;
699
+ currentIndex++;
700
+ } else if (previous[previousIndex][KEY] < current[currentIndex][KEY]) {
701
+ if (!splice) {
702
+ splice = newSplice();
703
+ }
704
+ splice[SPLICE_REMOVED]++;
705
+ previousIndex++;
706
+ } else {
707
+ if (!splice) {
708
+ splice = newSplice();
709
+ }
710
+ splice[SPLICE_ADDED]++;
711
+ ensureAssigned(splice, currentIndex);
712
+ currentIndex++;
713
+ }
714
+ }
715
+ if (currentIndex < current.length) {
716
+ if (!splice) {
717
+ splice = newSplice();
718
+ }
719
+ splice[SPLICE_ADDED] += current.length - currentIndex;
720
+ ensureAssigned(splice, currentIndex);
721
+ }
722
+ if (previousIndex < previous.length) {
723
+ if (!splice) {
724
+ splice = newSplice();
725
+ }
726
+ splice[SPLICE_REMOVED] += previous.length - previousIndex;
727
+ }
728
+ if (splice) {
729
+ ensureAssigned(splice, 0);
730
+ yield splice;
731
+ }
732
+ }
733
+
734
+ // ../replicache/src/btree/read.ts
735
+ var NODE_HEADER_SIZE = 11;
736
+ var BTreeRead = class {
737
+ _cache = /* @__PURE__ */ new Map();
738
+ _dagRead;
739
+ _formatVersion;
740
+ rootHash;
741
+ getEntrySize;
742
+ chunkHeaderSize;
743
+ constructor(dagRead, formatVersion, root = emptyHash, getEntrySize = getSizeOfEntry, chunkHeaderSize = NODE_HEADER_SIZE) {
744
+ this._dagRead = dagRead;
745
+ this._formatVersion = formatVersion;
746
+ this.rootHash = root;
747
+ this.getEntrySize = getEntrySize;
748
+ this.chunkHeaderSize = chunkHeaderSize;
749
+ }
750
+ async getNode(hash) {
751
+ if (hash === emptyHash) {
752
+ return emptyDataNodeImpl;
753
+ }
754
+ const cached = this._cache.get(hash);
755
+ if (cached) {
756
+ return cached;
757
+ }
758
+ const chunk = await this._dagRead.mustGetChunk(hash);
759
+ const data = parseBTreeNode(
760
+ chunk.data,
761
+ this._formatVersion,
762
+ this.getEntrySize
763
+ );
764
+ const impl = newNodeImpl(
765
+ data[NODE_ENTRIES],
766
+ hash,
767
+ data[NODE_LEVEL],
768
+ false
769
+ );
770
+ this._cache.set(hash, impl);
771
+ return impl;
772
+ }
773
+ async get(key) {
774
+ const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);
775
+ const index = binarySearch2(key, leaf.entries);
776
+ if (!binarySearchFound(index, leaf.entries, key)) {
777
+ return void 0;
778
+ }
779
+ return leaf.entries[index][1];
780
+ }
781
+ async has(key) {
782
+ const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);
783
+ const index = binarySearch2(key, leaf.entries);
784
+ return binarySearchFound(index, leaf.entries, key);
785
+ }
786
+ async isEmpty() {
787
+ const { rootHash } = this;
788
+ const node = await this.getNode(this.rootHash);
789
+ if (this.rootHash !== rootHash) {
790
+ return this.isEmpty();
791
+ }
792
+ return node.entries.length === 0;
793
+ }
794
+ // We don't do any encoding of the key in the map, so we have no way of
795
+ // determining from an entry.key alone whether it is a regular key or an
796
+ // encoded IndexKey in an index map. Without encoding regular map keys the
797
+ // caller has to deal with encoding and decoding the keys for the index map.
798
+ scan(fromKey) {
799
+ return scanForHash(
800
+ this.rootHash,
801
+ () => this.rootHash,
802
+ this.rootHash,
803
+ fromKey,
804
+ async (hash) => {
805
+ const cached = await this.getNode(hash);
806
+ if (cached) {
807
+ return [
808
+ cached.level,
809
+ cached.isMutable ? cached.entries.slice() : cached.entries
810
+ ];
811
+ }
812
+ const chunk = await this._dagRead.mustGetChunk(hash);
813
+ return parseBTreeNode(
814
+ chunk.data,
815
+ this._formatVersion,
816
+ this.getEntrySize
817
+ );
818
+ }
819
+ );
820
+ }
821
+ async *keys() {
822
+ const node = await this.getNode(this.rootHash);
823
+ yield* node.keys(this);
824
+ }
825
+ async *entries() {
826
+ const node = await this.getNode(this.rootHash);
827
+ yield* node.entriesIter(this);
828
+ }
829
+ [Symbol.asyncIterator]() {
830
+ return this.entries();
831
+ }
832
+ async *diff(last) {
833
+ const [currentNode, lastNode] = await Promise.all([
834
+ this.getNode(this.rootHash),
835
+ last.getNode(last.rootHash)
836
+ ]);
837
+ yield* diffNodes(lastNode, currentNode, last, this);
838
+ }
839
+ };
840
+ async function* diffNodes(last, current, lastTree, currentTree) {
841
+ if (last.level > current.level) {
842
+ const lastChild = await last.getCompositeChildren(
843
+ 0,
844
+ last.entries.length,
845
+ lastTree
846
+ );
847
+ yield* diffNodes(lastChild, current, lastTree, currentTree);
848
+ return;
849
+ }
850
+ if (current.level > last.level) {
851
+ const currentChild = await current.getCompositeChildren(
852
+ 0,
853
+ current.entries.length,
854
+ currentTree
855
+ );
856
+ yield* diffNodes(last, currentChild, lastTree, currentTree);
857
+ return;
858
+ }
859
+ if (isDataNodeImpl(last) && isDataNodeImpl(current)) {
860
+ yield* diffEntries(
861
+ last.entries,
862
+ current.entries
863
+ );
864
+ return;
865
+ }
866
+ const initialSplices = computeSplices(
867
+ last.entries,
868
+ current.entries
869
+ );
870
+ for (const splice of initialSplices) {
871
+ const [lastChild, currentChild] = await Promise.all([
872
+ last.getCompositeChildren(
873
+ splice[SPLICE_AT],
874
+ splice[SPLICE_REMOVED],
875
+ lastTree
876
+ ),
877
+ current.getCompositeChildren(
878
+ splice[SPLICE_FROM],
879
+ splice[SPLICE_ADDED],
880
+ currentTree
881
+ )
882
+ ]);
883
+ yield* diffNodes(lastChild, currentChild, lastTree, currentTree);
884
+ }
885
+ }
886
+ function* diffEntries(lastEntries, currentEntries) {
887
+ const lastLength = lastEntries.length;
888
+ const currentLength = currentEntries.length;
889
+ let i = 0;
890
+ let j = 0;
891
+ while (i < lastLength && j < currentLength) {
892
+ const lastKey = lastEntries[i][0];
893
+ const currentKey = currentEntries[j][0];
894
+ if (lastKey === currentKey) {
895
+ if (!deepEqual(lastEntries[i][1], currentEntries[j][1])) {
896
+ yield {
897
+ op: "change",
898
+ key: lastKey,
899
+ oldValue: lastEntries[i][1],
900
+ newValue: currentEntries[j][1]
901
+ };
902
+ }
903
+ i++;
904
+ j++;
905
+ } else if (lastKey < currentKey) {
906
+ yield {
907
+ op: "del",
908
+ key: lastKey,
909
+ oldValue: lastEntries[i][1]
910
+ };
911
+ i++;
912
+ } else {
913
+ yield {
914
+ op: "add",
915
+ key: currentKey,
916
+ newValue: currentEntries[j][1]
917
+ };
918
+ j++;
919
+ }
920
+ }
921
+ for (; i < lastLength; i++) {
922
+ yield {
923
+ op: "del",
924
+ key: lastEntries[i][0],
925
+ oldValue: lastEntries[i][1]
926
+ };
927
+ }
928
+ for (; j < currentLength; j++) {
929
+ yield {
930
+ op: "add",
931
+ key: currentEntries[j][0],
932
+ newValue: currentEntries[j][1]
933
+ };
934
+ }
935
+ }
936
+ async function* scanForHash(expectedRootHash, getRootHash, hash, fromKey, readNode) {
937
+ if (hash === emptyHash) {
938
+ return;
939
+ }
940
+ const data = await readNode(hash);
941
+ const entries = data[NODE_ENTRIES];
942
+ let i = 0;
943
+ if (fromKey) {
944
+ i = binarySearch2(fromKey, entries);
945
+ }
946
+ if (data[NODE_LEVEL] > 0) {
947
+ for (; i < entries.length; i++) {
948
+ yield* scanForHash(
949
+ expectedRootHash,
950
+ getRootHash,
951
+ entries[i][1],
952
+ fromKey,
953
+ readNode
954
+ );
955
+ fromKey = "";
956
+ }
957
+ } else {
958
+ for (; i < entries.length; i++) {
959
+ const rootHash = getRootHash();
960
+ if (expectedRootHash !== rootHash) {
961
+ yield* scanForHash(
962
+ rootHash,
963
+ getRootHash,
964
+ rootHash,
965
+ entries[i][0],
966
+ readNode
967
+ );
968
+ return;
969
+ }
970
+ yield entries[i];
971
+ }
972
+ }
973
+ }
974
+ async function allEntriesAsDiff(map, op) {
975
+ const diff3 = [];
976
+ const make = op === "add" ? (entry) => ({
977
+ op: "add",
978
+ key: entry[0],
979
+ newValue: entry[1]
980
+ }) : (entry) => ({
981
+ op: "del",
982
+ key: entry[0],
983
+ oldValue: entry[1]
984
+ });
985
+ for await (const entry of map.entries()) {
986
+ diff3.push(make(entry));
987
+ }
988
+ return diff3;
989
+ }
990
+
991
+ // ../shared/src/string-compare.ts
992
+ function stringCompare(a, b) {
993
+ if (a === b) {
994
+ return 0;
995
+ }
996
+ if (a < b) {
997
+ return -1;
998
+ }
999
+ return 1;
1000
+ }
1001
+
1002
+ // ../replicache/src/cookies.ts
1003
+ function compareCookies(a, b) {
1004
+ if (a === b) {
1005
+ return 0;
1006
+ }
1007
+ if (a === null) {
1008
+ return -1;
1009
+ }
1010
+ if (b === null) {
1011
+ return 1;
1012
+ }
1013
+ const cva = getCompareValue(a);
1014
+ const cvb = getCompareValue(b);
1015
+ if (typeof cva === "string" || typeof cvb === "string") {
1016
+ return stringCompare(String(cva), String(cvb));
1017
+ }
1018
+ return cva - cvb;
1019
+ }
1020
+ function getCompareValue(cookie) {
1021
+ if (typeof cookie === "string" || typeof cookie === "number") {
1022
+ return cookie;
1023
+ }
1024
+ return cookie.order;
1025
+ }
1026
+ function assertCookie(v) {
1027
+ if (v === null || typeof v === "string" || typeof v === "number") {
1028
+ return;
1029
+ }
1030
+ assertJSONObject(v);
1031
+ if (typeof v.order === "string" || typeof v.order === "number") {
1032
+ return;
1033
+ }
1034
+ throw new Error("Invalid cookie");
1035
+ }
1036
+
1037
+ // ../replicache/src/dag/chunk.ts
1038
+ function asRefs(sortedRefs) {
1039
+ return sortedRefs;
1040
+ }
1041
+ function toRefs(refs) {
1042
+ if (Array.isArray(refs)) {
1043
+ refs.sort();
1044
+ for (let i = 1; i < refs.length; i++) {
1045
+ assert(refs[i - 1] !== refs[i], "Refs must not have duplicates");
1046
+ }
1047
+ return asRefs(refs);
1048
+ }
1049
+ const refsArray = [...refs];
1050
+ refsArray.sort();
1051
+ return asRefs(refsArray);
1052
+ }
1053
+ var Chunk = class {
1054
+ hash;
1055
+ data;
1056
+ /**
1057
+ * Meta is an array of refs. If there are no refs we do not write a meta
1058
+ * chunk.
1059
+ */
1060
+ meta;
1061
+ constructor(hash, data, refs) {
1062
+ assert(
1063
+ !refs.includes(hash),
1064
+ "Chunk cannot reference itself"
1065
+ );
1066
+ assertDeepFrozen(data);
1067
+ this.hash = hash;
1068
+ this.data = data;
1069
+ this.meta = refs;
1070
+ }
1071
+ };
1072
+ function assertRefs(v) {
1073
+ if (!Array.isArray(v)) {
1074
+ throw new Error("Refs must be an array");
1075
+ }
1076
+ if (v.length > 0) {
1077
+ assertString(v[0]);
1078
+ for (let i = 1; i < v.length; i++) {
1079
+ assertString(v[i]);
1080
+ }
1081
+ }
1082
+ }
1083
+ function createChunk(data, refs, chunkHasher) {
1084
+ const hash = chunkHasher();
1085
+ return new Chunk(hash, data, refs);
1086
+ }
1087
+
1088
+ // ../replicache/src/db/meta-type-enum.ts
1089
+ var LocalDD31 = 4;
1090
+ var SnapshotDD31 = 5;
1091
+
1092
+ // ../replicache/src/db/commit.ts
1093
+ var DEFAULT_HEAD_NAME = "main";
1094
+ function commitIsLocalDD31(commit) {
1095
+ return isLocalMetaDD31(commit.meta);
1096
+ }
1097
+ function commitIsLocal(commit) {
1098
+ return commitIsLocalDD31(commit);
1099
+ }
1100
+ function commitIsSnapshot(commit) {
1101
+ return isSnapshotMetaDD31(commit.meta);
1102
+ }
1103
+ var Commit = class {
1104
+ chunk;
1105
+ constructor(chunk) {
1106
+ this.chunk = chunk;
1107
+ }
1108
+ get meta() {
1109
+ return this.chunk.data.meta;
1110
+ }
1111
+ get valueHash() {
1112
+ return this.chunk.data.valueHash;
1113
+ }
1114
+ getMutationID(clientID, dagRead) {
1115
+ return getMutationID(clientID, dagRead, this.meta);
1116
+ }
1117
+ async getNextMutationID(clientID, dagRead) {
1118
+ return await this.getMutationID(clientID, dagRead) + 1;
1119
+ }
1120
+ get indexes() {
1121
+ return this.chunk.data.indexes;
1122
+ }
1123
+ };
1124
+ async function getMutationID(clientID, dagRead, meta) {
1125
+ switch (meta.type) {
1126
+ case SnapshotDD31:
1127
+ return meta.lastMutationIDs[clientID] ?? 0;
1128
+ case LocalDD31: {
1129
+ if (meta.clientID === clientID) {
1130
+ return meta.mutationID;
1131
+ }
1132
+ const { basisHash } = meta;
1133
+ const basisCommit = await commitFromHash(basisHash, dagRead);
1134
+ return getMutationID(clientID, dagRead, basisCommit.meta);
1135
+ }
1136
+ default:
1137
+ unreachable(meta);
1138
+ }
1139
+ }
1140
+ async function localMutations(fromCommitHash, dagRead) {
1141
+ const commits = await commitChain(fromCommitHash, dagRead);
1142
+ return commits.filter((c) => commitIsLocal(c));
1143
+ }
1144
+ async function localMutationsDD31(fromCommitHash, dagRead) {
1145
+ const commits = await commitChain(fromCommitHash, dagRead);
1146
+ return commits.filter((c) => commitIsLocalDD31(c));
1147
+ }
1148
+ async function localMutationsGreaterThan(commit, mutationIDLimits, dagRead) {
1149
+ const commits = [];
1150
+ const remainingMutationIDLimits = new Map(Object.entries(mutationIDLimits));
1151
+ while (!commitIsSnapshot(commit) && remainingMutationIDLimits.size > 0) {
1152
+ if (commitIsLocalDD31(commit)) {
1153
+ const { meta } = commit;
1154
+ const mutationIDLowerLimit = remainingMutationIDLimits.get(meta.clientID);
1155
+ if (mutationIDLowerLimit !== void 0) {
1156
+ if (meta.mutationID <= mutationIDLowerLimit) {
1157
+ remainingMutationIDLimits.delete(meta.clientID);
1158
+ } else {
1159
+ commits.push(commit);
1160
+ }
1161
+ }
1162
+ }
1163
+ const { basisHash } = commit.meta;
1164
+ if (basisHash === null) {
1165
+ throw new Error(`Commit ${commit.chunk.hash} has no basis`);
1166
+ }
1167
+ commit = await commitFromHash(basisHash, dagRead);
1168
+ }
1169
+ return commits;
1170
+ }
1171
+ async function baseSnapshotFromHead(name, dagRead) {
1172
+ const hash = await dagRead.getHead(name);
1173
+ assert(hash, `Missing head ${name}`);
1174
+ return baseSnapshotFromHash(hash, dagRead);
1175
+ }
1176
+ async function baseSnapshotHashFromHash(hash, dagRead) {
1177
+ return (await baseSnapshotFromHash(hash, dagRead)).chunk.hash;
1178
+ }
1179
+ async function baseSnapshotFromHash(hash, dagRead) {
1180
+ const commit = await commitFromHash(hash, dagRead);
1181
+ return baseSnapshotFromCommit(commit, dagRead);
1182
+ }
1183
+ async function baseSnapshotFromCommit(commit, dagRead) {
1184
+ while (!commitIsSnapshot(commit)) {
1185
+ const { meta } = commit;
1186
+ if (isLocalMetaDD31(meta)) {
1187
+ commit = await commitFromHash(meta.baseSnapshotHash, dagRead);
1188
+ } else {
1189
+ const { basisHash } = meta;
1190
+ if (basisHash === null) {
1191
+ throw new Error(`Commit ${commit.chunk.hash} has no basis`);
1192
+ }
1193
+ commit = await commitFromHash(basisHash, dagRead);
1194
+ }
1195
+ }
1196
+ return commit;
1197
+ }
1198
+ function snapshotMetaParts(c, clientID) {
1199
+ const m = c.meta;
1200
+ const lmid = m.lastMutationIDs[clientID] ?? 0;
1201
+ return [lmid, m.cookieJSON];
1202
+ }
1203
+ function compareCookiesForSnapshots(a, b) {
1204
+ return compareCookies(a.meta.cookieJSON, b.meta.cookieJSON);
1205
+ }
1206
+ async function commitChain(fromCommitHash, dagRead) {
1207
+ let commit = await commitFromHash(fromCommitHash, dagRead);
1208
+ const commits = [];
1209
+ while (!commitIsSnapshot(commit)) {
1210
+ const { meta } = commit;
1211
+ const { basisHash } = meta;
1212
+ if (basisHash === null) {
1213
+ throw new Error(`Commit ${commit.chunk.hash} has no basis`);
1214
+ }
1215
+ commits.push(commit);
1216
+ commit = await commitFromHash(basisHash, dagRead);
1217
+ }
1218
+ commits.push(commit);
1219
+ return commits;
1220
+ }
1221
+ async function commitFromHash(hash, dagRead) {
1222
+ const chunk = await dagRead.mustGetChunk(hash);
1223
+ return fromChunk(chunk);
1224
+ }
1225
+ async function commitFromHead(name, dagRead) {
1226
+ const hash = await mustGetHeadHash(name, dagRead);
1227
+ return commitFromHash(hash, dagRead);
1228
+ }
1229
+ function assertLocalMetaDD31(v) {
1230
+ assertString(v.clientID);
1231
+ assertNumber(v.mutationID);
1232
+ assertString(v.mutatorName);
1233
+ if (!v.mutatorName) {
1234
+ throw new Error("Missing mutator name");
1235
+ }
1236
+ assertJSONValue(v.mutatorArgsJSON);
1237
+ if (v.originalHash !== null) {
1238
+ assertHash(v.originalHash);
1239
+ }
1240
+ assertNumber(v.timestamp);
1241
+ }
1242
+ function isLocalMetaDD31(meta) {
1243
+ return meta.type === LocalDD31;
1244
+ }
1245
+ function assertSnapshotMetaDD31(v) {
1246
+ if (v.basisHash !== null) {
1247
+ assertHash(v.basisHash);
1248
+ }
1249
+ assertJSONValue(v.cookieJSON);
1250
+ assertLastMutationIDs(v.lastMutationIDs);
1251
+ }
1252
+ function assertLastMutationIDs(v) {
1253
+ assertObject(v);
1254
+ for (const e of Object.values(v)) {
1255
+ assertNumber(e);
1256
+ }
1257
+ }
1258
+ function assertSnapshotCommitDD31(c) {
1259
+ assertSnapshotMetaDD31(c.meta);
1260
+ }
1261
+ function isSnapshotMetaDD31(meta) {
1262
+ return meta.type === SnapshotDD31;
1263
+ }
1264
+ function assertMeta(v) {
1265
+ assertObject(v);
1266
+ assertDeepFrozen(v);
1267
+ if (v.basisHash !== null) {
1268
+ assertString(v.basisHash);
1269
+ }
1270
+ assertNumber(v.type);
1271
+ switch (v.type) {
1272
+ case LocalDD31:
1273
+ assertLocalMetaDD31(v);
1274
+ break;
1275
+ case SnapshotDD31:
1276
+ assertSnapshotMetaDD31(v);
1277
+ break;
1278
+ default:
1279
+ throw new Error(`Invalid enum value ${v.type}`);
1280
+ }
1281
+ }
1282
+ function chunkIndexDefinitionEqualIgnoreName(a, b) {
1283
+ return a.jsonPointer === b.jsonPointer && (a.allowEmpty ?? false) === (b.allowEmpty ?? false) && a.keyPrefix === b.keyPrefix;
1284
+ }
1285
+ function assertChunkIndexDefinition(v) {
1286
+ assertObject(v);
1287
+ assertDeepFrozen(v);
1288
+ assertString(v.name);
1289
+ assertString(v.keyPrefix);
1290
+ assertString(v.jsonPointer);
1291
+ if (v.allowEmpty !== void 0) {
1292
+ assertBoolean(v.allowEmpty);
1293
+ }
1294
+ }
1295
+ function toChunkIndexDefinition(name, indexDefinition) {
1296
+ return {
1297
+ name,
1298
+ keyPrefix: indexDefinition.prefix ?? "",
1299
+ jsonPointer: indexDefinition.jsonPointer,
1300
+ allowEmpty: indexDefinition.allowEmpty ?? false
1301
+ };
1302
+ }
1303
+ function assertIndexRecord(v) {
1304
+ assertObject(v);
1305
+ assertDeepFrozen(v);
1306
+ assertChunkIndexDefinition(v.definition);
1307
+ assertString(v.valueHash);
1308
+ }
1309
+ function assertIndexRecords(v) {
1310
+ assertArray(v);
1311
+ assertDeepFrozen(v);
1312
+ for (const ir of v) {
1313
+ assertIndexRecord(ir);
1314
+ }
1315
+ }
1316
+ function newLocalDD31(createChunk2, basisHash, baseSnapshotHash, mutationID, mutatorName, mutatorArgsJSON, originalHash, valueHash, indexes, timestamp, clientID) {
1317
+ const meta = {
1318
+ type: LocalDD31,
1319
+ basisHash,
1320
+ baseSnapshotHash,
1321
+ mutationID,
1322
+ mutatorName,
1323
+ mutatorArgsJSON,
1324
+ originalHash,
1325
+ timestamp,
1326
+ clientID
1327
+ };
1328
+ return commitFromCommitData(
1329
+ createChunk2,
1330
+ makeCommitData(meta, valueHash, indexes)
1331
+ );
1332
+ }
1333
+ function newSnapshotDD31(createChunk2, basisHash, lastMutationIDs, cookieJSON, valueHash, indexes) {
1334
+ return commitFromCommitData(
1335
+ createChunk2,
1336
+ newSnapshotCommitDataDD31(
1337
+ basisHash,
1338
+ lastMutationIDs,
1339
+ cookieJSON,
1340
+ valueHash,
1341
+ indexes
1342
+ )
1343
+ );
1344
+ }
1345
+ function newSnapshotCommitDataDD31(basisHash, lastMutationIDs, cookieJSON, valueHash, indexes) {
1346
+ const meta = {
1347
+ type: SnapshotDD31,
1348
+ basisHash,
1349
+ lastMutationIDs,
1350
+ cookieJSON
1351
+ };
1352
+ return makeCommitData(meta, valueHash, indexes);
1353
+ }
1354
+ function fromChunk(chunk) {
1355
+ validateChunk(chunk);
1356
+ return new Commit(chunk);
1357
+ }
1358
+ function commitFromCommitData(createChunk2, data) {
1359
+ return new Commit(createChunk2(data, getRefs(data)));
1360
+ }
1361
+ function getRefs(data) {
1362
+ const refs = /* @__PURE__ */ new Set();
1363
+ refs.add(data.valueHash);
1364
+ const { meta } = data;
1365
+ switch (meta.type) {
1366
+ case LocalDD31:
1367
+ meta.basisHash && refs.add(meta.basisHash);
1368
+ break;
1369
+ case SnapshotDD31:
1370
+ break;
1371
+ default:
1372
+ unreachable(meta);
1373
+ }
1374
+ for (const index of data.indexes) {
1375
+ refs.add(index.valueHash);
1376
+ }
1377
+ return toRefs(refs);
1378
+ }
1379
+ function makeCommitData(meta, valueHash, indexes) {
1380
+ return deepFreeze({
1381
+ meta,
1382
+ valueHash,
1383
+ indexes
1384
+ });
1385
+ }
1386
+ function assertCommitData(v) {
1387
+ if (isProd) {
1388
+ return;
1389
+ }
1390
+ assertObject(v);
1391
+ assertDeepFrozen(v);
1392
+ assertMeta(v.meta);
1393
+ assertString(v.valueHash);
1394
+ assertIndexRecords(v.indexes);
1395
+ }
1396
+ function validateChunk(chunk) {
1397
+ const { data } = chunk;
1398
+ assertCommitData(data);
1399
+ const seen = /* @__PURE__ */ new Set();
1400
+ for (const index of data.indexes) {
1401
+ const { name } = index.definition;
1402
+ if (seen.has(name)) {
1403
+ throw new Error(`Duplicate index ${name}`);
1404
+ }
1405
+ seen.add(name);
1406
+ }
1407
+ }
1408
+
1409
+ // ../replicache/src/db/index-operation-enum.ts
1410
+ var Add = 0;
1411
+ var Remove = 1;
1412
+
1413
+ // ../replicache/src/db/index.ts
1414
+ var IndexRead = class {
1415
+ meta;
1416
+ map;
1417
+ constructor(meta, map) {
1418
+ this.meta = meta;
1419
+ this.map = map;
1420
+ }
1421
+ };
1422
+ var IndexWrite = class extends IndexRead {
1423
+ // Note: does not update self.meta.valueHash (doesn't need to at this point as flush
1424
+ // is only called during commit.)
1425
+ flush() {
1426
+ return this.map.flush();
1427
+ }
1428
+ clear() {
1429
+ return this.map.clear();
1430
+ }
1431
+ };
1432
+ async function indexValue(lc, index, op, key, val, jsonPointer, allowEmpty) {
1433
+ try {
1434
+ for (const entry of getIndexKeys(key, val, jsonPointer, allowEmpty)) {
1435
+ switch (op) {
1436
+ case Add:
1437
+ await index.put(entry, val);
1438
+ break;
1439
+ case Remove:
1440
+ await index.del(entry);
1441
+ break;
1442
+ }
1443
+ }
1444
+ } catch (e) {
1445
+ lc.info?.("Not indexing value", val, ":", e);
1446
+ }
1447
+ }
1448
+ function getIndexKeys(primary, value, jsonPointer, allowEmpty) {
1449
+ const target = evaluateJSONPointer(value, jsonPointer);
1450
+ if (target === void 0) {
1451
+ if (allowEmpty) {
1452
+ return [];
1453
+ }
1454
+ throw new Error(`No value at path: ${jsonPointer}`);
1455
+ }
1456
+ const values = Array.isArray(target) ? target : [target];
1457
+ const indexKeys = [];
1458
+ for (const value2 of values) {
1459
+ if (typeof value2 === "string") {
1460
+ indexKeys.push(encodeIndexKey([value2, primary]));
1461
+ } else {
1462
+ throw new Error("Unsupported target type");
1463
+ }
1464
+ }
1465
+ return indexKeys;
1466
+ }
1467
+ var KEY_VERSION_0 = "\0";
1468
+ var KEY_SEPARATOR = "\0";
1469
+ function encodeIndexKey(indexKey) {
1470
+ const secondary = indexKey[0];
1471
+ const primary = indexKey[1];
1472
+ if (secondary.includes("\0")) {
1473
+ throw new Error("Secondary key cannot contain null byte");
1474
+ }
1475
+ return KEY_VERSION_0 + secondary + KEY_SEPARATOR + primary;
1476
+ }
1477
+ function encodeIndexScanKey(secondary, primary) {
1478
+ const k = encodeIndexKey([secondary, primary || ""]);
1479
+ if (primary === void 0) {
1480
+ return k.slice(0, k.length - 1);
1481
+ }
1482
+ return k;
1483
+ }
1484
+ function decodeIndexKey(encodedIndexKey) {
1485
+ if (encodedIndexKey[0] !== KEY_VERSION_0) {
1486
+ throw new Error("Invalid version");
1487
+ }
1488
+ const versionLen = KEY_VERSION_0.length;
1489
+ const separatorLen = KEY_SEPARATOR.length;
1490
+ const separatorOffset = encodedIndexKey.indexOf(KEY_SEPARATOR, versionLen);
1491
+ if (separatorOffset === -1) {
1492
+ throw new Error("Invalid formatting");
1493
+ }
1494
+ const secondary = encodedIndexKey.slice(versionLen, separatorOffset);
1495
+ const primary = encodedIndexKey.slice(separatorOffset + separatorLen);
1496
+ return [secondary, primary];
1497
+ }
1498
+ function evaluateJSONPointer(value, pointer) {
1499
+ function parseIndex(s) {
1500
+ if (s.startsWith("+") || s.startsWith("0") && s.length !== 1) {
1501
+ return void 0;
1502
+ }
1503
+ return parseInt(s, 10);
1504
+ }
1505
+ if (pointer === "") {
1506
+ return value;
1507
+ }
1508
+ if (!pointer.startsWith("/")) {
1509
+ throw new Error(`Invalid JSON pointer: ${pointer}`);
1510
+ }
1511
+ const tokens = pointer.split("/").slice(1).map((x) => x.replace(/~1/g, "/").replace(/~0/g, "~"));
1512
+ let target = value;
1513
+ for (const token of tokens) {
1514
+ let targetOpt;
1515
+ if (Array.isArray(target)) {
1516
+ const i = parseIndex(token);
1517
+ if (i === void 0) {
1518
+ return void 0;
1519
+ }
1520
+ targetOpt = target[i];
1521
+ } else if (target === null) {
1522
+ return void 0;
1523
+ } else if (typeof target === "object") {
1524
+ target = target;
1525
+ targetOpt = target[token];
1526
+ }
1527
+ if (targetOpt === void 0) {
1528
+ return void 0;
1529
+ }
1530
+ target = targetOpt;
1531
+ }
1532
+ return target;
1533
+ }
1534
+
1535
+ // ../replicache/src/db/read.ts
1536
+ var Read = class {
1537
+ #dagRead;
1538
+ map;
1539
+ indexes;
1540
+ constructor(dagRead, map, indexes) {
1541
+ this.#dagRead = dagRead;
1542
+ this.map = map;
1543
+ this.indexes = indexes;
1544
+ }
1545
+ has(key) {
1546
+ return this.map.has(key);
1547
+ }
1548
+ get(key) {
1549
+ return this.map.get(key);
1550
+ }
1551
+ isEmpty() {
1552
+ return this.map.isEmpty();
1553
+ }
1554
+ getMapForIndex(indexName) {
1555
+ const idx = this.indexes.get(indexName);
1556
+ if (idx === void 0) {
1557
+ throw new Error(`Unknown index name: ${indexName}`);
1558
+ }
1559
+ return idx.map;
1560
+ }
1561
+ get closed() {
1562
+ return this.#dagRead.closed;
1563
+ }
1564
+ close() {
1565
+ this.#dagRead.release();
1566
+ }
1567
+ };
1568
+ function readFromDefaultHead(dagRead, formatVersion) {
1569
+ return readFromHead(DEFAULT_HEAD_NAME, dagRead, formatVersion);
1570
+ }
1571
+ async function readFromHead(name, dagRead, formatVersion) {
1572
+ const commit = await commitFromHead(name, dagRead);
1573
+ return readFromCommit(commit, dagRead, formatVersion);
1574
+ }
1575
+ async function readFromHash(hash, dagRead, formatVersion) {
1576
+ const commit = await commitFromHash(hash, dagRead);
1577
+ return readFromCommit(commit, dagRead, formatVersion);
1578
+ }
1579
+ function readFromCommit(commit, dagRead, formatVersion) {
1580
+ const indexes = readIndexesForRead(commit, dagRead, formatVersion);
1581
+ const map = new BTreeRead(dagRead, formatVersion, commit.valueHash);
1582
+ return new Read(dagRead, map, indexes);
1583
+ }
1584
+ function readIndexesForRead(commit, dagRead, formatVersion) {
1585
+ const m = /* @__PURE__ */ new Map();
1586
+ for (const index of commit.indexes) {
1587
+ m.set(
1588
+ index.definition.name,
1589
+ new IndexRead(
1590
+ index,
1591
+ new BTreeRead(dagRead, formatVersion, index.valueHash)
1592
+ )
1593
+ );
1594
+ }
1595
+ return m;
1596
+ }
1597
+
1598
+ // ../replicache/src/index-defs.ts
1599
+ var indexDefinitionSchema = readonlyObject({
1600
+ prefix: valita_exports.string().optional(),
1601
+ jsonPointer: valita_exports.string(),
1602
+ allowEmpty: valita_exports.boolean().optional()
1603
+ });
1604
+ var indexDefinitionsSchema = readonlyRecord(
1605
+ indexDefinitionSchema
1606
+ );
1607
+ function indexDefinitionEqual(a, b) {
1608
+ return a.jsonPointer === b.jsonPointer && (a.allowEmpty ?? false) === (b.allowEmpty ?? false) && (a.prefix ?? "") === (b.prefix ?? "");
1609
+ }
1610
+ function indexDefinitionsEqual(a, b) {
1611
+ if (Object.keys(a).length !== Object.keys(b).length) {
1612
+ return false;
1613
+ }
1614
+ for (const [aKey, aValue] of Object.entries(a)) {
1615
+ const bValue = b[aKey];
1616
+ if (!bValue || !indexDefinitionEqual(aValue, bValue)) {
1617
+ return false;
1618
+ }
1619
+ }
1620
+ return true;
1621
+ }
1622
+
1623
+ // ../replicache/src/persist/client-groups.ts
1624
+ var clientGroupSchema = readonlyObject({
1625
+ /**
1626
+ * The hash of the commit in the perdag last persisted to this client group.
1627
+ * Should only be updated by clients assigned to this client group.
1628
+ */
1629
+ headHash: hashSchema,
1630
+ /**
1631
+ * Set of mutator names common to all clients assigned to this client group.
1632
+ */
1633
+ mutatorNames: readonlyArray(valita_exports.string()),
1634
+ /**
1635
+ * Index definitions common to all clients assigned to this client group.
1636
+ */
1637
+ indexes: indexDefinitionsSchema,
1638
+ /**
1639
+ * The highest mutation ID of every client assigned to this client group.
1640
+ * Should only be updated by clients assigned to this client group. Read by
1641
+ * other clients to determine if there are unacknowledged pending mutations
1642
+ * for them to try to recover. This is redundant with information in the
1643
+ * commit graph at `headHash`, but allows other clients to determine if there
1644
+ * are unacknowledged pending mutations without having to load the commit
1645
+ * graph.
1646
+ */
1647
+ mutationIDs: readonlyRecord(valita_exports.number()),
1648
+ /**
1649
+ * The highest lastMutationID received from the server for every client
1650
+ * assigned to this client group.
1651
+ *
1652
+ * Should be updated by the clients assigned to this client group whenever
1653
+ * they persist to this client group. Read by other clients to determine if
1654
+ * there are unacknowledged pending mutations for them to recover and
1655
+ * *updated* by other clients upon successfully recovering pending mutations
1656
+ * to avoid redundant pushes of pending mutations.
1657
+ *
1658
+ * Note: This will be the same as the `lastMutationIDs` of the base snapshot
1659
+ * of the client group's commit graph when written by clients assigned to this
1660
+ * client group. However, when written by another client recovering mutations
1661
+ * it may be different because the other client does not update the commit
1662
+ * graph.
1663
+ */
1664
+ lastServerAckdMutationIDs: valita_exports.record(valita_exports.number()),
1665
+ /**
1666
+ * If the server deletes this client group it can signal that the client group
1667
+ * was deleted. If that happens we mark this client group as disabled so that
1668
+ * we do not use it again when creating new clients.
1669
+ */
1670
+ disabled: valita_exports.boolean()
1671
+ });
1672
+ var CLIENT_GROUPS_HEAD_NAME = "client-groups";
1673
+ function assertClientGroup(value) {
1674
+ assert2(value, clientGroupSchema);
1675
+ }
1676
+ function chunkDataToClientGroupMap(chunkData) {
1677
+ assertObject(chunkData);
1678
+ const clientGroups = /* @__PURE__ */ new Map();
1679
+ for (const [key, value] of Object.entries(chunkData)) {
1680
+ if (value !== void 0) {
1681
+ assertClientGroup(value);
1682
+ clientGroups.set(key, value);
1683
+ }
1684
+ }
1685
+ return clientGroups;
1686
+ }
1687
+ function clientGroupMapToChunkData(clientGroups, dagWrite) {
1688
+ const chunkData = {};
1689
+ for (const [clientGroupID, clientGroup] of clientGroups.entries()) {
1690
+ dagWrite.assertValidHash(clientGroup.headHash);
1691
+ chunkData[clientGroupID] = {
1692
+ ...clientGroup,
1693
+ mutatorNames: [...clientGroup.mutatorNames.values()]
1694
+ };
1695
+ }
1696
+ return deepFreeze(chunkData);
1697
+ }
1698
+ async function getClientGroupsAtHash(hash, dagRead) {
1699
+ const chunk = await dagRead.getChunk(hash);
1700
+ return chunkDataToClientGroupMap(chunk?.data);
1701
+ }
1702
+ async function getClientGroups(dagRead) {
1703
+ const hash = await dagRead.getHead(CLIENT_GROUPS_HEAD_NAME);
1704
+ if (!hash) {
1705
+ return /* @__PURE__ */ new Map();
1706
+ }
1707
+ return getClientGroupsAtHash(hash, dagRead);
1708
+ }
1709
+ async function setClientGroups(clientGroups, dagWrite) {
1710
+ const currClientGroups = await getClientGroups(dagWrite);
1711
+ for (const [clientGroupID, clientGroup] of clientGroups) {
1712
+ const currClientGroup = currClientGroups.get(clientGroupID);
1713
+ validateClientGroupUpdate(clientGroup, currClientGroup);
1714
+ }
1715
+ return setValidatedClientGroups(clientGroups, dagWrite);
1716
+ }
1717
+ async function setClientGroup(clientGroupID, clientGroup, dagWrite) {
1718
+ const currClientGroups = await getClientGroups(dagWrite);
1719
+ const currClientGroup = currClientGroups.get(clientGroupID);
1720
+ validateClientGroupUpdate(clientGroup, currClientGroup);
1721
+ const newClientGroups = new Map(currClientGroups);
1722
+ newClientGroups.set(clientGroupID, clientGroup);
1723
+ return setValidatedClientGroups(newClientGroups, dagWrite);
1724
+ }
1725
+ function validateClientGroupUpdate(clientGroup, currClientGroup) {
1726
+ const mutatorNamesSet = new Set(clientGroup.mutatorNames);
1727
+ assert(
1728
+ mutatorNamesSet.size === clientGroup.mutatorNames.length,
1729
+ "A client group's mutatorNames must be a set."
1730
+ );
1731
+ if (currClientGroup !== void 0) {
1732
+ assert(
1733
+ indexDefinitionsEqual(currClientGroup.indexes, clientGroup.indexes),
1734
+ "A client group's index definitions must never change."
1735
+ );
1736
+ assert(
1737
+ mutatorNamesEqual(mutatorNamesSet, currClientGroup.mutatorNames),
1738
+ "A client group's mutatorNames must never change."
1739
+ );
1740
+ }
1741
+ }
1742
+ async function setValidatedClientGroups(clientGroups, dagWrite) {
1743
+ const chunkData = clientGroupMapToChunkData(clientGroups, dagWrite);
1744
+ const refs = /* @__PURE__ */ new Set();
1745
+ for (const clientGroup of clientGroups.values()) {
1746
+ refs.add(clientGroup.headHash);
1747
+ }
1748
+ const chunk = dagWrite.createChunk(chunkData, toRefs(refs));
1749
+ await dagWrite.putChunk(chunk);
1750
+ await dagWrite.setHead(CLIENT_GROUPS_HEAD_NAME, chunk.hash);
1751
+ return clientGroups;
1752
+ }
1753
+ function mutatorNamesEqual(mutatorNamesSet, mutatorNames) {
1754
+ if (mutatorNames.length !== mutatorNamesSet.size) {
1755
+ return false;
1756
+ }
1757
+ for (const mutatorName of mutatorNames) {
1758
+ if (!mutatorNamesSet.has(mutatorName)) {
1759
+ return false;
1760
+ }
1761
+ }
1762
+ return true;
1763
+ }
1764
+ async function getClientGroup(id, dagRead) {
1765
+ const clientGroups = await getClientGroups(dagRead);
1766
+ return clientGroups.get(id);
1767
+ }
1768
+ function clientGroupHasPendingMutations(clientGroup) {
1769
+ for (const [clientID, mutationID] of Object.entries(
1770
+ clientGroup.mutationIDs
1771
+ )) {
1772
+ const lastServerAckdMutationID = clientGroup.lastServerAckdMutationIDs[clientID];
1773
+ if (lastServerAckdMutationID === void 0 && mutationID !== 0 || lastServerAckdMutationID < mutationID) {
1774
+ return true;
1775
+ }
1776
+ }
1777
+ return false;
1778
+ }
1779
+ async function disableClientGroup(clientGroupID, dagWrite) {
1780
+ const clientGroup = await getClientGroup(clientGroupID, dagWrite);
1781
+ if (!clientGroup) {
1782
+ return;
1783
+ }
1784
+ const disabledClientGroup = {
1785
+ ...clientGroup,
1786
+ disabled: true
1787
+ };
1788
+ await setClientGroup(clientGroupID, disabledClientGroup, dagWrite);
1789
+ }
1790
+
1791
+ // ../replicache/src/with-transactions.ts
1792
+ function withRead(store, fn) {
1793
+ return using(store.read(), fn);
1794
+ }
1795
+ function withWriteNoImplicitCommit(store, fn) {
1796
+ return using(store.write(), fn);
1797
+ }
1798
+ function withWrite(store, fn) {
1799
+ return using(store.write(), async (write) => {
1800
+ const result = await fn(write);
1801
+ await write.commit();
1802
+ return result;
1803
+ });
1804
+ }
1805
+ async function using(x, fn) {
1806
+ const write = await x;
1807
+ try {
1808
+ return await fn(write);
1809
+ } finally {
1810
+ write.release();
1811
+ }
1812
+ }
1813
+
1814
+ // ../replicache/src/async-iterable-to-array.ts
1815
+ async function asyncIterableToArray(it) {
1816
+ const arr = [];
1817
+ for await (const v of it) {
1818
+ arr.push(v);
1819
+ }
1820
+ return arr;
1821
+ }
1822
+
1823
+ // ../replicache/src/btree/diff.ts
1824
+ function diff(oldMap, newMap) {
1825
+ return asyncIterableToArray(newMap.diff(oldMap));
1826
+ }
1827
+
1828
+ // ../replicache/src/btree/write.ts
1829
+ import { Lock } from "@rocicorp/lock";
1830
+ var BTreeWrite = class extends BTreeRead {
1831
+ /**
1832
+ * This rw lock is used to ensure we do not mutate the btree in parallel. It
1833
+ * would be a problem if we didn't have the lock in cases like this:
1834
+ *
1835
+ * ```ts
1836
+ * const p1 = tree.put('a', 0);
1837
+ * const p2 = tree.put('b', 1);
1838
+ * await p1;
1839
+ * await p2;
1840
+ * ```
1841
+ *
1842
+ * because both `p1` and `p2` would start from the old root hash but a put
1843
+ * changes the root hash so the two concurrent puts would lead to only one of
1844
+ * them actually working, and it is not deterministic which one would finish
1845
+ * last.
1846
+ */
1847
+ #lock = new Lock();
1848
+ #modified = /* @__PURE__ */ new Map();
1849
+ minSize;
1850
+ maxSize;
1851
+ constructor(dagWrite, formatVersion, root = emptyHash, minSize = 8 * 1024, maxSize = 16 * 1024, getEntrySize = getSizeOfEntry, chunkHeaderSize) {
1852
+ super(dagWrite, formatVersion, root, getEntrySize, chunkHeaderSize);
1853
+ this.minSize = minSize;
1854
+ this.maxSize = maxSize;
1855
+ }
1856
+ #addToModified(node) {
1857
+ assert(node.isMutable);
1858
+ this.#modified.set(node.hash, node);
1859
+ this._cache.set(node.hash, node);
1860
+ }
1861
+ updateNode(node) {
1862
+ assert(node.isMutable);
1863
+ this.#modified.delete(node.hash);
1864
+ node.hash = newRandomHash();
1865
+ this.#addToModified(node);
1866
+ }
1867
+ newInternalNodeImpl(entries, level) {
1868
+ const n = new InternalNodeImpl(entries, newRandomHash(), level, true);
1869
+ this.#addToModified(n);
1870
+ return n;
1871
+ }
1872
+ newDataNodeImpl(entries) {
1873
+ const n = new DataNodeImpl(entries, newRandomHash(), true);
1874
+ this.#addToModified(n);
1875
+ return n;
1876
+ }
1877
+ newNodeImpl(entries, level) {
1878
+ const n = newNodeImpl(entries, newRandomHash(), level, true);
1879
+ this.#addToModified(n);
1880
+ return n;
1881
+ }
1882
+ put(key, value) {
1883
+ return this.#lock.withLock(async () => {
1884
+ const oldRootNode = await this.getNode(this.rootHash);
1885
+ const entrySize = this.getEntrySize(key, value);
1886
+ const rootNode = await oldRootNode.set(key, value, entrySize, this);
1887
+ if (rootNode.getChildNodeSize(this) > this.maxSize) {
1888
+ const headerSize = this.chunkHeaderSize;
1889
+ const partitions = partition(
1890
+ rootNode.entries,
1891
+ (value2) => value2[2],
1892
+ this.minSize - headerSize,
1893
+ this.maxSize - headerSize
1894
+ );
1895
+ const { level } = rootNode;
1896
+ const entries = partitions.map((entries2) => {
1897
+ const node = this.newNodeImpl(entries2, level);
1898
+ return createNewInternalEntryForNode(node, this.getEntrySize);
1899
+ });
1900
+ const newRoot = this.newInternalNodeImpl(entries, level + 1);
1901
+ this.rootHash = newRoot.hash;
1902
+ return;
1903
+ }
1904
+ this.rootHash = rootNode.hash;
1905
+ });
1906
+ }
1907
+ del(key) {
1908
+ return this.#lock.withLock(async () => {
1909
+ const oldRootNode = await this.getNode(this.rootHash);
1910
+ const newRootNode = await oldRootNode.del(key, this);
1911
+ const found = this.rootHash !== newRootNode.hash;
1912
+ if (found) {
1913
+ if (newRootNode.level > 0 && newRootNode.entries.length === 1) {
1914
+ this.rootHash = newRootNode.entries[0][1];
1915
+ } else {
1916
+ this.rootHash = newRootNode.hash;
1917
+ }
1918
+ }
1919
+ return found;
1920
+ });
1921
+ }
1922
+ clear() {
1923
+ return this.#lock.withLock(() => {
1924
+ this.#modified.clear();
1925
+ this.rootHash = emptyHash;
1926
+ });
1927
+ }
1928
+ flush() {
1929
+ return this.#lock.withLock(async () => {
1930
+ const dagWrite = this._dagRead;
1931
+ if (this.rootHash === emptyHash) {
1932
+ const chunk = dagWrite.createChunk(emptyDataNode, []);
1933
+ await dagWrite.putChunk(chunk);
1934
+ return chunk.hash;
1935
+ }
1936
+ const newChunks = [];
1937
+ const newRoot = gatherNewChunks(
1938
+ this.rootHash,
1939
+ newChunks,
1940
+ dagWrite.createChunk,
1941
+ this.#modified,
1942
+ this._formatVersion
1943
+ );
1944
+ await Promise.all(newChunks.map((chunk) => dagWrite.putChunk(chunk)));
1945
+ this.#modified.clear();
1946
+ this.rootHash = newRoot;
1947
+ return newRoot;
1948
+ });
1949
+ }
1950
+ };
1951
+ function gatherNewChunks(hash, newChunks, createChunk2, modified, formatVersion) {
1952
+ const node = modified.get(hash);
1953
+ if (node === void 0) {
1954
+ return hash;
1955
+ }
1956
+ if (isDataNodeImpl(node)) {
1957
+ const chunk2 = createChunk2(toChunkData(node, formatVersion), []);
1958
+ newChunks.push(chunk2);
1959
+ return chunk2.hash;
1960
+ }
1961
+ const refs = [];
1962
+ const { entries } = node;
1963
+ for (let i = 0; i < entries.length; i++) {
1964
+ const entry = entries[i];
1965
+ const childHash = entry[1];
1966
+ const newChildHash = gatherNewChunks(
1967
+ childHash,
1968
+ newChunks,
1969
+ createChunk2,
1970
+ modified,
1971
+ formatVersion
1972
+ );
1973
+ if (newChildHash !== childHash) {
1974
+ entries[i] = [entry[0], newChildHash, entry[2]];
1975
+ }
1976
+ refs.push(newChildHash);
1977
+ }
1978
+ const chunk = createChunk2(toChunkData(node, formatVersion), toRefs(refs));
1979
+ newChunks.push(chunk);
1980
+ return chunk.hash;
1981
+ }
1982
+
1983
+ // ../replicache/src/lazy.ts
1984
+ function lazy(factory) {
1985
+ let value;
1986
+ return () => {
1987
+ if (value === void 0) {
1988
+ value = factory();
1989
+ }
1990
+ return value;
1991
+ };
1992
+ }
1993
+
1994
+ // ../replicache/src/sync/diff.ts
1995
+ var DiffsMap = class extends Map {
1996
+ set(key, value) {
1997
+ if (value.length === 0) {
1998
+ return this;
1999
+ }
2000
+ return super.set(key, value);
2001
+ }
2002
+ };
2003
+ async function diff2(oldHash, newHash, read, diffConfig, formatVersion) {
2004
+ const [oldCommit, newCommit] = await Promise.all([
2005
+ commitFromHash(oldHash, read),
2006
+ commitFromHash(newHash, read)
2007
+ ]);
2008
+ return diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion);
2009
+ }
2010
+ async function diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion) {
2011
+ const diffsMap = new DiffsMap();
2012
+ if (!diffConfig.shouldComputeDiffs()) {
2013
+ return diffsMap;
2014
+ }
2015
+ const oldMap = new BTreeRead(read, formatVersion, oldCommit.valueHash);
2016
+ const newMap = new BTreeRead(read, formatVersion, newCommit.valueHash);
2017
+ const valueDiff = await diff(oldMap, newMap);
2018
+ diffsMap.set("", valueDiff);
2019
+ await addDiffsForIndexes(
2020
+ oldCommit,
2021
+ newCommit,
2022
+ read,
2023
+ diffsMap,
2024
+ diffConfig,
2025
+ formatVersion
2026
+ );
2027
+ return diffsMap;
2028
+ }
2029
+ async function addDiffsForIndexes(mainCommit, syncCommit, read, diffsMap, diffConfig, formatVersion) {
2030
+ const oldIndexes = readIndexesForRead(mainCommit, read, formatVersion);
2031
+ const newIndexes = readIndexesForRead(syncCommit, read, formatVersion);
2032
+ for (const [oldIndexName, oldIndex] of oldIndexes) {
2033
+ if (!diffConfig.shouldComputeDiffsForIndex(oldIndexName)) {
2034
+ continue;
2035
+ }
2036
+ const newIndex = newIndexes.get(oldIndexName);
2037
+ if (newIndex !== void 0) {
2038
+ assert(newIndex !== oldIndex);
2039
+ const diffs = await diff(oldIndex.map, newIndex.map);
2040
+ newIndexes.delete(oldIndexName);
2041
+ diffsMap.set(oldIndexName, diffs);
2042
+ } else {
2043
+ const diffs = await allEntriesAsDiff(oldIndex.map, "del");
2044
+ diffsMap.set(oldIndexName, diffs);
2045
+ }
2046
+ }
2047
+ for (const [newIndexName, newIndex] of newIndexes) {
2048
+ if (!diffConfig.shouldComputeDiffsForIndex(newIndexName)) {
2049
+ continue;
2050
+ }
2051
+ const diffs = await allEntriesAsDiff(newIndex.map, "add");
2052
+ diffsMap.set(newIndexName, diffs);
2053
+ }
2054
+ }
2055
+
2056
+ // ../replicache/src/db/write.ts
2057
+ var Write = class extends Read {
2058
+ #dagWrite;
2059
+ #basis;
2060
+ #meta;
2061
+ #clientID;
2062
+ #formatVersion;
2063
+ constructor(dagWrite, map, basis, meta, indexes, clientID, formatVersion) {
2064
+ super(dagWrite, map, indexes);
2065
+ this.#dagWrite = dagWrite;
2066
+ this.#basis = basis;
2067
+ this.#meta = meta;
2068
+ this.#clientID = clientID;
2069
+ this.#formatVersion = formatVersion;
2070
+ if (basis === void 0) {
2071
+ assert(meta.basisHash === emptyHash);
2072
+ } else {
2073
+ assert(meta.basisHash === basis.chunk.hash);
2074
+ }
2075
+ }
2076
+ /**
2077
+ * The value needs to be frozen since it is kept in memory and used later for
2078
+ * comparison as well as returned in `get`.
2079
+ */
2080
+ async put(lc, key, value) {
2081
+ const oldVal = lazy(() => this.map.get(key));
2082
+ await updateIndexes(lc, this.indexes, key, oldVal, value);
2083
+ await this.map.put(key, value);
2084
+ }
2085
+ getMutationID() {
2086
+ return getMutationID(this.#clientID, this.#dagWrite, this.#meta);
2087
+ }
2088
+ async del(lc, key) {
2089
+ const oldVal = lazy(() => this.map.get(key));
2090
+ if (oldVal !== void 0) {
2091
+ await updateIndexes(lc, this.indexes, key, oldVal, void 0);
2092
+ }
2093
+ return this.map.del(key);
2094
+ }
2095
+ async clear() {
2096
+ await this.map.clear();
2097
+ const ps = [];
2098
+ for (const idx of this.indexes.values()) {
2099
+ ps.push(idx.clear());
2100
+ }
2101
+ await Promise.all(ps);
2102
+ }
2103
+ async putCommit() {
2104
+ const valueHash = await this.map.flush();
2105
+ const indexRecords = [];
2106
+ for (const index of this.indexes.values()) {
2107
+ const valueHash2 = await index.flush();
2108
+ const indexRecord = {
2109
+ definition: index.meta.definition,
2110
+ valueHash: valueHash2
2111
+ };
2112
+ indexRecords.push(indexRecord);
2113
+ }
2114
+ let commit;
2115
+ const meta = this.#meta;
2116
+ switch (meta.type) {
2117
+ case LocalDD31: {
2118
+ assert(this.#formatVersion >= DD31);
2119
+ const {
2120
+ basisHash,
2121
+ mutationID,
2122
+ mutatorName,
2123
+ mutatorArgsJSON,
2124
+ originalHash,
2125
+ timestamp
2126
+ } = meta;
2127
+ commit = newLocalDD31(
2128
+ this.#dagWrite.createChunk,
2129
+ basisHash,
2130
+ await baseSnapshotHashFromHash(basisHash, this.#dagWrite),
2131
+ mutationID,
2132
+ mutatorName,
2133
+ mutatorArgsJSON,
2134
+ originalHash,
2135
+ valueHash,
2136
+ indexRecords,
2137
+ timestamp,
2138
+ this.#clientID
2139
+ );
2140
+ break;
2141
+ }
2142
+ case SnapshotDD31: {
2143
+ assert(this.#formatVersion > DD31);
2144
+ const { basisHash, lastMutationIDs, cookieJSON } = meta;
2145
+ commit = newSnapshotDD31(
2146
+ this.#dagWrite.createChunk,
2147
+ basisHash,
2148
+ lastMutationIDs,
2149
+ cookieJSON,
2150
+ valueHash,
2151
+ indexRecords
2152
+ );
2153
+ break;
2154
+ }
2155
+ }
2156
+ await this.#dagWrite.putChunk(commit.chunk);
2157
+ return commit;
2158
+ }
2159
+ // Return value is the hash of the new commit.
2160
+ async commit(headName) {
2161
+ const commit = await this.putCommit();
2162
+ const commitHash = commit.chunk.hash;
2163
+ await this.#dagWrite.setHead(headName, commitHash);
2164
+ await this.#dagWrite.commit();
2165
+ return commitHash;
2166
+ }
2167
+ async commitWithDiffs(headName, diffConfig) {
2168
+ const commit = this.putCommit();
2169
+ const diffMap = await this.#generateDiffs(diffConfig);
2170
+ const commitHash = (await commit).chunk.hash;
2171
+ await this.#dagWrite.setHead(headName, commitHash);
2172
+ await this.#dagWrite.commit();
2173
+ return [commitHash, diffMap];
2174
+ }
2175
+ async #generateDiffs(diffConfig) {
2176
+ const diffsMap = new DiffsMap();
2177
+ if (!diffConfig.shouldComputeDiffs()) {
2178
+ return diffsMap;
2179
+ }
2180
+ let valueDiff = [];
2181
+ if (this.#basis) {
2182
+ const basisMap = new BTreeRead(
2183
+ this.#dagWrite,
2184
+ this.#formatVersion,
2185
+ this.#basis.valueHash
2186
+ );
2187
+ valueDiff = await diff(basisMap, this.map);
2188
+ }
2189
+ diffsMap.set("", valueDiff);
2190
+ let basisIndexes;
2191
+ if (this.#basis) {
2192
+ basisIndexes = readIndexesForRead(
2193
+ this.#basis,
2194
+ this.#dagWrite,
2195
+ this.#formatVersion
2196
+ );
2197
+ } else {
2198
+ basisIndexes = /* @__PURE__ */ new Map();
2199
+ }
2200
+ for (const [name, index] of this.indexes) {
2201
+ if (!diffConfig.shouldComputeDiffsForIndex(name)) {
2202
+ continue;
2203
+ }
2204
+ const basisIndex = basisIndexes.get(name);
2205
+ assert(index !== basisIndex);
2206
+ const indexDiffResult = await (basisIndex ? diff(basisIndex.map, index.map) : (
2207
+ // No basis. All keys are new.
2208
+ allEntriesAsDiff(index.map, "add")
2209
+ ));
2210
+ diffsMap.set(name, indexDiffResult);
2211
+ }
2212
+ for (const [name, basisIndex] of basisIndexes) {
2213
+ if (!this.indexes.has(name) && diffConfig.shouldComputeDiffsForIndex(name)) {
2214
+ const indexDiffResult = await allEntriesAsDiff(basisIndex.map, "del");
2215
+ diffsMap.set(name, indexDiffResult);
2216
+ }
2217
+ }
2218
+ return diffsMap;
2219
+ }
2220
+ close() {
2221
+ this.#dagWrite.release();
2222
+ }
2223
+ };
2224
+ async function newWriteLocal(basisHash, mutatorName, mutatorArgsJSON, originalHash, dagWrite, timestamp, clientID, formatVersion) {
2225
+ const basis = await commitFromHash(basisHash, dagWrite);
2226
+ const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);
2227
+ const mutationID = await basis.getNextMutationID(clientID, dagWrite);
2228
+ const indexes = readIndexesForWrite(basis, dagWrite, formatVersion);
2229
+ assert(formatVersion >= DD31);
2230
+ return new Write(
2231
+ dagWrite,
2232
+ bTreeWrite,
2233
+ basis,
2234
+ {
2235
+ type: LocalDD31,
2236
+ basisHash,
2237
+ baseSnapshotHash: await baseSnapshotHashFromHash(basisHash, dagWrite),
2238
+ mutatorName,
2239
+ mutatorArgsJSON,
2240
+ mutationID,
2241
+ originalHash,
2242
+ timestamp,
2243
+ clientID
2244
+ },
2245
+ indexes,
2246
+ clientID,
2247
+ formatVersion
2248
+ );
2249
+ }
2250
+ async function newWriteSnapshotDD31(basisHash, lastMutationIDs, cookieJSON, dagWrite, clientID, formatVersion) {
2251
+ const basis = await commitFromHash(basisHash, dagWrite);
2252
+ const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);
2253
+ return new Write(
2254
+ dagWrite,
2255
+ bTreeWrite,
2256
+ basis,
2257
+ { basisHash, type: SnapshotDD31, lastMutationIDs, cookieJSON },
2258
+ readIndexesForWrite(basis, dagWrite, formatVersion),
2259
+ clientID,
2260
+ formatVersion
2261
+ );
2262
+ }
2263
+ async function updateIndexes(lc, indexes, key, oldValGetter, newVal) {
2264
+ const ps = [];
2265
+ for (const idx of indexes.values()) {
2266
+ const { keyPrefix } = idx.meta.definition;
2267
+ if (!keyPrefix || key.startsWith(keyPrefix)) {
2268
+ const oldVal = await oldValGetter();
2269
+ if (oldVal !== void 0) {
2270
+ ps.push(
2271
+ indexValue(
2272
+ lc,
2273
+ idx.map,
2274
+ Remove,
2275
+ key,
2276
+ oldVal,
2277
+ idx.meta.definition.jsonPointer,
2278
+ idx.meta.definition.allowEmpty ?? false
2279
+ )
2280
+ );
2281
+ }
2282
+ if (newVal !== void 0) {
2283
+ ps.push(
2284
+ indexValue(
2285
+ lc,
2286
+ idx.map,
2287
+ Add,
2288
+ key,
2289
+ newVal,
2290
+ idx.meta.definition.jsonPointer,
2291
+ idx.meta.definition.allowEmpty ?? false
2292
+ )
2293
+ );
2294
+ }
2295
+ }
2296
+ }
2297
+ await Promise.all(ps);
2298
+ }
2299
+ function readIndexesForWrite(commit, dagWrite, formatVersion) {
2300
+ const m = /* @__PURE__ */ new Map();
2301
+ for (const index of commit.indexes) {
2302
+ m.set(
2303
+ index.definition.name,
2304
+ new IndexWrite(
2305
+ index,
2306
+ new BTreeWrite(dagWrite, formatVersion, index.valueHash)
2307
+ )
2308
+ );
2309
+ }
2310
+ return m;
2311
+ }
2312
+ async function createIndexBTree(lc, dagWrite, valueMap, prefix, jsonPointer, allowEmpty, formatVersion) {
2313
+ const indexMap = new BTreeWrite(dagWrite, formatVersion);
2314
+ for await (const entry of valueMap.scan(prefix)) {
2315
+ const key = entry[0];
2316
+ if (!key.startsWith(prefix)) {
2317
+ break;
2318
+ }
2319
+ await indexValue(
2320
+ lc,
2321
+ indexMap,
2322
+ Add,
2323
+ key,
2324
+ entry[1],
2325
+ jsonPointer,
2326
+ allowEmpty
2327
+ );
2328
+ }
2329
+ return indexMap;
2330
+ }
2331
+
2332
+ // ../replicache/src/sync/ids.ts
2333
+ var clientGroupIDSchema = valita_exports.string();
2334
+ var clientIDSchema = valita_exports.string();
2335
+
2336
+ // ../replicache/src/persist/make-client-id.ts
2337
+ function makeClientID() {
2338
+ const length = 18;
2339
+ const high = randomUint64();
2340
+ const low = randomUint64();
2341
+ const combined = high << 64n | low;
2342
+ return combined.toString(32).slice(-length).padStart(length, "0");
2343
+ }
2344
+
2345
+ // ../replicache/src/persist/clients.ts
2346
+ var clientV5Schema = readonlyObject({
2347
+ heartbeatTimestampMs: valita_exports.number(),
2348
+ headHash: hashSchema,
2349
+ /**
2350
+ * The hash of a commit we are in the middle of refreshing into this client's
2351
+ * memdag.
2352
+ */
2353
+ tempRefreshHash: hashSchema.nullable(),
2354
+ /**
2355
+ * ID of this client's perdag client group. This needs to be sent in pull
2356
+ * request (to enable syncing all last mutation ids in the client group).
2357
+ */
2358
+ clientGroupID: clientGroupIDSchema
2359
+ });
2360
+ var clientV6Schema = readonlyObject({
2361
+ heartbeatTimestampMs: valita_exports.number(),
2362
+ /**
2363
+ * A set of hashes, which contains:
2364
+ * 1. The hash of the last commit this client refreshed from its client group
2365
+ * (this is the commit it bootstrapped from until it completes its first
2366
+ * refresh).
2367
+ * 2. One or more hashes that were added to retain chunks of a commit while it
2368
+ * was being refreshed into this client's memdag. (This can be one or more
2369
+ * because refresh's cleanup step is a separate transaction and can fail).
2370
+ * Upon refresh completing and successfully running its clean up step, this
2371
+ * set will contain a single hash: the hash of the last commit this client
2372
+ * refreshed.
2373
+ */
2374
+ refreshHashes: readonlyArray(hashSchema),
2375
+ /**
2376
+ * The hash of the last snapshot commit persisted by this client to this
2377
+ * client's client group, or null if has never persisted a snapshot.
2378
+ */
2379
+ persistHash: hashSchema.nullable(),
2380
+ /**
2381
+ * ID of this client's perdag client group. This needs to be sent in pull
2382
+ * request (to enable syncing all last mutation ids in the client group).
2383
+ */
2384
+ clientGroupID: clientGroupIDSchema
2385
+ });
2386
+ function isClientV6(client) {
2387
+ return client.refreshHashes !== void 0;
2388
+ }
2389
+ var CLIENTS_HEAD_NAME = "clients";
2390
+ var clientSchema = valita_exports.union(clientV5Schema, clientV6Schema);
2391
+ function assertClient(value) {
2392
+ assert2(value, clientSchema);
2393
+ }
2394
+ function assertClientV6(value) {
2395
+ assert2(value, clientV6Schema);
2396
+ }
2397
+ function chunkDataToClientMap(chunkData) {
2398
+ assertObject(chunkData);
2399
+ const clients = /* @__PURE__ */ new Map();
2400
+ for (const key in chunkData) {
2401
+ if (hasOwn(chunkData, key)) {
2402
+ const value = chunkData[key];
2403
+ if (value !== void 0) {
2404
+ assertClient(value);
2405
+ clients.set(key, value);
2406
+ }
2407
+ }
2408
+ }
2409
+ return clients;
2410
+ }
2411
+ function clientMapToChunkData(clients, dagWrite) {
2412
+ for (const client of clients.values()) {
2413
+ if (isClientV6(client)) {
2414
+ client.refreshHashes.forEach(dagWrite.assertValidHash);
2415
+ if (client.persistHash) {
2416
+ dagWrite.assertValidHash(client.persistHash);
2417
+ }
2418
+ } else {
2419
+ dagWrite.assertValidHash(client.headHash);
2420
+ if (client.tempRefreshHash) {
2421
+ dagWrite.assertValidHash(client.tempRefreshHash);
2422
+ }
2423
+ }
2424
+ }
2425
+ return deepFreeze(Object.fromEntries(clients));
2426
+ }
2427
+ async function getClients(dagRead) {
2428
+ const hash = await dagRead.getHead(CLIENTS_HEAD_NAME);
2429
+ return getClientsAtHash(hash, dagRead);
2430
+ }
2431
+ async function getClientsAtHash(hash, dagRead) {
2432
+ if (!hash) {
2433
+ return /* @__PURE__ */ new Map();
2434
+ }
2435
+ const chunk = await dagRead.getChunk(hash);
2436
+ return chunkDataToClientMap(chunk?.data);
2437
+ }
2438
+ var ClientStateNotFoundError = class extends Error {
2439
+ name = "ClientStateNotFoundError";
2440
+ id;
2441
+ constructor(id) {
2442
+ super(`Client state not found, id: ${id}`);
2443
+ this.id = id;
2444
+ }
2445
+ };
2446
+ async function assertHasClientState(id, dagRead) {
2447
+ if (!await hasClientState(id, dagRead)) {
2448
+ throw new ClientStateNotFoundError(id);
2449
+ }
2450
+ }
2451
+ async function hasClientState(id, dagRead) {
2452
+ return !!await getClient(id, dagRead);
2453
+ }
2454
+ async function getClient(id, dagRead) {
2455
+ const clients = await getClients(dagRead);
2456
+ return clients.get(id);
2457
+ }
2458
+ async function mustGetClient(id, dagRead) {
2459
+ const client = await getClient(id, dagRead);
2460
+ if (!client) {
2461
+ throw new ClientStateNotFoundError(id);
2462
+ }
2463
+ return client;
2464
+ }
2465
+ function initClientV6(newClientID, lc, perdag, mutatorNames, indexes, formatVersion, enableClientGroupForking) {
2466
+ return withWrite(perdag, async (dagWrite) => {
2467
+ async function setClientsAndClientGroupAndCommit(basisHash, cookieJSON, valueHash2, indexRecords2) {
2468
+ const newSnapshotData = newSnapshotCommitDataDD31(
2469
+ basisHash,
2470
+ {},
2471
+ cookieJSON,
2472
+ valueHash2,
2473
+ indexRecords2
2474
+ );
2475
+ const chunk = dagWrite.createChunk(
2476
+ newSnapshotData,
2477
+ getRefs(newSnapshotData)
2478
+ );
2479
+ const newClientGroupID = makeClientID();
2480
+ const newClient = {
2481
+ heartbeatTimestampMs: Date.now(),
2482
+ refreshHashes: [chunk.hash],
2483
+ persistHash: null,
2484
+ clientGroupID: newClientGroupID
2485
+ };
2486
+ const newClients = new Map(clients).set(newClientID, newClient);
2487
+ const clientGroup = {
2488
+ headHash: chunk.hash,
2489
+ mutatorNames,
2490
+ indexes,
2491
+ mutationIDs: {},
2492
+ lastServerAckdMutationIDs: {},
2493
+ disabled: false
2494
+ };
2495
+ await Promise.all([
2496
+ dagWrite.putChunk(chunk),
2497
+ setClients(newClients, dagWrite),
2498
+ setClientGroup(newClientGroupID, clientGroup, dagWrite)
2499
+ ]);
2500
+ return [newClient, chunk.hash, newClients, true];
2501
+ }
2502
+ const clients = await getClients(dagWrite);
2503
+ const res = await findMatchingClient(dagWrite, mutatorNames, indexes);
2504
+ if (res.type === FIND_MATCHING_CLIENT_TYPE_HEAD) {
2505
+ const { clientGroupID, headHash } = res;
2506
+ const newClient = {
2507
+ clientGroupID,
2508
+ refreshHashes: [headHash],
2509
+ heartbeatTimestampMs: Date.now(),
2510
+ persistHash: null
2511
+ };
2512
+ const newClients = new Map(clients).set(newClientID, newClient);
2513
+ await setClients(newClients, dagWrite);
2514
+ return [newClient, headHash, newClients, false];
2515
+ }
2516
+ if (!enableClientGroupForking || res.type === FIND_MATCHING_CLIENT_TYPE_NEW) {
2517
+ const emptyBTreeChunk = dagWrite.createChunk(emptyDataNode, []);
2518
+ await dagWrite.putChunk(emptyBTreeChunk);
2519
+ const indexRecords2 = [];
2520
+ for (const [name, indexDefinition] of Object.entries(indexes)) {
2521
+ const chunkIndexDefinition = toChunkIndexDefinition(
2522
+ name,
2523
+ indexDefinition
2524
+ );
2525
+ indexRecords2.push({
2526
+ definition: chunkIndexDefinition,
2527
+ valueHash: emptyBTreeChunk.hash
2528
+ });
2529
+ }
2530
+ return setClientsAndClientGroupAndCommit(
2531
+ null,
2532
+ null,
2533
+ emptyBTreeChunk.hash,
2534
+ indexRecords2
2535
+ );
2536
+ }
2537
+ assert(res.type === FIND_MATCHING_CLIENT_TYPE_FORK);
2538
+ const { snapshot } = res;
2539
+ const indexRecords = [];
2540
+ const { valueHash, indexes: oldIndexes } = snapshot;
2541
+ const map = new BTreeRead(dagWrite, formatVersion, valueHash);
2542
+ for (const [name, indexDefinition] of Object.entries(indexes)) {
2543
+ const { prefix = "", jsonPointer, allowEmpty = false } = indexDefinition;
2544
+ const chunkIndexDefinition = {
2545
+ name,
2546
+ keyPrefix: prefix,
2547
+ jsonPointer,
2548
+ allowEmpty
2549
+ };
2550
+ const oldIndex = findMatchingOldIndex(oldIndexes, chunkIndexDefinition);
2551
+ if (oldIndex) {
2552
+ indexRecords.push({
2553
+ definition: chunkIndexDefinition,
2554
+ valueHash: oldIndex.valueHash
2555
+ });
2556
+ } else {
2557
+ const indexBTree = await createIndexBTree(
2558
+ lc,
2559
+ dagWrite,
2560
+ map,
2561
+ prefix,
2562
+ jsonPointer,
2563
+ allowEmpty,
2564
+ formatVersion
2565
+ );
2566
+ indexRecords.push({
2567
+ definition: chunkIndexDefinition,
2568
+ valueHash: await indexBTree.flush()
2569
+ });
2570
+ }
2571
+ }
2572
+ return setClientsAndClientGroupAndCommit(
2573
+ snapshot.meta.basisHash,
2574
+ snapshot.meta.cookieJSON,
2575
+ snapshot.valueHash,
2576
+ indexRecords
2577
+ );
2578
+ });
2579
+ }
2580
+ function findMatchingOldIndex(oldIndexes, chunkIndexDefinition) {
2581
+ return oldIndexes.find(
2582
+ (index) => chunkIndexDefinitionEqualIgnoreName(index.definition, chunkIndexDefinition)
2583
+ );
2584
+ }
2585
+ var FIND_MATCHING_CLIENT_TYPE_NEW = 0;
2586
+ var FIND_MATCHING_CLIENT_TYPE_FORK = 1;
2587
+ var FIND_MATCHING_CLIENT_TYPE_HEAD = 2;
2588
+ async function findMatchingClient(dagRead, mutatorNames, indexes) {
2589
+ let newestCookie;
2590
+ let bestSnapshot;
2591
+ const mutatorNamesSet = new Set(mutatorNames);
2592
+ const clientGroups = await getClientGroups(dagRead);
2593
+ for (const [clientGroupID, clientGroup] of clientGroups) {
2594
+ if (!clientGroup.disabled && mutatorNamesEqual(mutatorNamesSet, clientGroup.mutatorNames) && indexDefinitionsEqual(indexes, clientGroup.indexes)) {
2595
+ return {
2596
+ type: FIND_MATCHING_CLIENT_TYPE_HEAD,
2597
+ clientGroupID,
2598
+ headHash: clientGroup.headHash
2599
+ };
2600
+ }
2601
+ const clientGroupSnapshotCommit = await baseSnapshotFromHash(
2602
+ clientGroup.headHash,
2603
+ dagRead
2604
+ );
2605
+ assertSnapshotCommitDD31(clientGroupSnapshotCommit);
2606
+ const { cookieJSON } = clientGroupSnapshotCommit.meta;
2607
+ if (newestCookie === void 0 || compareCookies(cookieJSON, newestCookie) > 0) {
2608
+ newestCookie = cookieJSON;
2609
+ bestSnapshot = clientGroupSnapshotCommit;
2610
+ }
2611
+ }
2612
+ if (bestSnapshot) {
2613
+ return {
2614
+ type: FIND_MATCHING_CLIENT_TYPE_FORK,
2615
+ snapshot: bestSnapshot
2616
+ };
2617
+ }
2618
+ return { type: FIND_MATCHING_CLIENT_TYPE_NEW };
2619
+ }
2620
+ function getRefsForClients(clients) {
2621
+ const refs = /* @__PURE__ */ new Set();
2622
+ for (const client of clients.values()) {
2623
+ if (isClientV6(client)) {
2624
+ for (const hash of client.refreshHashes) {
2625
+ refs.add(hash);
2626
+ }
2627
+ if (client.persistHash) {
2628
+ refs.add(client.persistHash);
2629
+ }
2630
+ } else {
2631
+ refs.add(client.headHash);
2632
+ if (client.tempRefreshHash) {
2633
+ refs.add(client.tempRefreshHash);
2634
+ }
2635
+ }
2636
+ }
2637
+ return toRefs(refs);
2638
+ }
2639
+ async function getClientGroupForClient(clientID, read) {
2640
+ const clientGroupID = await getClientGroupIDForClient(clientID, read);
2641
+ if (!clientGroupID) {
2642
+ return void 0;
2643
+ }
2644
+ return getClientGroup(clientGroupID, read);
2645
+ }
2646
+ async function getClientGroupIDForClient(clientID, read) {
2647
+ const client = await getClient(clientID, read);
2648
+ return client?.clientGroupID;
2649
+ }
2650
+ async function setClient(clientID, client, dagWrite) {
2651
+ const clients = await getClients(dagWrite);
2652
+ const newClients = new Map(clients).set(clientID, client);
2653
+ return setClients(newClients, dagWrite);
2654
+ }
2655
+ async function setClients(clients, dagWrite) {
2656
+ const chunkData = clientMapToChunkData(clients, dagWrite);
2657
+ const chunk = dagWrite.createChunk(chunkData, getRefsForClients(clients));
2658
+ await dagWrite.putChunk(chunk);
2659
+ await dagWrite.setHead(CLIENTS_HEAD_NAME, chunk.hash);
2660
+ return chunk.hash;
2661
+ }
2662
+
2663
+ // ../zero-protocol/src/inspect-down.ts
2664
+ var inspectQueryRowSchema = valita_exports.object({
2665
+ clientID: valita_exports.string(),
2666
+ queryID: valita_exports.string(),
2667
+ ast: astSchema,
2668
+ got: valita_exports.boolean(),
2669
+ deleted: valita_exports.boolean(),
2670
+ ttl: valita_exports.number(),
2671
+ inactivatedAt: valita_exports.number().nullable(),
2672
+ rowCount: valita_exports.number()
2673
+ });
2674
+ var inspectQueriesDownSchema = valita_exports.object({
2675
+ op: valita_exports.literal("queries"),
2676
+ id: valita_exports.string(),
2677
+ value: valita_exports.array(inspectQueryRowSchema)
2678
+ });
2679
+ var inspectDownBodySchema = valita_exports.union(inspectQueriesDownSchema);
2680
+ var inspectDownMessageSchema = valita_exports.tuple([
2681
+ valita_exports.literal("inspect"),
2682
+ inspectDownBodySchema
2683
+ ]);
2684
+
2685
+ // ../shared/src/random-values.ts
2686
+ function getNonCryptoRandomValues(array3) {
2687
+ if (array3 === null) {
2688
+ throw new TypeError("array cannot be null");
2689
+ }
2690
+ for (let i = 0; i < array3.length; i++) {
2691
+ array3[i] = Math.floor(Math.random() * 256);
2692
+ }
2693
+ return array3;
2694
+ }
2695
+
2696
+ // ../zero-client/src/util/nanoid.ts
2697
+ function nanoid(size = 21) {
2698
+ const randomBytes = getNonCryptoRandomValues(new Uint8Array(size));
2699
+ return randomBytes.reduce((id, byte) => {
2700
+ byte &= 63;
2701
+ if (byte < 36) {
2702
+ id += byte.toString(36);
2703
+ } else if (byte < 62) {
2704
+ id += (byte - 26).toString(36).toUpperCase();
2705
+ } else if (byte > 62) {
2706
+ id += "-";
2707
+ } else {
2708
+ id += "_";
2709
+ }
2710
+ return id;
2711
+ }, "");
2712
+ }
2713
+
2714
+ // ../zero-protocol/src/primary-key.ts
2715
+ var primaryKeySchema = readonly(
2716
+ valita_exports.tuple([valita_exports.string()]).concat(valita_exports.array(valita_exports.string()))
2717
+ );
2718
+ var primaryKeyValueSchema = valita_exports.union(
2719
+ valita_exports.string(),
2720
+ valita_exports.number(),
2721
+ valita_exports.boolean()
2722
+ );
2723
+ var primaryKeyValueRecordSchema = readonlyRecord(
2724
+ primaryKeyValueSchema
2725
+ );
2726
+
2727
+ // ../zero-client/src/client/keys.ts
2728
+ var DESIRED_QUERIES_KEY_PREFIX = "d/";
2729
+ var GOT_QUERIES_KEY_PREFIX = "g/";
2730
+ var ENTITIES_KEY_PREFIX = "e/";
2731
+ function toDesiredQueriesKey(clientID, hash) {
2732
+ return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash;
2733
+ }
2734
+ function desiredQueriesPrefixForClient(clientID) {
2735
+ return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
2736
+ }
2737
+ function toGotQueriesKey(hash) {
2738
+ return GOT_QUERIES_KEY_PREFIX + hash;
2739
+ }
2740
+ function toPrimaryKeyString(tableName, primaryKey, value) {
2741
+ if (primaryKey.length === 1) {
2742
+ return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
2743
+ }
2744
+ const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
2745
+ const str = JSON.stringify(values);
2746
+ const idSegment = h128(str);
2747
+ return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
2748
+ }
2749
+ function sourceNameFromKey(key) {
2750
+ const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
2751
+ return key.slice(ENTITIES_KEY_PREFIX.length, slash);
2752
+ }
2753
+
2754
+ export {
2755
+ stringCompare,
2756
+ compareCookies,
2757
+ assertCookie,
2758
+ deepFreeze,
2759
+ deepFreezeAllowUndefined,
2760
+ emptyHash,
2761
+ newRandomHash,
2762
+ assertHash,
2763
+ Chunk,
2764
+ assertRefs,
2765
+ createChunk,
2766
+ ChunkNotFoundError,
2767
+ mustGetChunk,
2768
+ mustGetHeadHash,
2769
+ DD31,
2770
+ V6,
2771
+ V7,
2772
+ Latest,
2773
+ getSizeOfValue,
2774
+ DEFAULT_HEAD_NAME,
2775
+ commitIsLocalDD31,
2776
+ localMutations,
2777
+ localMutationsDD31,
2778
+ localMutationsGreaterThan,
2779
+ baseSnapshotFromHead,
2780
+ baseSnapshotFromHash,
2781
+ baseSnapshotFromCommit,
2782
+ snapshotMetaParts,
2783
+ compareCookiesForSnapshots,
2784
+ commitFromHash,
2785
+ commitFromHead,
2786
+ assertLocalMetaDD31,
2787
+ isLocalMetaDD31,
2788
+ assertSnapshotMetaDD31,
2789
+ assertSnapshotCommitDD31,
2790
+ binarySearch,
2791
+ BTreeRead,
2792
+ encodeIndexScanKey,
2793
+ decodeIndexKey,
2794
+ readFromDefaultHead,
2795
+ readFromHash,
2796
+ asyncIterableToArray,
2797
+ diff,
2798
+ DiffsMap,
2799
+ diff2,
2800
+ diffCommits,
2801
+ addDiffsForIndexes,
2802
+ newWriteLocal,
2803
+ newWriteSnapshotDD31,
2804
+ getClientGroups,
2805
+ setClientGroups,
2806
+ setClientGroup,
2807
+ getClientGroup,
2808
+ clientGroupHasPendingMutations,
2809
+ disableClientGroup,
2810
+ withRead,
2811
+ withWriteNoImplicitCommit,
2812
+ withWrite,
2813
+ using,
2814
+ clientGroupIDSchema,
2815
+ clientIDSchema,
2816
+ makeClientID,
2817
+ assertClientV6,
2818
+ getClients,
2819
+ ClientStateNotFoundError,
2820
+ assertHasClientState,
2821
+ hasClientState,
2822
+ getClient,
2823
+ mustGetClient,
2824
+ initClientV6,
2825
+ getClientGroupForClient,
2826
+ getClientGroupIDForClient,
2827
+ setClient,
2828
+ setClients,
2829
+ getNonCryptoRandomValues,
2830
+ inspectQueriesDownSchema,
2831
+ inspectDownMessageSchema,
2832
+ primaryKeySchema,
2833
+ primaryKeyValueRecordSchema,
2834
+ nanoid,
2835
+ GOT_QUERIES_KEY_PREFIX,
2836
+ ENTITIES_KEY_PREFIX,
2837
+ toDesiredQueriesKey,
2838
+ desiredQueriesPrefixForClient,
2839
+ toGotQueriesKey,
2840
+ toPrimaryKeyString,
2841
+ sourceNameFromKey
2842
+ };
2843
+ //# sourceMappingURL=chunk-J3DNXL5V.js.map