@rocicorp/zero 0.17.2025030701 → 0.17.2025031200

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 (195) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/chunk-2Y24MEEQ.js +45 -0
  3. package/out/chunk-2Y24MEEQ.js.map +7 -0
  4. package/out/{chunk-6XQK3UTJ.js → chunk-6CQ6CUML.js} +4 -5
  5. package/out/chunk-6CQ6CUML.js.map +7 -0
  6. package/out/{chunk-YKI43S5O.js → chunk-VNV6U5BQ.js} +612 -249
  7. package/out/chunk-VNV6U5BQ.js.map +7 -0
  8. package/out/otel/src/log-options.d.ts +4 -0
  9. package/out/otel/src/log-options.d.ts.map +1 -1
  10. package/out/otel/src/log-options.js +6 -0
  11. package/out/otel/src/log-options.js.map +1 -1
  12. package/out/otel/src/maybe-time.js +1 -1
  13. package/out/react.js +3 -3
  14. package/out/react.js.map +2 -2
  15. package/out/shared/src/asserts.d.ts.map +1 -1
  16. package/out/shared/src/asserts.js +1 -2
  17. package/out/shared/src/asserts.js.map +1 -1
  18. package/out/shared/src/objects.d.ts +4 -0
  19. package/out/shared/src/objects.d.ts.map +1 -0
  20. package/out/shared/src/objects.js +25 -0
  21. package/out/shared/src/objects.js.map +1 -0
  22. package/out/solid.js +6 -4
  23. package/out/solid.js.map +2 -2
  24. package/out/z2s/src/compiler.d.ts.map +1 -1
  25. package/out/z2s/src/compiler.js +1 -1
  26. package/out/z2s/src/compiler.js.map +1 -1
  27. package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
  28. package/out/zero-cache/src/auth/load-permissions.js +0 -1
  29. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  30. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  31. package/out/zero-cache/src/auth/write-authorizer.js +1 -0
  32. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  33. package/out/zero-cache/src/config/zero-config.d.ts +4 -0
  34. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  35. package/out/zero-cache/src/db/lite-tables.d.ts +5 -1
  36. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  37. package/out/zero-cache/src/db/lite-tables.js +8 -1
  38. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  39. package/out/zero-cache/src/db/specs.d.ts +5 -5
  40. package/out/zero-cache/src/scripts/deploy-permissions.js +2 -1
  41. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  42. package/out/zero-cache/src/server/multi/config.d.ts +4 -0
  43. package/out/zero-cache/src/server/multi/config.d.ts.map +1 -1
  44. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  45. package/out/zero-cache/src/server/syncer.js +1 -1
  46. package/out/zero-cache/src/server/syncer.js.map +1 -1
  47. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +10 -10
  48. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +4 -4
  49. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
  50. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +8 -8
  51. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +12 -12
  52. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +4 -4
  53. package/out/zero-cache/src/services/dispatcher/connect-params.d.ts +1 -1
  54. package/out/zero-cache/src/services/dispatcher/connect-params.d.ts.map +1 -1
  55. package/out/zero-cache/src/services/dispatcher/connect-params.js +1 -1
  56. package/out/zero-cache/src/services/dispatcher/connect-params.js.map +1 -1
  57. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +3 -3
  58. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  59. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -3
  60. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  61. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
  62. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  63. package/out/zero-cache/src/services/view-syncer/client-handler.js +4 -2
  64. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  65. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts +5 -0
  66. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -0
  67. package/out/zero-cache/src/services/view-syncer/client-schema.js +74 -0
  68. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -0
  69. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +6 -2
  70. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  71. package/out/zero-cache/src/services/view-syncer/cvr-store.js +38 -15
  72. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  73. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +6 -2
  74. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  75. package/out/zero-cache/src/services/view-syncer/cvr.js +36 -15
  76. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  77. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +5 -4
  78. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  79. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +22 -16
  80. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  81. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +2 -0
  82. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +2 -1
  84. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  85. package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/view-syncer/schema/init.js +6 -0
  87. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  88. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +2 -2
  89. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/view-syncer/schema/types.js +4 -3
  91. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  92. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  93. package/out/zero-cache/src/services/view-syncer/snapshotter.js +4 -1
  94. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  95. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +2 -2
  96. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/view-syncer/view-syncer.js +27 -15
  98. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  99. package/out/zero-client/src/client/context.d.ts +10 -4
  100. package/out/zero-client/src/client/context.d.ts.map +1 -1
  101. package/out/zero-client/src/client/options.d.ts +8 -0
  102. package/out/zero-client/src/client/options.d.ts.map +1 -1
  103. package/out/zero-client/src/client/query-manager.d.ts +2 -1
  104. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  105. package/out/zero-client/src/client/zero.d.ts +3 -2
  106. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  107. package/out/zero-client/src/mod.d.ts +2 -2
  108. package/out/zero-client/src/mod.d.ts.map +1 -1
  109. package/out/zero-protocol/src/client-schema.d.ts +27 -0
  110. package/out/zero-protocol/src/client-schema.d.ts.map +1 -0
  111. package/out/zero-protocol/src/client-schema.js +28 -0
  112. package/out/zero-protocol/src/client-schema.js.map +1 -0
  113. package/out/zero-protocol/src/connect.d.ts +14 -0
  114. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  115. package/out/zero-protocol/src/connect.js +2 -0
  116. package/out/zero-protocol/src/connect.js.map +1 -1
  117. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  118. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  119. package/out/zero-protocol/src/protocol-version.js +2 -1
  120. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  121. package/out/zero-protocol/src/push.d.ts +2 -2
  122. package/out/zero-protocol/src/push.d.ts.map +1 -1
  123. package/out/zero-protocol/src/push.js +4 -1
  124. package/out/zero-protocol/src/push.js.map +1 -1
  125. package/out/zero-protocol/src/up.d.ts +8 -1
  126. package/out/zero-protocol/src/up.d.ts.map +1 -1
  127. package/out/zero-react/src/use-query.d.ts +4 -3
  128. package/out/zero-react/src/use-query.d.ts.map +1 -1
  129. package/out/zero-schema/src/builder/schema-builder.d.ts +7 -13
  130. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  131. package/out/zero-schema/src/builder/schema-builder.js +22 -13
  132. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  133. package/out/zero-schema/src/schema-config.d.ts +2 -4
  134. package/out/zero-schema/src/schema-config.d.ts.map +1 -1
  135. package/out/zero-schema/src/schema-config.js +1 -2
  136. package/out/zero-schema/src/schema-config.js.map +1 -1
  137. package/out/zero-schema/src/table-schema.d.ts +2 -2
  138. package/out/zero-schema/src/table-schema.d.ts.map +1 -1
  139. package/out/zero-solid/src/use-query.d.ts +2 -2
  140. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  141. package/out/zero.js +6 -3
  142. package/out/zql/src/builder/builder.d.ts +3 -2
  143. package/out/zql/src/builder/builder.d.ts.map +1 -1
  144. package/out/zql/src/builder/builder.js +48 -27
  145. package/out/zql/src/builder/builder.js.map +1 -1
  146. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  147. package/out/zql/src/ivm/exists.js +2 -6
  148. package/out/zql/src/ivm/exists.js.map +1 -1
  149. package/out/zql/src/ivm/fan-in.d.ts +1 -0
  150. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  151. package/out/zql/src/ivm/fan-in.js +100 -4
  152. package/out/zql/src/ivm/fan-in.js.map +1 -1
  153. package/out/zql/src/ivm/fan-out.d.ts +2 -1
  154. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  155. package/out/zql/src/ivm/fan-out.js +6 -12
  156. package/out/zql/src/ivm/fan-out.js.map +1 -1
  157. package/out/zql/src/ivm/join.d.ts.map +1 -1
  158. package/out/zql/src/ivm/join.js +134 -55
  159. package/out/zql/src/ivm/join.js.map +1 -1
  160. package/out/zql/src/ivm/memory-source.d.ts +17 -3
  161. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  162. package/out/zql/src/ivm/memory-source.js +108 -56
  163. package/out/zql/src/ivm/memory-source.js.map +1 -1
  164. package/out/zql/src/ivm/source.d.ts +4 -1
  165. package/out/zql/src/ivm/source.d.ts.map +1 -1
  166. package/out/zql/src/ivm/take.d.ts.map +1 -1
  167. package/out/zql/src/ivm/take.js +9 -31
  168. package/out/zql/src/ivm/take.js.map +1 -1
  169. package/out/zql/src/ivm/view-apply-change.js +2 -2
  170. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  171. package/out/zql/src/query/query-impl.d.ts +4 -2
  172. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  173. package/out/zql/src/query/query-impl.js +6 -4
  174. package/out/zql/src/query/query-impl.js.map +1 -1
  175. package/out/zql/src/query/query-internal.d.ts +3 -2
  176. package/out/zql/src/query/query-internal.d.ts.map +1 -1
  177. package/out/zql/src/query/query.d.ts +2 -2
  178. package/out/zql/src/query/query.d.ts.map +1 -1
  179. package/out/zql/src/query/query.js +1 -1
  180. package/out/zql/src/query/query.js.map +1 -1
  181. package/out/zql/src/query/ttl.d.ts +18 -0
  182. package/out/zql/src/query/ttl.d.ts.map +1 -0
  183. package/out/zql/src/query/ttl.js +33 -0
  184. package/out/zql/src/query/ttl.js.map +1 -0
  185. package/out/zqlite/src/db.js +1 -1
  186. package/out/zqlite/src/db.js.map +1 -1
  187. package/out/zqlite/src/table-source.d.ts +1 -1
  188. package/out/zqlite/src/table-source.d.ts.map +1 -1
  189. package/out/zqlite/src/table-source.js +10 -53
  190. package/out/zqlite/src/table-source.js.map +1 -1
  191. package/package.json +1 -1
  192. package/out/chunk-6XQK3UTJ.js.map +0 -7
  193. package/out/chunk-HARIWJ2J.js +0 -8
  194. package/out/chunk-HARIWJ2J.js.map +0 -7
  195. package/out/chunk-YKI43S5O.js.map +0 -7
