@rocicorp/zero 0.13.2025020400 → 0.13.2025020402

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/out/advanced.js +2 -2
  2. package/out/{chunk-RC3FUXOA.js → chunk-ADFMUREC.js} +1092 -928
  3. package/out/chunk-ADFMUREC.js.map +7 -0
  4. package/out/{chunk-ZVLXEWWB.js → chunk-Q6D7EOS6.js} +1 -1
  5. package/out/{chunk-ZVLXEWWB.js.map → chunk-Q6D7EOS6.js.map} +2 -2
  6. package/out/chunk-ULOTOBTC.js +1 -0
  7. package/out/react.js +44 -3
  8. package/out/react.js.map +3 -3
  9. package/out/replicache/src/patch-operation.d.ts +1 -1
  10. package/out/replicache/src/patch-operation.d.ts.map +1 -1
  11. package/out/solid.js +112 -37
  12. package/out/solid.js.map +2 -2
  13. package/out/zero-advanced/src/mod.d.ts +1 -1
  14. package/out/zero-advanced/src/mod.d.ts.map +1 -1
  15. package/out/zero-cache/src/auth/load-schema.d.ts +1 -1
  16. package/out/zero-cache/src/auth/load-schema.d.ts.map +1 -1
  17. package/out/zero-cache/src/auth/load-schema.js +8 -1
  18. package/out/zero-cache/src/auth/load-schema.js.map +1 -1
  19. package/out/zero-client/src/client/context.d.ts +2 -2
  20. package/out/zero-client/src/client/context.d.ts.map +1 -1
  21. package/out/zero-client/src/client/custom.d.ts +9 -2
  22. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  23. package/out/zero-client/src/client/ivm-source-repo.d.ts +34 -0
  24. package/out/zero-client/src/client/ivm-source-repo.d.ts.map +1 -0
  25. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  26. package/out/zero-client/src/client/zero-poke-handler.d.ts +2 -9
  27. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  28. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  29. package/out/zero-protocol/src/ast.d.ts +3 -4
  30. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  31. package/out/zero-protocol/src/ast.js +10 -56
  32. package/out/zero-protocol/src/ast.js.map +1 -1
  33. package/out/zero-protocol/src/push.d.ts +2 -0
  34. package/out/zero-protocol/src/push.d.ts.map +1 -1
  35. package/out/zero-protocol/src/push.js +24 -0
  36. package/out/zero-protocol/src/push.js.map +1 -1
  37. package/out/zero-schema/src/builder/schema-builder.d.ts +1 -0
  38. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  39. package/out/zero-schema/src/builder/schema-builder.js +49 -0
  40. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  41. package/out/zero-schema/src/mod.d.ts +5 -0
  42. package/out/zero-schema/src/mod.d.ts.map +1 -0
  43. package/out/zero-schema/src/name-mapper.d.ts +23 -0
  44. package/out/zero-schema/src/name-mapper.d.ts.map +1 -0
  45. package/out/zero-schema/src/name-mapper.js +77 -0
  46. package/out/zero-schema/src/name-mapper.js.map +1 -0
  47. package/out/zero-schema/src/permissions.d.ts.map +1 -1
  48. package/out/zero-solid/src/solid-view.d.ts +3 -2
  49. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  50. package/out/zero.js +2 -2
  51. package/out/zql/src/ivm/memory-source.d.ts +3 -1
  52. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  53. package/out/zql/src/ivm/memory-source.js +6 -2
  54. package/out/zql/src/ivm/memory-source.js.map +1 -1
  55. package/out/zql/src/ivm/view-apply-change.d.ts +34 -2
  56. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  57. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  58. package/package.json +1 -1
  59. package/out/chunk-5JO5DB4D.js +0 -50
  60. package/out/chunk-5JO5DB4D.js.map +0 -7
  61. package/out/chunk-ALG35NEG.js +0 -1
  62. package/out/chunk-RC3FUXOA.js.map +0 -7
  63. /package/out/{chunk-ALG35NEG.js.map → chunk-ULOTOBTC.js.map} +0 -0
@@ -18,7 +18,7 @@ import {
18
18
  throwInvalidType,
19
19
  unreachable,
20
20
  valuesEqual
21
- } from "./chunk-ZVLXEWWB.js";
21
+ } from "./chunk-Q6D7EOS6.js";
22
22
  import {
23
23
  __export,
24
24
  __reExport
@@ -1957,6 +1957,38 @@ function* joinIterables(...iters) {
1957
1957
  yield* iter;
1958
1958
  }
1959
1959
  }
1960
+ function* filterIter(iter, p) {
1961
+ let index = 0;
1962
+ for (const t2 of iter) {
1963
+ if (p(t2, index++)) {
1964
+ yield t2;
1965
+ }
1966
+ }
1967
+ }
1968
+ function* mapIter(iter, f) {
1969
+ let index = 0;
1970
+ for (const t2 of iter) {
1971
+ yield f(t2, index++);
1972
+ }
1973
+ }
1974
+ var IterWrapper = class _IterWrapper {
1975
+ iter;
1976
+ constructor(iter) {
1977
+ this.iter = iter;
1978
+ }
1979
+ [Symbol.iterator]() {
1980
+ return this.iter[Symbol.iterator]();
1981
+ }
1982
+ map(f) {
1983
+ return new _IterWrapper(mapIter(this.iter, f));
1984
+ }
1985
+ filter(p) {
1986
+ return new _IterWrapper(filterIter(this.iter, p));
1987
+ }
1988
+ };
1989
+ function wrapIterable(iter) {
1990
+ return new IterWrapper(iter);
1991
+ }
1960
1992
  function* mergeIterables(iterables, comparator2, distinct = false) {
1961
1993
  const iterators = iterables.map((i) => i[Symbol.iterator]());
1962
1994
  try {
@@ -8286,6 +8318,87 @@ function one(...args) {
8286
8318
  }));
8287
8319
  }
8288
8320
 
8321
+ // ../zero-schema/src/name-mapper.ts
8322
+ function clientToServer(tables) {
8323
+ return createMapperFrom("client", tables);
8324
+ }
8325
+ function serverToClient(tables) {
8326
+ return createMapperFrom("server", tables);
8327
+ }
8328
+ function createMapperFrom(src, tables) {
8329
+ const mapping = new Map(
8330
+ Object.entries(tables).map(
8331
+ ([tableName, { serverName: serverTableName, columns }]) => {
8332
+ let allColumnsSame = true;
8333
+ const names = {};
8334
+ for (const [name, { serverName }] of Object.entries(columns)) {
8335
+ if (serverName && serverName !== name) {
8336
+ allColumnsSame = false;
8337
+ }
8338
+ if (src === "client") {
8339
+ names[name] = serverName ?? name;
8340
+ } else {
8341
+ names[serverName ?? name] = name;
8342
+ }
8343
+ }
8344
+ return [
8345
+ src === "client" ? tableName : serverTableName ?? tableName,
8346
+ {
8347
+ tableName: src === "client" ? serverTableName ?? tableName : tableName,
8348
+ columns: names,
8349
+ allColumnsSame
8350
+ }
8351
+ ];
8352
+ }
8353
+ )
8354
+ );
8355
+ return new NameMapper(mapping);
8356
+ }
8357
+ var NameMapper = class {
8358
+ #tables = /* @__PURE__ */ new Map();
8359
+ constructor(tables) {
8360
+ this.#tables = tables;
8361
+ }
8362
+ #getTable(src, ctx) {
8363
+ const table2 = this.#tables.get(src);
8364
+ if (!table2) {
8365
+ throw new Error(
8366
+ `unknown table "${src}" ${!ctx ? "" : `in ${JSON.stringify(ctx)}`}`
8367
+ );
8368
+ }
8369
+ return table2;
8370
+ }
8371
+ tableName(src, context) {
8372
+ return this.#getTable(src, context).tableName;
8373
+ }
8374
+ columnName(table2, src, ctx) {
8375
+ const dst = this.#getTable(table2, ctx).columns[src];
8376
+ if (!dst) {
8377
+ throw new Error(
8378
+ `unknown column "${src}" of "${table2}" table ${!ctx ? "" : `in ${JSON.stringify(ctx)}`}`
8379
+ );
8380
+ }
8381
+ return dst;
8382
+ }
8383
+ row(table2, row) {
8384
+ const dest = this.#getTable(table2);
8385
+ const { allColumnsSame, columns } = dest;
8386
+ if (allColumnsSame) {
8387
+ return row;
8388
+ }
8389
+ const clientRow = {};
8390
+ for (const col in row) {
8391
+ clientRow[columns[col] ?? col] = row[col];
8392
+ }
8393
+ return clientRow;
8394
+ }
8395
+ columns(table2, cols) {
8396
+ const dest = this.#getTable(table2);
8397
+ const { allColumnsSame, columns } = dest;
8398
+ return cols === void 0 || allColumnsSame ? cols : cols.map((col) => columns[col] ?? col);
8399
+ }
8400
+ };
8401
+
8289
8402
  // ../zero-schema/src/builder/table-builder.ts
