@rocicorp/zero 0.19.2025040901 → 0.19.2025041100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/advanced.js +1 -2
- package/out/analyze-query/src/bin-analyze.js +73 -13
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.d.ts +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +2 -2
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/{chunk-JW7AJ755.js → chunk-GTRWLUIW.js} +281 -3022
- package/out/chunk-GTRWLUIW.js.map +7 -0
- package/out/chunk-J3DNXL5V.js +2843 -0
- package/out/chunk-J3DNXL5V.js.map +7 -0
- package/out/{chunk-56G3QAI6.js → chunk-N7NOL5CH.js} +38 -41
- package/out/{chunk-56G3QAI6.js.map → chunk-N7NOL5CH.js.map} +2 -2
- package/out/{chunk-2NCGIK6G.js → chunk-SKR5JO2A.js} +21 -1
- package/out/{chunk-2NCGIK6G.js.map → chunk-SKR5JO2A.js.map} +1 -1
- package/out/{inspector-R2AXP2NY.js → inspector-YQC2D2E3.js} +9 -10
- package/out/inspector-YQC2D2E3.js.map +7 -0
- package/out/react.js +20 -9
- package/out/react.js.map +2 -2
- package/out/shared/src/options.d.ts +1 -0
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +12 -10
- package/out/shared/src/options.js.map +1 -1
- package/out/solid.js +31 -22
- package/out/solid.js.map +3 -3
- package/out/zero/src/cli.d.ts +1 -1
- package/out/zero/src/cli.d.ts.map +1 -1
- package/out/zero/src/cli.js +1 -1
- package/out/zero/src/cli.js.map +1 -1
- package/out/zero/src/server/runner/main.d.ts +2 -0
- package/out/zero/src/server/runner/main.d.ts.map +1 -0
- package/out/zero/src/server/runner/main.js +2 -0
- package/out/zero/src/server/runner/main.js.map +1 -0
- package/out/zero/src/zero-cache-dev.d.ts.map +1 -1
- package/out/zero/src/zero-cache-dev.js +1 -1
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +7 -2
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +20 -4
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/server/{multi → runner}/config.d.ts +7 -2
- package/out/zero-cache/src/server/runner/config.d.ts.map +1 -0
- package/out/zero-cache/src/server/{multi → runner}/config.js +2 -1
- package/out/zero-cache/src/server/runner/config.js.map +1 -0
- package/out/zero-cache/src/server/runner/main.d.ts.map +1 -0
- package/out/zero-cache/src/server/runner/main.js.map +1 -0
- package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -0
- package/out/zero-cache/src/server/{multi → runner}/run-worker.js +27 -17
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -0
- package/out/zero-cache/src/server/runner/runtime.d.ts.map +1 -0
- package/out/zero-cache/src/server/runner/runtime.js.map +1 -0
- package/out/zero-cache/src/server/{multi/tenant-dispatcher.d.ts → runner/zero-dispatcher.d.ts} +4 -4
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -0
- package/out/zero-cache/src/server/{multi/tenant-dispatcher.js → runner/zero-dispatcher.js} +25 -12
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -0
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts +10 -1
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.js +15 -3
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +1 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +9 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +66 -25
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-pg/src/query.d.ts +0 -2
- package/out/zero-pg/src/query.d.ts.map +1 -1
- package/out/zero-pg/src/query.js +0 -3
- package/out/zero-pg/src/query.js.map +1 -1
- package/out/zero-react/src/use-query.d.ts +3 -1
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/create-query.d.ts +22 -0
- package/out/zero-solid/src/create-query.d.ts.map +1 -0
- package/out/zero-solid/src/mod.d.ts +1 -1
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +4 -3
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero.js +4 -5
- package/out/zql/src/ivm/array-view.d.ts +5 -1
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +8 -1
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +2 -1
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +5 -5
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +15 -10
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +8 -5
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.d.ts +0 -2
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.js +0 -3
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/typed-view.d.ts +2 -0
- package/out/zql/src/query/typed-view.d.ts.map +1 -1
- package/package.json +6 -2
- package/out/chunk-424PT5DM.js +0 -23
- package/out/chunk-424PT5DM.js.map +0 -7
- package/out/chunk-JW7AJ755.js.map +0 -7
- package/out/chunk-MB3DEFRC.js +0 -67
- package/out/chunk-MB3DEFRC.js.map +0 -7
- package/out/inspector-R2AXP2NY.js.map +0 -7
- package/out/zero/src/server/multi/main.d.ts +0 -2
- package/out/zero/src/server/multi/main.d.ts.map +0 -1
- package/out/zero/src/server/multi/main.js +0 -2
- package/out/zero/src/server/multi/main.js.map +0 -1
- package/out/zero-cache/src/server/multi/config.d.ts.map +0 -1
- package/out/zero-cache/src/server/multi/config.js.map +0 -1
- package/out/zero-cache/src/server/multi/main.d.ts.map +0 -1
- package/out/zero-cache/src/server/multi/main.js.map +0 -1
- package/out/zero-cache/src/server/multi/run-worker.d.ts.map +0 -1
- package/out/zero-cache/src/server/multi/run-worker.js.map +0 -1
- package/out/zero-cache/src/server/multi/runtime.d.ts.map +0 -1
- package/out/zero-cache/src/server/multi/runtime.js.map +0 -1
- package/out/zero-cache/src/server/multi/tenant-dispatcher.d.ts.map +0 -1
- package/out/zero-cache/src/server/multi/tenant-dispatcher.js.map +0 -1
- package/out/zero-solid/src/use-query.d.ts +0 -12
- package/out/zero-solid/src/use-query.d.ts.map +0 -1
- /package/out/zero-cache/src/server/{multi → runner}/main.d.ts +0 -0
- /package/out/zero-cache/src/server/{multi → runner}/main.js +0 -0
- /package/out/zero-cache/src/server/{multi → runner}/run-worker.d.ts +0 -0
- /package/out/zero-cache/src/server/{multi → runner}/runtime.d.ts +0 -0
- /package/out/zero-cache/src/server/{multi → runner}/runtime.js +0 -0
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./chunk-MB3DEFRC.js";
|
|
5
|
-
import {
|
|
2
|
+
__export,
|
|
3
|
+
__reExport,
|
|
6
4
|
applyChange,
|
|
7
5
|
assert,
|
|
8
|
-
assertArray,
|
|
9
|
-
assertBoolean,
|
|
10
|
-
assertNumber,
|
|
11
6
|
assertObject,
|
|
12
7
|
assertString,
|
|
13
8
|
compareValues,
|
|
@@ -17,11 +12,7 @@ import {
|
|
|
17
12
|
throwInvalidType,
|
|
18
13
|
unreachable,
|
|
19
14
|
valuesEqual
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import {
|
|
22
|
-
__export,
|
|
23
|
-
__reExport
|
|
24
|
-
} from "./chunk-424PT5DM.js";
|
|
15
|
+
} from "./chunk-SKR5JO2A.js";
|
|
25
16
|
|
|
26
17
|
// ../shared/src/valita.ts
|
|
27
18
|
var valita_exports = {};
|
|
@@ -232,33 +223,101 @@ function deepPartial(s) {
|
|
|
232
223
|
return v.object(shape);
|
|
233
224
|
}
|
|
234
225
|
|
|
235
|
-
// ../
|
|
236
|
-
var
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
226
|
+
// ../zql/src/query/ttl.ts
|
|
227
|
+
var DEFAULT_TTL = "none";
|
|
228
|
+
var multiplier = {
|
|
229
|
+
s: 1e3,
|
|
230
|
+
m: 60 * 1e3,
|
|
231
|
+
h: 60 * 60 * 1e3,
|
|
232
|
+
d: 24 * 60 * 60 * 1e3,
|
|
233
|
+
y: 365 * 24 * 60 * 60 * 1e3
|
|
243
234
|
};
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
235
|
+
function parseTTL(ttl) {
|
|
236
|
+
if (typeof ttl === "number") {
|
|
237
|
+
return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;
|
|
238
|
+
}
|
|
239
|
+
if (ttl === "none") {
|
|
240
|
+
return 0;
|
|
241
|
+
}
|
|
242
|
+
if (ttl === "forever") {
|
|
243
|
+
return -1;
|
|
244
|
+
}
|
|
245
|
+
const multi = multiplier[ttl[ttl.length - 1]];
|
|
246
|
+
return Number(ttl.slice(0, -1)) * multi;
|
|
247
|
+
}
|
|
248
|
+
function compareTTL(a, b) {
|
|
249
|
+
const ap = parseTTL(a);
|
|
250
|
+
const bp = parseTTL(b);
|
|
251
|
+
if (ap === -1 && bp !== -1) {
|
|
252
|
+
return 1;
|
|
253
|
+
}
|
|
254
|
+
if (ap !== -1 && bp === -1) {
|
|
255
|
+
return -1;
|
|
256
|
+
}
|
|
257
|
+
return ap - bp;
|
|
258
|
+
}
|
|
259
|
+
function normalizeTTL(ttl) {
|
|
260
|
+
if (typeof ttl === "string") {
|
|
261
|
+
return ttl;
|
|
262
|
+
}
|
|
263
|
+
if (ttl < 0) {
|
|
264
|
+
return "forever";
|
|
265
|
+
}
|
|
266
|
+
if (ttl === 0) {
|
|
267
|
+
return "none";
|
|
268
|
+
}
|
|
269
|
+
let shortest = ttl.toString();
|
|
270
|
+
const lengthOfNumber = shortest.length;
|
|
271
|
+
for (const unit of ["y", "d", "h", "m", "s"]) {
|
|
272
|
+
const multi = multiplier[unit];
|
|
273
|
+
const value = ttl / multi;
|
|
274
|
+
const candidate = `${value}${unit}`;
|
|
275
|
+
if (candidate.length < shortest.length) {
|
|
276
|
+
shortest = candidate;
|
|
277
|
+
}
|
|
248
278
|
}
|
|
249
|
-
|
|
279
|
+
return shortest.length < lengthOfNumber ? shortest : ttl;
|
|
250
280
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
281
|
+
|
|
282
|
+
// ../shared/src/has-own.ts
|
|
283
|
+
var { hasOwn } = Object;
|
|
284
|
+
|
|
285
|
+
// ../shared/src/hash.ts
|
|
286
|
+
import { xxHash32 } from "js-xxhash";
|
|
287
|
+
var h64 = (s) => hash(s, 2);
|
|
288
|
+
var h128 = (s) => hash(s, 4);
|
|
289
|
+
function hash(str, words) {
|
|
290
|
+
let hash2 = 0n;
|
|
291
|
+
for (let i = 0; i < words; i++) {
|
|
292
|
+
hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
|
|
293
|
+
}
|
|
254
294
|
return hash2;
|
|
255
295
|
}
|
|
256
296
|
|
|
257
|
-
// ../
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
297
|
+
// ../zero-protocol/src/ast.ts
|
|
298
|
+
import { compareUTF8 } from "compare-utf8";
|
|
299
|
+
|
|
300
|
+
// ../shared/src/arrays.ts
|
|
301
|
+
function defined(arr) {
|
|
302
|
+
let i = arr.findIndex((x) => x === void 0);
|
|
303
|
+
if (i < 0) {
|
|
304
|
+
return arr;
|
|
305
|
+
}
|
|
306
|
+
const defined2 = arr.slice(0, i);
|
|
307
|
+
for (i++; i < arr.length; i++) {
|
|
308
|
+
const x = arr[i];
|
|
309
|
+
if (x !== void 0) {
|
|
310
|
+
defined2.push(x);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
return defined2;
|
|
314
|
+
}
|
|
315
|
+
function areEqual(arr1, arr2) {
|
|
316
|
+
return arr1.length === arr2.length && arr1.every((e, i) => e === arr2[i]);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// ../shared/src/json-schema.ts
|
|
320
|
+
import * as valita from "@badrap/valita";
|
|
262
321
|
|
|
263
322
|
// ../shared/src/config.ts
|
|
264
323
|
var isProd = process.env.NODE_ENV === "production";
|
|
@@ -298,2812 +357,112 @@ function deepEqual(a, b) {
|
|
|
298
357
|
if (Array.isArray(b)) {
|
|
299
358
|
return false;
|
|
300
359
|
}
|
|
301
|
-
a = a;
|
|
302
|
-
b = b;
|
|
303
|
-
let aSize = 0;
|
|
304
|
-
for (const key in a) {
|
|
305
|
-
if (hasOwn(a, key)) {
|
|
306
|
-
if (!deepEqual(a[key], b[key])) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
309
|
-
aSize++;
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
let bSize = 0;
|
|
313
|
-
for (const key in b) {
|
|
314
|
-
if (hasOwn(b, key)) {
|
|
315
|
-
bSize++;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
return aSize === bSize;
|
|
319
|
-
}
|
|
320
|
-
function assertJSONValue(v2) {
|
|
321
|
-
if (isProd) {
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
switch (typeof v2) {
|
|
325
|
-
case "boolean":
|
|
326
|
-
case "number":
|
|
327
|
-
case "string":
|
|
328
|
-
return;
|
|
329
|
-
case "object":
|
|
330
|
-
if (v2 === null) {
|
|
331
|
-
return;
|
|
332
|
-
}
|
|
333
|
-
if (Array.isArray(v2)) {
|
|
334
|
-
return assertJSONArray(v2);
|
|
335
|
-
}
|
|
336
|
-
return assertObjectIsJSONObject(v2);
|
|
337
|
-
}
|
|
338
|
-
throwInvalidType(v2, "JSON value");
|
|
339
|
-
}
|
|
340
|
-
function assertJSONObject(v2) {
|
|
341
|
-
assertObject(v2);
|
|
342
|
-
assertObjectIsJSONObject(v2);
|
|
343
|
-
}
|
|
344
|
-
function assertObjectIsJSONObject(v2) {
|
|
345
|
-
for (const k in v2) {
|
|
346
|
-
if (hasOwn(v2, k)) {
|
|
347
|
-
const value = v2[k];
|
|
348
|
-
if (value !== void 0) {
|
|
349
|
-
assertJSONValue(value);
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
function assertJSONArray(v2) {
|
|
355
|
-
for (const item of v2) {
|
|
356
|
-
assertJSONValue(item);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
function isJSONValue(v2, path2) {
|
|
360
|
-
switch (typeof v2) {
|
|
361
|
-
case "boolean":
|
|
362
|
-
case "number":
|
|
363
|
-
case "string":
|
|
364
|
-
return true;
|
|
365
|
-
case "object":
|
|
366
|
-
if (v2 === null) {
|
|
367
|
-
return true;
|
|
368
|
-
}
|
|
369
|
-
if (Array.isArray(v2)) {
|
|
370
|
-
return isJSONArray(v2, path2);
|
|
371
|
-
}
|
|
372
|
-
return objectIsJSONObject(v2, path2);
|
|
373
|
-
}
|
|
374
|
-
return false;
|
|
375
|
-
}
|
|
376
|
-
function isJSONObject(v2, path2) {
|
|
377
|
-
if (typeof v2 !== "object" || v2 === null) {
|
|
378
|
-
return false;
|
|
379
|
-
}
|
|
380
|
-
return objectIsJSONObject(v2, path2);
|
|
381
|
-
}
|
|
382
|
-
function objectIsJSONObject(v2, path2) {
|
|
383
|
-
for (const k in v2) {
|
|
384
|
-
if (hasOwn(v2, k)) {
|
|
385
|
-
path2.push(k);
|
|
386
|
-
const value = v2[k];
|
|
387
|
-
if (value !== void 0 && !isJSONValue(value, path2)) {
|
|
388
|
-
return false;
|
|
389
|
-
}
|
|
390
|
-
path2.pop();
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return true;
|
|
394
|
-
}
|
|
395
|
-
function isJSONArray(v2, path2) {
|
|
396
|
-
for (let i = 0; i < v2.length; i++) {
|
|
397
|
-
path2.push(i);
|
|
398
|
-
if (!isJSONValue(v2[i], path2)) {
|
|
399
|
-
return false;
|
|
400
|
-
}
|
|
401
|
-
path2.pop();
|
|
402
|
-
}
|
|
403
|
-
return true;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// ../shared/src/random-uint64.ts
|
|
407
|
-
function randomUint64() {
|
|
408
|
-
const high = Math.floor(Math.random() * 4294967295);
|
|
409
|
-
const low = Math.floor(Math.random() * 4294967295);
|
|
410
|
-
return BigInt(high) << 32n | BigInt(low);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
// ../replicache/src/hash.ts
|
|
414
|
-
var STRING_LENGTH = 22;
|
|
415
|
-
var hashRe = /^[0-9a-v-]+$/;
|
|
416
|
-
var emptyUUID = "0".repeat(STRING_LENGTH);
|
|
417
|
-
var emptyHash = emptyUUID;
|
|
418
|
-
var newRandomHash = makeNewRandomHashFunctionInternal();
|
|
419
|
-
function toStringAndSlice(n, len) {
|
|
420
|
-
return n.toString(32).slice(-len).padStart(len, "0");
|
|
421
|
-
}
|
|
422
|
-
function makeNewRandomHashFunctionInternal() {
|
|
423
|
-
let base = "";
|
|
424
|
-
let i = 0;
|
|
425
|
-
return () => {
|
|
426
|
-
if (!base) {
|
|
427
|
-
base = toStringAndSlice(randomUint64(), 12);
|
|
428
|
-
}
|
|
429
|
-
const tail = toStringAndSlice(i++, 10);
|
|
430
|
-
return base + tail;
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
function isHash(value) {
|
|
434
|
-
return typeof value === "string" && hashRe.test(value);
|
|
435
|
-
}
|
|
436
|
-
function assertHash(value) {
|
|
437
|
-
assert2(value, hashSchema);
|
|
438
|
-
}
|
|
439
|
-
var hashSchema = valita_exports.string().assert(isHash, "Invalid hash");
|
|
440
|
-
|
|
441
|
-
// ../replicache/src/size-of-value.ts
|
|
442
|
-
var SIZE_TAG = 1;
|
|
443
|
-
var SIZE_INT32 = 4;
|
|
444
|
-
var SIZE_SMI = 5;
|
|
445
|
-
var SIZE_DOUBLE = 8;
|
|
446
|
-
function getSizeOfValue(value) {
|
|
447
|
-
switch (typeof value) {
|
|
448
|
-
case "string":
|
|
449
|
-
return SIZE_TAG + SIZE_INT32 + value.length;
|
|
450
|
-
case "number":
|
|
451
|
-
if (isSmi(value)) {
|
|
452
|
-
if (value <= -(2 ** 30) || value >= 2 ** 30 - 1) {
|
|
453
|
-
return SIZE_TAG + SIZE_SMI;
|
|
454
|
-
}
|
|
455
|
-
return SIZE_TAG + SIZE_INT32;
|
|
456
|
-
}
|
|
457
|
-
return SIZE_TAG + SIZE_DOUBLE;
|
|
458
|
-
case "boolean":
|
|
459
|
-
return SIZE_TAG;
|
|
460
|
-
case "object":
|
|
461
|
-
if (value === null) {
|
|
462
|
-
return SIZE_TAG;
|
|
463
|
-
}
|
|
464
|
-
if (Array.isArray(value)) {
|
|
465
|
-
let sum = 2 * SIZE_TAG + SIZE_INT32;
|
|
466
|
-
for (const element of value) {
|
|
467
|
-
sum += getSizeOfValue(element);
|
|
468
|
-
}
|
|
469
|
-
return sum;
|
|
470
|
-
}
|
|
471
|
-
{
|
|
472
|
-
const val = value;
|
|
473
|
-
let sum = 2 * SIZE_TAG + SIZE_INT32;
|
|
474
|
-
for (const k in val) {
|
|
475
|
-
if (hasOwn(val, k)) {
|
|
476
|
-
const propertyValue = val[k];
|
|
477
|
-
if (propertyValue !== void 0) {
|
|
478
|
-
sum += getSizeOfValue(k) + getSizeOfValue(propertyValue);
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
return sum;
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
throw new Error(`Invalid value. type: ${typeof value}, value: ${value}`);
|
|
486
|
-
}
|
|
487
|
-
function isSmi(value) {
|
|
488
|
-
return value === (value | 0);
|
|
489
|
-
}
|
|
490
|
-
var entryFixed = 2 * SIZE_TAG + SIZE_INT32 + SIZE_TAG + SIZE_INT32;
|
|
491
|
-
function getSizeOfEntry(key, value) {
|
|
492
|
-
return entryFixed + getSizeOfValue(key) + getSizeOfValue(value);
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// ../replicache/src/btree/node.ts
|
|
496
|
-
import { compareUTF8 } from "compare-utf8";
|
|
497
|
-
|
|
498
|
-
// ../shared/src/iterables.ts
|
|
499
|
-
function* joinIterables(...iters) {
|
|
500
|
-
for (const iter of iters) {
|
|
501
|
-
yield* iter;
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
function* filterIter(iter, p) {
|
|
505
|
-
let index = 0;
|
|
506
|
-
for (const t of iter) {
|
|
507
|
-
if (p(t, index++)) {
|
|
508
|
-
yield t;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
function* mapIter(iter, f) {
|
|
513
|
-
let index = 0;
|
|
514
|
-
for (const t of iter) {
|
|
515
|
-
yield f(t, index++);
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
var IterWrapper = class _IterWrapper {
|
|
519
|
-
iter;
|
|
520
|
-
constructor(iter) {
|
|
521
|
-
this.iter = iter;
|
|
522
|
-
}
|
|
523
|
-
[Symbol.iterator]() {
|
|
524
|
-
return this.iter[Symbol.iterator]();
|
|
525
|
-
}
|
|
526
|
-
map(f) {
|
|
527
|
-
return new _IterWrapper(mapIter(this.iter, f));
|
|
528
|
-
}
|
|
529
|
-
filter(p) {
|
|
530
|
-
return new _IterWrapper(filterIter(this.iter, p));
|
|
531
|
-
}
|
|
532
|
-
};
|
|
533
|
-
function wrapIterable(iter) {
|
|
534
|
-
return new IterWrapper(iter);
|
|
535
|
-
}
|
|
536
|
-
function* mergeIterables(iterables, comparator, distinct = false) {
|
|
537
|
-
const iterators = iterables.map((i) => i[Symbol.iterator]());
|
|
538
|
-
try {
|
|
539
|
-
const current = iterators.map((i) => i.next());
|
|
540
|
-
let lastYielded;
|
|
541
|
-
while (current.some((c) => !c.done)) {
|
|
542
|
-
const min = current.reduce(
|
|
543
|
-
(acc, c, i) => {
|
|
544
|
-
if (c.done) {
|
|
545
|
-
return acc;
|
|
546
|
-
}
|
|
547
|
-
if (acc === void 0 || comparator(c.value, acc[0]) < 0) {
|
|
548
|
-
return [c.value, i];
|
|
549
|
-
}
|
|
550
|
-
return acc;
|
|
551
|
-
},
|
|
552
|
-
void 0
|
|
553
|
-
);
|
|
554
|
-
assert(min !== void 0, "min is undefined");
|
|
555
|
-
current[min[1]] = iterators[min[1]].next();
|
|
556
|
-
if (lastYielded !== void 0 && distinct && comparator(lastYielded, min[0]) === 0) {
|
|
557
|
-
continue;
|
|
558
|
-
}
|
|
559
|
-
lastYielded = min[0];
|
|
560
|
-
yield min[0];
|
|
561
|
-
}
|
|
562
|
-
} finally {
|
|
563
|
-
for (const it of iterators) {
|
|
564
|
-
it.return?.();
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
// ../replicache/src/binary-search.ts
|
|
570
|
-
function binarySearch(high, compare) {
|
|
571
|
-
let low = 0;
|
|
572
|
-
while (low < high) {
|
|
573
|
-
const mid = low + (high - low >> 1);
|
|
574
|
-
const i = compare(mid);
|
|
575
|
-
if (i === 0) {
|
|
576
|
-
return mid;
|
|
577
|
-
}
|
|
578
|
-
if (i > 0) {
|
|
579
|
-
low = mid + 1;
|
|
580
|
-
} else {
|
|
581
|
-
high = mid;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
return low;
|
|
585
|
-
}
|
|
586
|
-
|
|
587
|
-
// ../replicache/src/frozen-json.ts
|
|
588
|
-
var deepFrozenObjects = /* @__PURE__ */ new WeakSet();
|
|
589
|
-
function deepFreeze(v2) {
|
|
590
|
-
if (isProd) {
|
|
591
|
-
return v2;
|
|
592
|
-
}
|
|
593
|
-
deepFreezeInternal(v2, []);
|
|
594
|
-
return v2;
|
|
595
|
-
}
|
|
596
|
-
function deepFreezeInternal(v2, seen) {
|
|
597
|
-
switch (typeof v2) {
|
|
598
|
-
case "undefined":
|
|
599
|
-
throw new TypeError("Unexpected value undefined");
|
|
600
|
-
case "boolean":
|
|
601
|
-
case "number":
|
|
602
|
-
case "string":
|
|
603
|
-
return;
|
|
604
|
-
case "object": {
|
|
605
|
-
if (v2 === null) {
|
|
606
|
-
return;
|
|
607
|
-
}
|
|
608
|
-
if (deepFrozenObjects.has(v2)) {
|
|
609
|
-
return;
|
|
610
|
-
}
|
|
611
|
-
deepFrozenObjects.add(v2);
|
|
612
|
-
if (seen.includes(v2)) {
|
|
613
|
-
throwInvalidType(v2, "Cyclic JSON object");
|
|
614
|
-
}
|
|
615
|
-
seen.push(v2);
|
|
616
|
-
Object.freeze(v2);
|
|
617
|
-
if (Array.isArray(v2)) {
|
|
618
|
-
deepFreezeArray(v2, seen);
|
|
619
|
-
} else {
|
|
620
|
-
deepFreezeObject(v2, seen);
|
|
621
|
-
}
|
|
622
|
-
seen.pop();
|
|
623
|
-
return;
|
|
624
|
-
}
|
|
625
|
-
default:
|
|
626
|
-
throwInvalidType(v2, "JSON value");
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
function deepFreezeArray(v2, seen) {
|
|
630
|
-
for (const item of v2) {
|
|
631
|
-
deepFreezeInternal(item, seen);
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
function deepFreezeObject(v2, seen) {
|
|
635
|
-
for (const k in v2) {
|
|
636
|
-
if (hasOwn(v2, k)) {
|
|
637
|
-
const value = v2[k];
|
|
638
|
-
if (value !== void 0) {
|
|
639
|
-
deepFreezeInternal(value, seen);
|
|
640
|
-
}
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
function assertDeepFrozen(v2) {
|
|
645
|
-
if (isProd) {
|
|
646
|
-
return;
|
|
647
|
-
}
|
|
648
|
-
if (!isDeepFrozen(v2, [])) {
|
|
649
|
-
throw new Error("Expected frozen object");
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
function isDeepFrozen(v2, seen) {
|
|
653
|
-
switch (typeof v2) {
|
|
654
|
-
case "boolean":
|
|
655
|
-
case "number":
|
|
656
|
-
case "string":
|
|
657
|
-
return true;
|
|
658
|
-
case "object":
|
|
659
|
-
if (v2 === null) {
|
|
660
|
-
return true;
|
|
661
|
-
}
|
|
662
|
-
if (deepFrozenObjects.has(v2)) {
|
|
663
|
-
return true;
|
|
664
|
-
}
|
|
665
|
-
if (!Object.isFrozen(v2)) {
|
|
666
|
-
return false;
|
|
667
|
-
}
|
|
668
|
-
if (seen.includes(v2)) {
|
|
669
|
-
throwInvalidType(v2, "Cyclic JSON object");
|
|
670
|
-
}
|
|
671
|
-
seen.push(v2);
|
|
672
|
-
if (Array.isArray(v2)) {
|
|
673
|
-
for (const item of v2) {
|
|
674
|
-
if (!isDeepFrozen(item, seen)) {
|
|
675
|
-
seen.pop();
|
|
676
|
-
return false;
|
|
677
|
-
}
|
|
678
|
-
}
|
|
679
|
-
} else {
|
|
680
|
-
for (const k in v2) {
|
|
681
|
-
if (hasOwn(v2, k)) {
|
|
682
|
-
const value = v2[k];
|
|
683
|
-
if (value !== void 0 && !isDeepFrozen(value, seen)) {
|
|
684
|
-
seen.pop();
|
|
685
|
-
return false;
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
deepFrozenObjects.add(v2);
|
|
691
|
-
seen.pop();
|
|
692
|
-
return true;
|
|
693
|
-
default:
|
|
694
|
-
throwInvalidType(v2, "JSON value");
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
function deepFreezeAllowUndefined(v2) {
|
|
698
|
-
if (v2 === void 0) {
|
|
699
|
-
return void 0;
|
|
700
|
-
}
|
|
701
|
-
return deepFreeze(v2);
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// ../replicache/src/btree/node.ts
|
|
705
|
-
var NODE_LEVEL = 0;
|
|
706
|
-
var NODE_ENTRIES = 1;
|
|
707
|
-
function makeNodeChunkData(level, entries, formatVersion) {
|
|
708
|
-
return deepFreeze([
|
|
709
|
-
level,
|
|
710
|
-
formatVersion >= V7 ? entries : entries.map((e) => e.slice(0, 2))
|
|
711
|
-
]);
|
|
712
|
-
}
|
|
713
|
-
async function findLeaf(key, hash2, source, expectedRootHash) {
|
|
714
|
-
const node = await source.getNode(hash2);
|
|
715
|
-
if (expectedRootHash !== source.rootHash) {
|
|
716
|
-
return findLeaf(key, source.rootHash, source, source.rootHash);
|
|
717
|
-
}
|
|
718
|
-
if (isDataNodeImpl(node)) {
|
|
719
|
-
return node;
|
|
720
|
-
}
|
|
721
|
-
const { entries } = node;
|
|
722
|
-
let i = binarySearch2(key, entries);
|
|
723
|
-
if (i === entries.length) {
|
|
724
|
-
i--;
|
|
725
|
-
}
|
|
726
|
-
const entry = entries[i];
|
|
727
|
-
return findLeaf(key, entry[1], source, expectedRootHash);
|
|
728
|
-
}
|
|
729
|
-
function binarySearch2(key, entries) {
|
|
730
|
-
return binarySearch(
|
|
731
|
-
entries.length,
|
|
732
|
-
(i) => compareUTF8(key, entries[i][0])
|
|
733
|
-
);
|
|
734
|
-
}
|
|
735
|
-
function binarySearchFound(i, entries, key) {
|
|
736
|
-
return i !== entries.length && entries[i][0] === key;
|
|
737
|
-
}
|
|
738
|
-
function parseBTreeNode(v2, formatVersion, getSizeOfEntry2) {
|
|
739
|
-
if (isProd && formatVersion >= V7) {
|
|
740
|
-
return v2;
|
|
741
|
-
}
|
|
742
|
-
assertArray(v2);
|
|
743
|
-
assertDeepFrozen(v2);
|
|
744
|
-
assert(v2.length >= 2);
|
|
745
|
-
const [level, entries] = v2;
|
|
746
|
-
assertNumber(level);
|
|
747
|
-
assertArray(entries);
|
|
748
|
-
const f = level > 0 ? assertString : assertJSONValue;
|
|
749
|
-
if (formatVersion >= V7) {
|
|
750
|
-
for (const e of entries) {
|
|
751
|
-
assertEntry(e, f);
|
|
752
|
-
}
|
|
753
|
-
return v2;
|
|
754
|
-
}
|
|
755
|
-
const newEntries = entries.map((e) => convertNonV7Entry(e, f, getSizeOfEntry2));
|
|
756
|
-
return [level, newEntries];
|
|
757
|
-
}
|
|
758
|
-
function assertEntry(entry, f) {
|
|
759
|
-
assertArray(entry);
|
|
760
|
-
assert(entry.length >= 3);
|
|
761
|
-
assertString(entry[0]);
|
|
762
|
-
f(entry[1]);
|
|
763
|
-
assertNumber(entry[2]);
|
|
764
|
-
}
|
|
765
|
-
function convertNonV7Entry(entry, f, getSizeOfEntry2) {
|
|
766
|
-
assertArray(entry);
|
|
767
|
-
assert(entry.length >= 2);
|
|
768
|
-
assertString(entry[0]);
|
|
769
|
-
f(entry[1]);
|
|
770
|
-
const entrySize = getSizeOfEntry2(entry[0], entry[1]);
|
|
771
|
-
return [entry[0], entry[1], entrySize];
|
|
772
|
-
}
|
|
773
|
-
var NodeImpl = class {
|
|
774
|
-
entries;
|
|
775
|
-
hash;
|
|
776
|
-
isMutable;
|
|
777
|
-
#childNodeSize = -1;
|
|
778
|
-
constructor(entries, hash2, isMutable) {
|
|
779
|
-
this.entries = entries;
|
|
780
|
-
this.hash = hash2;
|
|
781
|
-
this.isMutable = isMutable;
|
|
782
|
-
}
|
|
783
|
-
maxKey() {
|
|
784
|
-
return this.entries[this.entries.length - 1][0];
|
|
785
|
-
}
|
|
786
|
-
getChildNodeSize(tree) {
|
|
787
|
-
if (this.#childNodeSize !== -1) {
|
|
788
|
-
return this.#childNodeSize;
|
|
789
|
-
}
|
|
790
|
-
let sum = tree.chunkHeaderSize;
|
|
791
|
-
for (const entry of this.entries) {
|
|
792
|
-
sum += entry[2];
|
|
793
|
-
}
|
|
794
|
-
return this.#childNodeSize = sum;
|
|
795
|
-
}
|
|
796
|
-
_updateNode(tree) {
|
|
797
|
-
this.#childNodeSize = -1;
|
|
798
|
-
tree.updateNode(
|
|
799
|
-
this
|
|
800
|
-
);
|
|
801
|
-
}
|
|
802
|
-
};
|
|
803
|
-
function toChunkData(node, formatVersion) {
|
|
804
|
-
return makeNodeChunkData(node.level, node.entries, formatVersion);
|
|
805
|
-
}
|
|
806
|
-
var DataNodeImpl = class extends NodeImpl {
|
|
807
|
-
level = 0;
|
|
808
|
-
set(key, value, entrySize, tree) {
|
|
809
|
-
let deleteCount;
|
|
810
|
-
const i = binarySearch2(key, this.entries);
|
|
811
|
-
if (!binarySearchFound(i, this.entries, key)) {
|
|
812
|
-
deleteCount = 0;
|
|
813
|
-
} else {
|
|
814
|
-
deleteCount = 1;
|
|
815
|
-
}
|
|
816
|
-
return Promise.resolve(
|
|
817
|
-
this.#splice(tree, i, deleteCount, [key, value, entrySize])
|
|
818
|
-
);
|
|
819
|
-
}
|
|
820
|
-
#splice(tree, start, deleteCount, ...items) {
|
|
821
|
-
if (this.isMutable) {
|
|
822
|
-
this.entries.splice(start, deleteCount, ...items);
|
|
823
|
-
this._updateNode(tree);
|
|
824
|
-
return this;
|
|
825
|
-
}
|
|
826
|
-
const entries = readonlySplice(this.entries, start, deleteCount, ...items);
|
|
827
|
-
return tree.newDataNodeImpl(entries);
|
|
828
|
-
}
|
|
829
|
-
del(key, tree) {
|
|
830
|
-
const i = binarySearch2(key, this.entries);
|
|
831
|
-
if (!binarySearchFound(i, this.entries, key)) {
|
|
832
|
-
return Promise.resolve(this);
|
|
833
|
-
}
|
|
834
|
-
return Promise.resolve(this.#splice(tree, i, 1));
|
|
835
|
-
}
|
|
836
|
-
async *keys(_tree) {
|
|
837
|
-
for (const entry of this.entries) {
|
|
838
|
-
yield entry[0];
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
async *entriesIter(_tree) {
|
|
842
|
-
for (const entry of this.entries) {
|
|
843
|
-
yield entry;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
function readonlySplice(array5, start, deleteCount, ...items) {
|
|
848
|
-
const arr = array5.slice(0, start);
|
|
849
|
-
for (let i = 0; i < items.length; i++) {
|
|
850
|
-
arr.push(items[i]);
|
|
851
|
-
}
|
|
852
|
-
for (let i = start + deleteCount; i < array5.length; i++) {
|
|
853
|
-
arr.push(array5[i]);
|
|
854
|
-
}
|
|
855
|
-
return arr;
|
|
856
|
-
}
|
|
857
|
-
var InternalNodeImpl = class _InternalNodeImpl extends NodeImpl {
|
|
858
|
-
level;
|
|
859
|
-
constructor(entries, hash2, level, isMutable) {
|
|
860
|
-
super(entries, hash2, isMutable);
|
|
861
|
-
this.level = level;
|
|
862
|
-
}
|
|
863
|
-
async set(key, value, entrySize, tree) {
|
|
864
|
-
let i = binarySearch2(key, this.entries);
|
|
865
|
-
if (i === this.entries.length) {
|
|
866
|
-
i--;
|
|
867
|
-
}
|
|
868
|
-
const childHash = this.entries[i][1];
|
|
869
|
-
const oldChildNode = await tree.getNode(childHash);
|
|
870
|
-
const childNode = await oldChildNode.set(key, value, entrySize, tree);
|
|
871
|
-
const childNodeSize = childNode.getChildNodeSize(tree);
|
|
872
|
-
if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {
|
|
873
|
-
return this.#mergeAndPartition(tree, i, childNode);
|
|
874
|
-
}
|
|
875
|
-
const newEntry = createNewInternalEntryForNode(
|
|
876
|
-
childNode,
|
|
877
|
-
tree.getEntrySize
|
|
878
|
-
);
|
|
879
|
-
return this.#replaceChild(tree, i, newEntry);
|
|
880
|
-
}
|
|
881
|
-
/**
|
|
882
|
-
* This merges the child node entries with previous or next sibling and then
|
|
883
|
-
* partitions the merged entries.
|
|
884
|
-
*/
|
|
885
|
-
async #mergeAndPartition(tree, i, childNode) {
|
|
886
|
-
const level = this.level - 1;
|
|
887
|
-
const thisEntries = this.entries;
|
|
888
|
-
let values;
|
|
889
|
-
let startIndex;
|
|
890
|
-
let removeCount;
|
|
891
|
-
if (i > 0) {
|
|
892
|
-
const hash2 = thisEntries[i - 1][1];
|
|
893
|
-
const previousSibling = await tree.getNode(hash2);
|
|
894
|
-
values = joinIterables(
|
|
895
|
-
previousSibling.entries,
|
|
896
|
-
childNode.entries
|
|
897
|
-
);
|
|
898
|
-
startIndex = i - 1;
|
|
899
|
-
removeCount = 2;
|
|
900
|
-
} else if (i < thisEntries.length - 1) {
|
|
901
|
-
const hash2 = thisEntries[i + 1][1];
|
|
902
|
-
const nextSibling = await tree.getNode(hash2);
|
|
903
|
-
values = joinIterables(
|
|
904
|
-
childNode.entries,
|
|
905
|
-
nextSibling.entries
|
|
906
|
-
);
|
|
907
|
-
startIndex = i;
|
|
908
|
-
removeCount = 2;
|
|
909
|
-
} else {
|
|
910
|
-
values = childNode.entries;
|
|
911
|
-
startIndex = i;
|
|
912
|
-
removeCount = 1;
|
|
913
|
-
}
|
|
914
|
-
const partitions = partition(
|
|
915
|
-
values,
|
|
916
|
-
(value) => value[2],
|
|
917
|
-
tree.minSize - tree.chunkHeaderSize,
|
|
918
|
-
tree.maxSize - tree.chunkHeaderSize
|
|
919
|
-
);
|
|
920
|
-
const newEntries = [];
|
|
921
|
-
for (const entries2 of partitions) {
|
|
922
|
-
const node = tree.newNodeImpl(entries2, level);
|
|
923
|
-
const newHashEntry = createNewInternalEntryForNode(
|
|
924
|
-
node,
|
|
925
|
-
tree.getEntrySize
|
|
926
|
-
);
|
|
927
|
-
newEntries.push(newHashEntry);
|
|
928
|
-
}
|
|
929
|
-
if (this.isMutable) {
|
|
930
|
-
this.entries.splice(startIndex, removeCount, ...newEntries);
|
|
931
|
-
this._updateNode(tree);
|
|
932
|
-
return this;
|
|
933
|
-
}
|
|
934
|
-
const entries = readonlySplice(
|
|
935
|
-
thisEntries,
|
|
936
|
-
startIndex,
|
|
937
|
-
removeCount,
|
|
938
|
-
...newEntries
|
|
939
|
-
);
|
|
940
|
-
return tree.newInternalNodeImpl(entries, this.level);
|
|
941
|
-
}
|
|
942
|
-
#replaceChild(tree, index, newEntry) {
|
|
943
|
-
if (this.isMutable) {
|
|
944
|
-
this.entries.splice(index, 1, newEntry);
|
|
945
|
-
this._updateNode(tree);
|
|
946
|
-
return this;
|
|
947
|
-
}
|
|
948
|
-
const entries = readonlySplice(this.entries, index, 1, newEntry);
|
|
949
|
-
return tree.newInternalNodeImpl(entries, this.level);
|
|
950
|
-
}
|
|
951
|
-
async del(key, tree) {
|
|
952
|
-
const i = binarySearch2(key, this.entries);
|
|
953
|
-
if (i === this.entries.length) {
|
|
954
|
-
return this;
|
|
955
|
-
}
|
|
956
|
-
const childHash = this.entries[i][1];
|
|
957
|
-
const oldChildNode = await tree.getNode(childHash);
|
|
958
|
-
const oldHash = oldChildNode.hash;
|
|
959
|
-
const childNode = await oldChildNode.del(key, tree);
|
|
960
|
-
if (childNode.hash === oldHash) {
|
|
961
|
-
return this;
|
|
962
|
-
}
|
|
963
|
-
if (childNode.entries.length === 0) {
|
|
964
|
-
const entries = readonlySplice(this.entries, i, 1);
|
|
965
|
-
return tree.newInternalNodeImpl(entries, this.level);
|
|
966
|
-
}
|
|
967
|
-
if (i === 0 && this.entries.length === 1) {
|
|
968
|
-
return childNode;
|
|
969
|
-
}
|
|
970
|
-
if (childNode.getChildNodeSize(tree) > tree.minSize) {
|
|
971
|
-
const entry = createNewInternalEntryForNode(childNode, tree.getEntrySize);
|
|
972
|
-
return this.#replaceChild(tree, i, entry);
|
|
973
|
-
}
|
|
974
|
-
return this.#mergeAndPartition(tree, i, childNode);
|
|
975
|
-
}
|
|
976
|
-
async *keys(tree) {
|
|
977
|
-
for (const entry of this.entries) {
|
|
978
|
-
const childNode = await tree.getNode(entry[1]);
|
|
979
|
-
yield* childNode.keys(tree);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
async *entriesIter(tree) {
|
|
983
|
-
for (const entry of this.entries) {
|
|
984
|
-
const childNode = await tree.getNode(entry[1]);
|
|
985
|
-
yield* childNode.entriesIter(tree);
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
getChildren(start, length, tree) {
|
|
989
|
-
const ps = [];
|
|
990
|
-
for (let i = start; i < length && i < this.entries.length; i++) {
|
|
991
|
-
ps.push(tree.getNode(this.entries[i][1]));
|
|
992
|
-
}
|
|
993
|
-
return Promise.all(ps);
|
|
994
|
-
}
|
|
995
|
-
async getCompositeChildren(start, length, tree) {
|
|
996
|
-
const { level } = this;
|
|
997
|
-
if (length === 0) {
|
|
998
|
-
return new _InternalNodeImpl([], newRandomHash(), level - 1, true);
|
|
999
|
-
}
|
|
1000
|
-
const output = await this.getChildren(start, start + length, tree);
|
|
1001
|
-
if (level > 1) {
|
|
1002
|
-
const entries2 = [];
|
|
1003
|
-
for (const child of output) {
|
|
1004
|
-
entries2.push(...child.entries);
|
|
1005
|
-
}
|
|
1006
|
-
return new _InternalNodeImpl(entries2, newRandomHash(), level - 1, true);
|
|
1007
|
-
}
|
|
1008
|
-
assert(level === 1);
|
|
1009
|
-
const entries = [];
|
|
1010
|
-
for (const child of output) {
|
|
1011
|
-
entries.push(...child.entries);
|
|
1012
|
-
}
|
|
1013
|
-
return new DataNodeImpl(entries, newRandomHash(), true);
|
|
1014
|
-
}
|
|
1015
|
-
};
|
|
1016
|
-
function newNodeImpl(entries, hash2, level, isMutable) {
|
|
1017
|
-
if (level === 0) {
|
|
1018
|
-
return new DataNodeImpl(
|
|
1019
|
-
entries,
|
|
1020
|
-
hash2,
|
|
1021
|
-
isMutable
|
|
1022
|
-
);
|
|
1023
|
-
}
|
|
1024
|
-
return new InternalNodeImpl(entries, hash2, level, isMutable);
|
|
1025
|
-
}
|
|
1026
|
-
function isDataNodeImpl(node) {
|
|
1027
|
-
return node.level === 0;
|
|
1028
|
-
}
|
|
1029
|
-
function partition(values, getSizeOfEntry2, min, max) {
|
|
1030
|
-
const partitions = [];
|
|
1031
|
-
const sizes = [];
|
|
1032
|
-
let sum = 0;
|
|
1033
|
-
let accum = [];
|
|
1034
|
-
for (const value of values) {
|
|
1035
|
-
const size = getSizeOfEntry2(value);
|
|
1036
|
-
if (size >= max) {
|
|
1037
|
-
if (accum.length > 0) {
|
|
1038
|
-
partitions.push(accum);
|
|
1039
|
-
sizes.push(sum);
|
|
1040
|
-
}
|
|
1041
|
-
partitions.push([value]);
|
|
1042
|
-
sizes.push(size);
|
|
1043
|
-
sum = 0;
|
|
1044
|
-
accum = [];
|
|
1045
|
-
} else if (sum + size >= min) {
|
|
1046
|
-
accum.push(value);
|
|
1047
|
-
partitions.push(accum);
|
|
1048
|
-
sizes.push(sum + size);
|
|
1049
|
-
sum = 0;
|
|
1050
|
-
accum = [];
|
|
1051
|
-
} else {
|
|
1052
|
-
sum += size;
|
|
1053
|
-
accum.push(value);
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
if (sum > 0) {
|
|
1057
|
-
if (sizes.length > 0 && sum + sizes[sizes.length - 1] <= max) {
|
|
1058
|
-
partitions[partitions.length - 1].push(...accum);
|
|
1059
|
-
} else {
|
|
1060
|
-
partitions.push(accum);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
return partitions;
|
|
1064
|
-
}
|
|
1065
|
-
var emptyDataNode = makeNodeChunkData(
|
|
1066
|
-
0,
|
|
1067
|
-
[],
|
|
1068
|
-
Latest
|
|
1069
|
-
);
|
|
1070
|
-
var emptyDataNodeImpl = new DataNodeImpl([], emptyHash, false);
|
|
1071
|
-
function createNewInternalEntryForNode(node, getSizeOfEntry2) {
|
|
1072
|
-
const key = node.maxKey();
|
|
1073
|
-
const value = node.hash;
|
|
1074
|
-
const size = getSizeOfEntry2(key, value);
|
|
1075
|
-
return [key, value, size];
|
|
1076
|
-
}
|
|
1077
|
-
|
|
1078
|
-
// ../replicache/src/btree/splice.ts
|
|
1079
|
-
var SPLICE_UNASSIGNED = -1;
|
|
1080
|
-
var SPLICE_AT = 0;
|
|
1081
|
-
var SPLICE_REMOVED = 1;
|
|
1082
|
-
var SPLICE_ADDED = 2;
|
|
1083
|
-
var SPLICE_FROM = 3;
|
|
1084
|
-
var KEY = 0;
|
|
1085
|
-
var VALUE = 1;
|
|
1086
|
-
function* computeSplices(previous, current) {
|
|
1087
|
-
let previousIndex = 0;
|
|
1088
|
-
let currentIndex = 0;
|
|
1089
|
-
let splice;
|
|
1090
|
-
function ensureAssigned(splice2, index) {
|
|
1091
|
-
if (splice2[SPLICE_FROM] === SPLICE_UNASSIGNED) {
|
|
1092
|
-
splice2[SPLICE_FROM] = index;
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
function newSplice() {
|
|
1096
|
-
return [previousIndex, 0, 0, SPLICE_UNASSIGNED];
|
|
1097
|
-
}
|
|
1098
|
-
while (previousIndex < previous.length && currentIndex < current.length) {
|
|
1099
|
-
if (previous[previousIndex][KEY] === current[currentIndex][KEY]) {
|
|
1100
|
-
if (deepEqual(
|
|
1101
|
-
// These are really Hash | InternalValue
|
|
1102
|
-
previous[previousIndex][VALUE],
|
|
1103
|
-
current[currentIndex][VALUE]
|
|
1104
|
-
)) {
|
|
1105
|
-
if (splice) {
|
|
1106
|
-
ensureAssigned(splice, 0);
|
|
1107
|
-
yield splice;
|
|
1108
|
-
splice = void 0;
|
|
1109
|
-
}
|
|
1110
|
-
} else {
|
|
1111
|
-
if (!splice) {
|
|
1112
|
-
splice = newSplice();
|
|
1113
|
-
}
|
|
1114
|
-
splice[SPLICE_ADDED]++;
|
|
1115
|
-
splice[SPLICE_REMOVED]++;
|
|
1116
|
-
ensureAssigned(splice, currentIndex);
|
|
1117
|
-
}
|
|
1118
|
-
previousIndex++;
|
|
1119
|
-
currentIndex++;
|
|
1120
|
-
} else if (previous[previousIndex][KEY] < current[currentIndex][KEY]) {
|
|
1121
|
-
if (!splice) {
|
|
1122
|
-
splice = newSplice();
|
|
1123
|
-
}
|
|
1124
|
-
splice[SPLICE_REMOVED]++;
|
|
1125
|
-
previousIndex++;
|
|
1126
|
-
} else {
|
|
1127
|
-
if (!splice) {
|
|
1128
|
-
splice = newSplice();
|
|
1129
|
-
}
|
|
1130
|
-
splice[SPLICE_ADDED]++;
|
|
1131
|
-
ensureAssigned(splice, currentIndex);
|
|
1132
|
-
currentIndex++;
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
if (currentIndex < current.length) {
|
|
1136
|
-
if (!splice) {
|
|
1137
|
-
splice = newSplice();
|
|
1138
|
-
}
|
|
1139
|
-
splice[SPLICE_ADDED] += current.length - currentIndex;
|
|
1140
|
-
ensureAssigned(splice, currentIndex);
|
|
1141
|
-
}
|
|
1142
|
-
if (previousIndex < previous.length) {
|
|
1143
|
-
if (!splice) {
|
|
1144
|
-
splice = newSplice();
|
|
1145
|
-
}
|
|
1146
|
-
splice[SPLICE_REMOVED] += previous.length - previousIndex;
|
|
1147
|
-
}
|
|
1148
|
-
if (splice) {
|
|
1149
|
-
ensureAssigned(splice, 0);
|
|
1150
|
-
yield splice;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
// ../replicache/src/btree/read.ts
|
|
1155
|
-
var NODE_HEADER_SIZE = 11;
|
|
1156
|
-
var BTreeRead = class {
|
|
1157
|
-
_cache = /* @__PURE__ */ new Map();
|
|
1158
|
-
_dagRead;
|
|
1159
|
-
_formatVersion;
|
|
1160
|
-
rootHash;
|
|
1161
|
-
getEntrySize;
|
|
1162
|
-
chunkHeaderSize;
|
|
1163
|
-
constructor(dagRead, formatVersion, root = emptyHash, getEntrySize = getSizeOfEntry, chunkHeaderSize = NODE_HEADER_SIZE) {
|
|
1164
|
-
this._dagRead = dagRead;
|
|
1165
|
-
this._formatVersion = formatVersion;
|
|
1166
|
-
this.rootHash = root;
|
|
1167
|
-
this.getEntrySize = getEntrySize;
|
|
1168
|
-
this.chunkHeaderSize = chunkHeaderSize;
|
|
1169
|
-
}
|
|
1170
|
-
async getNode(hash2) {
|
|
1171
|
-
if (hash2 === emptyHash) {
|
|
1172
|
-
return emptyDataNodeImpl;
|
|
1173
|
-
}
|
|
1174
|
-
const cached = this._cache.get(hash2);
|
|
1175
|
-
if (cached) {
|
|
1176
|
-
return cached;
|
|
1177
|
-
}
|
|
1178
|
-
const chunk = await this._dagRead.mustGetChunk(hash2);
|
|
1179
|
-
const data = parseBTreeNode(
|
|
1180
|
-
chunk.data,
|
|
1181
|
-
this._formatVersion,
|
|
1182
|
-
this.getEntrySize
|
|
1183
|
-
);
|
|
1184
|
-
const impl = newNodeImpl(
|
|
1185
|
-
data[NODE_ENTRIES],
|
|
1186
|
-
hash2,
|
|
1187
|
-
data[NODE_LEVEL],
|
|
1188
|
-
false
|
|
1189
|
-
);
|
|
1190
|
-
this._cache.set(hash2, impl);
|
|
1191
|
-
return impl;
|
|
1192
|
-
}
|
|
1193
|
-
async get(key) {
|
|
1194
|
-
const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);
|
|
1195
|
-
const index = binarySearch2(key, leaf.entries);
|
|
1196
|
-
if (!binarySearchFound(index, leaf.entries, key)) {
|
|
1197
|
-
return void 0;
|
|
1198
|
-
}
|
|
1199
|
-
return leaf.entries[index][1];
|
|
1200
|
-
}
|
|
1201
|
-
async has(key) {
|
|
1202
|
-
const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);
|
|
1203
|
-
const index = binarySearch2(key, leaf.entries);
|
|
1204
|
-
return binarySearchFound(index, leaf.entries, key);
|
|
1205
|
-
}
|
|
1206
|
-
async isEmpty() {
|
|
1207
|
-
const { rootHash } = this;
|
|
1208
|
-
const node = await this.getNode(this.rootHash);
|
|
1209
|
-
if (this.rootHash !== rootHash) {
|
|
1210
|
-
return this.isEmpty();
|
|
1211
|
-
}
|
|
1212
|
-
return node.entries.length === 0;
|
|
1213
|
-
}
|
|
1214
|
-
// We don't do any encoding of the key in the map, so we have no way of
|
|
1215
|
-
// determining from an entry.key alone whether it is a regular key or an
|
|
1216
|
-
// encoded IndexKey in an index map. Without encoding regular map keys the
|
|
1217
|
-
// caller has to deal with encoding and decoding the keys for the index map.
|
|
1218
|
-
scan(fromKey) {
|
|
1219
|
-
return scanForHash(
|
|
1220
|
-
this.rootHash,
|
|
1221
|
-
() => this.rootHash,
|
|
1222
|
-
this.rootHash,
|
|
1223
|
-
fromKey,
|
|
1224
|
-
async (hash2) => {
|
|
1225
|
-
const cached = await this.getNode(hash2);
|
|
1226
|
-
if (cached) {
|
|
1227
|
-
return [
|
|
1228
|
-
cached.level,
|
|
1229
|
-
cached.isMutable ? cached.entries.slice() : cached.entries
|
|
1230
|
-
];
|
|
1231
|
-
}
|
|
1232
|
-
const chunk = await this._dagRead.mustGetChunk(hash2);
|
|
1233
|
-
return parseBTreeNode(
|
|
1234
|
-
chunk.data,
|
|
1235
|
-
this._formatVersion,
|
|
1236
|
-
this.getEntrySize
|
|
1237
|
-
);
|
|
1238
|
-
}
|
|
1239
|
-
);
|
|
1240
|
-
}
|
|
1241
|
-
async *keys() {
|
|
1242
|
-
const node = await this.getNode(this.rootHash);
|
|
1243
|
-
yield* node.keys(this);
|
|
1244
|
-
}
|
|
1245
|
-
async *entries() {
|
|
1246
|
-
const node = await this.getNode(this.rootHash);
|
|
1247
|
-
yield* node.entriesIter(this);
|
|
1248
|
-
}
|
|
1249
|
-
[Symbol.asyncIterator]() {
|
|
1250
|
-
return this.entries();
|
|
1251
|
-
}
|
|
1252
|
-
async *diff(last) {
|
|
1253
|
-
const [currentNode, lastNode] = await Promise.all([
|
|
1254
|
-
this.getNode(this.rootHash),
|
|
1255
|
-
last.getNode(last.rootHash)
|
|
1256
|
-
]);
|
|
1257
|
-
yield* diffNodes(lastNode, currentNode, last, this);
|
|
1258
|
-
}
|
|
1259
|
-
};
|
|
1260
|
-
async function* diffNodes(last, current, lastTree, currentTree) {
|
|
1261
|
-
if (last.level > current.level) {
|
|
1262
|
-
const lastChild = await last.getCompositeChildren(
|
|
1263
|
-
0,
|
|
1264
|
-
last.entries.length,
|
|
1265
|
-
lastTree
|
|
1266
|
-
);
|
|
1267
|
-
yield* diffNodes(lastChild, current, lastTree, currentTree);
|
|
1268
|
-
return;
|
|
1269
|
-
}
|
|
1270
|
-
if (current.level > last.level) {
|
|
1271
|
-
const currentChild = await current.getCompositeChildren(
|
|
1272
|
-
0,
|
|
1273
|
-
current.entries.length,
|
|
1274
|
-
currentTree
|
|
1275
|
-
);
|
|
1276
|
-
yield* diffNodes(last, currentChild, lastTree, currentTree);
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
if (isDataNodeImpl(last) && isDataNodeImpl(current)) {
|
|
1280
|
-
yield* diffEntries(
|
|
1281
|
-
last.entries,
|
|
1282
|
-
current.entries
|
|
1283
|
-
);
|
|
1284
|
-
return;
|
|
1285
|
-
}
|
|
1286
|
-
const initialSplices = computeSplices(
|
|
1287
|
-
last.entries,
|
|
1288
|
-
current.entries
|
|
1289
|
-
);
|
|
1290
|
-
for (const splice of initialSplices) {
|
|
1291
|
-
const [lastChild, currentChild] = await Promise.all([
|
|
1292
|
-
last.getCompositeChildren(
|
|
1293
|
-
splice[SPLICE_AT],
|
|
1294
|
-
splice[SPLICE_REMOVED],
|
|
1295
|
-
lastTree
|
|
1296
|
-
),
|
|
1297
|
-
current.getCompositeChildren(
|
|
1298
|
-
splice[SPLICE_FROM],
|
|
1299
|
-
splice[SPLICE_ADDED],
|
|
1300
|
-
currentTree
|
|
1301
|
-
)
|
|
1302
|
-
]);
|
|
1303
|
-
yield* diffNodes(lastChild, currentChild, lastTree, currentTree);
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
function* diffEntries(lastEntries, currentEntries) {
|
|
1307
|
-
const lastLength = lastEntries.length;
|
|
1308
|
-
const currentLength = currentEntries.length;
|
|
1309
|
-
let i = 0;
|
|
1310
|
-
let j = 0;
|
|
1311
|
-
while (i < lastLength && j < currentLength) {
|
|
1312
|
-
const lastKey = lastEntries[i][0];
|
|
1313
|
-
const currentKey = currentEntries[j][0];
|
|
1314
|
-
if (lastKey === currentKey) {
|
|
1315
|
-
if (!deepEqual(lastEntries[i][1], currentEntries[j][1])) {
|
|
1316
|
-
yield {
|
|
1317
|
-
op: "change",
|
|
1318
|
-
key: lastKey,
|
|
1319
|
-
oldValue: lastEntries[i][1],
|
|
1320
|
-
newValue: currentEntries[j][1]
|
|
1321
|
-
};
|
|
1322
|
-
}
|
|
1323
|
-
i++;
|
|
1324
|
-
j++;
|
|
1325
|
-
} else if (lastKey < currentKey) {
|
|
1326
|
-
yield {
|
|
1327
|
-
op: "del",
|
|
1328
|
-
key: lastKey,
|
|
1329
|
-
oldValue: lastEntries[i][1]
|
|
1330
|
-
};
|
|
1331
|
-
i++;
|
|
1332
|
-
} else {
|
|
1333
|
-
yield {
|
|
1334
|
-
op: "add",
|
|
1335
|
-
key: currentKey,
|
|
1336
|
-
newValue: currentEntries[j][1]
|
|
1337
|
-
};
|
|
1338
|
-
j++;
|
|
1339
|
-
}
|
|
1340
|
-
}
|
|
1341
|
-
for (; i < lastLength; i++) {
|
|
1342
|
-
yield {
|
|
1343
|
-
op: "del",
|
|
1344
|
-
key: lastEntries[i][0],
|
|
1345
|
-
oldValue: lastEntries[i][1]
|
|
1346
|
-
};
|
|
1347
|
-
}
|
|
1348
|
-
for (; j < currentLength; j++) {
|
|
1349
|
-
yield {
|
|
1350
|
-
op: "add",
|
|
1351
|
-
key: currentEntries[j][0],
|
|
1352
|
-
newValue: currentEntries[j][1]
|
|
1353
|
-
};
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
async function* scanForHash(expectedRootHash, getRootHash, hash2, fromKey, readNode) {
|
|
1357
|
-
if (hash2 === emptyHash) {
|
|
1358
|
-
return;
|
|
1359
|
-
}
|
|
1360
|
-
const data = await readNode(hash2);
|
|
1361
|
-
const entries = data[NODE_ENTRIES];
|
|
1362
|
-
let i = 0;
|
|
1363
|
-
if (fromKey) {
|
|
1364
|
-
i = binarySearch2(fromKey, entries);
|
|
1365
|
-
}
|
|
1366
|
-
if (data[NODE_LEVEL] > 0) {
|
|
1367
|
-
for (; i < entries.length; i++) {
|
|
1368
|
-
yield* scanForHash(
|
|
1369
|
-
expectedRootHash,
|
|
1370
|
-
getRootHash,
|
|
1371
|
-
entries[i][1],
|
|
1372
|
-
fromKey,
|
|
1373
|
-
readNode
|
|
1374
|
-
);
|
|
1375
|
-
fromKey = "";
|
|
1376
|
-
}
|
|
1377
|
-
} else {
|
|
1378
|
-
for (; i < entries.length; i++) {
|
|
1379
|
-
const rootHash = getRootHash();
|
|
1380
|
-
if (expectedRootHash !== rootHash) {
|
|
1381
|
-
yield* scanForHash(
|
|
1382
|
-
rootHash,
|
|
1383
|
-
getRootHash,
|
|
1384
|
-
rootHash,
|
|
1385
|
-
entries[i][0],
|
|
1386
|
-
readNode
|
|
1387
|
-
);
|
|
1388
|
-
return;
|
|
1389
|
-
}
|
|
1390
|
-
yield entries[i];
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
-
async function allEntriesAsDiff(map, op) {
|
|
1395
|
-
const diff3 = [];
|
|
1396
|
-
const make = op === "add" ? (entry) => ({
|
|
1397
|
-
op: "add",
|
|
1398
|
-
key: entry[0],
|
|
1399
|
-
newValue: entry[1]
|
|
1400
|
-
}) : (entry) => ({
|
|
1401
|
-
op: "del",
|
|
1402
|
-
key: entry[0],
|
|
1403
|
-
oldValue: entry[1]
|
|
1404
|
-
});
|
|
1405
|
-
for await (const entry of map.entries()) {
|
|
1406
|
-
diff3.push(make(entry));
|
|
1407
|
-
}
|
|
1408
|
-
return diff3;
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
// ../shared/src/string-compare.ts
|
|
1412
|
-
function stringCompare(a, b) {
|
|
1413
|
-
if (a === b) {
|
|
1414
|
-
return 0;
|
|
1415
|
-
}
|
|
1416
|
-
if (a < b) {
|
|
1417
|
-
return -1;
|
|
1418
|
-
}
|
|
1419
|
-
return 1;
|
|
1420
|
-
}
|
|
1421
|
-
|
|
1422
|
-
// ../replicache/src/cookies.ts
|
|
1423
|
-
function compareCookies(a, b) {
|
|
1424
|
-
if (a === b) {
|
|
1425
|
-
return 0;
|
|
1426
|
-
}
|
|
1427
|
-
if (a === null) {
|
|
1428
|
-
return -1;
|
|
1429
|
-
}
|
|
1430
|
-
if (b === null) {
|
|
1431
|
-
return 1;
|
|
1432
|
-
}
|
|
1433
|
-
const cva = getCompareValue(a);
|
|
1434
|
-
const cvb = getCompareValue(b);
|
|
1435
|
-
if (typeof cva === "string" || typeof cvb === "string") {
|
|
1436
|
-
return stringCompare(String(cva), String(cvb));
|
|
1437
|
-
}
|
|
1438
|
-
return cva - cvb;
|
|
1439
|
-
}
|
|
1440
|
-
function getCompareValue(cookie) {
|
|
1441
|
-
if (typeof cookie === "string" || typeof cookie === "number") {
|
|
1442
|
-
return cookie;
|
|
1443
|
-
}
|
|
1444
|
-
return cookie.order;
|
|
1445
|
-
}
|
|
1446
|
-
function assertCookie(v2) {
|
|
1447
|
-
if (v2 === null || typeof v2 === "string" || typeof v2 === "number") {
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1450
|
-
assertJSONObject(v2);
|
|
1451
|
-
if (typeof v2.order === "string" || typeof v2.order === "number") {
|
|
1452
|
-
return;
|
|
1453
|
-
}
|
|
1454
|
-
throw new Error("Invalid cookie");
|
|
1455
|
-
}
|
|
1456
|
-
|
|
1457
|
-
// ../replicache/src/dag/chunk.ts
|
|
1458
|
-
function asRefs(sortedRefs) {
|
|
1459
|
-
return sortedRefs;
|
|
1460
|
-
}
|
|
1461
|
-
function toRefs(refs) {
|
|
1462
|
-
if (Array.isArray(refs)) {
|
|
1463
|
-
refs.sort();
|
|
1464
|
-
for (let i = 1; i < refs.length; i++) {
|
|
1465
|
-
assert(refs[i - 1] !== refs[i], "Refs must not have duplicates");
|
|
1466
|
-
}
|
|
1467
|
-
return asRefs(refs);
|
|
1468
|
-
}
|
|
1469
|
-
const refsArray = [...refs];
|
|
1470
|
-
refsArray.sort();
|
|
1471
|
-
return asRefs(refsArray);
|
|
1472
|
-
}
|
|
1473
|
-
var Chunk = class {
|
|
1474
|
-
hash;
|
|
1475
|
-
data;
|
|
1476
|
-
/**
|
|
1477
|
-
* Meta is an array of refs. If there are no refs we do not write a meta
|
|
1478
|
-
* chunk.
|
|
1479
|
-
*/
|
|
1480
|
-
meta;
|
|
1481
|
-
constructor(hash2, data, refs) {
|
|
1482
|
-
assert(
|
|
1483
|
-
!refs.includes(hash2),
|
|
1484
|
-
"Chunk cannot reference itself"
|
|
1485
|
-
);
|
|
1486
|
-
assertDeepFrozen(data);
|
|
1487
|
-
this.hash = hash2;
|
|
1488
|
-
this.data = data;
|
|
1489
|
-
this.meta = refs;
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
function assertRefs(v2) {
|
|
1493
|
-
if (!Array.isArray(v2)) {
|
|
1494
|
-
throw new Error("Refs must be an array");
|
|
1495
|
-
}
|
|
1496
|
-
if (v2.length > 0) {
|
|
1497
|
-
assertString(v2[0]);
|
|
1498
|
-
for (let i = 1; i < v2.length; i++) {
|
|
1499
|
-
assertString(v2[i]);
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
function createChunk(data, refs, chunkHasher) {
|
|
1504
|
-
const hash2 = chunkHasher();
|
|
1505
|
-
return new Chunk(hash2, data, refs);
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
// ../replicache/src/db/meta-type-enum.ts
|
|
1509
|
-
var LocalDD31 = 4;
|
|
1510
|
-
var SnapshotDD31 = 5;
|
|
1511
|
-
|
|
1512
|
-
// ../replicache/src/db/commit.ts
|
|
1513
|
-
var DEFAULT_HEAD_NAME = "main";
|
|
1514
|
-
function commitIsLocalDD31(commit) {
|
|
1515
|
-
return isLocalMetaDD31(commit.meta);
|
|
1516
|
-
}
|
|
1517
|
-
function commitIsLocal(commit) {
|
|
1518
|
-
return commitIsLocalDD31(commit);
|
|
1519
|
-
}
|
|
1520
|
-
function commitIsSnapshot(commit) {
|
|
1521
|
-
return isSnapshotMetaDD31(commit.meta);
|
|
1522
|
-
}
|
|
1523
|
-
var Commit = class {
|
|
1524
|
-
chunk;
|
|
1525
|
-
constructor(chunk) {
|
|
1526
|
-
this.chunk = chunk;
|
|
1527
|
-
}
|
|
1528
|
-
get meta() {
|
|
1529
|
-
return this.chunk.data.meta;
|
|
1530
|
-
}
|
|
1531
|
-
get valueHash() {
|
|
1532
|
-
return this.chunk.data.valueHash;
|
|
1533
|
-
}
|
|
1534
|
-
getMutationID(clientID, dagRead) {
|
|
1535
|
-
return getMutationID(clientID, dagRead, this.meta);
|
|
1536
|
-
}
|
|
1537
|
-
async getNextMutationID(clientID, dagRead) {
|
|
1538
|
-
return await this.getMutationID(clientID, dagRead) + 1;
|
|
1539
|
-
}
|
|
1540
|
-
get indexes() {
|
|
1541
|
-
return this.chunk.data.indexes;
|
|
1542
|
-
}
|
|
1543
|
-
};
|
|
1544
|
-
async function getMutationID(clientID, dagRead, meta) {
|
|
1545
|
-
switch (meta.type) {
|
|
1546
|
-
case SnapshotDD31:
|
|
1547
|
-
return meta.lastMutationIDs[clientID] ?? 0;
|
|
1548
|
-
case LocalDD31: {
|
|
1549
|
-
if (meta.clientID === clientID) {
|
|
1550
|
-
return meta.mutationID;
|
|
1551
|
-
}
|
|
1552
|
-
const { basisHash } = meta;
|
|
1553
|
-
const basisCommit = await commitFromHash(basisHash, dagRead);
|
|
1554
|
-
return getMutationID(clientID, dagRead, basisCommit.meta);
|
|
1555
|
-
}
|
|
1556
|
-
default:
|
|
1557
|
-
unreachable(meta);
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
async function localMutations(fromCommitHash, dagRead) {
|
|
1561
|
-
const commits = await commitChain(fromCommitHash, dagRead);
|
|
1562
|
-
return commits.filter((c) => commitIsLocal(c));
|
|
1563
|
-
}
|
|
1564
|
-
async function localMutationsDD31(fromCommitHash, dagRead) {
|
|
1565
|
-
const commits = await commitChain(fromCommitHash, dagRead);
|
|
1566
|
-
return commits.filter((c) => commitIsLocalDD31(c));
|
|
1567
|
-
}
|
|
1568
|
-
async function localMutationsGreaterThan(commit, mutationIDLimits, dagRead) {
|
|
1569
|
-
const commits = [];
|
|
1570
|
-
const remainingMutationIDLimits = new Map(Object.entries(mutationIDLimits));
|
|
1571
|
-
while (!commitIsSnapshot(commit) && remainingMutationIDLimits.size > 0) {
|
|
1572
|
-
if (commitIsLocalDD31(commit)) {
|
|
1573
|
-
const { meta } = commit;
|
|
1574
|
-
const mutationIDLowerLimit = remainingMutationIDLimits.get(meta.clientID);
|
|
1575
|
-
if (mutationIDLowerLimit !== void 0) {
|
|
1576
|
-
if (meta.mutationID <= mutationIDLowerLimit) {
|
|
1577
|
-
remainingMutationIDLimits.delete(meta.clientID);
|
|
1578
|
-
} else {
|
|
1579
|
-
commits.push(commit);
|
|
1580
|
-
}
|
|
1581
|
-
}
|
|
1582
|
-
}
|
|
1583
|
-
const { basisHash } = commit.meta;
|
|
1584
|
-
if (basisHash === null) {
|
|
1585
|
-
throw new Error(`Commit ${commit.chunk.hash} has no basis`);
|
|
1586
|
-
}
|
|
1587
|
-
commit = await commitFromHash(basisHash, dagRead);
|
|
1588
|
-
}
|
|
1589
|
-
return commits;
|
|
1590
|
-
}
|
|
1591
|
-
async function baseSnapshotFromHead(name, dagRead) {
|
|
1592
|
-
const hash2 = await dagRead.getHead(name);
|
|
1593
|
-
assert(hash2, `Missing head ${name}`);
|
|
1594
|
-
return baseSnapshotFromHash(hash2, dagRead);
|
|
1595
|
-
}
|
|
1596
|
-
async function baseSnapshotHashFromHash(hash2, dagRead) {
|
|
1597
|
-
return (await baseSnapshotFromHash(hash2, dagRead)).chunk.hash;
|
|
1598
|
-
}
|
|
1599
|
-
async function baseSnapshotFromHash(hash2, dagRead) {
|
|
1600
|
-
const commit = await commitFromHash(hash2, dagRead);
|
|
1601
|
-
return baseSnapshotFromCommit(commit, dagRead);
|
|
1602
|
-
}
|
|
1603
|
-
async function baseSnapshotFromCommit(commit, dagRead) {
|
|
1604
|
-
while (!commitIsSnapshot(commit)) {
|
|
1605
|
-
const { meta } = commit;
|
|
1606
|
-
if (isLocalMetaDD31(meta)) {
|
|
1607
|
-
commit = await commitFromHash(meta.baseSnapshotHash, dagRead);
|
|
1608
|
-
} else {
|
|
1609
|
-
const { basisHash } = meta;
|
|
1610
|
-
if (basisHash === null) {
|
|
1611
|
-
throw new Error(`Commit ${commit.chunk.hash} has no basis`);
|
|
1612
|
-
}
|
|
1613
|
-
commit = await commitFromHash(basisHash, dagRead);
|
|
1614
|
-
}
|
|
1615
|
-
}
|
|
1616
|
-
return commit;
|
|
1617
|
-
}
|
|
1618
|
-
function snapshotMetaParts(c, clientID) {
|
|
1619
|
-
const m = c.meta;
|
|
1620
|
-
const lmid = m.lastMutationIDs[clientID] ?? 0;
|
|
1621
|
-
return [lmid, m.cookieJSON];
|
|
1622
|
-
}
|
|
1623
|
-
function compareCookiesForSnapshots(a, b) {
|
|
1624
|
-
return compareCookies(a.meta.cookieJSON, b.meta.cookieJSON);
|
|
1625
|
-
}
|
|
1626
|
-
async function commitChain(fromCommitHash, dagRead) {
|
|
1627
|
-
let commit = await commitFromHash(fromCommitHash, dagRead);
|
|
1628
|
-
const commits = [];
|
|
1629
|
-
while (!commitIsSnapshot(commit)) {
|
|
1630
|
-
const { meta } = commit;
|
|
1631
|
-
const { basisHash } = meta;
|
|
1632
|
-
if (basisHash === null) {
|
|
1633
|
-
throw new Error(`Commit ${commit.chunk.hash} has no basis`);
|
|
1634
|
-
}
|
|
1635
|
-
commits.push(commit);
|
|
1636
|
-
commit = await commitFromHash(basisHash, dagRead);
|
|
1637
|
-
}
|
|
1638
|
-
commits.push(commit);
|
|
1639
|
-
return commits;
|
|
1640
|
-
}
|
|
1641
|
-
async function commitFromHash(hash2, dagRead) {
|
|
1642
|
-
const chunk = await dagRead.mustGetChunk(hash2);
|
|
1643
|
-
return fromChunk(chunk);
|
|
1644
|
-
}
|
|
1645
|
-
async function commitFromHead(name, dagRead) {
|
|
1646
|
-
const hash2 = await mustGetHeadHash(name, dagRead);
|
|
1647
|
-
return commitFromHash(hash2, dagRead);
|
|
1648
|
-
}
|
|
1649
|
-
function assertLocalMetaDD31(v2) {
|
|
1650
|
-
assertString(v2.clientID);
|
|
1651
|
-
assertNumber(v2.mutationID);
|
|
1652
|
-
assertString(v2.mutatorName);
|
|
1653
|
-
if (!v2.mutatorName) {
|
|
1654
|
-
throw new Error("Missing mutator name");
|
|
1655
|
-
}
|
|
1656
|
-
assertJSONValue(v2.mutatorArgsJSON);
|
|
1657
|
-
if (v2.originalHash !== null) {
|
|
1658
|
-
assertHash(v2.originalHash);
|
|
1659
|
-
}
|
|
1660
|
-
assertNumber(v2.timestamp);
|
|
1661
|
-
}
|
|
1662
|
-
function isLocalMetaDD31(meta) {
|
|
1663
|
-
return meta.type === LocalDD31;
|
|
1664
|
-
}
|
|
1665
|
-
function assertSnapshotMetaDD31(v2) {
|
|
1666
|
-
if (v2.basisHash !== null) {
|
|
1667
|
-
assertHash(v2.basisHash);
|
|
1668
|
-
}
|
|
1669
|
-
assertJSONValue(v2.cookieJSON);
|
|
1670
|
-
assertLastMutationIDs(v2.lastMutationIDs);
|
|
1671
|
-
}
|
|
1672
|
-
function assertLastMutationIDs(v2) {
|
|
1673
|
-
assertObject(v2);
|
|
1674
|
-
for (const e of Object.values(v2)) {
|
|
1675
|
-
assertNumber(e);
|
|
1676
|
-
}
|
|
1677
|
-
}
|
|
1678
|
-
function assertSnapshotCommitDD31(c) {
|
|
1679
|
-
assertSnapshotMetaDD31(c.meta);
|
|
1680
|
-
}
|
|
1681
|
-
function isSnapshotMetaDD31(meta) {
|
|
1682
|
-
return meta.type === SnapshotDD31;
|
|
1683
|
-
}
|
|
1684
|
-
function assertMeta(v2) {
|
|
1685
|
-
assertObject(v2);
|
|
1686
|
-
assertDeepFrozen(v2);
|
|
1687
|
-
if (v2.basisHash !== null) {
|
|
1688
|
-
assertString(v2.basisHash);
|
|
1689
|
-
}
|
|
1690
|
-
assertNumber(v2.type);
|
|
1691
|
-
switch (v2.type) {
|
|
1692
|
-
case LocalDD31:
|
|
1693
|
-
assertLocalMetaDD31(v2);
|
|
1694
|
-
break;
|
|
1695
|
-
case SnapshotDD31:
|
|
1696
|
-
assertSnapshotMetaDD31(v2);
|
|
1697
|
-
break;
|
|
1698
|
-
default:
|
|
1699
|
-
throw new Error(`Invalid enum value ${v2.type}`);
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
function chunkIndexDefinitionEqualIgnoreName(a, b) {
|
|
1703
|
-
return a.jsonPointer === b.jsonPointer && (a.allowEmpty ?? false) === (b.allowEmpty ?? false) && a.keyPrefix === b.keyPrefix;
|
|
1704
|
-
}
|
|
1705
|
-
function assertChunkIndexDefinition(v2) {
|
|
1706
|
-
assertObject(v2);
|
|
1707
|
-
assertDeepFrozen(v2);
|
|
1708
|
-
assertString(v2.name);
|
|
1709
|
-
assertString(v2.keyPrefix);
|
|
1710
|
-
assertString(v2.jsonPointer);
|
|
1711
|
-
if (v2.allowEmpty !== void 0) {
|
|
1712
|
-
assertBoolean(v2.allowEmpty);
|
|
1713
|
-
}
|
|
1714
|
-
}
|
|
1715
|
-
function toChunkIndexDefinition(name, indexDefinition) {
|
|
1716
|
-
return {
|
|
1717
|
-
name,
|
|
1718
|
-
keyPrefix: indexDefinition.prefix ?? "",
|
|
1719
|
-
jsonPointer: indexDefinition.jsonPointer,
|
|
1720
|
-
allowEmpty: indexDefinition.allowEmpty ?? false
|
|
1721
|
-
};
|
|
1722
|
-
}
|
|
1723
|
-
function assertIndexRecord(v2) {
|
|
1724
|
-
assertObject(v2);
|
|
1725
|
-
assertDeepFrozen(v2);
|
|
1726
|
-
assertChunkIndexDefinition(v2.definition);
|
|
1727
|
-
assertString(v2.valueHash);
|
|
1728
|
-
}
|
|
1729
|
-
function assertIndexRecords(v2) {
|
|
1730
|
-
assertArray(v2);
|
|
1731
|
-
assertDeepFrozen(v2);
|
|
1732
|
-
for (const ir of v2) {
|
|
1733
|
-
assertIndexRecord(ir);
|
|
1734
|
-
}
|
|
1735
|
-
}
|
|
1736
|
-
function newLocalDD31(createChunk2, basisHash, baseSnapshotHash, mutationID, mutatorName, mutatorArgsJSON, originalHash, valueHash, indexes, timestamp, clientID) {
|
|
1737
|
-
const meta = {
|
|
1738
|
-
type: LocalDD31,
|
|
1739
|
-
basisHash,
|
|
1740
|
-
baseSnapshotHash,
|
|
1741
|
-
mutationID,
|
|
1742
|
-
mutatorName,
|
|
1743
|
-
mutatorArgsJSON,
|
|
1744
|
-
originalHash,
|
|
1745
|
-
timestamp,
|
|
1746
|
-
clientID
|
|
1747
|
-
};
|
|
1748
|
-
return commitFromCommitData(
|
|
1749
|
-
createChunk2,
|
|
1750
|
-
makeCommitData(meta, valueHash, indexes)
|
|
1751
|
-
);
|
|
1752
|
-
}
|
|
1753
|
-
function newSnapshotDD31(createChunk2, basisHash, lastMutationIDs, cookieJSON, valueHash, indexes) {
|
|
1754
|
-
return commitFromCommitData(
|
|
1755
|
-
createChunk2,
|
|
1756
|
-
newSnapshotCommitDataDD31(
|
|
1757
|
-
basisHash,
|
|
1758
|
-
lastMutationIDs,
|
|
1759
|
-
cookieJSON,
|
|
1760
|
-
valueHash,
|
|
1761
|
-
indexes
|
|
1762
|
-
)
|
|
1763
|
-
);
|
|
1764
|
-
}
|
|
1765
|
-
function newSnapshotCommitDataDD31(basisHash, lastMutationIDs, cookieJSON, valueHash, indexes) {
|
|
1766
|
-
const meta = {
|
|
1767
|
-
type: SnapshotDD31,
|
|
1768
|
-
basisHash,
|
|
1769
|
-
lastMutationIDs,
|
|
1770
|
-
cookieJSON
|
|
1771
|
-
};
|
|
1772
|
-
return makeCommitData(meta, valueHash, indexes);
|
|
1773
|
-
}
|
|
1774
|
-
function fromChunk(chunk) {
|
|
1775
|
-
validateChunk(chunk);
|
|
1776
|
-
return new Commit(chunk);
|
|
1777
|
-
}
|
|
1778
|
-
function commitFromCommitData(createChunk2, data) {
|
|
1779
|
-
return new Commit(createChunk2(data, getRefs(data)));
|
|
1780
|
-
}
|
|
1781
|
-
function getRefs(data) {
|
|
1782
|
-
const refs = /* @__PURE__ */ new Set();
|
|
1783
|
-
refs.add(data.valueHash);
|
|
1784
|
-
const { meta } = data;
|
|
1785
|
-
switch (meta.type) {
|
|
1786
|
-
case LocalDD31:
|
|
1787
|
-
meta.basisHash && refs.add(meta.basisHash);
|
|
1788
|
-
break;
|
|
1789
|
-
case SnapshotDD31:
|
|
1790
|
-
break;
|
|
1791
|
-
default:
|
|
1792
|
-
unreachable(meta);
|
|
1793
|
-
}
|
|
1794
|
-
for (const index of data.indexes) {
|
|
1795
|
-
refs.add(index.valueHash);
|
|
1796
|
-
}
|
|
1797
|
-
return toRefs(refs);
|
|
1798
|
-
}
|
|
1799
|
-
function makeCommitData(meta, valueHash, indexes) {
|
|
1800
|
-
return deepFreeze({
|
|
1801
|
-
meta,
|
|
1802
|
-
valueHash,
|
|
1803
|
-
indexes
|
|
1804
|
-
});
|
|
1805
|
-
}
|
|
1806
|
-
function assertCommitData(v2) {
|
|
1807
|
-
if (isProd) {
|
|
1808
|
-
return;
|
|
1809
|
-
}
|
|
1810
|
-
assertObject(v2);
|
|
1811
|
-
assertDeepFrozen(v2);
|
|
1812
|
-
assertMeta(v2.meta);
|
|
1813
|
-
assertString(v2.valueHash);
|
|
1814
|
-
assertIndexRecords(v2.indexes);
|
|
1815
|
-
}
|
|
1816
|
-
function validateChunk(chunk) {
|
|
1817
|
-
const { data } = chunk;
|
|
1818
|
-
assertCommitData(data);
|
|
1819
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1820
|
-
for (const index of data.indexes) {
|
|
1821
|
-
const { name } = index.definition;
|
|
1822
|
-
if (seen.has(name)) {
|
|
1823
|
-
throw new Error(`Duplicate index ${name}`);
|
|
1824
|
-
}
|
|
1825
|
-
seen.add(name);
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
|
|
1829
|
-
// ../replicache/src/db/index-operation-enum.ts
|
|
1830
|
-
var Add = 0;
|
|
1831
|
-
var Remove = 1;
|
|
1832
|
-
|
|
1833
|
-
// ../replicache/src/db/index.ts
|
|
1834
|
-
var IndexRead = class {
|
|
1835
|
-
meta;
|
|
1836
|
-
map;
|
|
1837
|
-
constructor(meta, map) {
|
|
1838
|
-
this.meta = meta;
|
|
1839
|
-
this.map = map;
|
|
1840
|
-
}
|
|
1841
|
-
};
|
|
1842
|
-
var IndexWrite = class extends IndexRead {
|
|
1843
|
-
// Note: does not update self.meta.valueHash (doesn't need to at this point as flush
|
|
1844
|
-
// is only called during commit.)
|
|
1845
|
-
flush() {
|
|
1846
|
-
return this.map.flush();
|
|
1847
|
-
}
|
|
1848
|
-
clear() {
|
|
1849
|
-
return this.map.clear();
|
|
1850
|
-
}
|
|
1851
|
-
};
|
|
1852
|
-
async function indexValue(lc, index, op, key, val, jsonPointer, allowEmpty) {
|
|
1853
|
-
try {
|
|
1854
|
-
for (const entry of getIndexKeys(key, val, jsonPointer, allowEmpty)) {
|
|
1855
|
-
switch (op) {
|
|
1856
|
-
case Add:
|
|
1857
|
-
await index.put(entry, val);
|
|
1858
|
-
break;
|
|
1859
|
-
case Remove:
|
|
1860
|
-
await index.del(entry);
|
|
1861
|
-
break;
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
} catch (e) {
|
|
1865
|
-
lc.info?.("Not indexing value", val, ":", e);
|
|
1866
|
-
}
|
|
1867
|
-
}
|
|
1868
|
-
function getIndexKeys(primary, value, jsonPointer, allowEmpty) {
|
|
1869
|
-
const target = evaluateJSONPointer(value, jsonPointer);
|
|
1870
|
-
if (target === void 0) {
|
|
1871
|
-
if (allowEmpty) {
|
|
1872
|
-
return [];
|
|
1873
|
-
}
|
|
1874
|
-
throw new Error(`No value at path: ${jsonPointer}`);
|
|
1875
|
-
}
|
|
1876
|
-
const values = Array.isArray(target) ? target : [target];
|
|
1877
|
-
const indexKeys = [];
|
|
1878
|
-
for (const value2 of values) {
|
|
1879
|
-
if (typeof value2 === "string") {
|
|
1880
|
-
indexKeys.push(encodeIndexKey([value2, primary]));
|
|
1881
|
-
} else {
|
|
1882
|
-
throw new Error("Unsupported target type");
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
return indexKeys;
|
|
1886
|
-
}
|
|
1887
|
-
var KEY_VERSION_0 = "\0";
|
|
1888
|
-
var KEY_SEPARATOR = "\0";
|
|
1889
|
-
function encodeIndexKey(indexKey) {
|
|
1890
|
-
const secondary = indexKey[0];
|
|
1891
|
-
const primary = indexKey[1];
|
|
1892
|
-
if (secondary.includes("\0")) {
|
|
1893
|
-
throw new Error("Secondary key cannot contain null byte");
|
|
1894
|
-
}
|
|
1895
|
-
return KEY_VERSION_0 + secondary + KEY_SEPARATOR + primary;
|
|
1896
|
-
}
|
|
1897
|
-
function encodeIndexScanKey(secondary, primary) {
|
|
1898
|
-
const k = encodeIndexKey([secondary, primary || ""]);
|
|
1899
|
-
if (primary === void 0) {
|
|
1900
|
-
return k.slice(0, k.length - 1);
|
|
1901
|
-
}
|
|
1902
|
-
return k;
|
|
1903
|
-
}
|
|
1904
|
-
function decodeIndexKey(encodedIndexKey) {
|
|
1905
|
-
if (encodedIndexKey[0] !== KEY_VERSION_0) {
|
|
1906
|
-
throw new Error("Invalid version");
|
|
1907
|
-
}
|
|
1908
|
-
const versionLen = KEY_VERSION_0.length;
|
|
1909
|
-
const separatorLen = KEY_SEPARATOR.length;
|
|
1910
|
-
const separatorOffset = encodedIndexKey.indexOf(KEY_SEPARATOR, versionLen);
|
|
1911
|
-
if (separatorOffset === -1) {
|
|
1912
|
-
throw new Error("Invalid formatting");
|
|
1913
|
-
}
|
|
1914
|
-
const secondary = encodedIndexKey.slice(versionLen, separatorOffset);
|
|
1915
|
-
const primary = encodedIndexKey.slice(separatorOffset + separatorLen);
|
|
1916
|
-
return [secondary, primary];
|
|
1917
|
-
}
|
|
1918
|
-
function evaluateJSONPointer(value, pointer) {
|
|
1919
|
-
function parseIndex(s) {
|
|
1920
|
-
if (s.startsWith("+") || s.startsWith("0") && s.length !== 1) {
|
|
1921
|
-
return void 0;
|
|
1922
|
-
}
|
|
1923
|
-
return parseInt(s, 10);
|
|
1924
|
-
}
|
|
1925
|
-
if (pointer === "") {
|
|
1926
|
-
return value;
|
|
1927
|
-
}
|
|
1928
|
-
if (!pointer.startsWith("/")) {
|
|
1929
|
-
throw new Error(`Invalid JSON pointer: ${pointer}`);
|
|
1930
|
-
}
|
|
1931
|
-
const tokens = pointer.split("/").slice(1).map((x) => x.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
1932
|
-
let target = value;
|
|
1933
|
-
for (const token of tokens) {
|
|
1934
|
-
let targetOpt;
|
|
1935
|
-
if (Array.isArray(target)) {
|
|
1936
|
-
const i = parseIndex(token);
|
|
1937
|
-
if (i === void 0) {
|
|
1938
|
-
return void 0;
|
|
1939
|
-
}
|
|
1940
|
-
targetOpt = target[i];
|
|
1941
|
-
} else if (target === null) {
|
|
1942
|
-
return void 0;
|
|
1943
|
-
} else if (typeof target === "object") {
|
|
1944
|
-
target = target;
|
|
1945
|
-
targetOpt = target[token];
|
|
1946
|
-
}
|
|
1947
|
-
if (targetOpt === void 0) {
|
|
1948
|
-
return void 0;
|
|
1949
|
-
}
|
|
1950
|
-
target = targetOpt;
|
|
1951
|
-
}
|
|
1952
|
-
return target;
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
// ../replicache/src/db/read.ts
|
|
1956
|
-
var Read = class {
|
|
1957
|
-
#dagRead;
|
|
1958
|
-
map;
|
|
1959
|
-
indexes;
|
|
1960
|
-
constructor(dagRead, map, indexes) {
|
|
1961
|
-
this.#dagRead = dagRead;
|
|
1962
|
-
this.map = map;
|
|
1963
|
-
this.indexes = indexes;
|
|
1964
|
-
}
|
|
1965
|
-
has(key) {
|
|
1966
|
-
return this.map.has(key);
|
|
1967
|
-
}
|
|
1968
|
-
get(key) {
|
|
1969
|
-
return this.map.get(key);
|
|
1970
|
-
}
|
|
1971
|
-
isEmpty() {
|
|
1972
|
-
return this.map.isEmpty();
|
|
1973
|
-
}
|
|
1974
|
-
getMapForIndex(indexName) {
|
|
1975
|
-
const idx = this.indexes.get(indexName);
|
|
1976
|
-
if (idx === void 0) {
|
|
1977
|
-
throw new Error(`Unknown index name: ${indexName}`);
|
|
1978
|
-
}
|
|
1979
|
-
return idx.map;
|
|
1980
|
-
}
|
|
1981
|
-
get closed() {
|
|
1982
|
-
return this.#dagRead.closed;
|
|
1983
|
-
}
|
|
1984
|
-
close() {
|
|
1985
|
-
this.#dagRead.release();
|
|
1986
|
-
}
|
|
1987
|
-
};
|
|
1988
|
-
function readFromDefaultHead(dagRead, formatVersion) {
|
|
1989
|
-
return readFromHead(DEFAULT_HEAD_NAME, dagRead, formatVersion);
|
|
1990
|
-
}
|
|
1991
|
-
async function readFromHead(name, dagRead, formatVersion) {
|
|
1992
|
-
const commit = await commitFromHead(name, dagRead);
|
|
1993
|
-
return readFromCommit(commit, dagRead, formatVersion);
|
|
1994
|
-
}
|
|
1995
|
-
async function readFromHash(hash2, dagRead, formatVersion) {
|
|
1996
|
-
const commit = await commitFromHash(hash2, dagRead);
|
|
1997
|
-
return readFromCommit(commit, dagRead, formatVersion);
|
|
1998
|
-
}
|
|
1999
|
-
function readFromCommit(commit, dagRead, formatVersion) {
|
|
2000
|
-
const indexes = readIndexesForRead(commit, dagRead, formatVersion);
|
|
2001
|
-
const map = new BTreeRead(dagRead, formatVersion, commit.valueHash);
|
|
2002
|
-
return new Read(dagRead, map, indexes);
|
|
2003
|
-
}
|
|
2004
|
-
function readIndexesForRead(commit, dagRead, formatVersion) {
|
|
2005
|
-
const m = /* @__PURE__ */ new Map();
|
|
2006
|
-
for (const index of commit.indexes) {
|
|
2007
|
-
m.set(
|
|
2008
|
-
index.definition.name,
|
|
2009
|
-
new IndexRead(
|
|
2010
|
-
index,
|
|
2011
|
-
new BTreeRead(dagRead, formatVersion, index.valueHash)
|
|
2012
|
-
)
|
|
2013
|
-
);
|
|
2014
|
-
}
|
|
2015
|
-
return m;
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
// ../replicache/src/index-defs.ts
|
|
2019
|
-
var indexDefinitionSchema = readonlyObject({
|
|
2020
|
-
prefix: valita_exports.string().optional(),
|
|
2021
|
-
jsonPointer: valita_exports.string(),
|
|
2022
|
-
allowEmpty: valita_exports.boolean().optional()
|
|
2023
|
-
});
|
|
2024
|
-
var indexDefinitionsSchema = readonlyRecord(
|
|
2025
|
-
indexDefinitionSchema
|
|
2026
|
-
);
|
|
2027
|
-
function indexDefinitionEqual(a, b) {
|
|
2028
|
-
return a.jsonPointer === b.jsonPointer && (a.allowEmpty ?? false) === (b.allowEmpty ?? false) && (a.prefix ?? "") === (b.prefix ?? "");
|
|
2029
|
-
}
|
|
2030
|
-
function indexDefinitionsEqual(a, b) {
|
|
2031
|
-
if (Object.keys(a).length !== Object.keys(b).length) {
|
|
2032
|
-
return false;
|
|
2033
|
-
}
|
|
2034
|
-
for (const [aKey, aValue] of Object.entries(a)) {
|
|
2035
|
-
const bValue = b[aKey];
|
|
2036
|
-
if (!bValue || !indexDefinitionEqual(aValue, bValue)) {
|
|
2037
|
-
return false;
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
return true;
|
|
2041
|
-
}
|
|
2042
|
-
|
|
2043
|
-
// ../replicache/src/persist/client-groups.ts
|
|
2044
|
-
var clientGroupSchema = readonlyObject({
|
|
2045
|
-
/**
|
|
2046
|
-
* The hash of the commit in the perdag last persisted to this client group.
|
|
2047
|
-
* Should only be updated by clients assigned to this client group.
|
|
2048
|
-
*/
|
|
2049
|
-
headHash: hashSchema,
|
|
2050
|
-
/**
|
|
2051
|
-
* Set of mutator names common to all clients assigned to this client group.
|
|
2052
|
-
*/
|
|
2053
|
-
mutatorNames: readonlyArray(valita_exports.string()),
|
|
2054
|
-
/**
|
|
2055
|
-
* Index definitions common to all clients assigned to this client group.
|
|
2056
|
-
*/
|
|
2057
|
-
indexes: indexDefinitionsSchema,
|
|
2058
|
-
/**
|
|
2059
|
-
* The highest mutation ID of every client assigned to this client group.
|
|
2060
|
-
* Should only be updated by clients assigned to this client group. Read by
|
|
2061
|
-
* other clients to determine if there are unacknowledged pending mutations
|
|
2062
|
-
* for them to try to recover. This is redundant with information in the
|
|
2063
|
-
* commit graph at `headHash`, but allows other clients to determine if there
|
|
2064
|
-
* are unacknowledged pending mutations without having to load the commit
|
|
2065
|
-
* graph.
|
|
2066
|
-
*/
|
|
2067
|
-
mutationIDs: readonlyRecord(valita_exports.number()),
|
|
2068
|
-
/**
|
|
2069
|
-
* The highest lastMutationID received from the server for every client
|
|
2070
|
-
* assigned to this client group.
|
|
2071
|
-
*
|
|
2072
|
-
* Should be updated by the clients assigned to this client group whenever
|
|
2073
|
-
* they persist to this client group. Read by other clients to determine if
|
|
2074
|
-
* there are unacknowledged pending mutations for them to recover and
|
|
2075
|
-
* *updated* by other clients upon successfully recovering pending mutations
|
|
2076
|
-
* to avoid redundant pushes of pending mutations.
|
|
2077
|
-
*
|
|
2078
|
-
* Note: This will be the same as the `lastMutationIDs` of the base snapshot
|
|
2079
|
-
* of the client group's commit graph when written by clients assigned to this
|
|
2080
|
-
* client group. However, when written by another client recovering mutations
|
|
2081
|
-
* it may be different because the other client does not update the commit
|
|
2082
|
-
* graph.
|
|
2083
|
-
*/
|
|
2084
|
-
lastServerAckdMutationIDs: valita_exports.record(valita_exports.number()),
|
|
2085
|
-
/**
|
|
2086
|
-
* If the server deletes this client group it can signal that the client group
|
|
2087
|
-
* was deleted. If that happens we mark this client group as disabled so that
|
|
2088
|
-
* we do not use it again when creating new clients.
|
|
2089
|
-
*/
|
|
2090
|
-
disabled: valita_exports.boolean()
|
|
2091
|
-
});
|
|
2092
|
-
var CLIENT_GROUPS_HEAD_NAME = "client-groups";
|
|
2093
|
-
function assertClientGroup(value) {
|
|
2094
|
-
assert2(value, clientGroupSchema);
|
|
2095
|
-
}
|
|
2096
|
-
function chunkDataToClientGroupMap(chunkData) {
|
|
2097
|
-
assertObject(chunkData);
|
|
2098
|
-
const clientGroups = /* @__PURE__ */ new Map();
|
|
2099
|
-
for (const [key, value] of Object.entries(chunkData)) {
|
|
2100
|
-
if (value !== void 0) {
|
|
2101
|
-
assertClientGroup(value);
|
|
2102
|
-
clientGroups.set(key, value);
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
return clientGroups;
|
|
2106
|
-
}
|
|
2107
|
-
function clientGroupMapToChunkData(clientGroups, dagWrite) {
|
|
2108
|
-
const chunkData = {};
|
|
2109
|
-
for (const [clientGroupID, clientGroup] of clientGroups.entries()) {
|
|
2110
|
-
dagWrite.assertValidHash(clientGroup.headHash);
|
|
2111
|
-
chunkData[clientGroupID] = {
|
|
2112
|
-
...clientGroup,
|
|
2113
|
-
mutatorNames: [...clientGroup.mutatorNames.values()]
|
|
2114
|
-
};
|
|
2115
|
-
}
|
|
2116
|
-
return deepFreeze(chunkData);
|
|
2117
|
-
}
|
|
2118
|
-
async function getClientGroupsAtHash(hash2, dagRead) {
|
|
2119
|
-
const chunk = await dagRead.getChunk(hash2);
|
|
2120
|
-
return chunkDataToClientGroupMap(chunk?.data);
|
|
2121
|
-
}
|
|
2122
|
-
async function getClientGroups(dagRead) {
|
|
2123
|
-
const hash2 = await dagRead.getHead(CLIENT_GROUPS_HEAD_NAME);
|
|
2124
|
-
if (!hash2) {
|
|
2125
|
-
return /* @__PURE__ */ new Map();
|
|
2126
|
-
}
|
|
2127
|
-
return getClientGroupsAtHash(hash2, dagRead);
|
|
2128
|
-
}
|
|
2129
|
-
async function setClientGroups(clientGroups, dagWrite) {
|
|
2130
|
-
const currClientGroups = await getClientGroups(dagWrite);
|
|
2131
|
-
for (const [clientGroupID, clientGroup] of clientGroups) {
|
|
2132
|
-
const currClientGroup = currClientGroups.get(clientGroupID);
|
|
2133
|
-
validateClientGroupUpdate(clientGroup, currClientGroup);
|
|
2134
|
-
}
|
|
2135
|
-
return setValidatedClientGroups(clientGroups, dagWrite);
|
|
2136
|
-
}
|
|
2137
|
-
async function setClientGroup(clientGroupID, clientGroup, dagWrite) {
|
|
2138
|
-
const currClientGroups = await getClientGroups(dagWrite);
|
|
2139
|
-
const currClientGroup = currClientGroups.get(clientGroupID);
|
|
2140
|
-
validateClientGroupUpdate(clientGroup, currClientGroup);
|
|
2141
|
-
const newClientGroups = new Map(currClientGroups);
|
|
2142
|
-
newClientGroups.set(clientGroupID, clientGroup);
|
|
2143
|
-
return setValidatedClientGroups(newClientGroups, dagWrite);
|
|
2144
|
-
}
|
|
2145
|
-
function validateClientGroupUpdate(clientGroup, currClientGroup) {
|
|
2146
|
-
const mutatorNamesSet = new Set(clientGroup.mutatorNames);
|
|
2147
|
-
assert(
|
|
2148
|
-
mutatorNamesSet.size === clientGroup.mutatorNames.length,
|
|
2149
|
-
"A client group's mutatorNames must be a set."
|
|
2150
|
-
);
|
|
2151
|
-
if (currClientGroup !== void 0) {
|
|
2152
|
-
assert(
|
|
2153
|
-
indexDefinitionsEqual(currClientGroup.indexes, clientGroup.indexes),
|
|
2154
|
-
"A client group's index definitions must never change."
|
|
2155
|
-
);
|
|
2156
|
-
assert(
|
|
2157
|
-
mutatorNamesEqual(mutatorNamesSet, currClientGroup.mutatorNames),
|
|
2158
|
-
"A client group's mutatorNames must never change."
|
|
2159
|
-
);
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
async function setValidatedClientGroups(clientGroups, dagWrite) {
|
|
2163
|
-
const chunkData = clientGroupMapToChunkData(clientGroups, dagWrite);
|
|
2164
|
-
const refs = /* @__PURE__ */ new Set();
|
|
2165
|
-
for (const clientGroup of clientGroups.values()) {
|
|
2166
|
-
refs.add(clientGroup.headHash);
|
|
2167
|
-
}
|
|
2168
|
-
const chunk = dagWrite.createChunk(chunkData, toRefs(refs));
|
|
2169
|
-
await dagWrite.putChunk(chunk);
|
|
2170
|
-
await dagWrite.setHead(CLIENT_GROUPS_HEAD_NAME, chunk.hash);
|
|
2171
|
-
return clientGroups;
|
|
2172
|
-
}
|
|
2173
|
-
function mutatorNamesEqual(mutatorNamesSet, mutatorNames) {
|
|
2174
|
-
if (mutatorNames.length !== mutatorNamesSet.size) {
|
|
2175
|
-
return false;
|
|
2176
|
-
}
|
|
2177
|
-
for (const mutatorName of mutatorNames) {
|
|
2178
|
-
if (!mutatorNamesSet.has(mutatorName)) {
|
|
2179
|
-
return false;
|
|
2180
|
-
}
|
|
2181
|
-
}
|
|
2182
|
-
return true;
|
|
2183
|
-
}
|
|
2184
|
-
async function getClientGroup(id, dagRead) {
|
|
2185
|
-
const clientGroups = await getClientGroups(dagRead);
|
|
2186
|
-
return clientGroups.get(id);
|
|
2187
|
-
}
|
|
2188
|
-
function clientGroupHasPendingMutations(clientGroup) {
|
|
2189
|
-
for (const [clientID, mutationID] of Object.entries(
|
|
2190
|
-
clientGroup.mutationIDs
|
|
2191
|
-
)) {
|
|
2192
|
-
const lastServerAckdMutationID = clientGroup.lastServerAckdMutationIDs[clientID];
|
|
2193
|
-
if (lastServerAckdMutationID === void 0 && mutationID !== 0 || lastServerAckdMutationID < mutationID) {
|
|
2194
|
-
return true;
|
|
2195
|
-
}
|
|
2196
|
-
}
|
|
2197
|
-
return false;
|
|
2198
|
-
}
|
|
2199
|
-
async function disableClientGroup(clientGroupID, dagWrite) {
|
|
2200
|
-
const clientGroup = await getClientGroup(clientGroupID, dagWrite);
|
|
2201
|
-
if (!clientGroup) {
|
|
2202
|
-
return;
|
|
2203
|
-
}
|
|
2204
|
-
const disabledClientGroup = {
|
|
2205
|
-
...clientGroup,
|
|
2206
|
-
disabled: true
|
|
2207
|
-
};
|
|
2208
|
-
await setClientGroup(clientGroupID, disabledClientGroup, dagWrite);
|
|
2209
|
-
}
|
|
2210
|
-
|
|
2211
|
-
// ../replicache/src/with-transactions.ts
|
|
2212
|
-
function withRead(store, fn) {
|
|
2213
|
-
return using(store.read(), fn);
|
|
2214
|
-
}
|
|
2215
|
-
function withWriteNoImplicitCommit(store, fn) {
|
|
2216
|
-
return using(store.write(), fn);
|
|
2217
|
-
}
|
|
2218
|
-
function withWrite(store, fn) {
|
|
2219
|
-
return using(store.write(), async (write) => {
|
|
2220
|
-
const result = await fn(write);
|
|
2221
|
-
await write.commit();
|
|
2222
|
-
return result;
|
|
2223
|
-
});
|
|
2224
|
-
}
|
|
2225
|
-
async function using(x, fn) {
|
|
2226
|
-
const write = await x;
|
|
2227
|
-
try {
|
|
2228
|
-
return await fn(write);
|
|
2229
|
-
} finally {
|
|
2230
|
-
write.release();
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
|
-
// ../replicache/src/async-iterable-to-array.ts
|
|
2235
|
-
async function asyncIterableToArray(it) {
|
|
2236
|
-
const arr = [];
|
|
2237
|
-
for await (const v2 of it) {
|
|
2238
|
-
arr.push(v2);
|
|
2239
|
-
}
|
|
2240
|
-
return arr;
|
|
2241
|
-
}
|
|
2242
|
-
|
|
2243
|
-
// ../replicache/src/btree/diff.ts
|
|
2244
|
-
function diff(oldMap, newMap) {
|
|
2245
|
-
return asyncIterableToArray(newMap.diff(oldMap));
|
|
2246
|
-
}
|
|
2247
|
-
|
|
2248
|
-
// ../replicache/src/btree/write.ts
|
|
2249
|
-
import { Lock } from "@rocicorp/lock";
|
|
2250
|
-
var BTreeWrite = class extends BTreeRead {
|
|
2251
|
-
/**
|
|
2252
|
-
* This rw lock is used to ensure we do not mutate the btree in parallel. It
|
|
2253
|
-
* would be a problem if we didn't have the lock in cases like this:
|
|
2254
|
-
*
|
|
2255
|
-
* ```ts
|
|
2256
|
-
* const p1 = tree.put('a', 0);
|
|
2257
|
-
* const p2 = tree.put('b', 1);
|
|
2258
|
-
* await p1;
|
|
2259
|
-
* await p2;
|
|
2260
|
-
* ```
|
|
2261
|
-
*
|
|
2262
|
-
* because both `p1` and `p2` would start from the old root hash but a put
|
|
2263
|
-
* changes the root hash so the two concurrent puts would lead to only one of
|
|
2264
|
-
* them actually working, and it is not deterministic which one would finish
|
|
2265
|
-
* last.
|
|
2266
|
-
*/
|
|
2267
|
-
#lock = new Lock();
|
|
2268
|
-
#modified = /* @__PURE__ */ new Map();
|
|
2269
|
-
minSize;
|
|
2270
|
-
maxSize;
|
|
2271
|
-
constructor(dagWrite, formatVersion, root = emptyHash, minSize = 8 * 1024, maxSize = 16 * 1024, getEntrySize = getSizeOfEntry, chunkHeaderSize) {
|
|
2272
|
-
super(dagWrite, formatVersion, root, getEntrySize, chunkHeaderSize);
|
|
2273
|
-
this.minSize = minSize;
|
|
2274
|
-
this.maxSize = maxSize;
|
|
2275
|
-
}
|
|
2276
|
-
#addToModified(node) {
|
|
2277
|
-
assert(node.isMutable);
|
|
2278
|
-
this.#modified.set(node.hash, node);
|
|
2279
|
-
this._cache.set(node.hash, node);
|
|
2280
|
-
}
|
|
2281
|
-
updateNode(node) {
|
|
2282
|
-
assert(node.isMutable);
|
|
2283
|
-
this.#modified.delete(node.hash);
|
|
2284
|
-
node.hash = newRandomHash();
|
|
2285
|
-
this.#addToModified(node);
|
|
2286
|
-
}
|
|
2287
|
-
newInternalNodeImpl(entries, level) {
|
|
2288
|
-
const n = new InternalNodeImpl(entries, newRandomHash(), level, true);
|
|
2289
|
-
this.#addToModified(n);
|
|
2290
|
-
return n;
|
|
2291
|
-
}
|
|
2292
|
-
newDataNodeImpl(entries) {
|
|
2293
|
-
const n = new DataNodeImpl(entries, newRandomHash(), true);
|
|
2294
|
-
this.#addToModified(n);
|
|
2295
|
-
return n;
|
|
2296
|
-
}
|
|
2297
|
-
newNodeImpl(entries, level) {
|
|
2298
|
-
const n = newNodeImpl(entries, newRandomHash(), level, true);
|
|
2299
|
-
this.#addToModified(n);
|
|
2300
|
-
return n;
|
|
2301
|
-
}
|
|
2302
|
-
put(key, value) {
|
|
2303
|
-
return this.#lock.withLock(async () => {
|
|
2304
|
-
const oldRootNode = await this.getNode(this.rootHash);
|
|
2305
|
-
const entrySize = this.getEntrySize(key, value);
|
|
2306
|
-
const rootNode = await oldRootNode.set(key, value, entrySize, this);
|
|
2307
|
-
if (rootNode.getChildNodeSize(this) > this.maxSize) {
|
|
2308
|
-
const headerSize = this.chunkHeaderSize;
|
|
2309
|
-
const partitions = partition(
|
|
2310
|
-
rootNode.entries,
|
|
2311
|
-
(value2) => value2[2],
|
|
2312
|
-
this.minSize - headerSize,
|
|
2313
|
-
this.maxSize - headerSize
|
|
2314
|
-
);
|
|
2315
|
-
const { level } = rootNode;
|
|
2316
|
-
const entries = partitions.map((entries2) => {
|
|
2317
|
-
const node = this.newNodeImpl(entries2, level);
|
|
2318
|
-
return createNewInternalEntryForNode(node, this.getEntrySize);
|
|
2319
|
-
});
|
|
2320
|
-
const newRoot = this.newInternalNodeImpl(entries, level + 1);
|
|
2321
|
-
this.rootHash = newRoot.hash;
|
|
2322
|
-
return;
|
|
2323
|
-
}
|
|
2324
|
-
this.rootHash = rootNode.hash;
|
|
2325
|
-
});
|
|
2326
|
-
}
|
|
2327
|
-
del(key) {
|
|
2328
|
-
return this.#lock.withLock(async () => {
|
|
2329
|
-
const oldRootNode = await this.getNode(this.rootHash);
|
|
2330
|
-
const newRootNode = await oldRootNode.del(key, this);
|
|
2331
|
-
const found = this.rootHash !== newRootNode.hash;
|
|
2332
|
-
if (found) {
|
|
2333
|
-
if (newRootNode.level > 0 && newRootNode.entries.length === 1) {
|
|
2334
|
-
this.rootHash = newRootNode.entries[0][1];
|
|
2335
|
-
} else {
|
|
2336
|
-
this.rootHash = newRootNode.hash;
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
return found;
|
|
2340
|
-
});
|
|
2341
|
-
}
|
|
2342
|
-
clear() {
|
|
2343
|
-
return this.#lock.withLock(() => {
|
|
2344
|
-
this.#modified.clear();
|
|
2345
|
-
this.rootHash = emptyHash;
|
|
2346
|
-
});
|
|
2347
|
-
}
|
|
2348
|
-
flush() {
|
|
2349
|
-
return this.#lock.withLock(async () => {
|
|
2350
|
-
const dagWrite = this._dagRead;
|
|
2351
|
-
if (this.rootHash === emptyHash) {
|
|
2352
|
-
const chunk = dagWrite.createChunk(emptyDataNode, []);
|
|
2353
|
-
await dagWrite.putChunk(chunk);
|
|
2354
|
-
return chunk.hash;
|
|
2355
|
-
}
|
|
2356
|
-
const newChunks = [];
|
|
2357
|
-
const newRoot = gatherNewChunks(
|
|
2358
|
-
this.rootHash,
|
|
2359
|
-
newChunks,
|
|
2360
|
-
dagWrite.createChunk,
|
|
2361
|
-
this.#modified,
|
|
2362
|
-
this._formatVersion
|
|
2363
|
-
);
|
|
2364
|
-
await Promise.all(newChunks.map((chunk) => dagWrite.putChunk(chunk)));
|
|
2365
|
-
this.#modified.clear();
|
|
2366
|
-
this.rootHash = newRoot;
|
|
2367
|
-
return newRoot;
|
|
2368
|
-
});
|
|
2369
|
-
}
|
|
2370
|
-
};
|
|
2371
|
-
function gatherNewChunks(hash2, newChunks, createChunk2, modified, formatVersion) {
|
|
2372
|
-
const node = modified.get(hash2);
|
|
2373
|
-
if (node === void 0) {
|
|
2374
|
-
return hash2;
|
|
2375
|
-
}
|
|
2376
|
-
if (isDataNodeImpl(node)) {
|
|
2377
|
-
const chunk2 = createChunk2(toChunkData(node, formatVersion), []);
|
|
2378
|
-
newChunks.push(chunk2);
|
|
2379
|
-
return chunk2.hash;
|
|
2380
|
-
}
|
|
2381
|
-
const refs = [];
|
|
2382
|
-
const { entries } = node;
|
|
2383
|
-
for (let i = 0; i < entries.length; i++) {
|
|
2384
|
-
const entry = entries[i];
|
|
2385
|
-
const childHash = entry[1];
|
|
2386
|
-
const newChildHash = gatherNewChunks(
|
|
2387
|
-
childHash,
|
|
2388
|
-
newChunks,
|
|
2389
|
-
createChunk2,
|
|
2390
|
-
modified,
|
|
2391
|
-
formatVersion
|
|
2392
|
-
);
|
|
2393
|
-
if (newChildHash !== childHash) {
|
|
2394
|
-
entries[i] = [entry[0], newChildHash, entry[2]];
|
|
2395
|
-
}
|
|
2396
|
-
refs.push(newChildHash);
|
|
2397
|
-
}
|
|
2398
|
-
const chunk = createChunk2(toChunkData(node, formatVersion), toRefs(refs));
|
|
2399
|
-
newChunks.push(chunk);
|
|
2400
|
-
return chunk.hash;
|
|
2401
|
-
}
|
|
2402
|
-
|
|
2403
|
-
// ../replicache/src/lazy.ts
|
|
2404
|
-
function lazy(factory) {
|
|
2405
|
-
let value;
|
|
2406
|
-
return () => {
|
|
2407
|
-
if (value === void 0) {
|
|
2408
|
-
value = factory();
|
|
2409
|
-
}
|
|
2410
|
-
return value;
|
|
2411
|
-
};
|
|
2412
|
-
}
|
|
2413
|
-
|
|
2414
|
-
// ../replicache/src/sync/diff.ts
|
|
2415
|
-
var DiffsMap = class extends Map {
|
|
2416
|
-
set(key, value) {
|
|
2417
|
-
if (value.length === 0) {
|
|
2418
|
-
return this;
|
|
2419
|
-
}
|
|
2420
|
-
return super.set(key, value);
|
|
2421
|
-
}
|
|
2422
|
-
};
|
|
2423
|
-
async function diff2(oldHash, newHash, read, diffConfig, formatVersion) {
|
|
2424
|
-
const [oldCommit, newCommit] = await Promise.all([
|
|
2425
|
-
commitFromHash(oldHash, read),
|
|
2426
|
-
commitFromHash(newHash, read)
|
|
2427
|
-
]);
|
|
2428
|
-
return diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion);
|
|
2429
|
-
}
|
|
2430
|
-
async function diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion) {
|
|
2431
|
-
const diffsMap = new DiffsMap();
|
|
2432
|
-
if (!diffConfig.shouldComputeDiffs()) {
|
|
2433
|
-
return diffsMap;
|
|
2434
|
-
}
|
|
2435
|
-
const oldMap = new BTreeRead(read, formatVersion, oldCommit.valueHash);
|
|
2436
|
-
const newMap = new BTreeRead(read, formatVersion, newCommit.valueHash);
|
|
2437
|
-
const valueDiff = await diff(oldMap, newMap);
|
|
2438
|
-
diffsMap.set("", valueDiff);
|
|
2439
|
-
await addDiffsForIndexes(
|
|
2440
|
-
oldCommit,
|
|
2441
|
-
newCommit,
|
|
2442
|
-
read,
|
|
2443
|
-
diffsMap,
|
|
2444
|
-
diffConfig,
|
|
2445
|
-
formatVersion
|
|
2446
|
-
);
|
|
2447
|
-
return diffsMap;
|
|
2448
|
-
}
|
|
2449
|
-
async function addDiffsForIndexes(mainCommit, syncCommit, read, diffsMap, diffConfig, formatVersion) {
|
|
2450
|
-
const oldIndexes = readIndexesForRead(mainCommit, read, formatVersion);
|
|
2451
|
-
const newIndexes = readIndexesForRead(syncCommit, read, formatVersion);
|
|
2452
|
-
for (const [oldIndexName, oldIndex] of oldIndexes) {
|
|
2453
|
-
if (!diffConfig.shouldComputeDiffsForIndex(oldIndexName)) {
|
|
2454
|
-
continue;
|
|
2455
|
-
}
|
|
2456
|
-
const newIndex = newIndexes.get(oldIndexName);
|
|
2457
|
-
if (newIndex !== void 0) {
|
|
2458
|
-
assert(newIndex !== oldIndex);
|
|
2459
|
-
const diffs = await diff(oldIndex.map, newIndex.map);
|
|
2460
|
-
newIndexes.delete(oldIndexName);
|
|
2461
|
-
diffsMap.set(oldIndexName, diffs);
|
|
2462
|
-
} else {
|
|
2463
|
-
const diffs = await allEntriesAsDiff(oldIndex.map, "del");
|
|
2464
|
-
diffsMap.set(oldIndexName, diffs);
|
|
2465
|
-
}
|
|
2466
|
-
}
|
|
2467
|
-
for (const [newIndexName, newIndex] of newIndexes) {
|
|
2468
|
-
if (!diffConfig.shouldComputeDiffsForIndex(newIndexName)) {
|
|
2469
|
-
continue;
|
|
2470
|
-
}
|
|
2471
|
-
const diffs = await allEntriesAsDiff(newIndex.map, "add");
|
|
2472
|
-
diffsMap.set(newIndexName, diffs);
|
|
2473
|
-
}
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2476
|
-
// ../replicache/src/db/write.ts
|
|
2477
|
-
var Write = class extends Read {
|
|
2478
|
-
#dagWrite;
|
|
2479
|
-
#basis;
|
|
2480
|
-
#meta;
|
|
2481
|
-
#clientID;
|
|
2482
|
-
#formatVersion;
|
|
2483
|
-
constructor(dagWrite, map, basis, meta, indexes, clientID, formatVersion) {
|
|
2484
|
-
super(dagWrite, map, indexes);
|
|
2485
|
-
this.#dagWrite = dagWrite;
|
|
2486
|
-
this.#basis = basis;
|
|
2487
|
-
this.#meta = meta;
|
|
2488
|
-
this.#clientID = clientID;
|
|
2489
|
-
this.#formatVersion = formatVersion;
|
|
2490
|
-
if (basis === void 0) {
|
|
2491
|
-
assert(meta.basisHash === emptyHash);
|
|
2492
|
-
} else {
|
|
2493
|
-
assert(meta.basisHash === basis.chunk.hash);
|
|
2494
|
-
}
|
|
2495
|
-
}
|
|
2496
|
-
/**
|
|
2497
|
-
* The value needs to be frozen since it is kept in memory and used later for
|
|
2498
|
-
* comparison as well as returned in `get`.
|
|
2499
|
-
*/
|
|
2500
|
-
async put(lc, key, value) {
|
|
2501
|
-
const oldVal = lazy(() => this.map.get(key));
|
|
2502
|
-
await updateIndexes(lc, this.indexes, key, oldVal, value);
|
|
2503
|
-
await this.map.put(key, value);
|
|
2504
|
-
}
|
|
2505
|
-
getMutationID() {
|
|
2506
|
-
return getMutationID(this.#clientID, this.#dagWrite, this.#meta);
|
|
2507
|
-
}
|
|
2508
|
-
async del(lc, key) {
|
|
2509
|
-
const oldVal = lazy(() => this.map.get(key));
|
|
2510
|
-
if (oldVal !== void 0) {
|
|
2511
|
-
await updateIndexes(lc, this.indexes, key, oldVal, void 0);
|
|
2512
|
-
}
|
|
2513
|
-
return this.map.del(key);
|
|
2514
|
-
}
|
|
2515
|
-
async clear() {
|
|
2516
|
-
await this.map.clear();
|
|
2517
|
-
const ps = [];
|
|
2518
|
-
for (const idx of this.indexes.values()) {
|
|
2519
|
-
ps.push(idx.clear());
|
|
2520
|
-
}
|
|
2521
|
-
await Promise.all(ps);
|
|
2522
|
-
}
|
|
2523
|
-
async putCommit() {
|
|
2524
|
-
const valueHash = await this.map.flush();
|
|
2525
|
-
const indexRecords = [];
|
|
2526
|
-
for (const index of this.indexes.values()) {
|
|
2527
|
-
const valueHash2 = await index.flush();
|
|
2528
|
-
const indexRecord = {
|
|
2529
|
-
definition: index.meta.definition,
|
|
2530
|
-
valueHash: valueHash2
|
|
2531
|
-
};
|
|
2532
|
-
indexRecords.push(indexRecord);
|
|
2533
|
-
}
|
|
2534
|
-
let commit;
|
|
2535
|
-
const meta = this.#meta;
|
|
2536
|
-
switch (meta.type) {
|
|
2537
|
-
case LocalDD31: {
|
|
2538
|
-
assert(this.#formatVersion >= DD31);
|
|
2539
|
-
const {
|
|
2540
|
-
basisHash,
|
|
2541
|
-
mutationID,
|
|
2542
|
-
mutatorName,
|
|
2543
|
-
mutatorArgsJSON,
|
|
2544
|
-
originalHash,
|
|
2545
|
-
timestamp
|
|
2546
|
-
} = meta;
|
|
2547
|
-
commit = newLocalDD31(
|
|
2548
|
-
this.#dagWrite.createChunk,
|
|
2549
|
-
basisHash,
|
|
2550
|
-
await baseSnapshotHashFromHash(basisHash, this.#dagWrite),
|
|
2551
|
-
mutationID,
|
|
2552
|
-
mutatorName,
|
|
2553
|
-
mutatorArgsJSON,
|
|
2554
|
-
originalHash,
|
|
2555
|
-
valueHash,
|
|
2556
|
-
indexRecords,
|
|
2557
|
-
timestamp,
|
|
2558
|
-
this.#clientID
|
|
2559
|
-
);
|
|
2560
|
-
break;
|
|
2561
|
-
}
|
|
2562
|
-
case SnapshotDD31: {
|
|
2563
|
-
assert(this.#formatVersion > DD31);
|
|
2564
|
-
const { basisHash, lastMutationIDs, cookieJSON } = meta;
|
|
2565
|
-
commit = newSnapshotDD31(
|
|
2566
|
-
this.#dagWrite.createChunk,
|
|
2567
|
-
basisHash,
|
|
2568
|
-
lastMutationIDs,
|
|
2569
|
-
cookieJSON,
|
|
2570
|
-
valueHash,
|
|
2571
|
-
indexRecords
|
|
2572
|
-
);
|
|
2573
|
-
break;
|
|
2574
|
-
}
|
|
2575
|
-
}
|
|
2576
|
-
await this.#dagWrite.putChunk(commit.chunk);
|
|
2577
|
-
return commit;
|
|
2578
|
-
}
|
|
2579
|
-
// Return value is the hash of the new commit.
|
|
2580
|
-
async commit(headName) {
|
|
2581
|
-
const commit = await this.putCommit();
|
|
2582
|
-
const commitHash = commit.chunk.hash;
|
|
2583
|
-
await this.#dagWrite.setHead(headName, commitHash);
|
|
2584
|
-
await this.#dagWrite.commit();
|
|
2585
|
-
return commitHash;
|
|
2586
|
-
}
|
|
2587
|
-
async commitWithDiffs(headName, diffConfig) {
|
|
2588
|
-
const commit = this.putCommit();
|
|
2589
|
-
const diffMap = await this.#generateDiffs(diffConfig);
|
|
2590
|
-
const commitHash = (await commit).chunk.hash;
|
|
2591
|
-
await this.#dagWrite.setHead(headName, commitHash);
|
|
2592
|
-
await this.#dagWrite.commit();
|
|
2593
|
-
return [commitHash, diffMap];
|
|
2594
|
-
}
|
|
2595
|
-
async #generateDiffs(diffConfig) {
|
|
2596
|
-
const diffsMap = new DiffsMap();
|
|
2597
|
-
if (!diffConfig.shouldComputeDiffs()) {
|
|
2598
|
-
return diffsMap;
|
|
2599
|
-
}
|
|
2600
|
-
let valueDiff = [];
|
|
2601
|
-
if (this.#basis) {
|
|
2602
|
-
const basisMap = new BTreeRead(
|
|
2603
|
-
this.#dagWrite,
|
|
2604
|
-
this.#formatVersion,
|
|
2605
|
-
this.#basis.valueHash
|
|
2606
|
-
);
|
|
2607
|
-
valueDiff = await diff(basisMap, this.map);
|
|
2608
|
-
}
|
|
2609
|
-
diffsMap.set("", valueDiff);
|
|
2610
|
-
let basisIndexes;
|
|
2611
|
-
if (this.#basis) {
|
|
2612
|
-
basisIndexes = readIndexesForRead(
|
|
2613
|
-
this.#basis,
|
|
2614
|
-
this.#dagWrite,
|
|
2615
|
-
this.#formatVersion
|
|
2616
|
-
);
|
|
2617
|
-
} else {
|
|
2618
|
-
basisIndexes = /* @__PURE__ */ new Map();
|
|
2619
|
-
}
|
|
2620
|
-
for (const [name, index] of this.indexes) {
|
|
2621
|
-
if (!diffConfig.shouldComputeDiffsForIndex(name)) {
|
|
2622
|
-
continue;
|
|
2623
|
-
}
|
|
2624
|
-
const basisIndex = basisIndexes.get(name);
|
|
2625
|
-
assert(index !== basisIndex);
|
|
2626
|
-
const indexDiffResult = await (basisIndex ? diff(basisIndex.map, index.map) : (
|
|
2627
|
-
// No basis. All keys are new.
|
|
2628
|
-
allEntriesAsDiff(index.map, "add")
|
|
2629
|
-
));
|
|
2630
|
-
diffsMap.set(name, indexDiffResult);
|
|
2631
|
-
}
|
|
2632
|
-
for (const [name, basisIndex] of basisIndexes) {
|
|
2633
|
-
if (!this.indexes.has(name) && diffConfig.shouldComputeDiffsForIndex(name)) {
|
|
2634
|
-
const indexDiffResult = await allEntriesAsDiff(basisIndex.map, "del");
|
|
2635
|
-
diffsMap.set(name, indexDiffResult);
|
|
2636
|
-
}
|
|
2637
|
-
}
|
|
2638
|
-
return diffsMap;
|
|
2639
|
-
}
|
|
2640
|
-
close() {
|
|
2641
|
-
this.#dagWrite.release();
|
|
2642
|
-
}
|
|
2643
|
-
};
|
|
2644
|
-
async function newWriteLocal(basisHash, mutatorName, mutatorArgsJSON, originalHash, dagWrite, timestamp, clientID, formatVersion) {
|
|
2645
|
-
const basis = await commitFromHash(basisHash, dagWrite);
|
|
2646
|
-
const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);
|
|
2647
|
-
const mutationID = await basis.getNextMutationID(clientID, dagWrite);
|
|
2648
|
-
const indexes = readIndexesForWrite(basis, dagWrite, formatVersion);
|
|
2649
|
-
assert(formatVersion >= DD31);
|
|
2650
|
-
return new Write(
|
|
2651
|
-
dagWrite,
|
|
2652
|
-
bTreeWrite,
|
|
2653
|
-
basis,
|
|
2654
|
-
{
|
|
2655
|
-
type: LocalDD31,
|
|
2656
|
-
basisHash,
|
|
2657
|
-
baseSnapshotHash: await baseSnapshotHashFromHash(basisHash, dagWrite),
|
|
2658
|
-
mutatorName,
|
|
2659
|
-
mutatorArgsJSON,
|
|
2660
|
-
mutationID,
|
|
2661
|
-
originalHash,
|
|
2662
|
-
timestamp,
|
|
2663
|
-
clientID
|
|
2664
|
-
},
|
|
2665
|
-
indexes,
|
|
2666
|
-
clientID,
|
|
2667
|
-
formatVersion
|
|
2668
|
-
);
|
|
2669
|
-
}
|
|
2670
|
-
async function newWriteSnapshotDD31(basisHash, lastMutationIDs, cookieJSON, dagWrite, clientID, formatVersion) {
|
|
2671
|
-
const basis = await commitFromHash(basisHash, dagWrite);
|
|
2672
|
-
const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);
|
|
2673
|
-
return new Write(
|
|
2674
|
-
dagWrite,
|
|
2675
|
-
bTreeWrite,
|
|
2676
|
-
basis,
|
|
2677
|
-
{ basisHash, type: SnapshotDD31, lastMutationIDs, cookieJSON },
|
|
2678
|
-
readIndexesForWrite(basis, dagWrite, formatVersion),
|
|
2679
|
-
clientID,
|
|
2680
|
-
formatVersion
|
|
2681
|
-
);
|
|
2682
|
-
}
|
|
2683
|
-
async function updateIndexes(lc, indexes, key, oldValGetter, newVal) {
|
|
2684
|
-
const ps = [];
|
|
2685
|
-
for (const idx of indexes.values()) {
|
|
2686
|
-
const { keyPrefix } = idx.meta.definition;
|
|
2687
|
-
if (!keyPrefix || key.startsWith(keyPrefix)) {
|
|
2688
|
-
const oldVal = await oldValGetter();
|
|
2689
|
-
if (oldVal !== void 0) {
|
|
2690
|
-
ps.push(
|
|
2691
|
-
indexValue(
|
|
2692
|
-
lc,
|
|
2693
|
-
idx.map,
|
|
2694
|
-
Remove,
|
|
2695
|
-
key,
|
|
2696
|
-
oldVal,
|
|
2697
|
-
idx.meta.definition.jsonPointer,
|
|
2698
|
-
idx.meta.definition.allowEmpty ?? false
|
|
2699
|
-
)
|
|
2700
|
-
);
|
|
2701
|
-
}
|
|
2702
|
-
if (newVal !== void 0) {
|
|
2703
|
-
ps.push(
|
|
2704
|
-
indexValue(
|
|
2705
|
-
lc,
|
|
2706
|
-
idx.map,
|
|
2707
|
-
Add,
|
|
2708
|
-
key,
|
|
2709
|
-
newVal,
|
|
2710
|
-
idx.meta.definition.jsonPointer,
|
|
2711
|
-
idx.meta.definition.allowEmpty ?? false
|
|
2712
|
-
)
|
|
2713
|
-
);
|
|
2714
|
-
}
|
|
2715
|
-
}
|
|
2716
|
-
}
|
|
2717
|
-
await Promise.all(ps);
|
|
2718
|
-
}
|
|
2719
|
-
function readIndexesForWrite(commit, dagWrite, formatVersion) {
|
|
2720
|
-
const m = /* @__PURE__ */ new Map();
|
|
2721
|
-
for (const index of commit.indexes) {
|
|
2722
|
-
m.set(
|
|
2723
|
-
index.definition.name,
|
|
2724
|
-
new IndexWrite(
|
|
2725
|
-
index,
|
|
2726
|
-
new BTreeWrite(dagWrite, formatVersion, index.valueHash)
|
|
2727
|
-
)
|
|
2728
|
-
);
|
|
2729
|
-
}
|
|
2730
|
-
return m;
|
|
2731
|
-
}
|
|
2732
|
-
async function createIndexBTree(lc, dagWrite, valueMap, prefix, jsonPointer, allowEmpty, formatVersion) {
|
|
2733
|
-
const indexMap = new BTreeWrite(dagWrite, formatVersion);
|
|
2734
|
-
for await (const entry of valueMap.scan(prefix)) {
|
|
2735
|
-
const key = entry[0];
|
|
2736
|
-
if (!key.startsWith(prefix)) {
|
|
2737
|
-
break;
|
|
2738
|
-
}
|
|
2739
|
-
await indexValue(
|
|
2740
|
-
lc,
|
|
2741
|
-
indexMap,
|
|
2742
|
-
Add,
|
|
2743
|
-
key,
|
|
2744
|
-
entry[1],
|
|
2745
|
-
jsonPointer,
|
|
2746
|
-
allowEmpty
|
|
2747
|
-
);
|
|
2748
|
-
}
|
|
2749
|
-
return indexMap;
|
|
2750
|
-
}
|
|
2751
|
-
|
|
2752
|
-
// ../replicache/src/sync/ids.ts
|
|
2753
|
-
var clientGroupIDSchema = valita_exports.string();
|
|
2754
|
-
var clientIDSchema = valita_exports.string();
|
|
2755
|
-
|
|
2756
|
-
// ../replicache/src/persist/make-client-id.ts
|
|
2757
|
-
function makeClientID() {
|
|
2758
|
-
const length = 18;
|
|
2759
|
-
const high = randomUint64();
|
|
2760
|
-
const low = randomUint64();
|
|
2761
|
-
const combined = high << 64n | low;
|
|
2762
|
-
return combined.toString(32).slice(-length).padStart(length, "0");
|
|
2763
|
-
}
|
|
2764
|
-
|
|
2765
|
-
// ../replicache/src/persist/clients.ts
|
|
2766
|
-
var clientV5Schema = readonlyObject({
|
|
2767
|
-
heartbeatTimestampMs: valita_exports.number(),
|
|
2768
|
-
headHash: hashSchema,
|
|
2769
|
-
/**
|
|
2770
|
-
* The hash of a commit we are in the middle of refreshing into this client's
|
|
2771
|
-
* memdag.
|
|
2772
|
-
*/
|
|
2773
|
-
tempRefreshHash: hashSchema.nullable(),
|
|
2774
|
-
/**
|
|
2775
|
-
* ID of this client's perdag client group. This needs to be sent in pull
|
|
2776
|
-
* request (to enable syncing all last mutation ids in the client group).
|
|
2777
|
-
*/
|
|
2778
|
-
clientGroupID: clientGroupIDSchema
|
|
2779
|
-
});
|
|
2780
|
-
var clientV6Schema = readonlyObject({
|
|
2781
|
-
heartbeatTimestampMs: valita_exports.number(),
|
|
2782
|
-
/**
|
|
2783
|
-
* A set of hashes, which contains:
|
|
2784
|
-
* 1. The hash of the last commit this client refreshed from its client group
|
|
2785
|
-
* (this is the commit it bootstrapped from until it completes its first
|
|
2786
|
-
* refresh).
|
|
2787
|
-
* 2. One or more hashes that were added to retain chunks of a commit while it
|
|
2788
|
-
* was being refreshed into this client's memdag. (This can be one or more
|
|
2789
|
-
* because refresh's cleanup step is a separate transaction and can fail).
|
|
2790
|
-
* Upon refresh completing and successfully running its clean up step, this
|
|
2791
|
-
* set will contain a single hash: the hash of the last commit this client
|
|
2792
|
-
* refreshed.
|
|
2793
|
-
*/
|
|
2794
|
-
refreshHashes: readonlyArray(hashSchema),
|
|
2795
|
-
/**
|
|
2796
|
-
* The hash of the last snapshot commit persisted by this client to this
|
|
2797
|
-
* client's client group, or null if has never persisted a snapshot.
|
|
2798
|
-
*/
|
|
2799
|
-
persistHash: hashSchema.nullable(),
|
|
2800
|
-
/**
|
|
2801
|
-
* ID of this client's perdag client group. This needs to be sent in pull
|
|
2802
|
-
* request (to enable syncing all last mutation ids in the client group).
|
|
2803
|
-
*/
|
|
2804
|
-
clientGroupID: clientGroupIDSchema
|
|
2805
|
-
});
|
|
2806
|
-
function isClientV6(client) {
|
|
2807
|
-
return client.refreshHashes !== void 0;
|
|
2808
|
-
}
|
|
2809
|
-
var CLIENTS_HEAD_NAME = "clients";
|
|
2810
|
-
var clientSchema = valita_exports.union(clientV5Schema, clientV6Schema);
|
|
2811
|
-
function assertClient(value) {
|
|
2812
|
-
assert2(value, clientSchema);
|
|
2813
|
-
}
|
|
2814
|
-
function assertClientV6(value) {
|
|
2815
|
-
assert2(value, clientV6Schema);
|
|
2816
|
-
}
|
|
2817
|
-
function chunkDataToClientMap(chunkData) {
|
|
2818
|
-
assertObject(chunkData);
|
|
2819
|
-
const clients = /* @__PURE__ */ new Map();
|
|
2820
|
-
for (const key in chunkData) {
|
|
2821
|
-
if (hasOwn(chunkData, key)) {
|
|
2822
|
-
const value = chunkData[key];
|
|
2823
|
-
if (value !== void 0) {
|
|
2824
|
-
assertClient(value);
|
|
2825
|
-
clients.set(key, value);
|
|
2826
|
-
}
|
|
2827
|
-
}
|
|
2828
|
-
}
|
|
2829
|
-
return clients;
|
|
2830
|
-
}
|
|
2831
|
-
function clientMapToChunkData(clients, dagWrite) {
|
|
2832
|
-
for (const client of clients.values()) {
|
|
2833
|
-
if (isClientV6(client)) {
|
|
2834
|
-
client.refreshHashes.forEach(dagWrite.assertValidHash);
|
|
2835
|
-
if (client.persistHash) {
|
|
2836
|
-
dagWrite.assertValidHash(client.persistHash);
|
|
2837
|
-
}
|
|
2838
|
-
} else {
|
|
2839
|
-
dagWrite.assertValidHash(client.headHash);
|
|
2840
|
-
if (client.tempRefreshHash) {
|
|
2841
|
-
dagWrite.assertValidHash(client.tempRefreshHash);
|
|
360
|
+
a = a;
|
|
361
|
+
b = b;
|
|
362
|
+
let aSize = 0;
|
|
363
|
+
for (const key in a) {
|
|
364
|
+
if (hasOwn(a, key)) {
|
|
365
|
+
if (!deepEqual(a[key], b[key])) {
|
|
366
|
+
return false;
|
|
2842
367
|
}
|
|
368
|
+
aSize++;
|
|
2843
369
|
}
|
|
2844
370
|
}
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
}
|
|
2851
|
-
async function getClientsAtHash(hash2, dagRead) {
|
|
2852
|
-
if (!hash2) {
|
|
2853
|
-
return /* @__PURE__ */ new Map();
|
|
2854
|
-
}
|
|
2855
|
-
const chunk = await dagRead.getChunk(hash2);
|
|
2856
|
-
return chunkDataToClientMap(chunk?.data);
|
|
2857
|
-
}
|
|
2858
|
-
var ClientStateNotFoundError = class extends Error {
|
|
2859
|
-
name = "ClientStateNotFoundError";
|
|
2860
|
-
id;
|
|
2861
|
-
constructor(id) {
|
|
2862
|
-
super(`Client state not found, id: ${id}`);
|
|
2863
|
-
this.id = id;
|
|
2864
|
-
}
|
|
2865
|
-
};
|
|
2866
|
-
async function assertHasClientState(id, dagRead) {
|
|
2867
|
-
if (!await hasClientState(id, dagRead)) {
|
|
2868
|
-
throw new ClientStateNotFoundError(id);
|
|
371
|
+
let bSize = 0;
|
|
372
|
+
for (const key in b) {
|
|
373
|
+
if (hasOwn(b, key)) {
|
|
374
|
+
bSize++;
|
|
375
|
+
}
|
|
2869
376
|
}
|
|
377
|
+
return aSize === bSize;
|
|
2870
378
|
}
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
async function getClient(id, dagRead) {
|
|
2875
|
-
const clients = await getClients(dagRead);
|
|
2876
|
-
return clients.get(id);
|
|
2877
|
-
}
|
|
2878
|
-
async function mustGetClient(id, dagRead) {
|
|
2879
|
-
const client = await getClient(id, dagRead);
|
|
2880
|
-
if (!client) {
|
|
2881
|
-
throw new ClientStateNotFoundError(id);
|
|
379
|
+
function assertJSONValue(v2) {
|
|
380
|
+
if (isProd) {
|
|
381
|
+
return;
|
|
2882
382
|
}
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
cookieJSON,
|
|
2892
|
-
valueHash2,
|
|
2893
|
-
indexRecords2
|
|
2894
|
-
);
|
|
2895
|
-
const chunk = dagWrite.createChunk(
|
|
2896
|
-
newSnapshotData,
|
|
2897
|
-
getRefs(newSnapshotData)
|
|
2898
|
-
);
|
|
2899
|
-
const newClientGroupID = makeClientID();
|
|
2900
|
-
const newClient = {
|
|
2901
|
-
heartbeatTimestampMs: Date.now(),
|
|
2902
|
-
refreshHashes: [chunk.hash],
|
|
2903
|
-
persistHash: null,
|
|
2904
|
-
clientGroupID: newClientGroupID
|
|
2905
|
-
};
|
|
2906
|
-
const newClients = new Map(clients).set(newClientID, newClient);
|
|
2907
|
-
const clientGroup = {
|
|
2908
|
-
headHash: chunk.hash,
|
|
2909
|
-
mutatorNames,
|
|
2910
|
-
indexes,
|
|
2911
|
-
mutationIDs: {},
|
|
2912
|
-
lastServerAckdMutationIDs: {},
|
|
2913
|
-
disabled: false
|
|
2914
|
-
};
|
|
2915
|
-
await Promise.all([
|
|
2916
|
-
dagWrite.putChunk(chunk),
|
|
2917
|
-
setClients(newClients, dagWrite),
|
|
2918
|
-
setClientGroup(newClientGroupID, clientGroup, dagWrite)
|
|
2919
|
-
]);
|
|
2920
|
-
return [newClient, chunk.hash, newClients, true];
|
|
2921
|
-
}
|
|
2922
|
-
const clients = await getClients(dagWrite);
|
|
2923
|
-
const res = await findMatchingClient(dagWrite, mutatorNames, indexes);
|
|
2924
|
-
if (res.type === FIND_MATCHING_CLIENT_TYPE_HEAD) {
|
|
2925
|
-
const { clientGroupID, headHash } = res;
|
|
2926
|
-
const newClient = {
|
|
2927
|
-
clientGroupID,
|
|
2928
|
-
refreshHashes: [headHash],
|
|
2929
|
-
heartbeatTimestampMs: Date.now(),
|
|
2930
|
-
persistHash: null
|
|
2931
|
-
};
|
|
2932
|
-
const newClients = new Map(clients).set(newClientID, newClient);
|
|
2933
|
-
await setClients(newClients, dagWrite);
|
|
2934
|
-
return [newClient, headHash, newClients, false];
|
|
2935
|
-
}
|
|
2936
|
-
if (!enableClientGroupForking || res.type === FIND_MATCHING_CLIENT_TYPE_NEW) {
|
|
2937
|
-
const emptyBTreeChunk = dagWrite.createChunk(emptyDataNode, []);
|
|
2938
|
-
await dagWrite.putChunk(emptyBTreeChunk);
|
|
2939
|
-
const indexRecords2 = [];
|
|
2940
|
-
for (const [name, indexDefinition] of Object.entries(indexes)) {
|
|
2941
|
-
const chunkIndexDefinition = toChunkIndexDefinition(
|
|
2942
|
-
name,
|
|
2943
|
-
indexDefinition
|
|
2944
|
-
);
|
|
2945
|
-
indexRecords2.push({
|
|
2946
|
-
definition: chunkIndexDefinition,
|
|
2947
|
-
valueHash: emptyBTreeChunk.hash
|
|
2948
|
-
});
|
|
383
|
+
switch (typeof v2) {
|
|
384
|
+
case "boolean":
|
|
385
|
+
case "number":
|
|
386
|
+
case "string":
|
|
387
|
+
return;
|
|
388
|
+
case "object":
|
|
389
|
+
if (v2 === null) {
|
|
390
|
+
return;
|
|
2949
391
|
}
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
null,
|
|
2953
|
-
emptyBTreeChunk.hash,
|
|
2954
|
-
indexRecords2
|
|
2955
|
-
);
|
|
2956
|
-
}
|
|
2957
|
-
assert(res.type === FIND_MATCHING_CLIENT_TYPE_FORK);
|
|
2958
|
-
const { snapshot } = res;
|
|
2959
|
-
const indexRecords = [];
|
|
2960
|
-
const { valueHash, indexes: oldIndexes } = snapshot;
|
|
2961
|
-
const map = new BTreeRead(dagWrite, formatVersion, valueHash);
|
|
2962
|
-
for (const [name, indexDefinition] of Object.entries(indexes)) {
|
|
2963
|
-
const { prefix = "", jsonPointer, allowEmpty = false } = indexDefinition;
|
|
2964
|
-
const chunkIndexDefinition = {
|
|
2965
|
-
name,
|
|
2966
|
-
keyPrefix: prefix,
|
|
2967
|
-
jsonPointer,
|
|
2968
|
-
allowEmpty
|
|
2969
|
-
};
|
|
2970
|
-
const oldIndex = findMatchingOldIndex(oldIndexes, chunkIndexDefinition);
|
|
2971
|
-
if (oldIndex) {
|
|
2972
|
-
indexRecords.push({
|
|
2973
|
-
definition: chunkIndexDefinition,
|
|
2974
|
-
valueHash: oldIndex.valueHash
|
|
2975
|
-
});
|
|
2976
|
-
} else {
|
|
2977
|
-
const indexBTree = await createIndexBTree(
|
|
2978
|
-
lc,
|
|
2979
|
-
dagWrite,
|
|
2980
|
-
map,
|
|
2981
|
-
prefix,
|
|
2982
|
-
jsonPointer,
|
|
2983
|
-
allowEmpty,
|
|
2984
|
-
formatVersion
|
|
2985
|
-
);
|
|
2986
|
-
indexRecords.push({
|
|
2987
|
-
definition: chunkIndexDefinition,
|
|
2988
|
-
valueHash: await indexBTree.flush()
|
|
2989
|
-
});
|
|
392
|
+
if (Array.isArray(v2)) {
|
|
393
|
+
return assertJSONArray(v2);
|
|
2990
394
|
}
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
snapshot.meta.cookieJSON,
|
|
2995
|
-
snapshot.valueHash,
|
|
2996
|
-
indexRecords
|
|
2997
|
-
);
|
|
2998
|
-
});
|
|
395
|
+
return assertObjectIsJSONObject(v2);
|
|
396
|
+
}
|
|
397
|
+
throwInvalidType(v2, "JSON value");
|
|
2999
398
|
}
|
|
3000
|
-
function
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
);
|
|
399
|
+
function assertJSONObject(v2) {
|
|
400
|
+
assertObject(v2);
|
|
401
|
+
assertObjectIsJSONObject(v2);
|
|
3004
402
|
}
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
const clientGroups = await getClientGroups(dagRead);
|
|
3013
|
-
for (const [clientGroupID, clientGroup] of clientGroups) {
|
|
3014
|
-
if (!clientGroup.disabled && mutatorNamesEqual(mutatorNamesSet, clientGroup.mutatorNames) && indexDefinitionsEqual(indexes, clientGroup.indexes)) {
|
|
3015
|
-
return {
|
|
3016
|
-
type: FIND_MATCHING_CLIENT_TYPE_HEAD,
|
|
3017
|
-
clientGroupID,
|
|
3018
|
-
headHash: clientGroup.headHash
|
|
3019
|
-
};
|
|
3020
|
-
}
|
|
3021
|
-
const clientGroupSnapshotCommit = await baseSnapshotFromHash(
|
|
3022
|
-
clientGroup.headHash,
|
|
3023
|
-
dagRead
|
|
3024
|
-
);
|
|
3025
|
-
assertSnapshotCommitDD31(clientGroupSnapshotCommit);
|
|
3026
|
-
const { cookieJSON } = clientGroupSnapshotCommit.meta;
|
|
3027
|
-
if (newestCookie === void 0 || compareCookies(cookieJSON, newestCookie) > 0) {
|
|
3028
|
-
newestCookie = cookieJSON;
|
|
3029
|
-
bestSnapshot = clientGroupSnapshotCommit;
|
|
403
|
+
function assertObjectIsJSONObject(v2) {
|
|
404
|
+
for (const k in v2) {
|
|
405
|
+
if (hasOwn(v2, k)) {
|
|
406
|
+
const value = v2[k];
|
|
407
|
+
if (value !== void 0) {
|
|
408
|
+
assertJSONValue(value);
|
|
409
|
+
}
|
|
3030
410
|
}
|
|
3031
411
|
}
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
};
|
|
412
|
+
}
|
|
413
|
+
function assertJSONArray(v2) {
|
|
414
|
+
for (const item of v2) {
|
|
415
|
+
assertJSONValue(item);
|
|
3037
416
|
}
|
|
3038
|
-
return { type: FIND_MATCHING_CLIENT_TYPE_NEW };
|
|
3039
417
|
}
|
|
3040
|
-
function
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
if (
|
|
3048
|
-
|
|
418
|
+
function isJSONValue(v2, path2) {
|
|
419
|
+
switch (typeof v2) {
|
|
420
|
+
case "boolean":
|
|
421
|
+
case "number":
|
|
422
|
+
case "string":
|
|
423
|
+
return true;
|
|
424
|
+
case "object":
|
|
425
|
+
if (v2 === null) {
|
|
426
|
+
return true;
|
|
3049
427
|
}
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
if (client.tempRefreshHash) {
|
|
3053
|
-
refs.add(client.tempRefreshHash);
|
|
428
|
+
if (Array.isArray(v2)) {
|
|
429
|
+
return isJSONArray(v2, path2);
|
|
3054
430
|
}
|
|
3055
|
-
|
|
431
|
+
return objectIsJSONObject(v2, path2);
|
|
3056
432
|
}
|
|
3057
|
-
return
|
|
433
|
+
return false;
|
|
3058
434
|
}
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
return void 0;
|
|
435
|
+
function isJSONObject(v2, path2) {
|
|
436
|
+
if (typeof v2 !== "object" || v2 === null) {
|
|
437
|
+
return false;
|
|
3063
438
|
}
|
|
3064
|
-
return
|
|
3065
|
-
}
|
|
3066
|
-
async function getClientGroupIDForClient(clientID, read) {
|
|
3067
|
-
const client = await getClient(clientID, read);
|
|
3068
|
-
return client?.clientGroupID;
|
|
3069
|
-
}
|
|
3070
|
-
async function setClient(clientID, client, dagWrite) {
|
|
3071
|
-
const clients = await getClients(dagWrite);
|
|
3072
|
-
const newClients = new Map(clients).set(clientID, client);
|
|
3073
|
-
return setClients(newClients, dagWrite);
|
|
3074
|
-
}
|
|
3075
|
-
async function setClients(clients, dagWrite) {
|
|
3076
|
-
const chunkData = clientMapToChunkData(clients, dagWrite);
|
|
3077
|
-
const chunk = dagWrite.createChunk(chunkData, getRefsForClients(clients));
|
|
3078
|
-
await dagWrite.putChunk(chunk);
|
|
3079
|
-
await dagWrite.setHead(CLIENTS_HEAD_NAME, chunk.hash);
|
|
3080
|
-
return chunk.hash;
|
|
439
|
+
return objectIsJSONObject(v2, path2);
|
|
3081
440
|
}
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
}
|
|
3092
|
-
const defined2 = arr.slice(0, i);
|
|
3093
|
-
for (i++; i < arr.length; i++) {
|
|
3094
|
-
const x = arr[i];
|
|
3095
|
-
if (x !== void 0) {
|
|
3096
|
-
defined2.push(x);
|
|
441
|
+
function objectIsJSONObject(v2, path2) {
|
|
442
|
+
for (const k in v2) {
|
|
443
|
+
if (hasOwn(v2, k)) {
|
|
444
|
+
path2.push(k);
|
|
445
|
+
const value = v2[k];
|
|
446
|
+
if (value !== void 0 && !isJSONValue(value, path2)) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
path2.pop();
|
|
3097
450
|
}
|
|
3098
451
|
}
|
|
3099
|
-
return
|
|
452
|
+
return true;
|
|
3100
453
|
}
|
|
3101
|
-
function
|
|
3102
|
-
|
|
454
|
+
function isJSONArray(v2, path2) {
|
|
455
|
+
for (let i = 0; i < v2.length; i++) {
|
|
456
|
+
path2.push(i);
|
|
457
|
+
if (!isJSONValue(v2[i], path2)) {
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
path2.pop();
|
|
461
|
+
}
|
|
462
|
+
return true;
|
|
3103
463
|
}
|
|
3104
464
|
|
|
3105
465
|
// ../shared/src/json-schema.ts
|
|
3106
|
-
import * as valita from "@badrap/valita";
|
|
3107
466
|
var path = [];
|
|
3108
467
|
var jsonSchema = valita_exports.unknown().chain((v2) => {
|
|
3109
468
|
if (isProd) {
|
|
@@ -3397,15 +756,15 @@ function cmpCondition(a, b) {
|
|
|
3397
756
|
}
|
|
3398
757
|
function compareValuePosition(a, b) {
|
|
3399
758
|
if (a.type !== b.type) {
|
|
3400
|
-
return
|
|
759
|
+
return compareUTF8(a.type, b.type);
|
|
3401
760
|
}
|
|
3402
761
|
switch (a.type) {
|
|
3403
762
|
case "literal":
|
|
3404
763
|
assert(b.type === "literal");
|
|
3405
|
-
return
|
|
764
|
+
return compareUTF8(String(a.value), String(b.value));
|
|
3406
765
|
case "column":
|
|
3407
766
|
assert(b.type === "column");
|
|
3408
|
-
return
|
|
767
|
+
return compareUTF8(a.name, b.name);
|
|
3409
768
|
case "static":
|
|
3410
769
|
throw new Error(
|
|
3411
770
|
"Static parameters should be resolved before normalization"
|
|
@@ -3413,7 +772,7 @@ function compareValuePosition(a, b) {
|
|
|
3413
772
|
}
|
|
3414
773
|
}
|
|
3415
774
|
function cmpRelated(a, b) {
|
|
3416
|
-
return
|
|
775
|
+
return compareUTF8(must(a.subquery.alias), must(b.subquery.alias));
|
|
3417
776
|
}
|
|
3418
777
|
function flattened(cond) {
|
|
3419
778
|
if (cond.type === "simple" || cond.type === "correlatedSubquery") {
|
|
@@ -3438,7 +797,7 @@ function flattened(cond) {
|
|
|
3438
797
|
}
|
|
3439
798
|
function compareUTF8MaybeNull(a, b) {
|
|
3440
799
|
if (a !== null && b !== null) {
|
|
3441
|
-
return
|
|
800
|
+
return compareUTF8(a, b);
|
|
3442
801
|
}
|
|
3443
802
|
if (b !== null) {
|
|
3444
803
|
return -1;
|
|
@@ -3449,109 +808,6 @@ function compareUTF8MaybeNull(a, b) {
|
|
|
3449
808
|
return 0;
|
|
3450
809
|
}
|
|
3451
810
|
|
|
3452
|
-
// ../zero-protocol/src/inspect-down.ts
|
|
3453
|
-
var inspectQueryRowSchema = valita_exports.object({
|
|
3454
|
-
clientID: valita_exports.string(),
|
|
3455
|
-
queryID: valita_exports.string(),
|
|
3456
|
-
ast: astSchema,
|
|
3457
|
-
got: valita_exports.boolean(),
|
|
3458
|
-
deleted: valita_exports.boolean(),
|
|
3459
|
-
ttl: valita_exports.number(),
|
|
3460
|
-
inactivatedAt: valita_exports.number().nullable(),
|
|
3461
|
-
rowCount: valita_exports.number()
|
|
3462
|
-
});
|
|
3463
|
-
var inspectQueriesDownSchema = valita_exports.object({
|
|
3464
|
-
op: valita_exports.literal("queries"),
|
|
3465
|
-
id: valita_exports.string(),
|
|
3466
|
-
value: valita_exports.array(inspectQueryRowSchema)
|
|
3467
|
-
});
|
|
3468
|
-
var inspectDownBodySchema = valita_exports.union(inspectQueriesDownSchema);
|
|
3469
|
-
var inspectDownMessageSchema = valita_exports.tuple([
|
|
3470
|
-
valita_exports.literal("inspect"),
|
|
3471
|
-
inspectDownBodySchema
|
|
3472
|
-
]);
|
|
3473
|
-
|
|
3474
|
-
// ../shared/src/random-values.ts
|
|
3475
|
-
function getNonCryptoRandomValues(array5) {
|
|
3476
|
-
if (array5 === null) {
|
|
3477
|
-
throw new TypeError("array cannot be null");
|
|
3478
|
-
}
|
|
3479
|
-
for (let i = 0; i < array5.length; i++) {
|
|
3480
|
-
array5[i] = Math.floor(Math.random() * 256);
|
|
3481
|
-
}
|
|
3482
|
-
return array5;
|
|
3483
|
-
}
|
|
3484
|
-
|
|
3485
|
-
// ../zero-client/src/util/nanoid.ts
|
|
3486
|
-
function nanoid(size = 21) {
|
|
3487
|
-
const randomBytes = getNonCryptoRandomValues(new Uint8Array(size));
|
|
3488
|
-
return randomBytes.reduce((id, byte) => {
|
|
3489
|
-
byte &= 63;
|
|
3490
|
-
if (byte < 36) {
|
|
3491
|
-
id += byte.toString(36);
|
|
3492
|
-
} else if (byte < 62) {
|
|
3493
|
-
id += (byte - 26).toString(36).toUpperCase();
|
|
3494
|
-
} else if (byte > 62) {
|
|
3495
|
-
id += "-";
|
|
3496
|
-
} else {
|
|
3497
|
-
id += "_";
|
|
3498
|
-
}
|
|
3499
|
-
return id;
|
|
3500
|
-
}, "");
|
|
3501
|
-
}
|
|
3502
|
-
|
|
3503
|
-
// ../shared/src/hash.ts
|
|
3504
|
-
import { xxHash32 } from "js-xxhash";
|
|
3505
|
-
var h64 = (s) => hash(s, 2);
|
|
3506
|
-
var h128 = (s) => hash(s, 4);
|
|
3507
|
-
function hash(str, words) {
|
|
3508
|
-
let hash2 = 0n;
|
|
3509
|
-
for (let i = 0; i < words; i++) {
|
|
3510
|
-
hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
|
|
3511
|
-
}
|
|
3512
|
-
return hash2;
|
|
3513
|
-
}
|
|
3514
|
-
|
|
3515
|
-
// ../zero-protocol/src/primary-key.ts
|
|
3516
|
-
var primaryKeySchema = readonly(
|
|
3517
|
-
valita_exports.tuple([valita_exports.string()]).concat(valita_exports.array(valita_exports.string()))
|
|
3518
|
-
);
|
|
3519
|
-
var primaryKeyValueSchema = valita_exports.union(
|
|
3520
|
-
valita_exports.string(),
|
|
3521
|
-
valita_exports.number(),
|
|
3522
|
-
valita_exports.boolean()
|
|
3523
|
-
);
|
|
3524
|
-
var primaryKeyValueRecordSchema = readonlyRecord(
|
|
3525
|
-
primaryKeyValueSchema
|
|
3526
|
-
);
|
|
3527
|
-
|
|
3528
|
-
// ../zero-client/src/client/keys.ts
|
|
3529
|
-
var DESIRED_QUERIES_KEY_PREFIX = "d/";
|
|
3530
|
-
var GOT_QUERIES_KEY_PREFIX = "g/";
|
|
3531
|
-
var ENTITIES_KEY_PREFIX = "e/";
|
|
3532
|
-
function toDesiredQueriesKey(clientID, hash2) {
|
|
3533
|
-
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash2;
|
|
3534
|
-
}
|
|
3535
|
-
function desiredQueriesPrefixForClient(clientID) {
|
|
3536
|
-
return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
|
|
3537
|
-
}
|
|
3538
|
-
function toGotQueriesKey(hash2) {
|
|
3539
|
-
return GOT_QUERIES_KEY_PREFIX + hash2;
|
|
3540
|
-
}
|
|
3541
|
-
function toPrimaryKeyString(tableName, primaryKey, value) {
|
|
3542
|
-
if (primaryKey.length === 1) {
|
|
3543
|
-
return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
|
|
3544
|
-
}
|
|
3545
|
-
const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
|
|
3546
|
-
const str = JSON.stringify(values);
|
|
3547
|
-
const idSegment = h128(str);
|
|
3548
|
-
return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
|
|
3549
|
-
}
|
|
3550
|
-
function sourceNameFromKey(key) {
|
|
3551
|
-
const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
|
|
3552
|
-
return key.slice(ENTITIES_KEY_PREFIX.length, slash);
|
|
3553
|
-
}
|
|
3554
|
-
|
|
3555
811
|
// ../zero-schema/src/table-schema.ts
|
|
3556
812
|
function isOneHop(r) {
|
|
3557
813
|
return r.length === 1;
|
|
@@ -3838,6 +1094,77 @@ var Exists = class {
|
|
|
3838
1094
|
}
|
|
3839
1095
|
};
|
|
3840
1096
|
|
|
1097
|
+
// ../shared/src/iterables.ts
|
|
1098
|
+
function* joinIterables(...iters) {
|
|
1099
|
+
for (const iter of iters) {
|
|
1100
|
+
yield* iter;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
function* filterIter(iter, p) {
|
|
1104
|
+
let index = 0;
|
|
1105
|
+
for (const t of iter) {
|
|
1106
|
+
if (p(t, index++)) {
|
|
1107
|
+
yield t;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
function* mapIter(iter, f) {
|
|
1112
|
+
let index = 0;
|
|
1113
|
+
for (const t of iter) {
|
|
1114
|
+
yield f(t, index++);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
var IterWrapper = class _IterWrapper {
|
|
1118
|
+
iter;
|
|
1119
|
+
constructor(iter) {
|
|
1120
|
+
this.iter = iter;
|
|
1121
|
+
}
|
|
1122
|
+
[Symbol.iterator]() {
|
|
1123
|
+
return this.iter[Symbol.iterator]();
|
|
1124
|
+
}
|
|
1125
|
+
map(f) {
|
|
1126
|
+
return new _IterWrapper(mapIter(this.iter, f));
|
|
1127
|
+
}
|
|
1128
|
+
filter(p) {
|
|
1129
|
+
return new _IterWrapper(filterIter(this.iter, p));
|
|
1130
|
+
}
|
|
1131
|
+
};
|
|
1132
|
+
function wrapIterable(iter) {
|
|
1133
|
+
return new IterWrapper(iter);
|
|
1134
|
+
}
|
|
1135
|
+
function* mergeIterables(iterables, comparator, distinct = false) {
|
|
1136
|
+
const iterators = iterables.map((i) => i[Symbol.iterator]());
|
|
1137
|
+
try {
|
|
1138
|
+
const current = iterators.map((i) => i.next());
|
|
1139
|
+
let lastYielded;
|
|
1140
|
+
while (current.some((c) => !c.done)) {
|
|
1141
|
+
const min = current.reduce(
|
|
1142
|
+
(acc, c, i) => {
|
|
1143
|
+
if (c.done) {
|
|
1144
|
+
return acc;
|
|
1145
|
+
}
|
|
1146
|
+
if (acc === void 0 || comparator(c.value, acc[0]) < 0) {
|
|
1147
|
+
return [c.value, i];
|
|
1148
|
+
}
|
|
1149
|
+
return acc;
|
|
1150
|
+
},
|
|
1151
|
+
void 0
|
|
1152
|
+
);
|
|
1153
|
+
assert(min !== void 0, "min is undefined");
|
|
1154
|
+
current[min[1]] = iterators[min[1]].next();
|
|
1155
|
+
if (lastYielded !== void 0 && distinct && comparator(lastYielded, min[0]) === 0) {
|
|
1156
|
+
continue;
|
|
1157
|
+
}
|
|
1158
|
+
lastYielded = min[0];
|
|
1159
|
+
yield min[0];
|
|
1160
|
+
}
|
|
1161
|
+
} finally {
|
|
1162
|
+
for (const it of iterators) {
|
|
1163
|
+
it.return?.();
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
|
|
3841
1168
|
// ../zql/src/ivm/fan-in.ts
|
|
3842
1169
|
var FanIn = class {
|
|
3843
1170
|
#inputs;
|
|
@@ -5550,10 +2877,12 @@ var ArrayView = class {
|
|
|
5550
2877
|
onDestroy;
|
|
5551
2878
|
#dirty = false;
|
|
5552
2879
|
#complete = false;
|
|
5553
|
-
|
|
2880
|
+
#updateTTL;
|
|
2881
|
+
constructor(input, format, queryComplete, updateTTL) {
|
|
5554
2882
|
this.#input = input;
|
|
5555
2883
|
this.#schema = input.getSchema();
|
|
5556
2884
|
this.#format = format;
|
|
2885
|
+
this.#updateTTL = updateTTL;
|
|
5557
2886
|
this.#root = { "": format.singular ? void 0 : [] };
|
|
5558
2887
|
input.setOutput(this);
|
|
5559
2888
|
if (queryComplete === true) {
|
|
@@ -5615,6 +2944,9 @@ var ArrayView = class {
|
|
|
5615
2944
|
this.#dirty = false;
|
|
5616
2945
|
this.#fireListeners();
|
|
5617
2946
|
}
|
|
2947
|
+
updateTTL(ttl) {
|
|
2948
|
+
this.#updateTTL(ttl);
|
|
2949
|
+
}
|
|
5618
2950
|
};
|
|
5619
2951
|
|
|
5620
2952
|
// ../zql/src/query/expression.ts
|
|
@@ -5757,8 +3089,8 @@ var negateOperatorMap = {
|
|
|
5757
3089
|
function negateOperator(op) {
|
|
5758
3090
|
return must(negateOperatorMap[op]);
|
|
5759
3091
|
}
|
|
5760
|
-
function filterUndefined(
|
|
5761
|
-
return
|
|
3092
|
+
function filterUndefined(array3) {
|
|
3093
|
+
return array3.filter((e) => e !== void 0);
|
|
5762
3094
|
}
|
|
5763
3095
|
function filterTrue(conditions) {
|
|
5764
3096
|
return conditions.filter((c) => !isAlwaysTrue(c));
|
|
@@ -5821,7 +3153,7 @@ function unwrap(c) {
|
|
|
5821
3153
|
}
|
|
5822
3154
|
|
|
5823
3155
|
// ../zql/src/query/query-impl.ts
|
|
5824
|
-
var
|
|
3156
|
+
var astSymbol = Symbol();
|
|
5825
3157
|
function newQuery(delegate, schema, table) {
|
|
5826
3158
|
return new QueryImpl(delegate, schema, table, { table }, defaultFormat);
|
|
5827
3159
|
}
|
|
@@ -5850,8 +3182,7 @@ var AbstractQuery = class {
|
|
|
5850
3182
|
this.#ast = ast;
|
|
5851
3183
|
this.format = format;
|
|
5852
3184
|
}
|
|
5853
|
-
|
|
5854
|
-
get [astForTestingSymbol]() {
|
|
3185
|
+
get [astSymbol]() {
|
|
5855
3186
|
return this.#ast;
|
|
5856
3187
|
}
|
|
5857
3188
|
hash() {
|
|
@@ -6242,6 +3573,9 @@ var QueryImpl = class extends AbstractQuery {
|
|
|
6242
3573
|
queryCompleteResolver.resolve(true);
|
|
6243
3574
|
}
|
|
6244
3575
|
});
|
|
3576
|
+
const updateTTL = (newTTL) => {
|
|
3577
|
+
this.#delegate.updateServerQuery(ast, newTTL);
|
|
3578
|
+
};
|
|
6245
3579
|
const input = buildPipeline(ast, this.#delegate);
|
|
6246
3580
|
let removeCommitObserver;
|
|
6247
3581
|
const onDestroy = () => {
|
|
@@ -6258,14 +3592,12 @@ var QueryImpl = class extends AbstractQuery {
|
|
|
6258
3592
|
(cb) => {
|
|
6259
3593
|
removeCommitObserver = this.#delegate.onTransactionCommit(cb);
|
|
6260
3594
|
},
|
|
6261
|
-
queryGot || queryCompleteResolver.promise
|
|
3595
|
+
queryGot || queryCompleteResolver.promise,
|
|
3596
|
+
updateTTL
|
|
6262
3597
|
)
|
|
6263
3598
|
);
|
|
6264
3599
|
return view;
|
|
6265
3600
|
}
|
|
6266
|
-
updateTTL(ttl) {
|
|
6267
|
-
this.#delegate.updateServerQuery(this._completeAst(), ttl);
|
|
6268
|
-
}
|
|
6269
3601
|
run() {
|
|
6270
3602
|
const v2 = this.materialize();
|
|
6271
3603
|
const ret = v2.data;
|
|
@@ -6311,8 +3643,13 @@ function addPrimaryKeysToAst(schema, ast) {
|
|
|
6311
3643
|
orderBy: addPrimaryKeys(schema, ast.orderBy)
|
|
6312
3644
|
};
|
|
6313
3645
|
}
|
|
6314
|
-
function arrayViewFactory(_query, input, format, onDestroy, onTransactionCommit, queryComplete) {
|
|
6315
|
-
const v2 = new ArrayView(
|
|
3646
|
+
function arrayViewFactory(_query, input, format, onDestroy, onTransactionCommit, queryComplete, updateTTL) {
|
|
3647
|
+
const v2 = new ArrayView(
|
|
3648
|
+
input,
|
|
3649
|
+
format,
|
|
3650
|
+
queryComplete,
|
|
3651
|
+
updateTTL
|
|
3652
|
+
);
|
|
6316
3653
|
v2.onDestroy = onDestroy;
|
|
6317
3654
|
onTransactionCommit(() => {
|
|
6318
3655
|
v2.flush();
|
|
@@ -6325,94 +3662,24 @@ function isCompoundKey(field) {
|
|
|
6325
3662
|
|
|
6326
3663
|
export {
|
|
6327
3664
|
isProd,
|
|
3665
|
+
hasOwn,
|
|
6328
3666
|
deepEqual,
|
|
6329
3667
|
assertJSONValue,
|
|
6330
3668
|
assertJSONObject,
|
|
6331
|
-
stringCompare,
|
|
6332
|
-
compareCookies,
|
|
6333
|
-
assertCookie,
|
|
6334
|
-
deepFreeze,
|
|
6335
|
-
deepFreezeAllowUndefined,
|
|
6336
3669
|
parse,
|
|
3670
|
+
assert2 as assert,
|
|
6337
3671
|
test,
|
|
3672
|
+
readonly,
|
|
6338
3673
|
readonlyObject,
|
|
6339
3674
|
readonlyArray,
|
|
3675
|
+
readonlyRecord,
|
|
6340
3676
|
valita_exports,
|
|
6341
|
-
emptyHash,
|
|
6342
|
-
newRandomHash,
|
|
6343
|
-
assertHash,
|
|
6344
|
-
Chunk,
|
|
6345
|
-
assertRefs,
|
|
6346
|
-
createChunk,
|
|
6347
|
-
ChunkNotFoundError,
|
|
6348
|
-
mustGetChunk,
|
|
6349
|
-
mustGetHeadHash,
|
|
6350
|
-
DD31,
|
|
6351
|
-
V6,
|
|
6352
|
-
V7,
|
|
6353
|
-
Latest,
|
|
6354
3677
|
joinIterables,
|
|
6355
3678
|
wrapIterable,
|
|
6356
|
-
getSizeOfValue,
|
|
6357
|
-
DEFAULT_HEAD_NAME,
|
|
6358
|
-
commitIsLocalDD31,
|
|
6359
|
-
localMutations,
|
|
6360
|
-
localMutationsDD31,
|
|
6361
|
-
localMutationsGreaterThan,
|
|
6362
|
-
baseSnapshotFromHead,
|
|
6363
|
-
baseSnapshotFromHash,
|
|
6364
|
-
baseSnapshotFromCommit,
|
|
6365
|
-
snapshotMetaParts,
|
|
6366
|
-
compareCookiesForSnapshots,
|
|
6367
|
-
commitFromHash,
|
|
6368
|
-
commitFromHead,
|
|
6369
|
-
assertLocalMetaDD31,
|
|
6370
|
-
isLocalMetaDD31,
|
|
6371
|
-
assertSnapshotMetaDD31,
|
|
6372
|
-
assertSnapshotCommitDD31,
|
|
6373
|
-
binarySearch,
|
|
6374
|
-
BTreeRead,
|
|
6375
|
-
encodeIndexScanKey,
|
|
6376
|
-
decodeIndexKey,
|
|
6377
|
-
readFromDefaultHead,
|
|
6378
|
-
readFromHash,
|
|
6379
|
-
asyncIterableToArray,
|
|
6380
|
-
diff,
|
|
6381
|
-
DiffsMap,
|
|
6382
|
-
diff2,
|
|
6383
|
-
diffCommits,
|
|
6384
|
-
addDiffsForIndexes,
|
|
6385
|
-
newWriteLocal,
|
|
6386
|
-
newWriteSnapshotDD31,
|
|
6387
|
-
getClientGroups,
|
|
6388
|
-
setClientGroups,
|
|
6389
|
-
setClientGroup,
|
|
6390
|
-
getClientGroup,
|
|
6391
|
-
clientGroupHasPendingMutations,
|
|
6392
|
-
disableClientGroup,
|
|
6393
|
-
withRead,
|
|
6394
|
-
withWriteNoImplicitCommit,
|
|
6395
|
-
withWrite,
|
|
6396
|
-
using,
|
|
6397
3679
|
jsonSchema,
|
|
6398
3680
|
jsonObjectSchema,
|
|
6399
|
-
clientGroupIDSchema,
|
|
6400
|
-
clientIDSchema,
|
|
6401
|
-
makeClientID,
|
|
6402
|
-
assertClientV6,
|
|
6403
|
-
getClients,
|
|
6404
|
-
ClientStateNotFoundError,
|
|
6405
|
-
assertHasClientState,
|
|
6406
|
-
hasClientState,
|
|
6407
|
-
getClient,
|
|
6408
|
-
mustGetClient,
|
|
6409
|
-
initClientV6,
|
|
6410
|
-
getClientGroupForClient,
|
|
6411
|
-
getClientGroupIDForClient,
|
|
6412
|
-
setClient,
|
|
6413
|
-
setClients,
|
|
6414
|
-
getNonCryptoRandomValues,
|
|
6415
3681
|
h64,
|
|
3682
|
+
h128,
|
|
6416
3683
|
rowSchema,
|
|
6417
3684
|
toStaticParam,
|
|
6418
3685
|
astSchema,
|
|
@@ -6425,22 +3692,14 @@ export {
|
|
|
6425
3692
|
transformFilters,
|
|
6426
3693
|
assertOrderingIncludesPK,
|
|
6427
3694
|
ExpressionBuilder,
|
|
3695
|
+
DEFAULT_TTL,
|
|
3696
|
+
parseTTL,
|
|
3697
|
+
compareTTL,
|
|
3698
|
+
normalizeTTL,
|
|
6428
3699
|
newQuery,
|
|
6429
3700
|
staticParam,
|
|
6430
3701
|
SUBQ_PREFIX,
|
|
6431
3702
|
defaultFormat,
|
|
6432
|
-
AbstractQuery
|
|
6433
|
-
inspectQueriesDownSchema,
|
|
6434
|
-
inspectDownMessageSchema,
|
|
6435
|
-
primaryKeySchema,
|
|
6436
|
-
primaryKeyValueRecordSchema,
|
|
6437
|
-
nanoid,
|
|
6438
|
-
GOT_QUERIES_KEY_PREFIX,
|
|
6439
|
-
ENTITIES_KEY_PREFIX,
|
|
6440
|
-
toDesiredQueriesKey,
|
|
6441
|
-
desiredQueriesPrefixForClient,
|
|
6442
|
-
toGotQueriesKey,
|
|
6443
|
-
toPrimaryKeyString,
|
|
6444
|
-
sourceNameFromKey
|
|
3703
|
+
AbstractQuery
|
|
6445
3704
|
};
|
|
6446
|
-
//# sourceMappingURL=chunk-
|
|
3705
|
+
//# sourceMappingURL=chunk-GTRWLUIW.js.map
|