@@ -1,6 +1,9 @@
1
1
  import {
2
- hasOwn
3
- } from "./chunk-HARIWJ2J.js";
2
+ DEFAULT_TTL,
3
+ compareTTL,
4
+ hasOwn,
5
+ parseTTL
6
+ } from "./chunk-2Y24MEEQ.js";
4
7
  import {
5
8
  applyChange,
6
9
  assert,
@@ -18,7 +21,7 @@ import {
18
21
  throwInvalidType,
19
22
  unreachable,
20
23
  valuesEqual
21
- } from "./chunk-6XQK3UTJ.js";
24
+ } from "./chunk-6CQ6CUML.js";
22
25
  import {
23
26
  __export,
24
27
  __reExport
@@ -8457,6 +8460,65 @@ function one(...args) {
8457
8460
  }));
8458
8461
  }
8459
8462
 
8463
+ // ../shared/src/hash.ts
8464
+ import { xxHash32 } from "js-xxhash";
8465
+ var h64 = (s) => hash(s, 2);
8466
+ var h128 = (s) => hash(s, 4);
8467
+ function hash(str, words) {
8468
+ let hash2 = 0n;
8469
+ for (let i = 0; i < words; i++) {
8470
+ hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
8471
+ }
8472
+ return hash2;
8473
+ }
8474
+
8475
+ // ../shared/src/objects.ts
8476
+ function mapEntries(input, mapper) {
8477
+ const output = {};
8478
+ for (const entry of Object.entries(input)) {
8479
+ const mapped = mapper(entry[0], entry[1]);
8480
+ output[mapped[0]] = mapped[1];
8481
+ }
8482
+ return output;
8483
+ }
8484
+ function mapAllEntries(input, mapper) {
8485
+ const output = {};
8486
+ for (const mapped of mapper(Object.entries(input))) {
8487
+ output[mapped[0]] = mapped[1];
8488
+ }
8489
+ return output;
8490
+ }
8491
+
8492
+ // ../zero-protocol/src/client-schema.ts
8493
+ var valueTypeSchema = valita_exports.union(
8494
+ valita_exports.literal("string"),
8495
+ valita_exports.literal("number"),
8496
+ valita_exports.literal("boolean"),
8497
+ valita_exports.literal("null"),
8498
+ valita_exports.literal("json")
8499
+ );
8500
+ var columnSchemaSchema = valita_exports.object({
8501
+ type: valueTypeSchema
8502
+ });
8503
+ var tableSchemaSchema = valita_exports.object({
8504
+ columns: valita_exports.record(columnSchemaSchema)
8505
+ });
8506
+ var clientSchemaSchema = valita_exports.object({
8507
+ tables: valita_exports.record(tableSchemaSchema)
8508
+ });
8509
+ var keyCmp = ([a], [b]) => a < b ? -1 : a > b ? 1 : 0;
8510
+ function normalizeClientSchema(schema) {
8511
+ return {
8512
+ tables: mapAllEntries(
8513
+ schema.tables,
8514
+ (tables) => tables.sort(keyCmp).map(([name, table2]) => [
8515
+ name,
8516
+ { columns: mapAllEntries(table2.columns, (e) => e.sort(keyCmp)) }
8517
+ ])
8518
+ )
8519
+ };
8520
+ }
8521
+
8460
8522
  // ../zero-schema/src/builder/table-builder.ts
8461
8523
  function table(name) {
8462
8524
  return new TableBuilder({
@@ -8575,7 +8637,7 @@ var ColumnBuilder = class _ColumnBuilder {
8575
8637
  };
8576
8638
 
8577
8639
  // ../zero-schema/src/builder/schema-builder.ts
8578
- function createSchema(version3, options) {
8640
+ function createSchema(options) {
8579
8641
  const retTables = {};
8580
8642
  const retRelationships = {};
8581
8643
  const serverNames = /* @__PURE__ */ new Set();
@@ -8606,7 +8668,6 @@ function createSchema(version3, options) {
8606
8668
  );
8607
8669
  });
8608
8670
  return {
8609
- version: version3,
8610
8671
  tables: retTables,
8611
8672
  relationships: retRelationships
8612
8673
  };
@@ -8629,6 +8690,22 @@ function checkRelationship(relationships2, tableName, tables) {
8629
8690
  });
8630
8691
  });
8631
8692
  }
8693
+ function clientSchemaFrom(schema) {
8694
+ const client = {
8695
+ tables: mapEntries(schema.tables, (name, { serverName, columns }) => [
8696
+ serverName ?? name,
8697
+ {
8698
+ columns: mapEntries(columns, (name2, { serverName: serverName2, type }) => [
8699
+ serverName2 ?? name2,
8700
+ { type }
8701
+ ])
8702
+ }
8703
+ ])
8704
+ };
8705
+ const clientSchema2 = normalizeClientSchema(client);
8706
+ const hash2 = h64(JSON.stringify(clientSchema2)).toString(36);
8707
+ return { clientSchema: clientSchema2, hash: hash2 };
8708
+ }
8632
8709
 
8633
8710
  // ../zero-protocol/src/ast.ts
8634
8711
  import { compareUTF8 as compareUTF83 } from "compare-utf8";