8290
8403
  function table(name) {
8291
8404
  return new TableBuilder({
@@ -8696,77 +8809,23 @@ function normalizeAST(ast) {
8696
8809
  }
8697
8810
  return normalized;
8698
8811
  }
8699
- function toServerAST(ast, tables) {
8700
- return transformAST(ast, clientToServer(tables));
8701
- }
8702
- function toServerCondition(cond, table2, tables) {
8703
- return transformWhere(cond, table2, clientToServer(tables));
8704
- }
8705
- function clientToServer(tables) {
8706
- const mustTable = (table2) => {
8707
- const t2 = tables[table2];
8708
- if (!table2) {
8709
- throw new Error(`invalid table "${table2}"`);
8710
- }
8711
- return t2;
8712
- };
8713
- return {
8714
- tableName: (table2) => mustTable(table2).serverName ?? table2,
8715
- columnName: (table2, col) => {
8716
- const c = mustTable(table2).columns[col];
8717
- if (!c) {
8718
- throw new Error(`invalid column "${col}" in table "${table2}"`);
8719
- }
8720
- return c.serverName ?? col;
8721
- },
8812
+ function mapAST(ast, mapper) {
8813
+ return transformAST(ast, {
8814
+ tableName: (table2) => mapper.tableName(table2),
8815
+ columnName: (table2, col) => mapper.columnName(table2, col),
8722
8816
  related: (r) => r,
8723
8817
  where: (w) => w,
8724
8818
  conditions: (c) => c
8725
- };
8726
- }
8727
- function toClientAST(ast, tables) {
8728
- return transformAST(ast, serverToClient(tables));
8819
+ });
8729
8820
  }
8730
- function serverToClient(tables) {
8731
- const tableNames = Object.fromEntries(
8732
- Object.entries(tables).map(([clientName, { serverName }]) => [
8733
- serverName ?? clientName,
8734
- clientName
8735
- ])
8736
- );
8737
- const columnNamesByTable = Object.fromEntries(
8738
- Object.entries(tables).map(
8739
- ([clientTable, { serverName: serverTable, columns }]) => {
8740
- const columnNames = Object.fromEntries(
8741
- Object.entries(columns).map(([clientName, { serverName }]) => [
8742
- serverName ?? clientName,
8743
- clientName
8744
- ])
8745
- );
8746
- return [serverTable ?? clientTable, columnNames];
8747
- }
8748
- )
8749
- );
8750
- function mustTable(table2, tables2) {
8751
- const t2 = tables2[table2];
8752
- if (!table2) {
8753
- throw new Error(`invalid table "${table2}"`);
8754
- }
8755
- return t2;
8756
- }
8757
- return {
8758
- tableName: (table2) => mustTable(table2, tableNames),
8759
- columnName: (table2, col) => {
8760
- const name = mustTable(table2, columnNamesByTable)[col];
8761
- if (!name) {
8762
- throw new Error(`invalid column "${col}" in table "${table2}"`);
8763
- }
8764
- return name;
8765
- },
8821
+ function mapCondition(cond, table2, mapper) {
8822
+ return transformWhere(cond, table2, {
8823
+ tableName: (table3) => mapper.tableName(table3),
8824
+ columnName: (table3, col) => mapper.columnName(table3, col),
8766
8825
  related: (r) => r,
8767
8826
  where: (w) => w,
8768
8827
  conditions: (c) => c
8769
- };
8828
+ });
8770
8829
  }
8771
8830
  function sortedRelated(related) {
8772
8831
  return related.sort(cmpRelated);
@@ -11424,18 +11483,19 @@ function compilePermissions(schema, authz, expressionBuilders) {
11424
11483
  if (!authz) {
11425
11484
  return void 0;
11426
11485
  }
11486
+ const nameMapper = clientToServer(schema.tables);
11427
11487
  const ret = {};
11428
11488
  for (const [tableName, tableConfig] of Object.entries(authz)) {
11429
11489
  const serverName = schema.tables[tableName].serverName ?? tableName;
11430
11490
  ret[serverName] = {
11431
11491
  row: compileRowConfig(
11432
- schema,
11492
+ nameMapper,
11433
11493
  tableName,
11434
11494
  tableConfig.row,
11435
11495
  expressionBuilders[tableName]
11436
11496
  ),
11437
11497
  cell: compileCellConfig(
11438
- schema,
11498
+ nameMapper,
11439
11499
  tableName,
11440
11500
  tableConfig.cell,
11441
11501
  expressionBuilders[tableName]
@@ -11444,66 +11504,93 @@ function compilePermissions(schema, authz, expressionBuilders) {
11444
11504
  }
11445
11505
  return ret;
11446
11506
  }
11447
- function compileRowConfig(schema, tableName, rowRules, expressionBuilder) {
11507
+ function compileRowConfig(clientToServer2, tableName, rowRules, expressionBuilder) {
11448
11508
  if (!rowRules) {
11449
11509
  return void 0;
11450
11510
  }
11451
11511
  return {
11452
- select: compileRules(schema, tableName, rowRules.select, expressionBuilder),
11453
- insert: compileRules(schema, tableName, rowRules.insert, expressionBuilder),
11512
+ select: compileRules(
11513
+ clientToServer2,
11514
+ tableName,
11515
+ rowRules.select,
11516
+ expressionBuilder
11517
+ ),
11518
+ insert: compileRules(
11519
+ clientToServer2,
11520
+ tableName,
11521
+ rowRules.insert,
11522
+ expressionBuilder
11523
+ ),
11454
11524
  update: {
11455
11525
  preMutation: compileRules(
11456
- schema,
11526
+ clientToServer2,
11457
11527
  tableName,
11458
11528
  rowRules.update?.preMutation,
11459
11529
  expressionBuilder
11460
11530
  ),
11461
11531
  postMutation: compileRules(
11462
- schema,
11532
+ clientToServer2,
11463
11533
  tableName,
11464
11534
  rowRules.update?.postMutation,
11465
11535
  expressionBuilder
11466
11536
  )
11467
11537
  },
11468
- delete: compileRules(schema, tableName, rowRules.delete, expressionBuilder)
11538
+ delete: compileRules(
11539
+ clientToServer2,
11540
+ tableName,
11541
+ rowRules.delete,
11542
+ expressionBuilder
11543
+ )
11469
11544
  };
11470
11545
  }
11471
- function compileRules(schema, tableName, rules, expressionBuilder) {
11546
+ function compileRules(clientToServer2, tableName, rules, expressionBuilder) {
11472
11547
  if (!rules) {
11473
11548
  return void 0;
11474
11549
  }
11475
11550
  return rules.map((rule) => {
11476
11551
  const cond = rule(authDataRef, expressionBuilder);
11477
- return [
11478
- "allow",
11479
- toServerCondition(cond, tableName, schema.tables)
11480
- ];
11552
+ return ["allow", mapCondition(cond, tableName, clientToServer2)];
11481
11553
  });
11482
11554
  }
11483
- function compileCellConfig(schema, tableName, cellRules, expressionBuilder) {
11555
+ function compileCellConfig(clientToServer2, tableName, cellRules, expressionBuilder) {
11484
11556
  if (!cellRules) {
11485
11557
  return void 0;
11486
11558
  }
11487
11559
  const ret = {};
11488
11560
  for (const [columnName, rules] of Object.entries(cellRules)) {
11489
11561
  ret[columnName] = {
11490
- select: compileRules(schema, tableName, rules.select, expressionBuilder),
11491
- insert: compileRules(schema, tableName, rules.insert, expressionBuilder),
11562
+ select: compileRules(
11563
+ clientToServer2,
11564
+ tableName,
11565
+ rules.select,
11566
+ expressionBuilder
11567
+ ),
11568
+ insert: compileRules(
11569
+ clientToServer2,
11570
+ tableName,
11571
+ rules.insert,
11572
+ expressionBuilder
11573
+ ),
11492
11574
  update: {
11493
11575
  preMutation: compileRules(
11494
- schema,
11576
+ clientToServer2,
11495
11577
  tableName,
11496
11578
  rules.update?.preMutation,
11497
11579
  expressionBuilder
11498
11580
  ),
11499
11581
  postMutation: compileRules(
11500
- schema,
11582
+ clientToServer2,
11501
11583
  tableName,
11502
11584
  rules.update?.postMutation,
11503
11585
  expressionBuilder
11504
11586
  )
11505
11587
  },
11506
- delete: compileRules(schema, tableName, rules.delete, expressionBuilder)
11588
+ delete: compileRules(
11589
+ clientToServer2,
11590
+ tableName,
11591
+ rules.delete,
11592
+ expressionBuilder
11593
+ )
11507
11594
  };
11508
11595
  }
11509
11596
  return ret;
@@ -11887,6 +11974,29 @@ var pushBodySchema = valita_exports.object({
11887
11974
  requestID: valita_exports.string()
11888
11975
  });
11889
11976
  var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pushBodySchema]);
11977
+ function mapCRUD(arg, map) {
11978
+ return {
11979
+ ops: arg.ops.map(({ op, tableName, primaryKey, value }) => {
11980
+ switch (op) {
11981
+ case "delete": {
11982
+ return {
11983
+ op,
11984
+ tableName: map.tableName(tableName),
11985
+ primaryKey: map.columns(tableName, primaryKey),
11986
+ value: map.row(tableName, value)
11987
+ };
11988
+ }
11989
+ default:
11990
+ return {
11991
+ op,
11992
+ tableName: map.tableName(tableName),
11993
+ primaryKey: map.columns(tableName, primaryKey),
11994
+ value: map.row(tableName, value)
11995
+ };
11996
+ }
11997
+ })
11998
+ };
11999
+ }
11890
12000
 
11891
12001
  // ../zero-client/src/util/nanoid.ts
11892
12002
  function nanoid(size = 21) {
@@ -11916,6 +12026,9 @@ var Disconnected = 0;
11916
12026
  var Connecting = 1;
11917
12027
  var Connected = 2;
11918
12028
 
12029
+ // ../zql/src/ivm/memory-storage.ts
12030
+ import { compareUTF8 as compareUTF84 } from "compare-utf8";
12031
+
11919
12032
  // ../shared/src/btree-set.ts
11920
12033
  var MAX_NODE_SIZE = 32;
11921
12034
  var BTreeSet = class _BTreeSet {
@@ -12403,885 +12516,965 @@ function indexOf(key, keys, failXor, comparator2) {
12403
12516
  var emptyLeaf = new BNode([]);
12404
12517
  emptyLeaf.isShared = true;
12405
12518
 
12406
- // ../zql/src/ivm/constraint.ts
12407
- function constraintMatchesRow(constraint, row) {
12408
- for (const key in constraint) {
12409
- if (!valuesEqual(row[key], constraint[key])) {
12410
- return false;
12519
+ // ../zql/src/ivm/memory-storage.ts
12520
+ function comparator(a, b) {
12521
+ return compareUTF84(a[0], b[0]);
12522
+ }
12523
+ var MemoryStorage = class {
12524
+ #data = new BTreeSet(comparator);
12525
+ set(key, value) {
12526
+ this.#data.add([key, value]);
12527
+ }
12528
+ get(key, def) {
12529
+ const r = this.#data.get([key, null]);
12530
+ if (r !== void 0) {
12531
+ return r[1];
12411
12532
  }
12533
+ return def;
12412
12534
  }
12413
- return true;
12414
- }
12415
- function constraintMatchesPrimaryKey(constraint, primary) {
12416
- const constraintKeys = Object.keys(constraint);
12417
- if (constraintKeys.length !== primary.length) {
12418
- return false;
12535
+ del(key) {
12536
+ this.#data.delete([key, null]);
12419
12537
  }
12420
- constraintKeys.sort(stringCompare);
12421
- for (let i = 0; i < constraintKeys.length; i++) {
12422
- if (constraintKeys[i][0] !== primary[i]) {
12423
- return false;
12538
+ *scan(options) {
12539
+ for (const entry of this.#data.valuesFrom(
12540
+ options && [options.prefix, null]
12541
+ )) {
12542
+ if (options && !entry[0].startsWith(options.prefix)) {
12543
+ return;
12544
+ }
12545
+ yield entry;
12424
12546
  }
12425
12547
  }
12426
- return true;
12548
+ cloneData() {
12549
+ return structuredClone(Object.fromEntries(this.#data.values()));
12550
+ }
12551
+ };
12552
+
12553
+ // ../zero-client/src/client/keys.ts
12554
+ var CLIENTS_KEY_PREFIX = "c/";
12555
+ var DESIRED_QUERIES_KEY_PREFIX = "d/";
12556
+ var GOT_QUERIES_KEY_PREFIX = "g/";
12557
+ var ENTITIES_KEY_PREFIX = "e/";
12558
+ function toClientsKey(clientID) {
12559
+ return CLIENTS_KEY_PREFIX + clientID;
12560
+ }
12561
+ function toDesiredQueriesKey(clientID, hash2) {
12562
+ return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash2;
12563
+ }
12564
+ function desiredQueriesPrefixForClient(clientID) {
12565
+ return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
12566
+ }
12567
+ function toGotQueriesKey(hash2) {
12568
+ return GOT_QUERIES_KEY_PREFIX + hash2;
12569
+ }
12570
+ function toPrimaryKeyString(tableName, primaryKey, value) {
12571
+ if (primaryKey.length === 1) {
12572
+ return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
12573
+ }
12574
+ const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
12575
+ const str = JSON.stringify(values);
12576
+ const idSegment = h128(str);
12577
+ return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
12427
12578
  }
12428
12579
 
12429
- // ../zql/src/ivm/memory-source.ts
12430
- var MemorySource = class {
12431
- #tableName;
12432
- #columns;
12433
- #primaryKey;
12434
- #primaryIndexSort;
12435
- #indexes = /* @__PURE__ */ new Map();
12436
- #connections = [];
12437
- #overlay;
12438
- constructor(tableName, columns, primaryKey) {
12439
- this.#tableName = tableName;
12440
- this.#columns = columns;
12441
- this.#primaryKey = primaryKey;
12442
- this.#primaryIndexSort = primaryKey.map((k) => [k, "asc"]);
12443
- const comparator2 = makeBoundComparator(this.#primaryIndexSort);
12444
- this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {
12445
- comparator: comparator2,
12446
- data: new BTreeSet(comparator2),
12447
- usedBy: /* @__PURE__ */ new Set()
12448
- });
12449
- assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);
12580
+ // ../zero-client/src/client/context.ts
12581
+ var ZeroContext = class {
12582
+ // It is a bummer to have to maintain separate MemorySources here and copy the
12583
+ // data in from the Replicache db. But we want the data to be accessible via
12584
+ // pipelines *synchronously* and the core Replicache infra is all async. So
12585
+ // that needs to be fixed.
12586
+ #mainSources;
12587
+ #addQuery;
12588
+ #batchViewUpdates;
12589
+ #commitListeners = /* @__PURE__ */ new Set();
12590
+ staticQueryParameters = void 0;
12591
+ constructor(mainSources, addQuery, batchViewUpdates) {
12592
+ this.#mainSources = mainSources;
12593
+ this.#addQuery = addQuery;
12594
+ this.#batchViewUpdates = batchViewUpdates;
12450
12595
  }
12451
- // Mainly for tests.
12452
- getSchemaInfo() {
12453
- return {
12454
- tableName: this.#tableName,
12455
- columns: this.#columns,
12456
- primaryKey: this.#primaryKey
12457
- };
12596
+ getSource(name) {
12597
+ return this.#mainSources.getSource(name);
12458
12598
  }
12459
- #getSchema(connection) {
12460
- return {
12461
- tableName: this.#tableName,
12462
- columns: this.#columns,
12463
- primaryKey: this.#primaryKey,
12464
- sort: connection.sort,
12465
- system: "client",
12466
- relationships: {},
12467
- isHidden: false,
12468
- compareRows: connection.compareRows
12469
- };
12599
+ addServerQuery(ast, gotCallback) {
12600
+ return this.#addQuery(ast, gotCallback);
12470
12601
  }
12471
- connect(sort, filters) {
12472
- const transformedFilters = transformFilters(filters);
12473
- const input = {
12474
- getSchema: () => schema,
12475
- fetch: (req) => this.#fetch(req, connection),
12476
- cleanup: (req) => this.#cleanup(req, connection),
12477
- setOutput: (output) => {
12478
- connection.output = output;
12479
- },
12480
- destroy: () => {
12481
- this.#disconnect(input);
12482
- },
12483
- fullyAppliedFilters: !transformedFilters.conditionsRemoved
12602
+ createStorage() {
12603
+ return new MemoryStorage();
12604
+ }
12605
+ onTransactionCommit(cb) {
12606
+ this.#commitListeners.add(cb);
12607
+ return () => {
12608
+ this.#commitListeners.delete(cb);
12484
12609
  };
12485
- const connection = {
12486
- input,
12487
- output: void 0,
12488
- sort,
12489
- compareRows: makeComparator(sort),
12490
- filters: transformedFilters.filters ? {
12491
- condition: transformedFilters.filters,
12492
- predicate: createPredicate(transformedFilters.filters)
12493
- } : void 0
12494
- };
12495
- const schema = this.#getSchema(connection);
12496
- assertOrderingIncludesPK(sort, this.#primaryKey);
12497
- this.#connections.push(connection);
12498
- return input;
12499
12610
  }
12500
- #disconnect(input) {
12501
- const idx = this.#connections.findIndex((c) => c.input === input);
12502
- assert(idx !== -1, "Connection not found");
12503
- const connection = this.#connections[idx];
12504
- this.#connections.splice(idx, 1);
12505
- const primaryIndexKey = JSON.stringify(this.#primaryIndexSort);
12506
- for (const [key, index] of this.#indexes) {
12507
- if (key === primaryIndexKey) {
12508
- continue;
12509
- }
12510
- index.usedBy.delete(connection);
12511
- if (index.usedBy.size === 0) {
12512
- this.#indexes.delete(key);
12513
- }
12514
- }
12611
+ batchViewUpdates(applyViewUpdates) {
12612
+ let result;
12613
+ let viewChangesPerformed = false;
12614
+ this.#batchViewUpdates(() => {
12615
+ result = applyViewUpdates();
12616
+ viewChangesPerformed = true;
12617
+ });
12618
+ assert(
12619
+ viewChangesPerformed,
12620
+ "batchViewUpdates must call applyViewUpdates synchronously."
12621
+ );
12622
+ return result;
12515
12623
  }
12516
- #getPrimaryIndex() {
12517
- const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));
12518
- assert(index, "Primary index not found");
12519
- return index;
12624
+ processChanges(changes) {
12625
+ this.batchViewUpdates(() => {
12626
+ try {
12627
+ for (const diff2 of changes) {
12628
+ const { key } = diff2;
12629
+ assert(key.startsWith(ENTITIES_KEY_PREFIX));
12630
+ const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
12631
+ const name = key.slice(ENTITIES_KEY_PREFIX.length, slash);
12632
+ const source = this.getSource(name);
12633
+ if (!source) {
12634
+ continue;
12635
+ }
12636
+ switch (diff2.op) {
12637
+ case "del":
12638
+ assert(typeof diff2.oldValue === "object");
12639
+ source.push({
12640
+ type: "remove",
12641
+ row: diff2.oldValue
12642
+ });
12643
+ break;
12644
+ case "add":
12645
+ assert(typeof diff2.newValue === "object");
12646
+ source.push({
12647
+ type: "add",
12648
+ row: diff2.newValue
12649
+ });
12650
+ break;
12651
+ case "change":
12652
+ assert(typeof diff2.newValue === "object");
12653
+ assert(typeof diff2.oldValue === "object");
12654
+ source.push({
12655
+ type: "edit",
12656
+ row: diff2.newValue,
12657
+ oldRow: diff2.oldValue
12658
+ });
12659
+ break;
12660
+ default:
12661
+ unreachable(diff2);
12662
+ }
12663
+ }
12664
+ } finally {
12665
+ this.#endTransaction();
12666
+ }
12667
+ });
12520
12668
  }
12521
- #getOrCreateIndex(sort, usedBy) {
12522
- const key = JSON.stringify(sort);
12523
- const index = this.#indexes.get(key);
12524
- if (index) {
12525
- index.usedBy.add(usedBy);
12526
- return index;
12527
- }
12528
- const comparator2 = makeBoundComparator(sort);
12529
- const data = new BTreeSet(comparator2);
12530
- for (const row of this.#getPrimaryIndex().data) {
12531
- data.add(row);
12669
+ #endTransaction() {
12670
+ for (const listener of this.#commitListeners) {
12671
+ listener();
12532
12672
  }
12533
- const newIndex = { comparator: comparator2, data, usedBy: /* @__PURE__ */ new Set([usedBy]) };
12534
- this.#indexes.set(key, newIndex);
12535
- return newIndex;
12536
- }
12537
- // For unit testing that we correctly clean up indexes.
12538
- getIndexKeys() {
12539
- return [...this.#indexes.keys()];
12540
12673
  }
12541
- *#fetch(req, from) {
12542
- let overlay;
12543
- const callingConnectionNum = this.#connections.indexOf(from);
12544
- assert(callingConnectionNum !== -1, "Output not found");
12545
- const conn = this.#connections[callingConnectionNum];
12546
- const { sort: requestedSort } = conn;
12547
- const indexSort = [];
12548
- if (req.constraint) {
12549
- for (const key of Object.keys(req.constraint)) {
12550
- indexSort.push([key, "asc"]);
12551
- }
12552
- }
12553
- if (this.#primaryKey.length > 1 || !req.constraint || !constraintMatchesPrimaryKey(req.constraint, this.#primaryKey)) {
12554
- indexSort.push(...requestedSort);
12674
+ };
12675
+
12676
+ // ../zero-client/src/client/crud.ts
12677
+ function makeCRUDMutate(schema, repMutate) {
12678
+ const { [CRUD_MUTATION_NAME]: zeroCRUD } = repMutate;
12679
+ let inBatch = false;
12680
+ const mutateBatch = async (body) => {
12681
+ if (inBatch) {
12682
+ throw new Error("Cannot call mutate inside a batch");
12555
12683
  }
12556
- const index = this.#getOrCreateIndex(indexSort, from);
12557
- const { data, comparator: compare } = index;
12558
- const comparator2 = (r1, r2) => compare(r1, r2) * (req.reverse ? -1 : 1);
12559
- if (this.#overlay) {
12560
- if (callingConnectionNum <= this.#overlay.outputIndex) {
12561
- overlay = this.#overlay;
12684
+ inBatch = true;
12685
+ try {
12686
+ const ops = [];
12687
+ const m = {};
12688
+ for (const name of Object.keys(schema.tables)) {
12689
+ m[name] = makeBatchCRUDMutate(name, schema, ops);
12562
12690
  }
12691
+ const rv = await body(m);
12692
+ await zeroCRUD({ ops });
12693
+ return rv;
12694
+ } finally {
12695
+ inBatch = false;
12563
12696
  }
12564
- const startAt = req.start?.row;
12565
- let scanStart;
12566
- if (req.constraint) {
12567
- scanStart = {};
12568
- for (const [key, dir] of indexSort) {
12569
- if (hasOwn(req.constraint, key)) {
12570
- scanStart[key] = req.constraint[key];
12571
- } else {
12572
- if (req.reverse) {
12573
- scanStart[key] = dir === "asc" ? maxValue : minValue;
12574
- } else {
12575
- scanStart[key] = dir === "asc" ? minValue : maxValue;
12576
- }
12577
- }
12578
- }
12579
- } else {
12580
- scanStart = startAt;
12697
+ };
12698
+ const assertNotInBatch = (tableName, op) => {
12699
+ if (inBatch) {
12700
+ throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);
12581
12701
  }
12582
- const withOverlay = generateWithOverlay(
12583
- startAt,
12584
- generateRows(data, scanStart, req.reverse),
12585
- req.constraint,
12586
- overlay,
12587
- comparator2,
12588
- conn.filters?.predicate
12589
- );
12590
- const withConstraint = generateWithConstraint(
12591
- generateWithStart(withOverlay, req.start, comparator2),
12592
- req.constraint
12702
+ };
12703
+ const mutate = {};
12704
+ for (const [name, tableSchema] of Object.entries(schema.tables)) {
12705
+ mutate[name] = makeEntityCRUDMutate(
12706
+ name,
12707
+ tableSchema.primaryKey,
12708
+ zeroCRUD,
12709
+ assertNotInBatch
12593
12710
  );
12594
- yield* conn.filters ? generateWithFilter(withConstraint, conn.filters.predicate) : withConstraint;
12595
12711
  }
12596
- #cleanup(req, connection) {
12597
- return this.#fetch(req, connection);
12598
- }
12599
- push(change) {
12600
- for (const _ of this.genPush(change)) {
12601
- }
12602
- }
12603
- *genPush(change) {
12604
- const primaryIndex = this.#getPrimaryIndex();
12605
- const { data } = primaryIndex;
12606
- switch (change.type) {
12607
- case "add":
12608
- assert(
12609
- !data.has(change.row),
12610
- () => `Row already exists ${JSON.stringify(change)}`
12611
- );
12612
- break;
12613
- case "remove":
12614
- assert(
12615
- data.has(change.row),
12616
- () => `Row not found ${JSON.stringify(change)}`
12617
- );
12618
- break;
12619
- case "edit":
12620
- assert(
12621
- data.has(change.oldRow),
12622
- () => `Row not found ${JSON.stringify(change)}`
12623
- );
12624
- break;
12625
- default:
12626
- unreachable(change);
12712
+ return {
12713
+ mutate,
12714
+ mutateBatch
12715
+ };
12716
+ }
12717
+ function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch) {
12718
+ return {
12719
+ insert: (value) => {
12720
+ assertNotInBatch(tableName, "insert");
12721
+ const op = {
12722
+ op: "insert",
12723
+ tableName,
12724
+ primaryKey,
12725
+ value
12726
+ };
12727
+ return zeroCRUD({ ops: [op] });
12728
+ },
12729
+ upsert: (value) => {
12730
+ assertNotInBatch(tableName, "upsert");
12731
+ const op = {
12732
+ op: "upsert",
12733
+ tableName,
12734
+ primaryKey,
12735
+ value
12736
+ };
12737
+ return zeroCRUD({ ops: [op] });
12738
+ },
12739
+ update: (value) => {
12740
+ assertNotInBatch(tableName, "update");
12741
+ const op = {
12742
+ op: "update",
12743
+ tableName,
12744
+ primaryKey,
12745
+ value
12746
+ };
12747
+ return zeroCRUD({ ops: [op] });
12748
+ },
12749
+ delete: (id) => {
12750
+ assertNotInBatch(tableName, "delete");
12751
+ const op = {
12752
+ op: "delete",
12753
+ tableName,
12754
+ primaryKey,
12755
+ value: id
12756
+ };
12757
+ return zeroCRUD({ ops: [op] });
12627
12758
  }
12628
- const outputChange = change.type === "edit" ? {
12629
- type: change.type,
12630
- oldNode: {
12631
- row: change.oldRow,
12632
- relationships: {}
12633
- },
12634
- node: {
12635
- row: change.row,
12636
- relationships: {}
12637
- }
12638
- } : {
12639
- type: change.type,
12640
- node: {
12641
- row: change.row,
12642
- relationships: {}
12643
- }
12644
- };
12645
- for (const [
12646
- outputIndex,
12647
- { output, filters }
12648
- ] of this.#connections.entries()) {
12649
- if (output) {
12650
- this.#overlay = { outputIndex, change };
12651
- filterPush(outputChange, output, filters?.predicate);
12652
- yield;
12653
- }
12759
+ };
12760
+ }
12761
+ function makeBatchCRUDMutate(tableName, schema, ops) {
12762
+ const { primaryKey } = schema.tables[tableName];
12763
+ return {
12764
+ insert: (value) => {
12765
+ const op = {
12766
+ op: "insert",
12767
+ tableName,
12768
+ primaryKey,
12769
+ value
12770
+ };
12771
+ ops.push(op);
12772
+ return promiseVoid;
12773
+ },
12774
+ upsert: (value) => {
12775
+ const op = {
12776
+ op: "upsert",
12777
+ tableName,
12778
+ primaryKey,
12779
+ value
12780
+ };
12781
+ ops.push(op);
12782
+ return promiseVoid;
12783
+ },
12784
+ update: (value) => {
12785
+ const op = {
12786
+ op: "update",
12787
+ tableName,
12788
+ primaryKey,
12789
+ value
12790
+ };
12791
+ ops.push(op);
12792
+ return promiseVoid;
12793
+ },
12794
+ delete: (id) => {
12795
+ const op = {
12796
+ op: "delete",
12797
+ tableName,
12798
+ primaryKey,
12799
+ value: id
12800
+ };
12801
+ ops.push(op);
12802
+ return promiseVoid;
12654
12803
  }
12655
- this.#overlay = void 0;
12656
- for (const { data: data2 } of this.#indexes.values()) {
12657
- switch (change.type) {
12658
- case "add": {
12659
- const added = data2.add(change.row);
12660
- assert(added);
12804
+ };
12805
+ }
12806
+ function makeCRUDMutator(schema) {
12807
+ return async function zeroCRUDMutator(tx, crudArg) {
12808
+ for (const op of crudArg.ops) {
12809
+ switch (op.op) {
12810
+ case "insert":
12811
+ await insertImpl(tx, op, schema);
12661
12812
  break;
12662
- }
12663
- case "remove": {
12664
- const removed = data2.delete(change.row);
12665
- assert(removed);
12813
+ case "upsert":
12814
+ await upsertImpl(tx, op, schema);
12666
12815
  break;
12667
- }
12668
- case "edit": {
12669
- const removed = data2.delete(change.oldRow);
12670
- assert(removed);
12671
- data2.add(change.row);
12816
+ case "update":
12817
+ await updateImpl(tx, op, schema);
12818
+ break;
12819
+ case "delete":
12820
+ await deleteImpl(tx, op, schema);
12672
12821
  break;
12673
- }
12674
- default:
12675
- unreachable(change);
12676
12822
  }
12677
12823
  }
12678
- }
12679
- };
12680
- function* generateWithConstraint(it, constraint) {
12681
- for (const node of it) {
12682
- if (constraint && !constraintMatchesRow(constraint, node.row)) {
12683
- break;
12684
- }
12685
- yield node;
12686
- }
12824
+ };
12687
12825
  }
12688
- function* generateWithFilter(it, filter) {
12689
- for (const node of it) {
12690
- if (filter(node.row)) {
12691
- yield node;
12826
+ function defaultOptionalFieldsToNull(schema, value) {
12827
+ let rv = value;
12828
+ for (const name in schema.columns) {
12829
+ if (rv[name] === void 0) {
12830
+ rv = { ...rv, [name]: null };
12692
12831
  }
12693
12832
  }
12833
+ return rv;
12694
12834
  }
12695
- function* generateWithStart(nodes, start, compare) {
12696
- if (!start) {
12697
- yield* nodes;
12698
- return;
12835
+ async function insertImpl(tx, arg, schema) {
12836
+ const key = toPrimaryKeyString(
12837
+ arg.tableName,
12838
+ schema.tables[arg.tableName].primaryKey,
12839
+ arg.value
12840
+ );
12841
+ if (!await tx.has(key)) {
12842
+ const val = defaultOptionalFieldsToNull(
12843
+ schema.tables[arg.tableName],
12844
+ arg.value
12845
+ );
12846
+ await tx.set(key, val);
12699
12847
  }
12700
- let started = false;
12701
- for (const node of nodes) {
12702
- if (!started) {
12703
- if (start.basis === "at") {
12704
- if (compare(node.row, start.row) >= 0) {
12705
- started = true;
12706
- }
12707
- } else if (start.basis === "after") {
12708
- if (compare(node.row, start.row) > 0) {
12709
- started = true;
12710
- }
12711
- }
12712
- }
12713
- if (started) {
12714
- yield node;
12848
+ }
12849
+ async function upsertImpl(tx, arg, schema) {
12850
+ const key = toPrimaryKeyString(
12851
+ arg.tableName,
12852
+ schema.tables[arg.tableName].primaryKey,
12853
+ arg.value
12854
+ );
12855
+ const val = defaultOptionalFieldsToNull(
12856
+ schema.tables[arg.tableName],
12857
+ arg.value
12858
+ );
12859
+ await tx.set(key, val);
12860
+ }
12861
+ async function updateImpl(tx, arg, schema) {
12862
+ const key = toPrimaryKeyString(
12863
+ arg.tableName,
12864
+ schema.tables[arg.tableName].primaryKey,
12865
+ arg.value
12866
+ );
12867
+ const prev = await tx.get(key);
12868
+ if (prev === void 0) {
12869
+ return;
12870
+ }
12871
+ const update = arg.value;
12872
+ const next = { ...prev };
12873
+ for (const k in update) {
12874
+ if (update[k] !== void 0) {
12875
+ next[k] = update[k];
12715
12876
  }
12716
12877
  }
12878
+ await tx.set(key, next);
12717
12879
  }
12718
- function* generateWithOverlay(startAt, rows, constraint, overlay, compare, filterPredicate) {
12719
- const overlays = computeOverlays(
12720
- startAt,
12721
- constraint,
12722
- overlay,
12723
- compare,
12724
- filterPredicate
12880
+ async function deleteImpl(tx, arg, schema) {
12881
+ const key = toPrimaryKeyString(
12882
+ arg.tableName,
12883
+ schema.tables[arg.tableName].primaryKey,
12884
+ arg.value
12725
12885
  );
12726
- yield* generateWithOverlayInner(rows, overlays, compare);
12886
+ await tx.del(key);
12727
12887
  }
12728
- function computeOverlays(startAt, constraint, overlay, compare, filterPredicate) {
12729
- let overlays = {
12730
- add: void 0,
12731
- remove: void 0
12732
- };
12733
- switch (overlay?.change.type) {
12734
- case "add":
12735
- overlays = {
12736
- add: overlay.change.row,
12737
- remove: void 0
12738
- };
12739
- break;
12740
- case "remove":
12741
- overlays = {
12742
- add: void 0,
12743
- remove: overlay.change.row
12744
- };
12745
- break;
12746
- case "edit":
12747
- overlays = {
12748
- add: overlay.change.row,
12749
- remove: overlay.change.oldRow
12750
- };
12751
- break;
12752
- }
12753
- if (startAt) {
12754
- overlays = overlaysForStartAt(overlays, startAt, compare);
12888
+
12889
+ // ../zero-client/src/client/custom.ts
12890
+ var TransactionImpl = class {
12891
+ constructor(repTx, schema, ivmSourceRepo) {
12892
+ must(repTx.reason === "initial" || repTx.reason === "rebase");
12893
+ this.clientID = repTx.clientID;
12894
+ this.mutationID = repTx.mutationID;
12895
+ this.reason = repTx.reason === "initial" ? "optimistic" : "rebase";
12896
+ this.mutate = makeSchemaCRUD(schema, repTx);
12897
+ this.query = makeSchemaQuery(
12898
+ schema,
12899
+ this.reason === "optimistic" ? ivmSourceRepo.main : (
12900
+ // TODO: we don't initialize the sync branch yet.
12901
+ // to fix in the next PR.
12902
+ ivmSourceRepo.main
12903
+ )
12904
+ );
12755
12905
  }
12756
- if (constraint) {
12757
- overlays = overlaysForConstraint(overlays, constraint);
12906
+ clientID;
12907
+ mutationID;
12908
+ reason;
12909
+ mutate;
12910
+ query;
12911
+ };
12912
+ function makeReplicacheMutator(mutator, schema, ivmSourceRepo) {
12913
+ return (repTx, args) => {
12914
+ const tx = new TransactionImpl(repTx, schema, ivmSourceRepo);
12915
+ return mutator(tx, args);
12916
+ };
12917
+ }
12918
+ function makeSchemaQuery(schema, ivmBranch) {
12919
+ const rv = {};
12920
+ const context = new ZeroContext(
12921
+ ivmBranch,
12922
+ () => () => {
12923
+ },
12924
+ (applyViewUpdates) => applyViewUpdates()
12925
+ );
12926
+ for (const name of Object.keys(schema.tables)) {
12927
+ rv[name] = newQuery(context, schema, name);
12758
12928
  }
12759
- if (filterPredicate) {
12760
- overlays = overlaysForFilterPredicate(overlays, filterPredicate);
12929
+ return rv;
12930
+ }
12931
+ function makeSchemaCRUD(schema, tx) {
12932
+ const mutate = {};
12933
+ for (const [name] of Object.entries(schema.tables)) {
12934
+ mutate[name] = makeTableCRUD(schema, name, tx);
12761
12935
  }
12762
- return overlays;
12936
+ return mutate;
12763
12937
  }
12764
- function overlaysForStartAt({ add, remove }, startAt, compare) {
12765
- const undefinedIfBeforeStartAt = (row) => row === void 0 || compare(row, startAt) < 0 ? void 0 : row;
12938
+ function makeTableCRUD(schema, tableName, tx) {
12939
+ const table2 = must(schema.tables[tableName]);
12940
+ const { primaryKey } = table2;
12766
12941
  return {
12767
- add: undefinedIfBeforeStartAt(add),
12768
- remove: undefinedIfBeforeStartAt(remove)
12942
+ insert: (value) => insertImpl(tx, { op: "insert", tableName, primaryKey, value }, schema),
12943
+ upsert: (value) => upsertImpl(tx, { op: "upsert", tableName, primaryKey, value }, schema),
12944
+ update: (value) => updateImpl(tx, { op: "update", tableName, primaryKey, value }, schema),
12945
+ delete: (id) => deleteImpl(tx, { op: "delete", tableName, primaryKey, value: id }, schema)
12769
12946
  };
12770
12947
  }
12771
- function overlaysForConstraint({ add, remove }, constraint) {
12772
- const undefinedIfDoesntMatchConstraint = (row) => row === void 0 || !constraintMatchesRow(constraint, row) ? void 0 : row;
12773
- return {
12774
- add: undefinedIfDoesntMatchConstraint(add),
12775
- remove: undefinedIfDoesntMatchConstraint(remove)
12776
- };
12948
+
12949
+ // ../zero-client/src/client/enable-analytics.ts
12950
+ var IPV4_ADDRESS_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
12951
+ var IPV6_ADDRESS_HOSTNAME_REGEX = /^\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\]$/;
12952
+ var IP_ADDRESS_HOSTNAME_REGEX = new RegExp(
12953
+ `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`
12954
+ );
12955
+ function shouldEnableAnalytics(server, enableAnalytics = true) {
12956
+ if (!enableAnalytics) {
12957
+ return false;
12958
+ }
12959
+ const serverURL = server === null ? null : new URL(server);
12960
+ const socketHostname = serverURL?.hostname;
12961
+ return server !== null && socketHostname !== void 0 && socketHostname !== "localhost" && !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname);
12777
12962
  }
12778
- function overlaysForFilterPredicate({ add, remove }, filterPredicate) {
12779
- const undefinedIfDoesntMatchFilter = (row) => row === void 0 || !filterPredicate(row) ? void 0 : row;
12780
- return {
12781
- add: undefinedIfDoesntMatchFilter(add),
12782
- remove: undefinedIfDoesntMatchFilter(remove)
12783
- };
12963
+
12964
+ // ../zero-client/src/client/http-string.ts
12965
+ function toWSString(url) {
12966
+ return "ws" + url.slice(4);
12784
12967
  }
12785
- function* generateWithOverlayInner(rowIterator, overlays, compare) {
12786
- let addOverlayYielded = false;
12787
- let removeOverlaySkipped = false;
12788
- for (const row of rowIterator) {
12789
- if (!addOverlayYielded && overlays.add) {
12790
- const cmp2 = compare(overlays.add, row);
12791
- if (cmp2 < 0) {
12792
- addOverlayYielded = true;
12793
- yield { row: overlays.add, relationships: {} };
12794
- }
12968
+ function appendPath(url, toAppend) {
12969
+ return url + (url.endsWith("/") ? toAppend.substring(1) : toAppend);
12970
+ }
12971
+
12972
+ // ../zql/src/ivm/constraint.ts
12973
+ function constraintMatchesRow(constraint, row) {
12974
+ for (const key in constraint) {
12975
+ if (!valuesEqual(row[key], constraint[key])) {
12976
+ return false;
12795
12977
  }
12796
- if (!removeOverlaySkipped && overlays.remove) {
12797
- const cmp2 = compare(overlays.remove, row);
12798
- if (cmp2 === 0) {
12799
- removeOverlaySkipped = true;
12978
+ }
12979
+ return true;
12980
+ }
12981
+ function constraintMatchesPrimaryKey(constraint, primary) {
12982
+ const constraintKeys = Object.keys(constraint);
12983
+ if (constraintKeys.length !== primary.length) {
12984
+ return false;
12985
+ }
12986
+ constraintKeys.sort(stringCompare);
12987
+ for (let i = 0; i < constraintKeys.length; i++) {
12988
+ if (constraintKeys[i][0] !== primary[i]) {
12989
+ return false;
12990
+ }
12991
+ }
12992
+ return true;
12993
+ }
12994
+
12995
+ // ../zql/src/ivm/memory-source.ts
12996
+ var MemorySource = class _MemorySource {
12997
+ #tableName;
12998
+ #columns;
12999
+ #primaryKey;
13000
+ #primaryIndexSort;
13001
+ #indexes = /* @__PURE__ */ new Map();
13002
+ #connections = [];
13003
+ #overlay;
13004
+ constructor(tableName, columns, primaryKey, primaryIndexData) {
13005
+ this.#tableName = tableName;
13006
+ this.#columns = columns;
13007
+ this.#primaryKey = primaryKey;
13008
+ this.#primaryIndexSort = primaryKey.map((k) => [k, "asc"]);
13009
+ const comparator2 = makeBoundComparator(this.#primaryIndexSort);
13010
+ this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {
13011
+ comparator: comparator2,
13012
+ data: primaryIndexData ?? new BTreeSet(comparator2),
13013
+ usedBy: /* @__PURE__ */ new Set()
13014
+ });
13015
+ assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);
13016
+ }
13017
+ // Mainly for tests.
13018
+ getSchemaInfo() {
13019
+ return {
13020
+ tableName: this.#tableName,
13021
+ columns: this.#columns,
13022
+ primaryKey: this.#primaryKey
13023
+ };
13024
+ }
13025
+ fork() {
13026
+ const primaryIndex = this.#getPrimaryIndex();
13027
+ return new _MemorySource(
13028
+ this.#tableName,
13029
+ this.#columns,
13030
+ this.#primaryKey,
13031
+ primaryIndex.data.clone()
13032
+ );
13033
+ }
13034
+ #getSchema(connection) {
13035
+ return {
13036
+ tableName: this.#tableName,
13037
+ columns: this.#columns,
13038
+ primaryKey: this.#primaryKey,
13039
+ sort: connection.sort,
13040
+ system: "client",
13041
+ relationships: {},
13042
+ isHidden: false,
13043
+ compareRows: connection.compareRows
13044
+ };
13045
+ }
13046
+ connect(sort, filters) {
13047
+ const transformedFilters = transformFilters(filters);
13048
+ const input = {
13049
+ getSchema: () => schema,
13050
+ fetch: (req) => this.#fetch(req, connection),
13051
+ cleanup: (req) => this.#cleanup(req, connection),
13052
+ setOutput: (output) => {
13053
+ connection.output = output;
13054
+ },
13055
+ destroy: () => {
13056
+ this.#disconnect(input);
13057
+ },
13058
+ fullyAppliedFilters: !transformedFilters.conditionsRemoved
13059
+ };
13060
+ const connection = {
13061
+ input,
13062
+ output: void 0,
13063
+ sort,
13064
+ compareRows: makeComparator(sort),
13065
+ filters: transformedFilters.filters ? {
13066
+ condition: transformedFilters.filters,
13067
+ predicate: createPredicate(transformedFilters.filters)
13068
+ } : void 0
13069
+ };
13070
+ const schema = this.#getSchema(connection);
13071
+ assertOrderingIncludesPK(sort, this.#primaryKey);
13072
+ this.#connections.push(connection);
13073
+ return input;
13074
+ }
13075
+ #disconnect(input) {
13076
+ const idx = this.#connections.findIndex((c) => c.input === input);
13077
+ assert(idx !== -1, "Connection not found");
13078
+ const connection = this.#connections[idx];
13079
+ this.#connections.splice(idx, 1);
13080
+ const primaryIndexKey = JSON.stringify(this.#primaryIndexSort);
13081
+ for (const [key, index] of this.#indexes) {
13082
+ if (key === primaryIndexKey) {
12800
13083
  continue;
12801
13084
  }
13085
+ index.usedBy.delete(connection);
13086
+ if (index.usedBy.size === 0) {
13087
+ this.#indexes.delete(key);
13088
+ }
12802
13089
  }
12803
- yield { row, relationships: {} };
12804
13090
  }
12805
- if (!addOverlayYielded && overlays.add) {
12806
- yield { row: overlays.add, relationships: {} };
13091
+ #getPrimaryIndex() {
13092
+ const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));
13093
+ assert(index, "Primary index not found");
13094
+ return index;
12807
13095
  }
12808
- }
12809
- var minValue = Symbol("min-value");
12810
- var maxValue = Symbol("max-value");
12811
- function makeBoundComparator(sort) {
12812
- return (a, b) => {
12813
- for (const entry of sort) {
12814
- const key = entry[0];
12815
- const cmp2 = compareBounds(a[key], b[key]);
12816
- if (cmp2 !== 0) {
12817
- return entry[1] === "asc" ? cmp2 : -cmp2;
12818
- }
13096
+ #getOrCreateIndex(sort, usedBy) {
13097
+ const key = JSON.stringify(sort);
13098
+ const index = this.#indexes.get(key);
13099
+ if (index) {
13100
+ index.usedBy.add(usedBy);
13101
+ return index;
12819
13102
  }
12820
- return 0;
12821
- };
12822
- }
12823
- function compareBounds(a, b) {
12824
- if (a === b) {
12825
- return 0;
12826
- }
12827
- if (a === minValue) {
12828
- return -1;
12829
- }
12830
- if (b === minValue) {
12831
- return 1;
12832
- }
12833
- if (a === maxValue) {
12834
- return 1;
12835
- }
12836
- if (b === maxValue) {
12837
- return -1;
12838
- }
12839
- return compareValues(a, b);
12840
- }
12841
- function* generateRows(data, scanStart, reverse) {
12842
- yield* data[reverse ? "valuesFromReversed" : "valuesFrom"](
12843
- scanStart
12844
- );
12845
- }
12846
-
12847
- // ../zql/src/ivm/memory-storage.ts
12848
- import { compareUTF8 as compareUTF84 } from "compare-utf8";
12849
- function comparator(a, b) {
12850
- return compareUTF84(a[0], b[0]);
12851
- }
12852
- var MemoryStorage = class {
12853
- #data = new BTreeSet(comparator);
12854
- set(key, value) {
12855
- this.#data.add([key, value]);
12856
- }
12857
- get(key, def) {
12858
- const r = this.#data.get([key, null]);
12859
- if (r !== void 0) {
12860
- return r[1];
13103
+ const comparator2 = makeBoundComparator(sort);
13104
+ const data = new BTreeSet(comparator2);
13105
+ for (const row of this.#getPrimaryIndex().data) {
13106
+ data.add(row);
12861
13107
  }
12862
- return def;
13108
+ const newIndex = { comparator: comparator2, data, usedBy: /* @__PURE__ */ new Set([usedBy]) };
13109
+ this.#indexes.set(key, newIndex);
13110
+ return newIndex;
12863
13111
  }
12864
- del(key) {
12865
- this.#data.delete([key, null]);
13112
+ // For unit testing that we correctly clean up indexes.
13113
+ getIndexKeys() {
13114
+ return [...this.#indexes.keys()];
12866
13115
  }
12867
- *scan(options) {
12868
- for (const entry of this.#data.valuesFrom(
12869
- options && [options.prefix, null]
12870
- )) {
12871
- if (options && !entry[0].startsWith(options.prefix)) {
12872
- return;
13116
+ *#fetch(req, from) {
13117
+ let overlay;
13118
+ const callingConnectionNum = this.#connections.indexOf(from);
13119
+ assert(callingConnectionNum !== -1, "Output not found");
13120
+ const conn = this.#connections[callingConnectionNum];
13121
+ const { sort: requestedSort } = conn;
13122
+ const indexSort = [];
13123
+ if (req.constraint) {
13124
+ for (const key of Object.keys(req.constraint)) {
13125
+ indexSort.push([key, "asc"]);
12873
13126
  }
12874
- yield entry;
12875
13127
  }
12876
- }
12877
- cloneData() {
12878
- return structuredClone(Object.fromEntries(this.#data.values()));
12879
- }
12880
- };
12881
-
12882
- // ../zero-client/src/client/keys.ts
12883
- var CLIENTS_KEY_PREFIX = "c/";
12884
- var DESIRED_QUERIES_KEY_PREFIX = "d/";
12885
- var GOT_QUERIES_KEY_PREFIX = "g/";
12886
- var ENTITIES_KEY_PREFIX = "e/";
12887
- function toClientsKey(clientID) {
12888
- return CLIENTS_KEY_PREFIX + clientID;
12889
- }
12890
- function toDesiredQueriesKey(clientID, hash2) {
12891
- return DESIRED_QUERIES_KEY_PREFIX + clientID + "/" + hash2;
12892
- }
12893
- function desiredQueriesPrefixForClient(clientID) {
12894
- return DESIRED_QUERIES_KEY_PREFIX + clientID + "/";
12895
- }
12896
- function toGotQueriesKey(hash2) {
12897
- return GOT_QUERIES_KEY_PREFIX + hash2;
12898
- }
12899
- function toPrimaryKeyString(tableName, primaryKey, value) {
12900
- if (primaryKey.length === 1) {
12901
- return ENTITIES_KEY_PREFIX + tableName + "/" + parse(value[primaryKey[0]], primaryKeyValueSchema);
12902
- }
12903
- const values = primaryKey.map((k) => parse(value[k], primaryKeyValueSchema));
12904
- const str = JSON.stringify(values);
12905
- const idSegment = h128(str);
12906
- return ENTITIES_KEY_PREFIX + tableName + "/" + idSegment;
12907
- }
12908
-
12909
- // ../zero-client/src/client/context.ts
12910
- var ZeroContext = class {
12911
- // It is a bummer to have to maintain separate MemorySources here and copy the
12912
- // data in from the Replicache db. But we want the data to be accessible via
12913
- // pipelines *synchronously* and the core Replicache infra is all async. So
12914
- // that needs to be fixed.
12915
- #sources = /* @__PURE__ */ new Map();
12916
- #tables;
12917
- #addQuery;
12918
- #batchViewUpdates;
12919
- #commitListeners = /* @__PURE__ */ new Set();
12920
- staticQueryParameters = void 0;
12921
- constructor(tables, addQuery, batchViewUpdates) {
12922
- this.#tables = tables;
12923
- this.#addQuery = addQuery;
12924
- this.#batchViewUpdates = batchViewUpdates;
12925
- }
12926
- getSource(name) {
12927
- if (this.#sources.has(name)) {
12928
- return this.#sources.get(name);
13128
+ if (this.#primaryKey.length > 1 || !req.constraint || !constraintMatchesPrimaryKey(req.constraint, this.#primaryKey)) {
13129
+ indexSort.push(...requestedSort);
12929
13130
  }
12930
- const schema = this.#tables[name];
12931
- const source = schema ? new MemorySource(name, schema.columns, schema.primaryKey) : void 0;
12932
- this.#sources.set(name, source);
12933
- return source;
12934
- }
12935
- addServerQuery(ast, gotCallback) {
12936
- return this.#addQuery(ast, gotCallback);
12937
- }
12938
- createStorage() {
12939
- return new MemoryStorage();
12940
- }
12941
- onTransactionCommit(cb) {
12942
- this.#commitListeners.add(cb);
12943
- return () => {
12944
- this.#commitListeners.delete(cb);
12945
- };
12946
- }
12947
- batchViewUpdates(applyViewUpdates) {
12948
- let result;
12949
- let viewChangesPerformed = false;
12950
- this.#batchViewUpdates(() => {
12951
- result = applyViewUpdates();
12952
- viewChangesPerformed = true;
12953
- });
12954
- assert(
12955
- viewChangesPerformed,
12956
- "batchViewUpdates must call applyViewUpdates synchronously."
12957
- );
12958
- return result;
12959
- }
12960
- processChanges(changes) {
12961
- try {
12962
- this.batchViewUpdates(() => {
12963
- for (const diff2 of changes) {
12964
- const { key } = diff2;
12965
- assert(key.startsWith(ENTITIES_KEY_PREFIX));
12966
- const slash = key.indexOf("/", ENTITIES_KEY_PREFIX.length);
12967
- const name = key.slice(ENTITIES_KEY_PREFIX.length, slash);
12968
- const source = this.getSource(name);
12969
- if (!source) {
12970
- continue;
12971
- }
12972
- switch (diff2.op) {
12973
- case "del":
12974
- assert(typeof diff2.oldValue === "object");
12975
- source.push({
12976
- type: "remove",
12977
- row: diff2.oldValue
12978
- });
12979
- break;
12980
- case "add":
12981
- assert(typeof diff2.newValue === "object");
12982
- source.push({
12983
- type: "add",
12984
- row: diff2.newValue
12985
- });
12986
- break;
12987
- case "change":
12988
- assert(typeof diff2.newValue === "object");
12989
- assert(typeof diff2.oldValue === "object");
12990
- source.push({
12991
- type: "edit",
12992
- row: diff2.newValue,
12993
- oldRow: diff2.oldValue
12994
- });
12995
- break;
12996
- default:
12997
- unreachable(diff2);
13131
+ const index = this.#getOrCreateIndex(indexSort, from);
13132
+ const { data, comparator: compare } = index;
13133
+ const comparator2 = (r1, r2) => compare(r1, r2) * (req.reverse ? -1 : 1);
13134
+ if (this.#overlay) {
13135
+ if (callingConnectionNum <= this.#overlay.outputIndex) {
13136
+ overlay = this.#overlay;
13137
+ }
13138
+ }
13139
+ const startAt = req.start?.row;
13140
+ let scanStart;
13141
+ if (req.constraint) {
13142
+ scanStart = {};
13143
+ for (const [key, dir] of indexSort) {
13144
+ if (hasOwn(req.constraint, key)) {
13145
+ scanStart[key] = req.constraint[key];
13146
+ } else {
13147
+ if (req.reverse) {
13148
+ scanStart[key] = dir === "asc" ? maxValue : minValue;
13149
+ } else {
13150
+ scanStart[key] = dir === "asc" ? minValue : maxValue;
12998
13151
  }
12999
13152
  }
13000
- });
13001
- } finally {
13002
- this.#endTransaction();
13153
+ }
13154
+ } else {
13155
+ scanStart = startAt;
13156
+ }
13157
+ const withOverlay = generateWithOverlay(
13158
+ startAt,
13159
+ generateRows(data, scanStart, req.reverse),
13160
+ req.constraint,
13161
+ overlay,
13162
+ comparator2,
13163
+ conn.filters?.predicate
13164
+ );
13165
+ const withConstraint = generateWithConstraint(
13166
+ generateWithStart(withOverlay, req.start, comparator2),
13167
+ req.constraint
13168
+ );
13169
+ yield* conn.filters ? generateWithFilter(withConstraint, conn.filters.predicate) : withConstraint;
13170
+ }
13171
+ #cleanup(req, connection) {
13172
+ return this.#fetch(req, connection);
13173
+ }
13174
+ push(change) {
13175
+ for (const _ of this.genPush(change)) {
13003
13176
  }
13004
13177
  }
13005
- #endTransaction() {
13006
- for (const listener of this.#commitListeners) {
13007
- listener();
13178
+ *genPush(change) {
13179
+ const primaryIndex = this.#getPrimaryIndex();
13180
+ const { data } = primaryIndex;
13181
+ switch (change.type) {
13182
+ case "add":
13183
+ assert(
13184
+ !data.has(change.row),
13185
+ () => `Row already exists ${JSON.stringify(change)}`
13186
+ );
13187
+ break;
13188
+ case "remove":
13189
+ assert(
13190
+ data.has(change.row),
13191
+ () => `Row not found ${JSON.stringify(change)}`
13192
+ );
13193
+ break;
13194
+ case "edit":
13195
+ assert(
13196
+ data.has(change.oldRow),
13197
+ () => `Row not found ${JSON.stringify(change)}`
13198
+ );
13199
+ break;
13200
+ default:
13201
+ unreachable(change);
13202
+ }
13203
+ const outputChange = change.type === "edit" ? {
13204
+ type: change.type,
13205
+ oldNode: {
13206
+ row: change.oldRow,
13207
+ relationships: {}
13208
+ },
13209
+ node: {
13210
+ row: change.row,
13211
+ relationships: {}
13212
+ }
13213
+ } : {
13214
+ type: change.type,
13215
+ node: {
13216
+ row: change.row,
13217
+ relationships: {}
13218
+ }
13219
+ };
13220
+ for (const [
13221
+ outputIndex,
13222
+ { output, filters }
13223
+ ] of this.#connections.entries()) {
13224
+ if (output) {
13225
+ this.#overlay = { outputIndex, change };
13226
+ filterPush(outputChange, output, filters?.predicate);
13227
+ yield;
13228
+ }
13229
+ }
13230
+ this.#overlay = void 0;
13231
+ for (const { data: data2 } of this.#indexes.values()) {
13232
+ switch (change.type) {
13233
+ case "add": {
13234
+ const added = data2.add(change.row);
13235
+ assert(added);
13236
+ break;
13237
+ }
13238
+ case "remove": {
13239
+ const removed = data2.delete(change.row);
13240
+ assert(removed);
13241
+ break;
13242
+ }
13243
+ case "edit": {
13244
+ const removed = data2.delete(change.oldRow);
13245
+ assert(removed);
13246
+ data2.add(change.row);
13247
+ break;
13248
+ }
13249
+ default:
13250
+ unreachable(change);
13251
+ }
13008
13252
  }
13009
13253
  }
13010
13254
  };
13011
-
13012
- // ../zero-client/src/client/crud.ts
13013
- function makeCRUDMutate(schema, repMutate) {
13014
- const { [CRUD_MUTATION_NAME]: zeroCRUD } = repMutate;
13015
- let inBatch = false;
13016
- const mutateBatch = async (body) => {
13017
- if (inBatch) {
13018
- throw new Error("Cannot call mutate inside a batch");
13255
+ function* generateWithConstraint(it, constraint) {
13256
+ for (const node of it) {
13257
+ if (constraint && !constraintMatchesRow(constraint, node.row)) {
13258
+ break;
13019
13259
  }
13020
- inBatch = true;
13021
- try {
13022
- const ops = [];
13023
- const m = {};
13024
- for (const name of Object.keys(schema.tables)) {
13025
- m[name] = makeBatchCRUDMutate(name, schema, ops);
13260
+ yield node;
13261
+ }
13262
+ }
13263
+ function* generateWithFilter(it, filter) {
13264
+ for (const node of it) {
13265
+ if (filter(node.row)) {
13266
+ yield node;
13267
+ }
13268
+ }
13269
+ }
13270
+ function* generateWithStart(nodes, start, compare) {
13271
+ if (!start) {
13272
+ yield* nodes;
13273
+ return;
13274
+ }
13275
+ let started = false;
13276
+ for (const node of nodes) {
13277
+ if (!started) {
13278
+ if (start.basis === "at") {
13279
+ if (compare(node.row, start.row) >= 0) {
13280
+ started = true;
13281
+ }
13282
+ } else if (start.basis === "after") {
13283
+ if (compare(node.row, start.row) > 0) {
13284
+ started = true;
13285
+ }
13026
13286
  }
13027
- const rv = await body(m);
13028
- await zeroCRUD({ ops });
13029
- return rv;
13030
- } finally {
13031
- inBatch = false;
13032
13287
  }
13033
- };
13034
- const assertNotInBatch = (tableName, op) => {
13035
- if (inBatch) {
13036
- throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);
13288
+ if (started) {
13289
+ yield node;
13037
13290
  }
13038
- };
13039
- const mutate = {};
13040
- for (const [name, tableSchema] of Object.entries(schema.tables)) {
13041
- mutate[name] = makeEntityCRUDMutate(
13042
- name,
13043
- tableSchema.primaryKey,
13044
- zeroCRUD,
13045
- assertNotInBatch
13046
- );
13047
13291
  }
13048
- return {
13049
- mutate,
13050
- mutateBatch
13051
- };
13052
13292
  }
13053
- function makeEntityCRUDMutate(tableName, primaryKey, zeroCRUD, assertNotInBatch) {
13054
- return {
13055
- insert: (value) => {
13056
- assertNotInBatch(tableName, "insert");
13057
- const op = {
13058
- op: "insert",
13059
- tableName,
13060
- primaryKey,
13061
- value
13062
- };
13063
- return zeroCRUD({ ops: [op] });
13064
- },
13065
- upsert: (value) => {
13066
- assertNotInBatch(tableName, "upsert");
13067
- const op = {
13068
- op: "upsert",
13069
- tableName,
13070
- primaryKey,
13071
- value
13072
- };
13073
- return zeroCRUD({ ops: [op] });
13074
- },
13075
- update: (value) => {
13076
- assertNotInBatch(tableName, "update");
13077
- const op = {
13078
- op: "update",
13079
- tableName,
13080
- primaryKey,
13081
- value
13082
- };
13083
- return zeroCRUD({ ops: [op] });
13084
- },
13085
- delete: (id) => {
13086
- assertNotInBatch(tableName, "delete");
13087
- const op = {
13088
- op: "delete",
13089
- tableName,
13090
- primaryKey,
13091
- value: id
13092
- };
13093
- return zeroCRUD({ ops: [op] });
13094
- }
13095
- };
13293
+ function* generateWithOverlay(startAt, rows, constraint, overlay, compare, filterPredicate) {
13294
+ const overlays = computeOverlays(
13295
+ startAt,
13296
+ constraint,
13297
+ overlay,
13298
+ compare,
13299
+ filterPredicate
13300
+ );
13301
+ yield* generateWithOverlayInner(rows, overlays, compare);
13096
13302
  }
13097
- function makeBatchCRUDMutate(tableName, schema, ops) {
13098
- const { primaryKey } = schema.tables[tableName];
13099
- return {
13100
- insert: (value) => {
13101
- const op = {
13102
- op: "insert",
13103
- tableName,
13104
- primaryKey,
13105
- value
13106
- };
13107
- ops.push(op);
13108
- return promiseVoid;
13109
- },
13110
- upsert: (value) => {
13111
- const op = {
13112
- op: "upsert",
13113
- tableName,
13114
- primaryKey,
13115
- value
13303
+ function computeOverlays(startAt, constraint, overlay, compare, filterPredicate) {
13304
+ let overlays = {
13305
+ add: void 0,
13306
+ remove: void 0
13307
+ };
13308
+ switch (overlay?.change.type) {
13309
+ case "add":
13310
+ overlays = {
13311
+ add: overlay.change.row,
13312
+ remove: void 0
13116
13313
  };
13117
- ops.push(op);
13118
- return promiseVoid;
13119
- },
13120
- update: (value) => {
13121
- const op = {
13122
- op: "update",
13123
- tableName,
13124
- primaryKey,
13125
- value
13314
+ break;
13315
+ case "remove":
13316
+ overlays = {
13317
+ add: void 0,
13318
+ remove: overlay.change.row
13126
13319
  };
13127
- ops.push(op);
13128
- return promiseVoid;
13129
- },
13130
- delete: (id) => {
13131
- const op = {
13132
- op: "delete",
13133
- tableName,
13134
- primaryKey,
13135
- value: id
13320
+ break;
13321
+ case "edit":
13322
+ overlays = {
13323
+ add: overlay.change.row,
13324
+ remove: overlay.change.oldRow
13136
13325
  };
13137
- ops.push(op);
13138
- return promiseVoid;
13139
- }
13326
+ break;
13327
+ }
13328
+ if (startAt) {
13329
+ overlays = overlaysForStartAt(overlays, startAt, compare);
13330
+ }
13331
+ if (constraint) {
13332
+ overlays = overlaysForConstraint(overlays, constraint);
13333
+ }
13334
+ if (filterPredicate) {
13335
+ overlays = overlaysForFilterPredicate(overlays, filterPredicate);
13336
+ }
13337
+ return overlays;
13338
+ }
13339
+ function overlaysForStartAt({ add, remove }, startAt, compare) {
13340
+ const undefinedIfBeforeStartAt = (row) => row === void 0 || compare(row, startAt) < 0 ? void 0 : row;
13341
+ return {
13342
+ add: undefinedIfBeforeStartAt(add),
13343
+ remove: undefinedIfBeforeStartAt(remove)
13140
13344
  };
13141
13345
  }
13142
- function makeCRUDMutator(schema) {
13143
- return async function zeroCRUDMutator(tx, crudArg) {
13144
- for (const op of crudArg.ops) {
13145
- switch (op.op) {
13146
- case "insert":
13147
- await insertImpl(tx, op, schema);
13148
- break;
13149
- case "upsert":
13150
- await upsertImpl(tx, op, schema);
13151
- break;
13152
- case "update":
13153
- await updateImpl(tx, op, schema);
13154
- break;
13155
- case "delete":
13156
- await deleteImpl(tx, op, schema);
13157
- break;
13158
- }
13159
- }
13346
+ function overlaysForConstraint({ add, remove }, constraint) {
13347
+ const undefinedIfDoesntMatchConstraint = (row) => row === void 0 || !constraintMatchesRow(constraint, row) ? void 0 : row;
13348
+ return {
13349
+ add: undefinedIfDoesntMatchConstraint(add),
13350
+ remove: undefinedIfDoesntMatchConstraint(remove)
13160
13351
  };
13161
13352
  }
13162
- function defaultOptionalFieldsToNull(schema, value) {
13163
- let rv = value;
13164
- for (const name in schema.columns) {
13165
- if (rv[name] === void 0) {
13166
- rv = { ...rv, [name]: null };
13353
+ function overlaysForFilterPredicate({ add, remove }, filterPredicate) {
13354
+ const undefinedIfDoesntMatchFilter = (row) => row === void 0 || !filterPredicate(row) ? void 0 : row;
13355
+ return {
13356
+ add: undefinedIfDoesntMatchFilter(add),
13357
+ remove: undefinedIfDoesntMatchFilter(remove)
13358
+ };
13359
+ }
13360
+ function* generateWithOverlayInner(rowIterator, overlays, compare) {
13361
+ let addOverlayYielded = false;
13362
+ let removeOverlaySkipped = false;
13363
+ for (const row of rowIterator) {
13364
+ if (!addOverlayYielded && overlays.add) {
13365
+ const cmp2 = compare(overlays.add, row);
13366
+ if (cmp2 < 0) {
13367
+ addOverlayYielded = true;
13368
+ yield { row: overlays.add, relationships: {} };
13369
+ }
13370
+ }
13371
+ if (!removeOverlaySkipped && overlays.remove) {
13372
+ const cmp2 = compare(overlays.remove, row);
13373
+ if (cmp2 === 0) {
13374
+ removeOverlaySkipped = true;
13375
+ continue;
13376
+ }
13167
13377
  }
13378
+ yield { row, relationships: {} };
13168
13379
  }
13169
- return rv;
13170
- }
13171
- async function insertImpl(tx, arg, schema) {
13172
- const key = toPrimaryKeyString(
13173
- arg.tableName,
13174
- schema.tables[arg.tableName].primaryKey,
13175
- arg.value
13176
- );
13177
- if (!await tx.has(key)) {
13178
- const val = defaultOptionalFieldsToNull(
13179
- schema.tables[arg.tableName],
13180
- arg.value
13181
- );
13182
- await tx.set(key, val);
13380
+ if (!addOverlayYielded && overlays.add) {
13381
+ yield { row: overlays.add, relationships: {} };
13183
13382
  }
13184
13383
  }
13185
- async function upsertImpl(tx, arg, schema) {
13186
- const key = toPrimaryKeyString(
13187
- arg.tableName,
13188
- schema.tables[arg.tableName].primaryKey,
13189
- arg.value
13190
- );
13191
- const val = defaultOptionalFieldsToNull(
13192
- schema.tables[arg.tableName],
13193
- arg.value
13194
- );
13195
- await tx.set(key, val);
13384
+ var minValue = Symbol("min-value");
13385
+ var maxValue = Symbol("max-value");
13386
+ function makeBoundComparator(sort) {
13387
+ return (a, b) => {
13388
+ for (const entry of sort) {
13389
+ const key = entry[0];
13390
+ const cmp2 = compareBounds(a[key], b[key]);
13391
+ if (cmp2 !== 0) {
13392
+ return entry[1] === "asc" ? cmp2 : -cmp2;
13393
+ }
13394
+ }
13395
+ return 0;
13396
+ };
13196
13397
  }
13197
- async function updateImpl(tx, arg, schema) {
13198
- const key = toPrimaryKeyString(
13199
- arg.tableName,
13200
- schema.tables[arg.tableName].primaryKey,
13201
- arg.value
13202
- );
13203
- const prev = await tx.get(key);
13204
- if (prev === void 0) {
13205
- return;
13398
+ function compareBounds(a, b) {
13399
+ if (a === b) {
13400
+ return 0;
13206
13401
  }
13207
- const update = arg.value;
13208
- const next = { ...prev };
13209
- for (const k in update) {
13210
- if (update[k] !== void 0) {
13211
- next[k] = update[k];
13212
- }
13402
+ if (a === minValue) {
13403
+ return -1;
13213
13404
  }
13214
- await tx.set(key, next);
13405
+ if (b === minValue) {
13406
+ return 1;
13407
+ }
13408
+ if (a === maxValue) {
13409
+ return 1;
13410
+ }
13411
+ if (b === maxValue) {
13412
+ return -1;
13413
+ }
13414
+ return compareValues(a, b);
13215
13415
  }
13216
- async function deleteImpl(tx, arg, schema) {
13217
- const key = toPrimaryKeyString(
13218
- arg.tableName,
13219
- schema.tables[arg.tableName].primaryKey,
13220
- arg.value
13416
+ function* generateRows(data, scanStart, reverse) {
13417
+ yield* data[reverse ? "valuesFromReversed" : "valuesFrom"](
13418
+ scanStart
13221
13419
  );
13222
- await tx.del(key);
13223
13420
  }
13224
13421
 
13225
- // ../zero-client/src/client/custom.ts
13226
- var TransactionImpl = class {
13227
- constructor(repTx, schema) {
13228
- must(repTx.reason === "initial" || repTx.reason === "rebase");
13229
- this.clientID = repTx.clientID;
13230
- this.mutationID = repTx.mutationID;
13231
- this.reason = repTx.reason === "initial" ? "optimistic" : "rebase";
13232
- this.mutate = makeSchemaCRUD(schema, repTx);
13422
+ // ../zero-client/src/client/ivm-source-repo.ts
13423
+ var IVMSourceRepo = class {
13424
+ #main;
13425
+ #tables;
13426
+ sync;
13427
+ constructor(tables) {
13428
+ this.#main = new IVMSourceBranch(tables);
13429
+ this.#tables = tables;
13430
+ }
13431
+ get main() {
13432
+ return this.#main;
13433
+ }
13434
+ /**
13435
+ * Creates a new empty branch.
13436
+ */
13437
+ newBranch() {
13438
+ return new IVMSourceBranch(this.#tables);
13233
13439
  }
13234
- clientID;
13235
- mutationID;
13236
- reason;
13237
- mutate;
13238
13440
  };
13239
- function makeReplicacheMutator(mutator, schema) {
13240
- return (repTx, args) => {
13241
- const tx = new TransactionImpl(repTx, schema);
13242
- return mutator(tx, args);
13243
- };
13244
- }
13245
- function makeSchemaCRUD(schema, tx) {
13246
- const mutate = {};
13247
- for (const [name] of Object.entries(schema.tables)) {
13248
- mutate[name] = makeTableCRUD(schema, name, tx);
13441
+ var IVMSourceBranch = class _IVMSourceBranch {
13442
+ #sources;
13443
+ #tables;
13444
+ constructor(tables, sources = /* @__PURE__ */ new Map()) {
13445
+ this.#tables = tables;
13446
+ this.#sources = sources;
13249
13447
  }
13250
- return mutate;
13251
- }
13252
- function makeTableCRUD(schema, tableName, tx) {
13253
- const table2 = must(schema.tables[tableName]);
13254
- const { primaryKey } = table2;
13255
- return {
13256
- insert: (value) => insertImpl(tx, { op: "insert", tableName, primaryKey, value }, schema),
13257
- upsert: (value) => upsertImpl(tx, { op: "upsert", tableName, primaryKey, value }, schema),
13258
- update: (value) => updateImpl(tx, { op: "update", tableName, primaryKey, value }, schema),
13259
- delete: (id) => deleteImpl(tx, { op: "delete", tableName, primaryKey, value: id }, schema)
13260
- };
13261
- }
13262
-
13263
- // ../zero-client/src/client/enable-analytics.ts
13264
- var IPV4_ADDRESS_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
13265
- var IPV6_ADDRESS_HOSTNAME_REGEX = /^\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\]$/;
13266
- var IP_ADDRESS_HOSTNAME_REGEX = new RegExp(
13267
- `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`
13268
- );
13269
- function shouldEnableAnalytics(server, enableAnalytics = true) {
13270
- if (!enableAnalytics) {
13271
- return false;
13448
+ getSource(name) {
13449
+ if (this.#sources.has(name)) {
13450
+ return this.#sources.get(name);
13451
+ }
13452
+ const schema = this.#tables[name];
13453
+ const source = schema ? new MemorySource(name, schema.columns, schema.primaryKey) : void 0;
13454
+ this.#sources.set(name, source);
13455
+ return source;
13272
13456
  }
13273
- const serverURL = server === null ? null : new URL(server);
13274
- const socketHostname = serverURL?.hostname;
13275
- return server !== null && socketHostname !== void 0 && socketHostname !== "localhost" && !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname);
13276
- }
13277
-
13278
- // ../zero-client/src/client/http-string.ts
13279
- function toWSString(url) {
13280
- return "ws" + url.slice(4);
13281
- }
13282
- function appendPath(url, toAppend) {
13283
- return url + (url.endsWith("/") ? toAppend.substring(1) : toAppend);
13284
- }
13457
+ /**
13458
+ * Creates a new IVMSourceBranch that is a copy of the current one.
13459
+ *
13460
+ * This is used when:
13461
+ * 1. We need to rebase a change. We fork the `sync` branch and run the mutations against the fork.
13462
+ * 2. We need to create `main` at startup.
13463
+ * 3. We need to create a new `sync` head because we got a new server snapshot.
13464
+ * The old `sync` head is forked and the new server snapshot is applied to the fork.
13465
+ */
13466
+ fork() {
13467
+ return new _IVMSourceBranch(
13468
+ this.#tables,
13469
+ new Map(
13470
+ wrapIterable(this.#sources.entries()).map(([name, source]) => [
13471
+ name,
13472
+ source?.fork()
13473
+ ])
13474
+ )
13475
+ );
13476
+ }
13477
+ };
13285
13478
 
13286
13479
  // ../zero-client/src/client/log-options.ts
13287
13480
  import {
@@ -13508,7 +13701,7 @@ function makeMessage(message, context, logLevel) {
13508
13701
  }
13509
13702
 
13510
13703
  // ../zero-client/src/client/version.ts
13511
- var version2 = "0.13.2025020400";
13704
+ var version2 = "0.13.2025020402";
13512
13705
 
13513
13706
  // ../zero-client/src/client/log-options.ts
13514
13707
  var LevelFilterLogSink = class {
@@ -13809,7 +14002,7 @@ var Success = 1;
13809
14002
  // ../zero-client/src/client/query-manager.ts
13810
14003
  var QueryManager = class {
13811
14004
  #clientID;
13812
- #tables;
14005
+ #clientToServer;
13813
14006
  #send;
13814
14007
  #queries = /* @__PURE__ */ new Map();
13815
14008
  #recentQueriesMaxSize;
@@ -13817,7 +14010,7 @@ var QueryManager = class {
13817
14010
  #gotQueries = /* @__PURE__ */ new Set();
13818
14011
  constructor(clientID, tables, send2, experimentalWatch, recentQueriesMaxSize) {
13819
14012
  this.#clientID = clientID;
13820
- this.#tables = tables;
14013
+ this.#clientToServer = clientToServer(tables);
13821
14014
  this.#recentQueriesMaxSize = recentQueriesMaxSize;
13822
14015
  this.#send = send2;
13823
14016
  experimentalWatch(
@@ -13901,7 +14094,7 @@ var QueryManager = class {
13901
14094
  let entry = this.#queries.get(astHash);
13902
14095
  this.#recentQueries.delete(astHash);
13903
14096
  if (!entry) {
13904
- const serverAST = toServerAST(normalized, this.#tables);
14097
+ const serverAST = mapAST(normalized, this.#clientToServer);
13905
14098
  entry = {
13906
14099
  normalized: serverAST,
13907
14100
  count: 1,
@@ -14138,26 +14331,6 @@ function getServer(server) {
14138
14331
 
14139
14332
  // ../zero-client/src/client/zero-poke-handler.ts
14140
14333
  import { Lock as Lock4 } from "@rocicorp/lock";
14141
- function makeClientNames(schema) {
14142
- return new Map(
14143
- Object.entries(schema.tables).map(
14144
- ([tableName, { serverName: serverTableName, columns }]) => {
14145
- let allSame = true;
14146
- const names = {};
14147
- for (const [name, { serverName }] of Object.entries(columns)) {
14148
- if (serverName && serverName !== name) {
14149
- allSame = false;
14150
- }
14151
- names[serverName ?? name] = name;
14152
- }
14153
- return [
14154
- serverTableName ?? tableName,
14155
- { tableName, columns: allSame ? null : names }
14156
- ];
14157
- }
14158
- )
14159
- );
14160
- }
14161
14334
  var PokeHandler = class {
14162
14335
  #replicachePoke;
14163
14336
  #onPokeError;
@@ -14171,14 +14344,14 @@ var PokeHandler = class {
14171
14344
  // order poke errors.
14172
14345
  #pokeLock = new Lock4();
14173
14346
  #schema;
14174
- #clientNames;
14347
+ #serverToClient;
14175
14348
  #raf = getBrowserGlobalMethod("requestAnimationFrame") ?? rafFallback;
14176
14349
  constructor(replicachePoke, onPokeError, clientID, schema, lc) {
14177
14350
  this.#replicachePoke = replicachePoke;
14178
14351
  this.#onPokeError = onPokeError;
14179
14352
  this.#clientID = clientID;
14180
14353
  this.#schema = schema;
14181
- this.#clientNames = makeClientNames(schema);
14354
+ this.#serverToClient = serverToClient(schema.tables);
14182
14355
  this.#lc = lc.withContext("PokeHandler");
14183
14356
  }
14184
14357
  handlePokeStart(pokeStart) {
@@ -14259,7 +14432,7 @@ var PokeHandler = class {
14259
14432
  const merged = mergePokes(
14260
14433
  this.#pokeBuffer,
14261
14434
  this.#schema,
14262
- this.#clientNames
14435
+ this.#serverToClient
14263
14436
  );
14264
14437
  this.#pokeBuffer.length = 0;
14265
14438
  if (merged === void 0) {
@@ -14289,7 +14462,7 @@ var PokeHandler = class {
14289
14462
  this.#pokeBuffer.length = 0;
14290
14463
  }
14291
14464
  };
14292
- function mergePokes(pokeBuffer, schema, clientNames) {
14465
+ function mergePokes(pokeBuffer, schema, serverToClient2) {
14293
14466
  if (pokeBuffer.length === 0) {
14294
14467
  return void 0;
14295
14468
  }
@@ -14329,7 +14502,7 @@ function mergePokes(pokeBuffer, schema, clientNames) {
14329
14502
  (op) => queryPatchOpToReplicachePatchOp(
14330
14503
  op,
14331
14504
  (hash2) => toDesiredQueriesKey(clientID, hash2),
14332
- schema
14505
+ serverToClient2
14333
14506
  )
14334
14507
  )
14335
14508
  );
@@ -14338,14 +14511,18 @@ function mergePokes(pokeBuffer, schema, clientNames) {
14338
14511
  if (pokePart.gotQueriesPatch) {
14339
14512
  mergedPatch.push(
14340
14513
  ...pokePart.gotQueriesPatch.map(
14341
- (op) => queryPatchOpToReplicachePatchOp(op, toGotQueriesKey, schema)
14514
+ (op) => queryPatchOpToReplicachePatchOp(
14515
+ op,
14516
+ toGotQueriesKey,
14517
+ serverToClient2
14518
+ )
14342
14519
  )
14343
14520
  );
14344
14521
  }
14345
14522
  if (pokePart.rowsPatch) {
14346
14523
  mergedPatch.push(
14347
14524
  ...pokePart.rowsPatch.map(
14348
- (p) => rowsPatchOpToReplicachePatchOp(p, schema, clientNames)
14525
+ (p) => rowsPatchOpToReplicachePatchOp(p, schema, serverToClient2)
14349
14526
  )
14350
14527
  );
14351
14528
  }
@@ -14378,7 +14555,7 @@ function clientsPatchOpToReplicachePatchOp(op) {
14378
14555
  };
14379
14556
  }
14380
14557
  }
14381
- function queryPatchOpToReplicachePatchOp(op, toKey, schema) {
14558
+ function queryPatchOpToReplicachePatchOp(op, toKey, serverToClient2) {
14382
14559
  switch (op.op) {
14383
14560
  case "clear":
14384
14561
  return op;
@@ -14392,19 +14569,15 @@ function queryPatchOpToReplicachePatchOp(op, toKey, schema) {
14392
14569
  return {
14393
14570
  op: "put",
14394
14571
  key: toKey(op.hash),
14395
- value: toClientAST(op.ast, schema.tables)
14572
+ value: mapAST(op.ast, serverToClient2)
14396
14573
  };
14397
14574
  }
14398
14575
  }
14399
- function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
14576
+ function rowsPatchOpToReplicachePatchOp(op, schema, serverToClient2) {
14400
14577
  if (op.op === "clear") {
14401
14578
  return op;
14402
14579
  }
14403
- const names = clientNames.get(op.tableName);
14404
- if (!names) {
14405
- throw new Error(`unknown table name in ${JSON.stringify(op)}`);
14406
- }
14407
- const { tableName, columns } = names;
14580
+ const tableName = serverToClient2.tableName(op.tableName, op);
14408
14581
  switch (op.op) {
14409
14582
  case "del":
14410
14583
  return {
@@ -14412,7 +14585,7 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
14412
14585
  key: toPrimaryKeyString(
14413
14586
  tableName,
14414
14587
  schema.tables[tableName].primaryKey,
14415
- toClientRow(op.id, columns)
14588
+ serverToClient2.row(op.tableName, op.id)
14416
14589
  )
14417
14590
  };
14418
14591
  case "put":
@@ -14421,9 +14594,9 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
14421
14594
  key: toPrimaryKeyString(
14422
14595
  tableName,
14423
14596
  schema.tables[tableName].primaryKey,
14424
- toClientRow(op.value, columns)
14597
+ serverToClient2.row(op.tableName, op.value)
14425
14598
  ),
14426
- value: toClientRow(op.value, columns)
14599
+ value: serverToClient2.row(op.tableName, op.value)
14427
14600
  };
14428
14601
  case "update":
14429
14602
  return {
@@ -14431,28 +14604,15 @@ function rowsPatchOpToReplicachePatchOp(op, schema, clientNames) {
14431
14604
  key: toPrimaryKeyString(
14432
14605
  tableName,
14433
14606
  schema.tables[tableName].primaryKey,
14434
- toClientRow(op.id, columns)
14607
+ serverToClient2.row(op.tableName, op.id)
14435
14608
  ),
14436
- merge: op.merge ? toClientRow(op.merge, columns) : void 0,
14437
- constrain: toClientColumns(op.constrain, columns)
14609
+ merge: op.merge ? serverToClient2.row(op.tableName, op.merge) : void 0,
14610
+ constrain: serverToClient2.columns(op.tableName, op.constrain)
14438
14611
  };
14439
14612
  default:
14440
14613
  throw new Error("to be implemented");
14441
14614
  }
14442
14615
  }
14443
- function toClientRow(row, names) {
14444
- if (names === null) {
14445
- return row;
14446
- }
14447
- const clientRow = {};
14448
- for (const col in row) {
14449
- clientRow[names[col] ?? col] = row[col];
14450
- }
14451
- return clientRow;
14452
- }
14453
- function toClientColumns(columns, names) {
14454
- return !names || !columns ? columns : columns.map((col) => names[col] ?? col);
14455
- }
14456
14616
  function rafFallback(callback) {
14457
14617
  setTimeout(callback, 0);
14458
14618
  }
@@ -14511,6 +14671,8 @@ var Zero = class {
14511
14671
  #enableAnalytics;
14512
14672
  #pokeHandler;
14513
14673
  #queryManager;
14674
+ #ivmSources;
14675
+ #clientToServer;
14514
14676
  /**
14515
14677
  * The queries we sent when inside the sec-protocol header when establishing a connection.
14516
14678
  * More queries could be registered while we're waiting for the 'connected' message
@@ -14625,13 +14787,14 @@ var Zero = class {
14625
14787
  const replicacheMutators = {
14626
14788
  [CRUD_MUTATION_NAME]: makeCRUDMutator(schema)
14627
14789
  };
14790
+ this.#ivmSources = new IVMSourceRepo(schema.tables);
14628
14791
  for (const [namespace, mutatorsForNamespace] of Object.entries(
14629
14792
  options.mutators ?? {}
14630
14793
  )) {
14631
14794
  for (const [name, mutator] of Object.entries(
14632
14795
  mutatorsForNamespace
14633
14796
  )) {
14634
- replicacheMutators[customMutatorKey(namespace, name)] = makeReplicacheMutator(mutator, schema);
14797
+ replicacheMutators[customMutatorKey(namespace, name)] = makeReplicacheMutator(mutator, schema, this.#ivmSources);
14635
14798
  }
14636
14799
  }
14637
14800
  this.storageKey = storageKey ?? "";
@@ -14713,8 +14876,9 @@ var Zero = class {
14713
14876
  rep.experimentalWatch.bind(rep),
14714
14877
  maxRecentQueries
14715
14878
  );
14879
+ this.#clientToServer = clientToServer(schema.tables);
14716
14880
  this.#zeroContext = new ZeroContext(
14717
- schema.tables,
14881
+ this.#ivmSources.main,
14718
14882
  (ast, gotCallback) => this.#queryManager.add(ast, gotCallback),
14719
14883
  batchViewUpdates
14720
14884
  );
@@ -15250,7 +15414,7 @@ var Zero = class {
15250
15414
  id: m.id,
15251
15415
  clientID: m.clientID,
15252
15416
  name: m.name,
15253
- args: [m.args]
15417
+ args: [mapCRUD(m.args, this.#clientToServer)]
15254
15418
  } : {
15255
15419
  type: Custom,
15256
15420
  timestamp,
@@ -15649,4 +15813,4 @@ export {
15649
15813
  escapeLike,
15650
15814
  Zero
15651
15815
  };
15652
- //# sourceMappingURL=chunk-RC3FUXOA.js.map
15816
+ //# sourceMappingURL=chunk-ADFMUREC.js.map