@@ -8976,18 +9053,6 @@ function compareUTF8MaybeNull(a, b) {
8976
9053
  // ../zql/src/query/query-impl.ts
8977
9054
  import { resolver as resolver7 } from "@rocicorp/resolver";
8978
9055
 
8979
- // ../shared/src/hash.ts
8980
- import { xxHash32 } from "js-xxhash";
8981
- var h64 = (s) => hash(s, 2);
8982
- var h128 = (s) => hash(s, 4);
8983
- function hash(str, words) {
8984
- let hash2 = 0n;
8985
- for (let i = 0; i < words; i++) {
8986
- hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
8987
- }
8988
- return hash2;
8989
- }
8990
-
8991
9056
  // ../zero-protocol/src/ast-hash.ts
8992
9057
  var hashCache = /* @__PURE__ */ new WeakMap();
8993
9058
  function hashOfAST(ast) {
@@ -9059,7 +9124,10 @@ var Exists = class {
9059
9124
  this.#relationshipName = relationshipName;
9060
9125
  this.#input.setOutput(this);
9061
9126
  this.#storage = storage;
9062
- assert(this.#input.getSchema().relationships[relationshipName]);
9127
+ assert(
9128
+ this.#input.getSchema().relationships[relationshipName],
9129
+ `Input schema missing ${relationshipName}`
9130
+ );
9063
9131
  this.#not = type === "NOT EXISTS";
9064
9132
  this.#parentJoinKey = parentJoinKey;
9065
9133
  this.#noSizeReuse = areEqual(
@@ -9153,9 +9221,7 @@ var Exists = class {
9153
9221
  case "remove": {
9154
9222
  let size = this.#getSize(change.node);
9155
9223
  if (size !== void 0) {
9156
- if (size === 0) {
9157
- return;
9158
- }
9224
+ assert(size > 0);
9159
9225
  size--;
9160
9226
  this.#setSize(change.node, size);
9161
9227
  } else {
@@ -9273,17 +9339,17 @@ var Exists = class {
9273
9339
  // ../zql/src/ivm/fan-in.ts
9274
9340
  var FanIn = class {
9275
9341
  #inputs;
9276
- #fanOut;
9277
9342
  #schema;
9278
9343
  #output = throwOutput;
9344
+ #accumulatedPushes;
9279
9345
  constructor(fanOut, inputs) {
9280
9346
  this.#inputs = inputs;
9281
9347
  this.#schema = fanOut.getSchema();
9282
- this.#fanOut = fanOut;
9283
9348
  for (const input of inputs) {
9284
9349
  input.setOutput(this);
9285
9350
  assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);
9286
9351
  }
9352
+ this.#accumulatedPushes = [];
9287
9353
  }
9288
9354
  setOutput(output) {
9289
9355
  this.#output = output;
@@ -9311,8 +9377,102 @@ var FanIn = class {
9311
9377
  );
9312
9378
  }
9313
9379
  push(change) {
9314
- this.#fanOut.onFanInReceivedPush();
9315
- this.#output.push(change);
9380
+ this.#accumulatedPushes.push(change);
9381
+ }
9382
+ fanOutDonePushingToAllBranches(fanOutChangeType) {
9383
+ if (this.#inputs.length === 0) {
9384
+ assert(
9385
+ this.#accumulatedPushes.length === 0,
9386
+ "If there are no inputs then fan-in should not receive any pushes."
9387
+ );
9388
+ return;
9389
+ }
9390
+ if (this.#accumulatedPushes.length === 0) {
9391
+ return;
9392
+ }
9393
+ const candidatesToPush = /* @__PURE__ */ new Map();
9394
+ for (const change of this.#accumulatedPushes) {
9395
+ if (fanOutChangeType === "child" && change.type !== "child") {
9396
+ assert(
9397
+ candidatesToPush.has(change.type) === false,
9398
+ () => `Fan-in:child expected at most one ${change.type} when fan-out is of type child`
9399
+ );
9400
+ }
9401
+ candidatesToPush.set(change.type, change);
9402
+ }
9403
+ this.#accumulatedPushes = [];
9404
+ const types = [...candidatesToPush.keys()];
9405
+ switch (fanOutChangeType) {
9406
+ case "remove":
9407
+ assert(
9408
+ types.length === 1 && types[0] === "remove",
9409
+ "Fan-in:remove expected all removes"
9410
+ );
9411
+ this.#output.push(must(candidatesToPush.get("remove")));
9412
+ return;
9413
+ case "add":
9414
+ assert(
9415
+ types.length === 1 && types[0] === "add",
9416
+ "Fan-in:add expected all adds"
9417
+ );
9418
+ this.#output.push(must(candidatesToPush.get("add")));
9419
+ return;
9420
+ case "edit": {
9421
+ assert(
9422
+ types.every(
9423
+ (type) => type === "add" || type === "remove" || type === "edit"
9424
+ ),
9425
+ "Fan-in:edit expected all adds, removes, or edits"
9426
+ );
9427
+ const addChange = candidatesToPush.get("add");
9428
+ const removeChange = candidatesToPush.get("remove");
9429
+ const editChange = candidatesToPush.get("edit");
9430
+ if (editChange) {
9431
+ this.#output.push(editChange);
9432
+ return;
9433
+ }
9434
+ if (addChange && removeChange) {
9435
+ this.#output.push({
9436
+ type: "edit",
9437
+ node: addChange.node,
9438
+ oldNode: removeChange.node
9439
+ });
9440
+ return;
9441
+ }
9442
+ this.#output.push(must(addChange ?? removeChange));
9443
+ return;
9444
+ }
9445
+ case "child": {
9446
+ assert(
9447
+ types.every(
9448
+ (type) => type === "add" || // exists can change child to add or remove
9449
+ type === "remove" || // exists can change child to add or remove
9450
+ type === "child"
9451
+ // other operators may preserve the child change
9452
+ ),
9453
+ "Fan-in:child expected all adds, removes, or children"
9454
+ );
9455
+ assert(
9456
+ types.length <= 2,
9457
+ "Fan-in:child expected at most 2 types on a child change from fan-out"
9458
+ );
9459
+ const childChange = candidatesToPush.get("child");
9460
+ if (childChange) {
9461
+ this.#output.push(childChange);
9462
+ return;
9463
+ }
9464
+ const addChange = candidatesToPush.get("add");
9465
+ const removeChange = candidatesToPush.get("remove");
9466
+ assert(
9467
+ addChange === void 0 || removeChange === void 0,
9468
+ "Fan-in:child expected either add or remove, not both"
9469
+ );
9470
+ this.#output.push(must(addChange ?? removeChange));
9471
+ return;
9472
+ }
9473
+ default:
9474
+ fanOutChangeType;
9475
+ }
9316
9476
  }
9317
9477
  };
9318
9478
 
@@ -9320,16 +9480,15 @@ var FanIn = class {
9320
9480
  var FanOut = class {
9321
9481
  #input;
9322
9482
  #outputs = [];
9323
- // FanOut is paired with a FanIn.
9324
- // Once FanIn has received a push from FanOut along
9325
- // any branch, FanOut no longer needs to push that value
9326
- // across the rest of its outputs..
9327
- #fanInReceivedPush = false;
9483
+ #fanIn;
9328
9484
  #destroyCount = 0;
9329
9485
  constructor(input) {
9330
9486
  this.#input = input;
9331
9487
  input.setOutput(this);
9332
9488
  }
9489
+ setFanIn(fanIn) {
9490
+ this.#fanIn = fanIn;
9491
+ }
9333
9492
  setOutput(output) {
9334
9493
  this.#outputs.push(output);
9335
9494
  }
@@ -9352,17 +9511,14 @@ var FanOut = class {
9352
9511
  cleanup(req) {
9353
9512
  return this.#input.cleanup(req);
9354
9513
  }
9355
- onFanInReceivedPush() {
9356
- this.#fanInReceivedPush = true;
9357
- }
9358
9514
  push(change) {
9359
- this.#fanInReceivedPush = false;
9360
9515
  for (const out of this.#outputs) {
9361
9516
  out.push(change);
9362
- if (this.#fanInReceivedPush) {
9363
- return;
9364
- }
9365
9517
  }
9518
+ must(
9519
+ this.#fanIn,
9520
+ "fan-out must have a corresponding fan-in set!"
9521
+ ).fanOutDonePushingToAllBranches(change.type);
9366
9522
  }
9367
9523
  };
9368
9524
 
@@ -9461,6 +9617,7 @@ var Join = class {
9461
9617
  #relationshipName;
9462
9618
  #schema;
9463
9619
  #output = throwOutput;
9620
+ #inprogressChildChange;
9464
9621
  constructor({
9465
9622
  parent,
9466
9623
  child,
@@ -9564,34 +9721,27 @@ var Join = class {
9564
9721
  });
9565
9722
  break;
9566
9723
  case "edit": {
9567
- if (rowEqualsForCompoundKey(
9568
- change.oldNode.row,
9569
- change.node.row,
9570
- this.#parentKey
9571
- )) {
9572
- this.#output.push({
9573
- type: "edit",
9574
- oldNode: this.#processParentNode(
9575
- change.oldNode.row,
9576
- change.oldNode.relationships,
9577
- "cleanup"
9578
- ),
9579
- node: this.#processParentNode(
9580
- change.node.row,
9581
- change.node.relationships,
9582
- "fetch"
9583
- )
9584
- });
9585
- } else {
9586
- this.#pushParent({
9587
- type: "remove",
9588
- node: change.oldNode
9589
- });
9590
- this.#pushParent({
9591
- type: "add",
9592
- node: change.node
9593
- });
9594
- }
9724
+ assert(
9725
+ rowEqualsForCompoundKey(
9726
+ change.oldNode.row,
9727
+ change.node.row,
9728
+ this.#parentKey
9729
+ ),
9730
+ `Parent edit must not change relationship.`
9731
+ );
9732
+ this.#output.push({
9733
+ type: "edit",
9734
+ oldNode: this.#processParentNode(
9735
+ change.oldNode.row,
9736
+ change.oldNode.relationships,
9737
+ "cleanup"
9738
+ ),
9739
+ node: this.#processParentNode(
9740
+ change.node.row,
9741
+ change.node.relationships,
9742
+ "fetch"
9743
+ )
9744
+ });
9595
9745
  break;
9596
9746
  }
9597
9747
  default:
@@ -9600,25 +9750,34 @@ var Join = class {
9600
9750
  }
9601
9751
  #pushChild(change) {
9602
9752
  const pushChildChange = (childRow, change2) => {
9603
- const parentNodes = this.#parent.fetch({
9604
- constraint: Object.fromEntries(
9605
- this.#parentKey.map((key, i) => [key, childRow[this.#childKey[i]]])
9606
- )
9607
- });
9608
- for (const parentNode of parentNodes) {
9609
- const childChange = {
9610
- type: "child",
9611
- node: this.#processParentNode(
9612
- parentNode.row,
9613
- parentNode.relationships,
9614
- "fetch"
9615
- ),
9616
- child: {
9617
- relationshipName: this.#relationshipName,
9618
- change: change2
9619
- }
9620
- };
9621
- this.#output.push(childChange);
9753
+ this.#inprogressChildChange = {
9754
+ change: change2,
9755
+ position: void 0
9756
+ };
9757
+ try {
9758
+ const parentNodes = this.#parent.fetch({
9759
+ constraint: Object.fromEntries(
9760
+ this.#parentKey.map((key, i) => [key, childRow[this.#childKey[i]]])
9761
+ )
9762
+ });
9763
+ for (const parentNode of parentNodes) {
9764
+ this.#inprogressChildChange.position = parentNode.row;
9765
+ const childChange = {
9766
+ type: "child",
9767
+ node: this.#processParentNode(
9768
+ parentNode.row,
9769
+ parentNode.relationships,
9770
+ "fetch"
9771
+ ),
9772
+ child: {
9773
+ relationshipName: this.#relationshipName,
9774
+ change: change2
9775
+ }
9776
+ };
9777
+ this.#output.push(childChange);
9778
+ }
9779
+ } finally {
9780
+ this.#inprogressChildChange = void 0;
9622
9781
  }
9623
9782
  };
9624
9783
  switch (change.type) {
@@ -9632,24 +9791,92 @@ var Join = class {
9632
9791
  case "edit": {
9633
9792
  const childRow = change.node.row;
9634
9793
  const oldChildRow = change.oldNode.row;
9635
- if (rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey)) {
9636
- pushChildChange(childRow, change);
9637
- } else {
9638
- pushChildChange(oldChildRow, {
9639
- type: "remove",
9640
- node: change.oldNode
9641
- });
9642
- pushChildChange(childRow, {
9643
- type: "add",
9644
- node: change.node
9645
- });
9646
- }
9794
+ assert(
9795
+ rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),
9796
+ "Child edit must not change relationship."
9797
+ );
9798
+ pushChildChange(childRow, change);
9647
9799
  break;
9648
9800
  }
9649
9801
  default:
9650
9802
  unreachable(change);
9651
9803
  }
9652
9804
  }
9805
+ *#generateChildStreamWithOverlay(stream, overlay) {
9806
+ let applied = false;
9807
+ let editOldApplied = false;
9808
+ let editNewApplied = false;
9809
+ for (const child of stream) {
9810
+ let yieldChild = true;
9811
+ if (!applied) {
9812
+ switch (overlay.type) {
9813
+ case "add": {
9814
+ if (this.#child.getSchema().compareRows(overlay.node.row, child.row) === 0) {
9815
+ applied = true;
9816
+ yieldChild = false;
9817
+ }
9818
+ break;
9819
+ }
9820
+ case "remove": {
9821
+ if (this.#child.getSchema().compareRows(overlay.node.row, child.row) < 0) {
9822
+ applied = true;
9823
+ yield overlay.node;
9824
+ }
9825
+ break;
9826
+ }
9827
+ case "edit": {
9828
+ if (this.#child.getSchema().compareRows(overlay.oldNode.row, child.row) < 0) {
9829
+ editOldApplied = true;
9830
+ if (editNewApplied) {
9831
+ applied = true;
9832
+ }
9833
+ yield overlay.oldNode;
9834
+ }
9835
+ if (this.#child.getSchema().compareRows(overlay.node.row, child.row) === 0) {
9836
+ editNewApplied = true;
9837
+ if (editOldApplied) {
9838
+ applied = true;
9839
+ }
9840
+ yieldChild = false;
9841
+ }
9842
+ break;
9843
+ }
9844
+ case "child": {
9845
+ if (this.#child.getSchema().compareRows(overlay.node.row, child.row) === 0) {
9846
+ applied = true;
9847
+ yield {
9848
+ row: child.row,
9849
+ relationships: {
9850
+ ...child.relationships,
9851
+ [overlay.child.relationshipName]: () => this.#generateChildStreamWithOverlay(
9852
+ child.relationships[overlay.child.relationshipName](),
9853
+ overlay.child.change
9854
+ )
9855
+ }
9856
+ };
9857
+ yieldChild = false;
9858
+ }
9859
+ break;
9860
+ }
9861
+ }
9862
+ }
9863
+ if (yieldChild) {
9864
+ yield child;
9865
+ }
9866
+ }
9867
+ if (!applied) {
9868
+ if (overlay.type === "remove") {
9869
+ applied = true;
9870
+ yield overlay.node;
9871
+ } else if (overlay.type === "edit") {
9872
+ assert(editNewApplied);
9873
+ editOldApplied = true;
9874
+ applied = true;
9875
+ yield overlay.oldNode;
9876
+ }
9877
+ }
9878
+ assert(applied);
9879
+ }
9653
9880
  #processParentNode(parentNodeRow, parentNodeRelations, mode) {
9654
9881
  let method = mode;
9655
9882
  let storageUpdated = false;
@@ -9685,7 +9912,7 @@ var Join = class {
9685
9912
  );
9686
9913
  }
9687
9914
  }
9688
- return this.#child[method]({
9915
+ const stream = this.#child[method]({
9689
9916
  constraint: Object.fromEntries(
9690
9917
  this.#childKey.map((key, i) => [
9691
9918
  key,
@@ -9693,6 +9920,19 @@ var Join = class {
9693
9920
  ])
9694
9921
  )
9695
9922
  });
9923
+ if (this.#inprogressChildChange && this.#isJoinMatch(
9924
+ parentNodeRow,
9925
+ this.#inprogressChildChange.change.node.row
9926
+ ) && this.#inprogressChildChange.position && this.#schema.compareRows(
9927
+ parentNodeRow,
9928
+ this.#inprogressChildChange.position
9929
+ ) > 0) {
9930
+ return this.#generateChildStreamWithOverlay(
9931
+ stream,
9932
+ this.#inprogressChildChange.change
9933
+ );
9934
+ }
9935
+ return stream;
9696
9936
  };
9697
9937
  return {
9698
9938
  row: parentNodeRow,
@@ -9702,6 +9942,14 @@ var Join = class {
9702
9942
  }
9703
9943
  };
9704
9944
  }
9945
+ #isJoinMatch(parent, child) {
9946
+ for (let i = 0; i < this.#parentKey.length; i++) {
9947
+ if (!valuesEqual(parent[this.#parentKey[i]], child[this.#childKey[i]])) {
9948
+ return false;
9949
+ }
9950
+ }
9951
+ return true;
9952
+ }
9705
9953
  };
9706
9954
  function makeStorageKeyForValues(values) {
9707
9955
  const json2 = JSON.stringify(["pKeySet", ...values]);
@@ -9719,7 +9967,7 @@ function makeStorageKey(key, primaryKey, row) {
9719
9967
  }
9720
9968
  function rowEqualsForCompoundKey(a, b, key) {
9721
9969
  for (let i = 0; i < key.length; i++) {
9722
- if (!valuesEqual(a[key[i]], b[key[i]])) {
9970
+ if (compareValues(a[key[i]], b[key[i]]) !== 0) {
9723
9971
  return false;
9724
9972
  }
9725
9973
  }
@@ -10011,6 +10259,7 @@ var Take = class {
10011
10259
  type: "remove",
10012
10260
  node: boundNode
10013
10261
  };
10262
+ this.#output.push(change);
10014
10263
  this.#setTakeState(
10015
10264
  takeStateKey,
10016
10265
  takeState.size,
@@ -10018,7 +10267,6 @@ var Take = class {
10018
10267
  maxBound
10019
10268
  );
10020
10269
  this.#output.push(removeChange);
10021
- this.#output.push(change);
10022
10270
  } else if (change.type === "remove") {
10023
10271
  if (takeState.bound === void 0) {
10024
10272
  return;
@@ -10065,13 +10313,13 @@ var Take = class {
10065
10313
  }
10066
10314
  }
10067
10315
  if (newBound?.push) {
10316
+ this.#output.push(change);
10068
10317
  this.#setTakeState(
10069
10318
  takeStateKey,
10070
10319
  takeState.size,
10071
10320
  newBound.node.row,
10072
10321
  maxBound
10073
10322
  );
10074
- this.#output.push(change);
10075
10323
  this.#output.push({
10076
10324
  type: "add",
10077
10325
  node: newBound.node
@@ -10092,17 +10340,10 @@ var Take = class {
10092
10340
  }
10093
10341
  }
10094
10342
  #pushEditChange(change) {
10095
- if (this.#partitionKeyComparator && this.#partitionKeyComparator(change.oldNode.row, change.node.row) !== 0) {
10096
- this.push({
10097
- type: "remove",
10098
- node: change.oldNode
10099
- });
10100
- this.push({
10101
- type: "add",
10102
- node: change.node
10103
- });
10104
- return;
10105
- }
10343
+ assert(
10344
+ !this.#partitionKeyComparator || this.#partitionKeyComparator(change.oldNode.row, change.node.row) === 0,
10345
+ "Unexpected change of partition key"
10346
+ );
10106
10347
  const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.oldNode.row);
10107
10348
  if (!takeState) {
10108
10349
  return;
@@ -10173,10 +10414,6 @@ var Take = class {
10173
10414
  newBoundNode.row,
10174
10415
  maxBound
10175
10416
  );
10176
- this.#output.push({
10177
- type: "remove",
10178
- node: change.oldNode
10179
- });
10180
10417
  this.#output.push({
10181
10418
  type: "add",
10182
10419
  node: newBoundNode
@@ -10200,6 +10437,10 @@ var Take = class {
10200
10437
  }),
10201
10438
  2
10202
10439
  );
10440
+ this.#output.push({
10441
+ type: "add",
10442
+ node: change.node
10443
+ });
10203
10444
  this.#setTakeState(
10204
10445
  takeStateKey,
10205
10446
  takeState.size,
@@ -10210,10 +10451,6 @@ var Take = class {
10210
10451
  type: "remove",
10211
10452
  node: oldBoundNode
10212
10453
  });
10213
- this.#output.push({
10214
- type: "add",
10215
- node: change.node
10216
- });
10217
10454
  return;
10218
10455
  }
10219
10456
  if (oldCmp < 0) {
@@ -10238,16 +10475,16 @@ var Take = class {
10238
10475
  replaceBoundAndForwardChange();
10239
10476
  return;
10240
10477
  }
10478
+ this.#output.push({
10479
+ type: "remove",
10480
+ node: change.oldNode
10481
+ });
10241
10482
  this.#setTakeState(
10242
10483
  takeStateKey,
10243
10484
  takeState.size,
10244
10485
  afterBoundNode.row,
10245
10486
  maxBound
10246
10487
  );
10247
- this.#output.push({
10248
- type: "remove",
10249
- node: change.oldNode
10250
- });
10251
10488
  this.#output.push({
10252
10489
  type: "add",
10253
10490
  node: afterBoundNode
@@ -10521,55 +10758,75 @@ function transformFilters(filters) {
10521
10758
 
10522
10759
  // ../zql/src/builder/builder.ts
10523
10760
  function buildPipeline(ast, delegate) {
10524
- return buildPipelineInternal(ast, delegate);
10761
+ return buildPipelineInternal(ast, delegate, "");
10525
10762
  }
10526
- function buildPipelineInternal(ast, delegate, partitionKey) {
10763
+ function buildPipelineInternal(ast, delegate, name, partitionKey) {
10527
10764
  const source = delegate.getSource(ast.table);
10528
10765
  if (!source) {
10529
10766
  throw new Error(`Source not found: ${ast.table}`);
10530
10767
  }
10531
- const conn = source.connect(must(ast.orderBy), ast.where);
10532
- let end = conn;
10533
- const { fullyAppliedFilters } = conn;
10534
10768
  ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
10769
+ const csqsFromCondition = gatherCorrelatedSubqueryQueriesFromCondition(
10770
+ ast.where
10771
+ );
10772
+ const splitEditKeys = partitionKey ? new Set(partitionKey) : /* @__PURE__ */ new Set();
10773
+ for (const csq of csqsFromCondition) {
10774
+ for (const key of csq.correlation.parentField) {
10775
+ splitEditKeys.add(key);
10776
+ }
10777
+ }
10778
+ if (ast.related) {
10779
+ for (const csq of ast.related) {
10780
+ for (const key of csq.correlation.parentField) {
10781
+ splitEditKeys.add(key);
10782
+ }
10783
+ }
10784
+ }
10785
+ const conn = source.connect(must(ast.orderBy), ast.where, splitEditKeys);
10786
+ let end = delegate.decorateInput(conn, `${name}:source(${ast.table})`);
10787
+ const { fullyAppliedFilters } = conn;
10535
10788
  if (ast.start) {
10536
- end = new Skip(end, ast.start);
10789
+ end = delegate.decorateInput(new Skip(end, ast.start), `${name}:skip)`);
10537
10790
  }
10538
- for (const csq of gatherCorrelatedSubqueryQueriesFromCondition(ast.where)) {
10539
- end = applyCorrelatedSubQuery(csq, delegate, end);
10791
+ for (const csq of csqsFromCondition) {
10792
+ end = applyCorrelatedSubQuery(csq, delegate, end, name);
10540
10793
  }
10541
10794
  if (ast.where && !fullyAppliedFilters) {
10542
- end = applyWhere(end, ast.where, delegate);
10795
+ end = applyWhere(end, ast.where, delegate, name);
10543
10796
  }
10544
- if (ast.limit) {
10545
- end = new Take(end, delegate.createStorage(), ast.limit, partitionKey);
10797
+ if (ast.limit !== void 0) {
10798
+ const takeName = `${name}:take`;
10799
+ end = delegate.decorateInput(
10800
+ new Take(end, delegate.createStorage(takeName), ast.limit, partitionKey),
10801
+ takeName
10802
+ );
10546
10803
  }
10547
10804
  if (ast.related) {
10548
10805
  for (const csq of ast.related) {
10549
- end = applyCorrelatedSubQuery(csq, delegate, end);
10806
+ end = applyCorrelatedSubQuery(csq, delegate, end, name);
10550
10807
  }
10551
10808
  }
10552
10809
  return end;
10553
10810
  }
10554
- function applyWhere(input, condition, delegate) {
10811
+ function applyWhere(input, condition, delegate, name) {
10555
10812
  switch (condition.type) {
10556
10813
  case "and":
10557
- return applyAnd(input, condition, delegate);
10814
+ return applyAnd(input, condition, delegate, name);
10558
10815
  case "or":
10559
- return applyOr(input, condition, delegate);
10816
+ return applyOr(input, condition, delegate, name);
10560
10817
  case "correlatedSubquery":
10561
- return applyCorrelatedSubqueryCondition(input, condition, delegate);
10818
+ return applyCorrelatedSubqueryCondition(input, condition, delegate, name);
10562
10819
  case "simple":
10563
10820
  return applySimpleCondition(input, condition);
10564
10821
  }
10565
10822
  }
10566
- function applyAnd(input, condition, delegate) {
10823
+ function applyAnd(input, condition, delegate, name) {
10567
10824
  for (const subCondition of condition.conditions) {
10568
- input = applyWhere(input, subCondition, delegate);
10825
+ input = applyWhere(input, subCondition, delegate, name);
10569
10826
  }
10570
10827
  return input;
10571
10828
  }
10572
- function applyOr(input, condition, delegate) {
10829
+ function applyOr(input, condition, delegate, name) {
10573
10830
  const [subqueryConditions, otherConditions] = groupSubqueryConditions(condition);
10574
10831
  if (subqueryConditions.length === 0) {
10575
10832
  return new Filter(
@@ -10582,7 +10839,7 @@ function applyOr(input, condition, delegate) {
10582
10839
  }
10583
10840
  const fanOut = new FanOut(input);
10584
10841
  const branches = subqueryConditions.map(
10585
- (subCondition) => applyWhere(fanOut, subCondition, delegate)
10842
+ (subCondition) => applyWhere(fanOut, subCondition, delegate, name)
10586
10843
  );
10587
10844
  if (otherConditions.length > 0) {
10588
10845
  branches.push(
@@ -10595,7 +10852,9 @@ function applyOr(input, condition, delegate) {
10595
10852
  )
10596
10853
  );
10597
10854
  }
10598
- return new FanIn(fanOut, branches);
10855
+ const ret = new FanIn(fanOut, branches);
10856
+ fanOut.setFanIn(ret);
10857
+ return ret;
10599
10858
  }
10600
10859
  function groupSubqueryConditions(condition) {
10601
10860
  const partitioned = [[], []];
@@ -10621,33 +10880,39 @@ function isNotAndDoesNotContainSubquery(condition) {
10621
10880
  function applySimpleCondition(input, condition) {
10622
10881
  return new Filter(input, createPredicate(condition));
10623
10882
  }
10624
- function applyCorrelatedSubQuery(sq, delegate, end) {
10883
+ function applyCorrelatedSubQuery(sq, delegate, end, name) {
10625
10884
  assert(sq.subquery.alias, "Subquery must have an alias");
10626
10885
  const child = buildPipelineInternal(
10627
10886
  sq.subquery,
10628
10887
  delegate,
10888
+ `${name}.${sq.subquery.alias}`,
10629
10889
  sq.correlation.childField
10630
10890
  );
10891
+ const joinName = `${name}:join(${sq.subquery.alias})`;
10631
10892
  end = new Join({
10632
10893
  parent: end,
10633
10894
  child,
10634
- storage: delegate.createStorage(),
10895
+ storage: delegate.createStorage(joinName),
10635
10896
  parentKey: sq.correlation.parentField,
10636
10897
  childKey: sq.correlation.childField,
10637
10898
  relationshipName: sq.subquery.alias,
10638
10899
  hidden: sq.hidden ?? false,
10639
10900
  system: sq.system ?? "client"
10640
10901
  });
10641
- return end;
10902
+ return delegate.decorateInput(end, joinName);
10642
10903
  }
10643
- function applyCorrelatedSubqueryCondition(input, condition, delegate) {
10904
+ function applyCorrelatedSubqueryCondition(input, condition, delegate, name) {
10644
10905
  assert(condition.op === "EXISTS" || condition.op === "NOT EXISTS");
10645
- return new Exists(
10646
- input,
10647
- delegate.createStorage(),
10648
- must(condition.related.subquery.alias),
10649
- condition.related.correlation.parentField,
10650
- condition.op
10906
+ const existsName = `${name}:exists(${condition.related.subquery.alias})`;
10907
+ return delegate.decorateInput(
10908
+ new Exists(
10909
+ input,
10910
+ delegate.createStorage(existsName),
10911
+ must(condition.related.subquery.alias),
10912
+ condition.related.correlation.parentField,
10913
+ condition.op
10914
+ ),
10915
+ existsName
10651
10916
  );
10652
10917
  }
10653
10918
  function gatherCorrelatedSubqueryQueriesFromCondition(condition) {
@@ -11044,9 +11309,6 @@ function unwrap(c) {
11044
11309
  return { type: c.type, conditions: flatten(c.type, c.conditions.map(unwrap)) };
11045
11310
  }
11046
11311
 
11047
- // ../zql/src/query/query.ts
11048
- var DEFAULT_TTL = 1e4;
11049
-
11050
11312
  // ../zql/src/query/query-impl.ts
11051
11313
  var astForTestingSymbol = Symbol();
11052
11314
  function newQuery(delegate, schema, table2) {
@@ -11085,9 +11347,7 @@ var AbstractQuery = class {
11085
11347
  }
11086
11348
  hash() {
11087
11349
  if (!this.#hash) {
11088
- const ast = this._completeAst();
11089
- const hash2 = hashOfAST(ast);
11090
- this.#hash = hash2;
11350
+ this.#hash = hashOfAST(this._completeAst());
11091
11351
  }
11092
11352
  return this.#hash;
11093
11353
  }
@@ -11452,6 +11712,7 @@ var QueryImpl = class extends AbstractQuery {
11452
11712
  return newQueryWithDetails(this.#delegate, schema, tableName, ast, format);
11453
11713
  }
11454
11714
  materialize(factoryOrTTL, ttl = DEFAULT_TTL) {
11715
+ const t0 = Date.now();
11455
11716
  let factory;
11456
11717
  if (typeof factoryOrTTL === "function") {
11457
11718
  factory = factoryOrTTL;
@@ -11463,6 +11724,8 @@ var QueryImpl = class extends AbstractQuery {
11463
11724
  let queryGot = false;
11464
11725
  const removeServerQuery = this.#delegate.addServerQuery(ast, ttl, (got) => {
11465
11726
  if (got) {
11727
+ const t1 = Date.now();
11728
+ this.#delegate.onQueryMaterialized(this.hash(), ast, t1 - t0);
11466
11729
  queryGot = true;
11467
11730
  queryCompleteResolver.resolve(true);
11468
11731
  }
@@ -11875,6 +12138,7 @@ var connectedMessageSchema = valita_exports.tuple([
11875
12138
  ]);
11876
12139
  var initConnectionBodySchema = valita_exports.object({
11877
12140
  desiredQueriesPatch: queriesPatchSchema,
12141
+ clientSchema: clientSchemaSchema.optional(),
11878
12142
  deleted: deleteClientsBodySchema.optional()
11879
12143
  });
11880
12144
  var initConnectionMessageSchema = valita_exports.tuple([
@@ -12103,7 +12367,7 @@ var CRUD = "crud";
12103
12367
  var Custom = "custom";
12104
12368
 
12105
12369
  // ../zero-protocol/src/protocol-version.ts
12106
- var PROTOCOL_VERSION = 6;
12370
+ var PROTOCOL_VERSION = 7;
12107
12371
  var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 2;
12108
12372
  assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
12109
12373
  var MIN_SERVER_SUPPORTED_PERMISSIONS_PROTOCOL = 4;
@@ -12168,7 +12432,10 @@ var pushBodySchema = valita_exports.object({
12168
12432
  clientGroupID: valita_exports.string(),
12169
12433
  mutations: valita_exports.array(mutationSchema),
12170
12434
  pushVersion: valita_exports.number(),
12171
- schemaVersion: valita_exports.number(),
12435
+ // For legacy (CRUD) mutations, the schema is tied to the client group /
12436
+ // sync connection. For custom mutations, schema versioning is delegated
12437
+ // to the custom protocol / api-server.
12438
+ schemaVersion: valita_exports.number().optional(),
12172
12439
  timestamp: valita_exports.number(),
12173
12440
  requestID: valita_exports.string()
12174
12441
  });
@@ -12811,6 +13078,7 @@ var MemorySource = class _MemorySource {
12811
13078
  #indexes = /* @__PURE__ */ new Map();
12812
13079
  #connections = [];
12813
13080
  #overlay;
13081
+ #splitEditOverlay;
12814
13082
  constructor(tableName, columns, primaryKey, primaryIndexData) {
12815
13083
  this.#tableName = tableName;
12816
13084
  this.#columns = columns;
@@ -12853,7 +13121,7 @@ var MemorySource = class _MemorySource {
12853
13121
  compareRows: connection.compareRows
12854
13122
  };
12855
13123
  }
12856
- connect(sort, filters) {
13124
+ connect(sort, filters, splitEditKeys) {
12857
13125
  const transformedFilters = transformFilters(filters);
12858
13126
  const input = {
12859
13127
  getSchema: () => schema,
@@ -12871,6 +13139,7 @@ var MemorySource = class _MemorySource {
12871
13139
  input,
12872
13140
  output: void 0,
12873
13141
  sort,
13142
+ splitEditKeys,
12874
13143
  compareRows: makeComparator(sort),
12875
13144
  filters: transformedFilters.filters ? {
12876
13145
  condition: transformedFilters.filters,
@@ -12924,10 +13193,9 @@ var MemorySource = class _MemorySource {
12924
13193
  return [...this.#indexes.keys()];
12925
13194
  }
12926
13195
  *#fetch(req, from) {
12927
- let overlay;
12928
- const callingConnectionNum = this.#connections.indexOf(from);
12929
- assert(callingConnectionNum !== -1, "Output not found");
12930
- const conn = this.#connections[callingConnectionNum];
13196
+ const callingConnectionIndex = this.#connections.indexOf(from);
13197
+ assert(callingConnectionIndex !== -1, "Output not found");
13198
+ const conn = this.#connections[callingConnectionIndex];
12931
13199
  const { sort: requestedSort } = conn;
12932
13200
  const indexSort = [];
12933
13201
  if (req.constraint) {
@@ -12941,11 +13209,6 @@ var MemorySource = class _MemorySource {
12941
13209
  const index = this.#getOrCreateIndex(indexSort, from);
12942
13210
  const { data, comparator: compare } = index;
12943
13211
  const comparator2 = (r1, r2) => compare(r1, r2) * (req.reverse ? -1 : 1);
12944
- if (this.#overlay) {
12945
- if (callingConnectionNum <= this.#overlay.outputIndex) {
12946
- overlay = this.#overlay;
12947
- }
12948
- }
12949
13212
  const startAt = req.start?.row;
12950
13213
  let scanStart;
12951
13214
  if (req.constraint) {
@@ -12968,7 +13231,9 @@ var MemorySource = class _MemorySource {
12968
13231
  startAt,
12969
13232
  generateRows(data, scanStart, req.reverse),
12970
13233
  req.constraint,
12971
- overlay,
13234
+ this.#overlay,
13235
+ this.#splitEditOverlay,
13236
+ callingConnectionIndex,
12972
13237
  comparator2,
12973
13238
  conn.filters?.predicate
12974
13239
  );
@@ -12988,56 +13253,18 @@ var MemorySource = class _MemorySource {
12988
13253
  *genPush(change) {
12989
13254
  const primaryIndex = this.#getPrimaryIndex();
12990
13255
  const { data } = primaryIndex;
12991
- switch (change.type) {
12992
- case "add":
12993
- assert(
12994
- !data.has(change.row),
12995
- () => `Row already exists ${JSON.stringify(change)}`
12996
- );
12997
- break;
12998
- case "remove":
12999
- assert(
13000
- data.has(change.row),
13001
- () => `Row not found ${JSON.stringify(change)}`
13002
- );
13003
- break;
13004
- case "edit":
13005
- assert(
13006
- data.has(change.oldRow),
13007
- () => `Row not found ${JSON.stringify(change)}`
13008
- );
13009
- break;
13010
- default:
13011
- unreachable(change);
13012
- }
13013
- const outputChange = change.type === "edit" ? {
13014
- type: change.type,
13015
- oldNode: {
13016
- row: change.oldRow,
13017
- relationships: {}
13018
- },
13019
- node: {
13020
- row: change.row,
13021
- relationships: {}
13022
- }
13023
- } : {
13024
- type: change.type,
13025
- node: {
13026
- row: change.row,
13027
- relationships: {}
13028
- }
13029
- };
13030
- for (const [
13031
- outputIndex,
13032
- { output, filters }
13033
- ] of this.#connections.entries()) {
13034
- if (output) {
13035
- this.#overlay = { outputIndex, change };
13036
- filterPush(outputChange, output, filters?.predicate);
13037
- yield;
13038
- }
13256
+ const exists = (row) => data.has(row);
13257
+ const setOverlay = (o) => this.#overlay = o;
13258
+ const setSplitEditOverlay = (o) => this.#splitEditOverlay = o;
13259
+ for (const x of genPush(
13260
+ change,
13261
+ exists,
13262
+ this.#connections.entries(),
13263
+ setOverlay,
13264
+ setSplitEditOverlay
13265
+ )) {
13266
+ yield x;
13039
13267
  }
13040
- this.#overlay = void 0;
13041
13268
  for (const { data: data2 } of this.#indexes.values()) {
13042
13269
  switch (change.type) {
13043
13270
  case "add": {
@@ -13077,6 +13304,89 @@ function* generateWithFilter(it, filter) {
13077
13304
  }
13078
13305
  }
13079
13306
  }
13307
+ function* genPush(change, exists, connections, setOverlay, setSplitEditOverlay) {
13308
+ switch (change.type) {
13309
+ case "add":
13310
+ assert(
13311
+ !exists(change.row),
13312
+ () => `Row already exists ${stringify(change)}`
13313
+ );
13314
+ break;
13315
+ case "remove":
13316
+ assert(exists(change.row), () => `Row not found ${stringify(change)}`);
13317
+ break;
13318
+ case "edit":
13319
+ assert(exists(change.oldRow), () => `Row not found ${stringify(change)}`);
13320
+ break;
13321
+ default:
13322
+ unreachable(change);
13323
+ }
13324
+ for (const [outputIndex, { output, splitEditKeys, filters }] of connections) {
13325
+ if (output) {
13326
+ let splitEdit = false;
13327
+ if (change.type === "edit" && splitEditKeys) {
13328
+ for (const key of splitEditKeys) {
13329
+ if (!valuesEqual(change.row[key], change.oldRow[key])) {
13330
+ splitEdit = true;
13331
+ break;
13332
+ }
13333
+ }
13334
+ }
13335
+ if (splitEdit) {
13336
+ assert(change.type === "edit");
13337
+ setSplitEditOverlay({
13338
+ outputIndex,
13339
+ change: {
13340
+ type: "remove",
13341
+ row: change.oldRow
13342
+ }
13343
+ });
13344
+ const outputRemove = {
13345
+ type: "remove",
13346
+ node: {
13347
+ row: change.oldRow,
13348
+ relationships: {}
13349
+ }
13350
+ };
13351
+ filterPush(outputRemove, output, filters?.predicate);
13352
+ yield;
13353
+ setSplitEditOverlay(void 0);
13354
+ setOverlay({ outputIndex, change });
13355
+ const outputAdd = {
13356
+ type: "add",
13357
+ node: {
13358
+ row: change.row,
13359
+ relationships: {}
13360
+ }
13361
+ };
13362
+ filterPush(outputAdd, output, filters?.predicate);
13363
+ yield;
13364
+ } else {
13365
+ setOverlay({ outputIndex, change });
13366
+ const outputChange = change.type === "edit" ? {
13367
+ type: change.type,
13368
+ oldNode: {
13369
+ row: change.oldRow,
13370
+ relationships: {}
13371
+ },
13372
+ node: {
13373
+ row: change.row,
13374
+ relationships: {}
13375
+ }
13376
+ } : {
13377
+ type: change.type,
13378
+ node: {
13379
+ row: change.row,
13380
+ relationships: {}
13381
+ }
13382
+ };
13383
+ filterPush(outputChange, output, filters?.predicate);
13384
+ yield;
13385
+ }
13386
+ }
13387
+ }
13388
+ setOverlay(void 0);
13389
+ }
13080
13390
  function* generateWithStart(nodes, start, compare) {
13081
13391
  if (!start) {
13082
13392
  yield* nodes;
@@ -13100,11 +13410,17 @@ function* generateWithStart(nodes, start, compare) {
13100
13410
  }
13101
13411
  }
13102
13412
  }
13103
- function* generateWithOverlay(startAt, rows, constraint, overlay, compare, filterPredicate) {
13413
+ function* generateWithOverlay(startAt, rows, constraint, overlay, splitEditOverlay, connectionIndex, compare, filterPredicate) {
13414
+ let overlayToApply = void 0;
13415
+ if (splitEditOverlay && splitEditOverlay.outputIndex === connectionIndex) {
13416
+ overlayToApply = splitEditOverlay;
13417
+ } else if (overlay && connectionIndex <= overlay.outputIndex) {
13418
+ overlayToApply = overlay;
13419
+ }
13104
13420
  const overlays = computeOverlays(
13105
13421
  startAt,
13106
13422
  constraint,
13107
- overlay,
13423
+ overlayToApply,
13108
13424
  compare,
13109
13425
  filterPredicate
13110
13426
  );
@@ -13228,6 +13544,12 @@ function* generateRows(data, scanStart, reverse) {
13228
13544
  scanStart
13229
13545
  );
13230
13546
  }
13547
+ function stringify(change) {
13548
+ return JSON.stringify(
13549
+ change,
13550
+ (_, v2) => typeof v2 === "bigint" ? v2.toString() : v2
13551
+ );
13552
+ }
13231
13553
 
13232
13554
  // ../zero-client/src/client/keys.ts
13233
13555
  var DESIRED_QUERIES_KEY_PREFIX = "d/";
@@ -13393,11 +13715,15 @@ var ZeroContext = class {
13393
13715
  #addQuery;
13394
13716
  #batchViewUpdates;
13395
13717
  #commitListeners = /* @__PURE__ */ new Set();
13718
+ slowMaterializeThreshold;
13719
+ lc;
13396
13720
  staticQueryParameters = void 0;
13397
- constructor(mainSources, addQuery, batchViewUpdates) {
13721
+ constructor(lc, mainSources, addQuery, batchViewUpdates, slowMaterializeThreshold) {
13398
13722
  this.#mainSources = mainSources;
13399
13723
  this.#addQuery = addQuery;
13400
13724
  this.#batchViewUpdates = batchViewUpdates;
13725
+ this.lc = lc;
13726
+ this.slowMaterializeThreshold = slowMaterializeThreshold;
13401
13727
  }
13402
13728
  getSource(name) {
13403
13729
  return this.#mainSources.getSource(name);
@@ -13405,9 +13731,29 @@ var ZeroContext = class {
13405
13731
  addServerQuery(ast, ttl, gotCallback) {
13406
13732
  return this.#addQuery(ast, ttl, gotCallback);
13407
13733
  }
13734
+ onQueryMaterialized(hash2, ast, duration) {
13735
+ if (this.slowMaterializeThreshold !== void 0 && duration > this.slowMaterializeThreshold) {
13736
+ this.lc.warn?.(
13737
+ "Slow query materialization (including server/network)",
13738
+ hash2,
13739
+ ast,
13740
+ duration
13741
+ );
13742
+ } else {
13743
+ this.lc.debug?.(
13744
+ "Materialized query (including server/network)",
13745
+ hash2,
13746
+ ast,
13747
+ duration
13748
+ );
13749
+ }
13750
+ }
13408
13751
  createStorage() {
13409
13752
  return new MemoryStorage();
13410
13753
  }
13754
+ decorateInput(input) {
13755
+ return input;
13756
+ }
13411
13757
  onTransactionCommit(cb) {
13412
13758
  this.#commitListeners.add(cb);
13413
13759
  return () => {
@@ -14062,7 +14408,7 @@ function makeMessage(message, context, logLevel) {
14062
14408
  }
14063
14409
 
14064
14410
  // ../zero-client/src/client/version.ts
14065
- var version2 = "0.17.2025030701";
14411
+ var version2 = "0.17.2025031200";
14066
14412
 
14067
14413
  // ../zero-client/src/client/log-options.ts
14068
14414
  var LevelFilterLogSink = class {
@@ -14431,7 +14777,7 @@ var QueryManager = class {
14431
14777
  }
14432
14778
  for (const [hash2, { normalized, ttl }] of this.#queries) {
14433
14779
  if (!existingQueryHashes.has(hash2)) {
14434
- patch.set(hash2, { op: "put", hash: hash2, ast: normalized, ttl });
14780
+ patch.set(hash2, { op: "put", hash: hash2, ast: normalized, ttl: parseTTL(ttl) });
14435
14781
  }
14436
14782
  }
14437
14783
  if (lastPatch) {
@@ -14459,7 +14805,7 @@ var QueryManager = class {
14459
14805
  entry = {
14460
14806
  normalized: serverAST,
14461
14807
  count: 1,
14462
- gotCallbacks: gotCallback === void 0 ? [] : [gotCallback],
14808
+ gotCallbacks: gotCallback ? [gotCallback] : [],
14463
14809
  ttl
14464
14810
  };
14465
14811
  this.#queries.set(astHash, entry);
@@ -14467,19 +14813,24 @@ var QueryManager = class {
14467
14813
  "changeDesiredQueries",
14468
14814
  {
14469
14815
  desiredQueriesPatch: [
14470
- { op: "put", hash: astHash, ast: serverAST, ttl }
14816
+ { op: "put", hash: astHash, ast: serverAST, ttl: parseTTL(ttl) }
14471
14817
  ]
14472
14818
  }
14473
14819
  ]);
14474
14820
  } else {
14475
14821
  ++entry.count;
14476
- if (ttl !== void 0 && (entry.ttl === void 0 || ttl > entry.ttl)) {
14822
+ if (compareTTL(ttl, entry.ttl) > 0) {
14477
14823
  entry.ttl = ttl;
14478
14824
  this.#send([
14479
14825
  "changeDesiredQueries",
14480
14826
  {
14481
14827
  desiredQueriesPatch: [
14482
- { op: "put", hash: astHash, ast: entry.normalized, ttl }
14828
+ {
14829
+ op: "put",
14830
+ hash: astHash,
14831
+ ast: entry.normalized,
14832
+ ttl: parseTTL(ttl)
14833
+ }
14483
14834
  ]
14484
14835
  }
14485
14836
  ]);
@@ -14497,11 +14848,10 @@ var QueryManager = class {
14497
14848
  return;
14498
14849
  }
14499
14850
  removed = true;
14500
- this.#remove(astHash, gotCallback);
14851
+ this.#remove(entry, astHash, gotCallback);
14501
14852
  };
14502
14853
  }
14503
- #remove(astHash, gotCallback) {
14504
- const entry = must(this.#queries.get(astHash));
14854
+ #remove(entry, astHash, gotCallback) {
14505
14855
  if (gotCallback) {
14506
14856
  const index = entry.gotCallbacks.indexOf(gotCallback);
14507
14857
  entry.gotCallbacks.splice(index, 1);
@@ -14998,7 +15348,7 @@ function updateNeededReloadReason(reason, serverErrMsg) {
14998
15348
  reasonMsg = "The server no longer supports this client's protocol version.";
14999
15349
  break;
15000
15350
  case "SchemaVersionNotSupported":
15001
- reasonMsg = "The server no longer supports this client's schema version.";
15351
+ reasonMsg = "Client and server schemas incompatible.";
15002
15352
  break;
15003
15353
  default:
15004
15354
  unreachable(type);
@@ -15025,6 +15375,7 @@ var Zero = class {
15025
15375
  #lc;
15026
15376
  #logOptions;
15027
15377
  #enableAnalytics;
15378
+ #clientSchema;
15028
15379
  #pokeHandler;
15029
15380
  #queryManager;
15030
15381
  #ivmMain;
@@ -15122,7 +15473,8 @@ var Zero = class {
15122
15473
  hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,
15123
15474
  schema,
15124
15475
  batchViewUpdates = (applyViewUpdates) => applyViewUpdates(),
15125
- maxRecentQueries = 0
15476
+ maxRecentQueries = 0,
15477
+ slowMaterializeThreshold = 5e3
15126
15478
  } = options;
15127
15479
  if (!userID) {
15128
15480
  throw new Error("ZeroOptions.userID must not be empty.");
@@ -15170,10 +15522,12 @@ var Zero = class {
15170
15522
  }
15171
15523
  }
15172
15524
  this.storageKey = storageKey ?? "";
15525
+ const { clientSchema: clientSchema2, hash: hash2 } = clientSchemaFrom(schema);
15526
+ this.#clientSchema = clientSchema2;
15173
15527
  const replicacheOptions = {
15174
- // The schema stored in IDB is dependent upon both the application schema
15528
+ // The schema stored in IDB is dependent upon both the ClientSchema
15175
15529
  // and the AST schema (i.e. PROTOCOL_VERSION).
15176
- schemaVersion: `${schema.version}.${PROTOCOL_VERSION}`,
15530
+ schemaVersion: `${PROTOCOL_VERSION}.${hash2}`,
15177
15531
  logLevel: logOptions.logLevel,
15178
15532
  logSinks: [logOptions.logSink],
15179
15533
  mutators: replicacheMutators,
@@ -15260,9 +15614,11 @@ var Zero = class {
15260
15614
  this.#lc
15261
15615
  );
15262
15616
  this.#zeroContext = new ZeroContext(
15617
+ this.#lc,
15263
15618
  this.#ivmMain,
15264
15619
  (ast, ttl, gotCallback) => this.#queryManager.add(ast, ttl, gotCallback),
15265
- batchViewUpdates
15620
+ batchViewUpdates,
15621
+ slowMaterializeThreshold
15266
15622
  );
15267
15623
  rep.experimentalWatch(
15268
15624
  (diff3) => this.#zeroContext.processChanges(diff3),
@@ -15470,10 +15826,14 @@ var Zero = class {
15470
15826
  case "error":
15471
15827
  return this.#handleErrorMessage(lc, downMessage);
15472
15828
  case "pong":
15829
+ resetBackoff();
15473
15830
  return this.#onPong();
15474
15831
  case "pokeStart":
15475
15832
  return this.#handlePokeStart(lc, downMessage);
15476
15833
  case "pokePart":
15834
+ if (downMessage[1].rowsPatch) {
15835
+ resetBackoff();
15836
+ }
15477
15837
  return this.#handlePokePart(lc, downMessage);
15478
15838
  case "pokeEnd":
15479
15839
  return this.#handlePokeEnd(lc, downMessage);
@@ -15607,11 +15967,15 @@ var Zero = class {
15607
15967
  }
15608
15968
  ]);
15609
15969
  } else if (this.#initConnectionQueries === void 0) {
15970
+ const clientSchema2 = this.#clientSchema;
15610
15971
  send(socket, [
15611
15972
  "initConnection",
15612
15973
  {
15613
15974
  desiredQueriesPatch: [...queriesPatch.values()],
15614
- deleted: skipEmptyDeletedClients(this.#deletedClients)
15975
+ deleted: skipEmptyDeletedClients(this.#deletedClients),
15976
+ // The clientSchema only needs to be sent for the very first request.
15977
+ // Henceforth it is stored with the CVR and verified automatically.
15978
+ ...this.#connectCookie === null ? { clientSchema: clientSchema2 } : {}
15615
15979
  }
15616
15980
  ]);
15617
15981
  this.#deletedClients = void 0;
@@ -15679,7 +16043,7 @@ var Zero = class {
15679
16043
  this.#connectCookie,
15680
16044
  this.clientID,
15681
16045
  await this.clientGroupID,
15682
- this.#options.schema.version,
16046
+ this.#clientSchema,
15683
16047
  this.userID,
15684
16048
  this.#rep.auth,
15685
16049
  this.#lastMutationIDReceived,
@@ -15775,7 +16139,6 @@ var Zero = class {
15775
16139
  );
15776
16140
  }
15777
16141
  #handlePokeStart(_lc, pokeMessage) {
15778
- resetBackoff();
15779
16142
  this.#abortPingTimeout();
15780
16143
  this.#pokeHandler.handlePokeStart(pokeMessage[1]);
15781
16144
  }
@@ -15860,8 +16223,6 @@ var Zero = class {
15860
16223
  clientGroupID: req.clientGroupID,
15861
16224
  mutations: [zeroM],
15862
16225
  pushVersion: req.pushVersion,
15863
- // Zero schema versions are always numbers.
15864
- schemaVersion: parseInt(req.schemaVersion),
15865
16226
  requestID
15866
16227
  }
15867
16228
  ];
@@ -16106,7 +16467,7 @@ var Zero = class {
16106
16467
  return this.#online;
16107
16468
  }
16108
16469
  /**
16109
- * Starts a a ping and waits for a pong.
16470
+ * Starts a ping and waits for a pong.
16110
16471
  *
16111
16472
  * If it takes too long to get a pong we disconnect and this returns
16112
16473
  * {@code PingResult.TimedOut}.
@@ -16154,14 +16515,13 @@ var Zero = class {
16154
16515
  return rv;
16155
16516
  }
16156
16517
  };
16157
- async function createSocket(rep, queryManager, deleteClientsManager, socketOrigin, baseCookie, clientID, clientGroupID, schemaVersion, userID, auth, lmid, wsid, debugPerf, lc, maxHeaderLength = 1024 * 8, additionalConnectParams) {
16518
+ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigin, baseCookie, clientID, clientGroupID, clientSchema2, userID, auth, lmid, wsid, debugPerf, lc, maxHeaderLength = 1024 * 8, additionalConnectParams) {
16158
16519
  const url = new URL(
16159
16520
  appendPath(socketOrigin, `/sync/v${PROTOCOL_VERSION}/connect`)
16160
16521
  );
16161
16522
  const { searchParams } = url;
16162
16523
  searchParams.set("clientID", clientID);
16163
16524
  searchParams.set("clientGroupID", clientGroupID);
16164
- searchParams.set("schemaVersion", schemaVersion.toString());
16165
16525
  searchParams.set("userID", userID);
16166
16526
  searchParams.set("baseCookie", baseCookie === null ? "" : String(baseCookie));
16167
16527
  searchParams.set("ts", String(performance.now()));
@@ -16189,7 +16549,10 @@ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigi
16189
16549
  "initConnection",
16190
16550
  {
16191
16551
  desiredQueriesPatch: [...queriesPatch.values()],
16192
- deleted: skipEmptyDeletedClients(deletedClients)
16552
+ deleted: skipEmptyDeletedClients(deletedClients),
16553
+ // The clientSchema only needs to be sent for the very first request.
16554
+ // Henceforth it is stored with the CVR and verified automatically.
16555
+ ...baseCookie === null ? { clientSchema: clientSchema2 } : {}
16193
16556
  }
16194
16557
  ],
16195
16558
  auth
@@ -16266,4 +16629,4 @@ export {
16266
16629
  escapeLike,
16267
16630
  Zero
16268
16631
  };
16269
- //# sourceMappingURL=chunk-YKI43S5O.js.map
16632
+ //# sourceMappingURL=chunk-VNV6U5BQ.js.map