@rocicorp/zero 0.17.2025030601 → 0.17.2025031100

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 (234) hide show
  1. package/out/advanced.js +1 -1
  2. package/out/{chunk-EENFDWT4.js → chunk-2TJNN7K4.js} +550 -230
  3. package/out/chunk-2TJNN7K4.js.map +7 -0
  4. package/out/{chunk-Q6D7EOS6.js → chunk-6CQ6CUML.js} +55 -25
  5. package/out/chunk-6CQ6CUML.js.map +7 -0
  6. package/out/{chunk-HARIWJ2J.js → chunk-HLTH2AYN.js} +6 -2
  7. package/out/chunk-HLTH2AYN.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/replicache/src/db/rebase.d.ts +3 -2
  16. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  17. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  18. package/out/replicache/src/replicache-impl.d.ts +7 -1
  19. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  20. package/out/replicache/src/replicache-options.d.ts +51 -0
  21. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  22. package/out/replicache/src/transactions.d.ts +4 -1
  23. package/out/replicache/src/transactions.d.ts.map +1 -1
  24. package/out/shared/src/asserts.d.ts.map +1 -1
  25. package/out/shared/src/asserts.js +1 -2
  26. package/out/shared/src/asserts.js.map +1 -1
  27. package/out/shared/src/objects.d.ts +4 -0
  28. package/out/shared/src/objects.d.ts.map +1 -0
  29. package/out/shared/src/objects.js +25 -0
  30. package/out/shared/src/objects.js.map +1 -0
  31. package/out/solid.js +28 -6
  32. package/out/solid.js.map +2 -2
  33. package/out/z2s/src/compiler.d.ts.map +1 -1
  34. package/out/z2s/src/compiler.js +1 -1
  35. package/out/z2s/src/compiler.js.map +1 -1
  36. package/out/zero-advanced/src/mod.d.ts +3 -0
  37. package/out/zero-advanced/src/mod.d.ts.map +1 -1
  38. package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
  39. package/out/zero-cache/src/auth/load-permissions.js +0 -1
  40. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  41. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  42. package/out/zero-cache/src/auth/write-authorizer.js +1 -0
  43. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  44. package/out/zero-cache/src/config/zero-config.d.ts +4 -0
  45. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  46. package/out/zero-cache/src/db/lite-tables.d.ts +5 -1
  47. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  48. package/out/zero-cache/src/db/lite-tables.js +8 -1
  49. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  50. package/out/zero-cache/src/db/specs.d.ts +5 -5
  51. package/out/zero-cache/src/scripts/deploy-permissions.js +2 -1
  52. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  53. package/out/zero-cache/src/server/multi/config.d.ts +4 -0
  54. package/out/zero-cache/src/server/multi/config.d.ts.map +1 -1
  55. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  56. package/out/zero-cache/src/server/syncer.js +1 -1
  57. package/out/zero-cache/src/server/syncer.js.map +1 -1
  58. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  59. package/out/zero-cache/src/services/change-source/pg/change-source.js +9 -4
  60. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  61. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +10 -10
  62. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +4 -4
  63. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
  64. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +8 -19
  65. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  66. package/out/zero-cache/src/services/change-source/protocol/current/data.js +12 -3
  67. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  68. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +12 -27
  69. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  70. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +4 -9
  71. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  72. package/out/zero-cache/src/services/dispatcher/connect-params.d.ts +1 -1
  73. package/out/zero-cache/src/services/dispatcher/connect-params.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/dispatcher/connect-params.js +1 -1
  75. package/out/zero-cache/src/services/dispatcher/connect-params.js.map +1 -1
  76. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +3 -3
  77. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  78. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -3
  79. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  80. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  81. package/out/zero-cache/src/services/replicator/change-processor.js +68 -33
  82. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  83. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +2 -2
  84. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  85. package/out/zero-cache/src/services/replicator/schema/change-log.js +3 -2
  86. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  87. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
  88. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  89. package/out/zero-cache/src/services/view-syncer/client-handler.js +4 -2
  90. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  91. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts +5 -0
  92. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -0
  93. package/out/zero-cache/src/services/view-syncer/client-schema.js +74 -0
  94. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -0
  95. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +6 -2
  96. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  97. package/out/zero-cache/src/services/view-syncer/cvr-store.js +42 -21
  98. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  99. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +6 -2
  100. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  101. package/out/zero-cache/src/services/view-syncer/cvr.js +39 -17
  102. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  103. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +5 -4
  104. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  105. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +22 -16
  106. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  107. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +2 -0
  108. package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
  109. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +2 -5
  110. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  111. package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
  112. package/out/zero-cache/src/services/view-syncer/schema/init.js +12 -0
  113. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  114. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +2 -2
  115. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  116. package/out/zero-cache/src/services/view-syncer/schema/types.js +4 -3
  117. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  118. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  119. package/out/zero-cache/src/services/view-syncer/snapshotter.js +4 -1
  120. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  121. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +2 -2
  122. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  123. package/out/zero-cache/src/services/view-syncer/view-syncer.js +35 -27
  124. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  125. package/out/zero-cache/src/types/lite.d.ts +4 -1
  126. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  127. package/out/zero-cache/src/types/lite.js +10 -5
  128. package/out/zero-cache/src/types/lite.js.map +1 -1
  129. package/out/zero-client/src/client/context.d.ts +10 -4
  130. package/out/zero-client/src/client/context.d.ts.map +1 -1
  131. package/out/zero-client/src/client/custom.d.ts +11 -2
  132. package/out/zero-client/src/client/custom.d.ts.map +1 -1
  133. package/out/zero-client/src/client/options.d.ts +8 -0
  134. package/out/zero-client/src/client/options.d.ts.map +1 -1
  135. package/out/zero-client/src/client/query-manager.d.ts +2 -1
  136. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  137. package/out/zero-client/src/client/zero.d.ts +3 -2
  138. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  139. package/out/zero-client/src/mod.d.ts +2 -2
  140. package/out/zero-client/src/mod.d.ts.map +1 -1
  141. package/out/zero-protocol/src/client-schema.d.ts +27 -0
  142. package/out/zero-protocol/src/client-schema.d.ts.map +1 -0
  143. package/out/zero-protocol/src/client-schema.js +28 -0
  144. package/out/zero-protocol/src/client-schema.js.map +1 -0
  145. package/out/zero-protocol/src/connect.d.ts +14 -0
  146. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  147. package/out/zero-protocol/src/connect.js +2 -0
  148. package/out/zero-protocol/src/connect.js.map +1 -1
  149. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  150. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  151. package/out/zero-protocol/src/protocol-version.js +2 -1
  152. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  153. package/out/zero-protocol/src/push.d.ts +2 -2
  154. package/out/zero-protocol/src/push.d.ts.map +1 -1
  155. package/out/zero-protocol/src/push.js +4 -1
  156. package/out/zero-protocol/src/push.js.map +1 -1
  157. package/out/zero-protocol/src/up.d.ts +8 -1
  158. package/out/zero-protocol/src/up.d.ts.map +1 -1
  159. package/out/zero-react/src/use-query.d.ts +4 -3
  160. package/out/zero-react/src/use-query.d.ts.map +1 -1
  161. package/out/zero-schema/src/builder/schema-builder.d.ts +7 -13
  162. package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
  163. package/out/zero-schema/src/builder/schema-builder.js +22 -13
  164. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  165. package/out/zero-schema/src/schema-config.d.ts +2 -4
  166. package/out/zero-schema/src/schema-config.d.ts.map +1 -1
  167. package/out/zero-schema/src/schema-config.js +1 -2
  168. package/out/zero-schema/src/schema-config.js.map +1 -1
  169. package/out/zero-schema/src/table-schema.d.ts +2 -2
  170. package/out/zero-schema/src/table-schema.d.ts.map +1 -1
  171. package/out/zero-solid/src/solid-view.d.ts +1 -2
  172. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  173. package/out/zero-solid/src/use-query.d.ts +2 -2
  174. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  175. package/out/zero.js +5 -3
  176. package/out/zql/src/builder/builder.d.ts +3 -2
  177. package/out/zql/src/builder/builder.d.ts.map +1 -1
  178. package/out/zql/src/builder/builder.js +48 -27
  179. package/out/zql/src/builder/builder.js.map +1 -1
  180. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  181. package/out/zql/src/ivm/array-view.js +3 -2
  182. package/out/zql/src/ivm/array-view.js.map +1 -1
  183. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  184. package/out/zql/src/ivm/exists.js +1 -1
  185. package/out/zql/src/ivm/exists.js.map +1 -1
  186. package/out/zql/src/ivm/fan-in.d.ts +1 -0
  187. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  188. package/out/zql/src/ivm/fan-in.js +100 -4
  189. package/out/zql/src/ivm/fan-in.js.map +1 -1
  190. package/out/zql/src/ivm/fan-out.d.ts +2 -1
  191. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  192. package/out/zql/src/ivm/fan-out.js +6 -12
  193. package/out/zql/src/ivm/fan-out.js.map +1 -1
  194. package/out/zql/src/ivm/join.d.ts.map +1 -1
  195. package/out/zql/src/ivm/join.js +12 -41
  196. package/out/zql/src/ivm/join.js.map +1 -1
  197. package/out/zql/src/ivm/memory-source.d.ts +17 -3
  198. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  199. package/out/zql/src/ivm/memory-source.js +108 -56
  200. package/out/zql/src/ivm/memory-source.js.map +1 -1
  201. package/out/zql/src/ivm/source.d.ts +4 -1
  202. package/out/zql/src/ivm/source.d.ts.map +1 -1
  203. package/out/zql/src/ivm/take.d.ts.map +1 -1
  204. package/out/zql/src/ivm/take.js +2 -20
  205. package/out/zql/src/ivm/take.js.map +1 -1
  206. package/out/zql/src/ivm/view-apply-change.d.ts +9 -1
  207. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  208. package/out/zql/src/ivm/view-apply-change.js +58 -16
  209. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  210. package/out/zql/src/ivm/view.d.ts +1 -1
  211. package/out/zql/src/ivm/view.d.ts.map +1 -1
  212. package/out/zql/src/query/query-impl.d.ts +3 -1
  213. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  214. package/out/zql/src/query/query-impl.js +4 -3
  215. package/out/zql/src/query/query-impl.js.map +1 -1
  216. package/out/zql/src/query/query-internal.d.ts +3 -2
  217. package/out/zql/src/query/query-internal.d.ts.map +1 -1
  218. package/out/zql/src/query/query.d.ts +2 -1
  219. package/out/zql/src/query/query.d.ts.map +1 -1
  220. package/out/zql/src/query/query.js.map +1 -1
  221. package/out/zql/src/query/ttl.d.ts +18 -0
  222. package/out/zql/src/query/ttl.d.ts.map +1 -0
  223. package/out/zql/src/query/ttl.js +33 -0
  224. package/out/zql/src/query/ttl.js.map +1 -0
  225. package/out/zqlite/src/db.js +1 -1
  226. package/out/zqlite/src/db.js.map +1 -1
  227. package/out/zqlite/src/table-source.d.ts +1 -1
  228. package/out/zqlite/src/table-source.d.ts.map +1 -1
  229. package/out/zqlite/src/table-source.js +10 -53
  230. package/out/zqlite/src/table-source.js.map +1 -1
  231. package/package.json +3 -3
  232. package/out/chunk-EENFDWT4.js.map +0 -7
  233. package/out/chunk-HARIWJ2J.js.map +0 -7
  234. package/out/chunk-Q6D7EOS6.js.map +0 -7
@@ -1,6 +1,7 @@
1
1
  import {
2
+ DEFAULT_TTL,
2
3
  hasOwn
3
- } from "./chunk-HARIWJ2J.js";
4
+ } from "./chunk-HLTH2AYN.js";
4
5
  import {
5
6
  applyChange,
6
7
  assert,
@@ -18,7 +19,7 @@ import {
18
19
  throwInvalidType,
19
20
  unreachable,
20
21
  valuesEqual
21
- } from "./chunk-Q6D7EOS6.js";
22
+ } from "./chunk-6CQ6CUML.js";
22
23
  import {
23
24
  __export,
24
25
  __reExport
@@ -4162,13 +4163,16 @@ var SubscriptionTransactionWrapper = class {
4162
4163
  return this.#scans;
4163
4164
  }
4164
4165
  };
4166
+ var zeroData = Symbol();
4165
4167
  var WriteTransactionImpl = class extends ReadTransactionImpl {
4166
4168
  reason;
4167
4169
  mutationID;
4168
- constructor(clientID, mutationID, reason, dbWrite, lc, rpcName = "openWriteTransaction") {
4170
+ [zeroData];
4171
+ constructor(clientID, mutationID, reason, zData, dbWrite, lc, rpcName = "openWriteTransaction") {
4169
4172
  super(clientID, dbWrite, lc, rpcName);
4170
4173
  this.mutationID = mutationID;
4171
4174
  this.reason = reason;
4175
+ this[zeroData] = zData;
4172
4176
  }
4173
4177
  put(key, value) {
4174
4178
  return this.set(key, value);
@@ -4717,7 +4721,7 @@ async function createIndexBTree(lc, dagWrite, valueMap, prefix, jsonPointer, all
4717
4721
  }
4718
4722
 
4719
4723
  // ../replicache/src/db/rebase.ts
4720
- async function rebaseMutation(mutation, dagWrite, basisHash, mutators, lc, mutationClientID, formatVersion) {
4724
+ async function rebaseMutation(mutation, dagWrite, basisHash, mutators, lc, mutationClientID, formatVersion, zeroData2) {
4721
4725
  const localMeta = mutation.meta;
4722
4726
  const name = localMeta.mutatorName;
4723
4727
  if (isLocalMetaDD31(localMeta)) {
@@ -4760,13 +4764,14 @@ async function rebaseMutation(mutation, dagWrite, basisHash, mutators, lc, mutat
4760
4764
  mutationClientID,
4761
4765
  await dbWrite.getMutationID(),
4762
4766
  "rebase",
4767
+ zeroData2,
4763
4768
  dbWrite,
4764
4769
  lc
4765
4770
  );
4766
4771
  await mutatorImpl(tx, args);
4767
4772
  return dbWrite;
4768
4773
  }
4769
- async function rebaseMutationAndPutCommit(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion) {
4774
+ async function rebaseMutationAndPutCommit(mutation, dagWrite, basis, mutators, lc, mutationClientID, formatVersion, zeroData2) {
4770
4775
  const tx = await rebaseMutation(
4771
4776
  mutation,
4772
4777
  dagWrite,
@@ -4774,11 +4779,12 @@ async function rebaseMutationAndPutCommit(mutation, dagWrite, basis, mutators, l
4774
4779
  mutators,
4775
4780
  lc,
4776
4781
  mutationClientID,
4777
- formatVersion
4782
+ formatVersion,
4783
+ zeroData2
4778
4784
  );
4779
4785
  return tx.putCommit();
4780
4786
  }
4781
- async function rebaseMutationAndCommit(mutation, dagWrite, basis, headName, mutators, lc, mutationClientID, formatVersion) {
4787
+ async function rebaseMutationAndCommit(mutation, dagWrite, basis, headName, mutators, lc, mutationClientID, formatVersion, zeroData2) {
4782
4788
  const dbWrite = await rebaseMutation(
4783
4789
  mutation,
4784
4790
  dagWrite,
@@ -4786,7 +4792,8 @@ async function rebaseMutationAndCommit(mutation, dagWrite, basis, headName, muta
4786
4792
  mutators,
4787
4793
  lc,
4788
4794
  mutationClientID,
4789
- formatVersion
4795
+ formatVersion,
4796
+ zeroData2
4790
4797
  );
4791
4798
  return dbWrite.commit(headName);
4792
4799
  }
@@ -6383,7 +6390,8 @@ async function rebase(mutations, basis, write, mutators, mutationIDs, lc, format
6383
6390
  mutators,
6384
6391
  lc,
6385
6392
  meta.clientID,
6386
- formatVersion
6393
+ formatVersion,
6394
+ void 0
6387
6395
  )).chunk.hash;
6388
6396
  }
6389
6397
  }
@@ -6548,7 +6556,8 @@ async function refresh(lc, memdag, perdag, clientID, mutators, diffConfig, close
6548
6556
  mutators,
6549
6557
  lc,
6550
6558
  newMemdagMutations[i].meta.clientID,
6551
- formatVersion
6559
+ formatVersion,
6560
+ void 0
6552
6561
  )).chunk.hash;
6553
6562
  }
6554
6563
  const newMemdagHeadCommit = await commitFromHash(
@@ -7584,7 +7593,8 @@ var ReplicacheImpl = class {
7584
7593
  this.#mutatorRegistry,
7585
7594
  lc,
7586
7595
  isLocalMetaDD31(meta) ? meta.clientID : clientID,
7587
- Latest
7596
+ Latest,
7597
+ void 0
7588
7598
  )
7589
7599
  );
7590
7600
  }
@@ -8131,6 +8141,7 @@ var ReplicacheImpl = class {
8131
8141
  clientID,
8132
8142
  await dbWrite.getMutationID(),
8133
8143
  "initial",
8144
+ void 0,
8134
8145
  dbWrite,
8135
8146
  this.#lc
8136
8147
  );
@@ -8447,6 +8458,65 @@ function one(...args) {
8447
8458
  }));
8448
8459
  }
8449
8460
 
8461
+ // ../shared/src/hash.ts
8462
+ import { xxHash32 } from "js-xxhash";
8463
+ var h64 = (s) => hash(s, 2);
8464
+ var h128 = (s) => hash(s, 4);
8465
+ function hash(str, words) {
8466
+ let hash2 = 0n;
8467
+ for (let i = 0; i < words; i++) {
8468
+ hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
8469
+ }
8470
+ return hash2;
8471
+ }
8472
+
8473
+ // ../shared/src/objects.ts
8474
+ function mapEntries(input, mapper) {
8475
+ const output = {};
8476
+ for (const entry of Object.entries(input)) {
8477
+ const mapped = mapper(entry[0], entry[1]);
8478
+ output[mapped[0]] = mapped[1];
8479
+ }
8480
+ return output;
8481
+ }
8482
+ function mapAllEntries(input, mapper) {
8483
+ const output = {};
8484
+ for (const mapped of mapper(Object.entries(input))) {
8485
+ output[mapped[0]] = mapped[1];
8486
+ }
8487
+ return output;
8488
+ }
8489
+
8490
+ // ../zero-protocol/src/client-schema.ts
8491
+ var valueTypeSchema = valita_exports.union(
8492
+ valita_exports.literal("string"),
8493
+ valita_exports.literal("number"),
8494
+ valita_exports.literal("boolean"),
8495
+ valita_exports.literal("null"),
8496
+ valita_exports.literal("json")
8497
+ );
8498
+ var columnSchemaSchema = valita_exports.object({
8499
+ type: valueTypeSchema
8500
+ });
8501
+ var tableSchemaSchema = valita_exports.object({
8502
+ columns: valita_exports.record(columnSchemaSchema)
8503
+ });
8504
+ var clientSchemaSchema = valita_exports.object({
8505
+ tables: valita_exports.record(tableSchemaSchema)
8506
+ });
8507
+ var keyCmp = ([a], [b]) => a < b ? -1 : a > b ? 1 : 0;
8508
+ function normalizeClientSchema(schema) {
8509
+ return {
8510
+ tables: mapAllEntries(
8511
+ schema.tables,
8512
+ (tables) => tables.sort(keyCmp).map(([name, table2]) => [
8513
+ name,
8514
+ { columns: mapAllEntries(table2.columns, (e) => e.sort(keyCmp)) }
8515
+ ])
8516
+ )
8517
+ };
8518
+ }
8519
+
8450
8520
  // ../zero-schema/src/builder/table-builder.ts
8451
8521
  function table(name) {
8452
8522
  return new TableBuilder({
@@ -8565,7 +8635,7 @@ var ColumnBuilder = class _ColumnBuilder {
8565
8635
  };
8566
8636
 
8567
8637
  // ../zero-schema/src/builder/schema-builder.ts
8568
- function createSchema(version3, options) {
8638
+ function createSchema(options) {
8569
8639
  const retTables = {};
8570
8640
  const retRelationships = {};
8571
8641
  const serverNames = /* @__PURE__ */ new Set();
@@ -8596,7 +8666,6 @@ function createSchema(version3, options) {
8596
8666
  );
8597
8667
  });
8598
8668
  return {
8599
- version: version3,
8600
8669
  tables: retTables,
8601
8670
  relationships: retRelationships
8602
8671
  };
@@ -8619,6 +8688,22 @@ function checkRelationship(relationships2, tableName, tables) {
8619
8688
  });
8620
8689
  });
8621
8690
  }
8691
+ function clientSchemaFrom(schema) {
8692
+ const client = {
8693
+ tables: mapEntries(schema.tables, (name, { serverName, columns }) => [
8694
+ serverName ?? name,
8695
+ {
8696
+ columns: mapEntries(columns, (name2, { serverName: serverName2, type }) => [
8697
+ serverName2 ?? name2,
8698
+ { type }
8699
+ ])
8700
+ }
8701
+ ])
8702
+ };
8703
+ const clientSchema2 = normalizeClientSchema(client);
8704
+ const hash2 = h64(JSON.stringify(clientSchema2)).toString(36);
8705
+ return { clientSchema: clientSchema2, hash: hash2 };
8706
+ }
8622
8707
 
8623
8708
  // ../zero-protocol/src/ast.ts
8624
8709
  import { compareUTF8 as compareUTF83 } from "compare-utf8";
@@ -8966,18 +9051,6 @@ function compareUTF8MaybeNull(a, b) {
8966
9051
  // ../zql/src/query/query-impl.ts
8967
9052
  import { resolver as resolver7 } from "@rocicorp/resolver";
8968
9053
 
8969
- // ../shared/src/hash.ts
8970
- import { xxHash32 } from "js-xxhash";
8971
- var h64 = (s) => hash(s, 2);
8972
- var h128 = (s) => hash(s, 4);
8973
- function hash(str, words) {
8974
- let hash2 = 0n;
8975
- for (let i = 0; i < words; i++) {
8976
- hash2 = (hash2 << 32n) + BigInt(xxHash32(str, i));
8977
- }
8978
- return hash2;
8979
- }
8980
-
8981
9054
  // ../zero-protocol/src/ast-hash.ts
8982
9055
  var hashCache = /* @__PURE__ */ new WeakMap();
8983
9056
  function hashOfAST(ast) {
@@ -9049,7 +9122,10 @@ var Exists = class {
9049
9122
  this.#relationshipName = relationshipName;
9050
9123
  this.#input.setOutput(this);
9051
9124
  this.#storage = storage;
9052
- assert(this.#input.getSchema().relationships[relationshipName]);
9125
+ assert(
9126
+ this.#input.getSchema().relationships[relationshipName],
9127
+ `Input schema missing ${relationshipName}`
9128
+ );
9053
9129
  this.#not = type === "NOT EXISTS";
9054
9130
  this.#parentJoinKey = parentJoinKey;
9055
9131
  this.#noSizeReuse = areEqual(
@@ -9263,17 +9339,17 @@ var Exists = class {
9263
9339
  // ../zql/src/ivm/fan-in.ts
9264
9340
  var FanIn = class {
9265
9341
  #inputs;
9266
- #fanOut;
9267
9342
  #schema;
9268
9343
  #output = throwOutput;
9344
+ #accumulatedPushes;
9269
9345
  constructor(fanOut, inputs) {
9270
9346
  this.#inputs = inputs;
9271
9347
  this.#schema = fanOut.getSchema();
9272
- this.#fanOut = fanOut;
9273
9348
  for (const input of inputs) {
9274
9349
  input.setOutput(this);
9275
9350
  assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);
9276
9351
  }
9352
+ this.#accumulatedPushes = [];
9277
9353
  }
9278
9354
  setOutput(output) {
9279
9355
  this.#output = output;
@@ -9301,8 +9377,102 @@ var FanIn = class {
9301
9377
  );
9302
9378
  }
9303
9379
  push(change) {
9304
- this.#fanOut.onFanInReceivedPush();
9305
- 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
+ }
9306
9476
  }
9307
9477
  };
9308
9478
 
@@ -9310,16 +9480,15 @@ var FanIn = class {
9310
9480
  var FanOut = class {
9311
9481
  #input;
9312
9482
  #outputs = [];
9313
- // FanOut is paired with a FanIn.
9314
- // Once FanIn has received a push from FanOut along
9315
- // any branch, FanOut no longer needs to push that value
9316
- // across the rest of its outputs..
9317
- #fanInReceivedPush = false;
9483
+ #fanIn;
9318
9484
  #destroyCount = 0;
9319
9485
  constructor(input) {
9320
9486
  this.#input = input;
9321
9487
  input.setOutput(this);
9322
9488
  }
9489
+ setFanIn(fanIn) {
9490
+ this.#fanIn = fanIn;
9491
+ }
9323
9492
  setOutput(output) {
9324
9493
  this.#outputs.push(output);
9325
9494
  }
@@ -9342,17 +9511,14 @@ var FanOut = class {
9342
9511
  cleanup(req) {
9343
9512
  return this.#input.cleanup(req);
9344
9513
  }
9345
- onFanInReceivedPush() {
9346
- this.#fanInReceivedPush = true;
9347
- }
9348
9514
  push(change) {
9349
- this.#fanInReceivedPush = false;
9350
9515
  for (const out of this.#outputs) {
9351
9516
  out.push(change);
9352
- if (this.#fanInReceivedPush) {
9353
- return;
9354
- }
9355
9517
  }
9518
+ must(
9519
+ this.#fanIn,
9520
+ "fan-out must have a corresponding fan-in set!"
9521
+ ).fanOutDonePushingToAllBranches(change.type);
9356
9522
  }
9357
9523
  };
9358
9524
 
@@ -9554,34 +9720,27 @@ var Join = class {
9554
9720
  });
9555
9721
  break;
9556
9722
  case "edit": {
9557
- if (rowEqualsForCompoundKey(
9558
- change.oldNode.row,
9559
- change.node.row,
9560
- this.#parentKey
9561
- )) {
9562
- this.#output.push({
9563
- type: "edit",
9564
- oldNode: this.#processParentNode(
9565
- change.oldNode.row,
9566
- change.oldNode.relationships,
9567
- "cleanup"
9568
- ),
9569
- node: this.#processParentNode(
9570
- change.node.row,
9571
- change.node.relationships,
9572
- "fetch"
9573
- )
9574
- });
9575
- } else {
9576
- this.#pushParent({
9577
- type: "remove",
9578
- node: change.oldNode
9579
- });
9580
- this.#pushParent({
9581
- type: "add",
9582
- node: change.node
9583
- });
9584
- }
9723
+ assert(
9724
+ rowEqualsForCompoundKey(
9725
+ change.oldNode.row,
9726
+ change.node.row,
9727
+ this.#parentKey
9728
+ ),
9729
+ `Parent edit must not change relationship.`
9730
+ );
9731
+ this.#output.push({
9732
+ type: "edit",
9733
+ oldNode: this.#processParentNode(
9734
+ change.oldNode.row,
9735
+ change.oldNode.relationships,
9736
+ "cleanup"
9737
+ ),
9738
+ node: this.#processParentNode(
9739
+ change.node.row,
9740
+ change.node.relationships,
9741
+ "fetch"
9742
+ )
9743
+ });
9585
9744
  break;
9586
9745
  }
9587
9746
  default:
@@ -9622,18 +9781,11 @@ var Join = class {
9622
9781
  case "edit": {
9623
9782
  const childRow = change.node.row;
9624
9783
  const oldChildRow = change.oldNode.row;
9625
- if (rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey)) {
9626
- pushChildChange(childRow, change);
9627
- } else {
9628
- pushChildChange(oldChildRow, {
9629
- type: "remove",
9630
- node: change.oldNode
9631
- });
9632
- pushChildChange(childRow, {
9633
- type: "add",
9634
- node: change.node
9635
- });
9636
- }
9784
+ assert(
9785
+ rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),
9786
+ "Child edit must not change relationship."
9787
+ );
9788
+ pushChildChange(childRow, change);
9637
9789
  break;
9638
9790
  }
9639
9791
  default:
@@ -9709,7 +9861,7 @@ function makeStorageKey(key, primaryKey, row) {
9709
9861
  }
9710
9862
  function rowEqualsForCompoundKey(a, b, key) {
9711
9863
  for (let i = 0; i < key.length; i++) {
9712
- if (!valuesEqual(a[key[i]], b[key[i]])) {
9864
+ if (compareValues(a[key[i]], b[key[i]]) !== 0) {
9713
9865
  return false;
9714
9866
  }
9715
9867
  }
@@ -10082,17 +10234,10 @@ var Take = class {
10082
10234
  }
10083
10235
  }
10084
10236
  #pushEditChange(change) {
10085
- if (this.#partitionKeyComparator && this.#partitionKeyComparator(change.oldNode.row, change.node.row) !== 0) {
10086
- this.push({
10087
- type: "remove",
10088
- node: change.oldNode
10089
- });
10090
- this.push({
10091
- type: "add",
10092
- node: change.node
10093
- });
10094
- return;
10095
- }
10237
+ assert(
10238
+ !this.#partitionKeyComparator || this.#partitionKeyComparator(change.oldNode.row, change.node.row) === 0,
10239
+ "Unexpected change of partition key"
10240
+ );
10096
10241
  const { takeState, takeStateKey, maxBound, constraint } = this.#getStateAndConstraint(change.oldNode.row);
10097
10242
  if (!takeState) {
10098
10243
  return;
@@ -10511,55 +10656,75 @@ function transformFilters(filters) {
10511
10656
 
10512
10657
  // ../zql/src/builder/builder.ts
10513
10658
  function buildPipeline(ast, delegate) {
10514
- return buildPipelineInternal(ast, delegate);
10659
+ return buildPipelineInternal(ast, delegate, "");
10515
10660
  }
10516
- function buildPipelineInternal(ast, delegate, partitionKey) {
10661
+ function buildPipelineInternal(ast, delegate, name, partitionKey) {
10517
10662
  const source = delegate.getSource(ast.table);
10518
10663
  if (!source) {
10519
10664
  throw new Error(`Source not found: ${ast.table}`);
10520
10665
  }
10521
- const conn = source.connect(must(ast.orderBy), ast.where);
10522
- let end = conn;
10523
- const { fullyAppliedFilters } = conn;
10524
10666
  ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
10667
+ const csqsFromCondition = gatherCorrelatedSubqueryQueriesFromCondition(
10668
+ ast.where
10669
+ );
10670
+ const splitEditKeys = partitionKey ? new Set(partitionKey) : /* @__PURE__ */ new Set();
10671
+ for (const csq of csqsFromCondition) {
10672
+ for (const key of csq.correlation.parentField) {
10673
+ splitEditKeys.add(key);
10674
+ }
10675
+ }
10676
+ if (ast.related) {
10677
+ for (const csq of ast.related) {
10678
+ for (const key of csq.correlation.parentField) {
10679
+ splitEditKeys.add(key);
10680
+ }
10681
+ }
10682
+ }
10683
+ const conn = source.connect(must(ast.orderBy), ast.where, splitEditKeys);
10684
+ let end = delegate.decorateInput(conn, `${name}:source(${ast.table})`);
10685
+ const { fullyAppliedFilters } = conn;
10525
10686
  if (ast.start) {
10526
- end = new Skip(end, ast.start);
10687
+ end = delegate.decorateInput(new Skip(end, ast.start), `${name}:skip)`);
10527
10688
  }
10528
- for (const csq of gatherCorrelatedSubqueryQueriesFromCondition(ast.where)) {
10529
- end = applyCorrelatedSubQuery(csq, delegate, end);
10689
+ for (const csq of csqsFromCondition) {
10690
+ end = applyCorrelatedSubQuery(csq, delegate, end, name);
10530
10691
  }
10531
10692
  if (ast.where && !fullyAppliedFilters) {
10532
- end = applyWhere(end, ast.where, delegate);
10693
+ end = applyWhere(end, ast.where, delegate, name);
10533
10694
  }
10534
- if (ast.limit) {
10535
- end = new Take(end, delegate.createStorage(), ast.limit, partitionKey);
10695
+ if (ast.limit !== void 0) {
10696
+ const takeName = `${name}:take`;
10697
+ end = delegate.decorateInput(
10698
+ new Take(end, delegate.createStorage(takeName), ast.limit, partitionKey),
10699
+ takeName
10700
+ );
10536
10701
  }
10537
10702
  if (ast.related) {
10538
10703
  for (const csq of ast.related) {
10539
- end = applyCorrelatedSubQuery(csq, delegate, end);
10704
+ end = applyCorrelatedSubQuery(csq, delegate, end, name);
10540
10705
  }
10541
10706
  }
10542
10707
  return end;
10543
10708
  }
10544
- function applyWhere(input, condition, delegate) {
10709
+ function applyWhere(input, condition, delegate, name) {
10545
10710
  switch (condition.type) {
10546
10711
  case "and":
10547
- return applyAnd(input, condition, delegate);
10712
+ return applyAnd(input, condition, delegate, name);
10548
10713
  case "or":
10549
- return applyOr(input, condition, delegate);
10714
+ return applyOr(input, condition, delegate, name);
10550
10715
  case "correlatedSubquery":
10551
- return applyCorrelatedSubqueryCondition(input, condition, delegate);
10716
+ return applyCorrelatedSubqueryCondition(input, condition, delegate, name);
10552
10717
  case "simple":
10553
10718
  return applySimpleCondition(input, condition);
10554
10719
  }
10555
10720
  }
10556
- function applyAnd(input, condition, delegate) {
10721
+ function applyAnd(input, condition, delegate, name) {
10557
10722
  for (const subCondition of condition.conditions) {
10558
- input = applyWhere(input, subCondition, delegate);
10723
+ input = applyWhere(input, subCondition, delegate, name);
10559
10724
  }
10560
10725
  return input;
10561
10726
  }
10562
- function applyOr(input, condition, delegate) {
10727
+ function applyOr(input, condition, delegate, name) {
10563
10728
  const [subqueryConditions, otherConditions] = groupSubqueryConditions(condition);
10564
10729
  if (subqueryConditions.length === 0) {
10565
10730
  return new Filter(
@@ -10572,7 +10737,7 @@ function applyOr(input, condition, delegate) {
10572
10737
  }
10573
10738
  const fanOut = new FanOut(input);
10574
10739
  const branches = subqueryConditions.map(
10575
- (subCondition) => applyWhere(fanOut, subCondition, delegate)
10740
+ (subCondition) => applyWhere(fanOut, subCondition, delegate, name)
10576
10741
  );
10577
10742
  if (otherConditions.length > 0) {
10578
10743
  branches.push(
@@ -10585,7 +10750,9 @@ function applyOr(input, condition, delegate) {
10585
10750
  )
10586
10751
  );
10587
10752
  }
10588
- return new FanIn(fanOut, branches);
10753
+ const ret = new FanIn(fanOut, branches);
10754
+ fanOut.setFanIn(ret);
10755
+ return ret;
10589
10756
  }
10590
10757
  function groupSubqueryConditions(condition) {
10591
10758
  const partitioned = [[], []];
@@ -10611,33 +10778,39 @@ function isNotAndDoesNotContainSubquery(condition) {
10611
10778
  function applySimpleCondition(input, condition) {
10612
10779
  return new Filter(input, createPredicate(condition));
10613
10780
  }
10614
- function applyCorrelatedSubQuery(sq, delegate, end) {
10781
+ function applyCorrelatedSubQuery(sq, delegate, end, name) {
10615
10782
  assert(sq.subquery.alias, "Subquery must have an alias");
10616
10783
  const child = buildPipelineInternal(
10617
10784
  sq.subquery,
10618
10785
  delegate,
10786
+ `${name}.${sq.subquery.alias}`,
10619
10787
  sq.correlation.childField
10620
10788
  );
10789
+ const joinName = `${name}:join(${sq.subquery.alias})`;
10621
10790
  end = new Join({
10622
10791
  parent: end,
10623
10792
  child,
10624
- storage: delegate.createStorage(),
10793
+ storage: delegate.createStorage(joinName),
10625
10794
  parentKey: sq.correlation.parentField,
10626
10795
  childKey: sq.correlation.childField,
10627
10796
  relationshipName: sq.subquery.alias,
10628
10797
  hidden: sq.hidden ?? false,
10629
10798
  system: sq.system ?? "client"
10630
10799
  });
10631
- return end;
10800
+ return delegate.decorateInput(end, joinName);
10632
10801
  }
10633
- function applyCorrelatedSubqueryCondition(input, condition, delegate) {
10802
+ function applyCorrelatedSubqueryCondition(input, condition, delegate, name) {
10634
10803
  assert(condition.op === "EXISTS" || condition.op === "NOT EXISTS");
10635
- return new Exists(
10636
- input,
10637
- delegate.createStorage(),
10638
- must(condition.related.subquery.alias),
10639
- condition.related.correlation.parentField,
10640
- condition.op
10804
+ const existsName = `${name}:exists(${condition.related.subquery.alias})`;
10805
+ return delegate.decorateInput(
10806
+ new Exists(
10807
+ input,
10808
+ delegate.createStorage(existsName),
10809
+ must(condition.related.subquery.alias),
10810
+ condition.related.correlation.parentField,
10811
+ condition.op
10812
+ ),
10813
+ existsName
10641
10814
  );
10642
10815
  }
10643
10816
  function gatherCorrelatedSubqueryQueriesFromCondition(condition) {
@@ -10753,6 +10926,7 @@ var ArrayView = class {
10753
10926
  onDestroy;
10754
10927
  #dirty = false;
10755
10928
  #complete = false;
10929
+ #refCountMap = /* @__PURE__ */ new WeakMap();
10756
10930
  constructor(input, format = { singular: false, relationships: {} }, queryComplete = true) {
10757
10931
  this.#input = input;
10758
10932
  this.#schema = input.getSchema();
@@ -10802,14 +10976,22 @@ var ArrayView = class {
10802
10976
  { type: "add", node },
10803
10977
  this.#schema,
10804
10978
  "",
10805
- this.#format
10979
+ this.#format,
10980
+ this.#refCountMap
10806
10981
  );
10807
10982
  }
10808
10983
  this.flush();
10809
10984
  }
10810
10985
  push(change) {
10811
10986
  this.#dirty = true;
10812
- applyChange(this.#root, change, this.#schema, "", this.#format);
10987
+ applyChange(
10988
+ this.#root,
10989
+ change,
10990
+ this.#schema,
10991
+ "",
10992
+ this.#format,
10993
+ this.#refCountMap
10994
+ );
10813
10995
  }
10814
10996
  flush() {
10815
10997
  if (!this.#dirty) {
@@ -11025,9 +11207,6 @@ function unwrap(c) {
11025
11207
  return { type: c.type, conditions: flatten(c.type, c.conditions.map(unwrap)) };
11026
11208
  }
11027
11209
 
11028
- // ../zql/src/query/query.ts
11029
- var DEFAULT_TTL = 1e4;
11030
-
11031
11210
  // ../zql/src/query/query-impl.ts
11032
11211
  var astForTestingSymbol = Symbol();
11033
11212
  function newQuery(delegate, schema, table2) {
@@ -11066,9 +11245,7 @@ var AbstractQuery = class {
11066
11245
  }
11067
11246
  hash() {
11068
11247
  if (!this.#hash) {
11069
- const ast = this._completeAst();
11070
- const hash2 = hashOfAST(ast);
11071
- this.#hash = hash2;
11248
+ this.#hash = hashOfAST(this._completeAst());
11072
11249
  }
11073
11250
  return this.#hash;
11074
11251
  }
@@ -11433,6 +11610,7 @@ var QueryImpl = class extends AbstractQuery {
11433
11610
  return newQueryWithDetails(this.#delegate, schema, tableName, ast, format);
11434
11611
  }
11435
11612
  materialize(factoryOrTTL, ttl = DEFAULT_TTL) {
11613
+ const t0 = Date.now();
11436
11614
  let factory;
11437
11615
  if (typeof factoryOrTTL === "function") {
11438
11616
  factory = factoryOrTTL;
@@ -11444,6 +11622,8 @@ var QueryImpl = class extends AbstractQuery {
11444
11622
  let queryGot = false;
11445
11623
  const removeServerQuery = this.#delegate.addServerQuery(ast, ttl, (got) => {
11446
11624
  if (got) {
11625
+ const t1 = Date.now();
11626
+ this.#delegate.onQueryMaterialized(this.hash(), ast, t1 - t0);
11447
11627
  queryGot = true;
11448
11628
  queryCompleteResolver.resolve(true);
11449
11629
  }
@@ -11812,6 +11992,40 @@ function escapeLike(val) {
11812
11992
  return val.replace(/[%_]/g, "\\$&");
11813
11993
  }
11814
11994
 
11995
+ // ../zql/src/query/ttl.ts
11996
+ var DEFAULT_TTL2 = "none";
11997
+ var multiplier = {
11998
+ s: 1e3,
11999
+ m: 60 * 1e3,
12000
+ h: 60 * 60 * 1e3,
12001
+ d: 24 * 60 * 60 * 1e3,
12002
+ y: 365 * 24 * 60 * 60 * 1e3
12003
+ };
12004
+ function parseTTL(ttl) {
12005
+ if (typeof ttl === "number") {
12006
+ return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;
12007
+ }
12008
+ if (ttl === "none") {
12009
+ return 0;
12010
+ }
12011
+ if (ttl === "forever") {
12012
+ return -1;
12013
+ }
12014
+ const multi = multiplier[ttl[ttl.length - 1]];
12015
+ return Number(ttl.slice(0, -1)) * multi;
12016
+ }
12017
+ function compareTTL(a, b) {
12018
+ const ap = parseTTL(a);
12019
+ const bp = parseTTL(b);
12020
+ if (ap === -1 && bp !== -1) {
12021
+ return 1;
12022
+ }
12023
+ if (ap !== -1 && bp === -1) {
12024
+ return -1;
12025
+ }
12026
+ return ap - bp;
12027
+ }
12028
+
11815
12029
  // ../zero-client/src/client/zero.ts
11816
12030
  import { LogContext as LogContext4 } from "@rocicorp/logger";
11817
12031
  import { resolver as resolver8 } from "@rocicorp/resolver";
@@ -11856,6 +12070,7 @@ var connectedMessageSchema = valita_exports.tuple([
11856
12070
  ]);
11857
12071
  var initConnectionBodySchema = valita_exports.object({
11858
12072
  desiredQueriesPatch: queriesPatchSchema,
12073
+ clientSchema: clientSchemaSchema.optional(),
11859
12074
  deleted: deleteClientsBodySchema.optional()
11860
12075
  });
11861
12076
  var initConnectionMessageSchema = valita_exports.tuple([
@@ -12084,7 +12299,7 @@ var CRUD = "crud";
12084
12299
  var Custom = "custom";
12085
12300
 
12086
12301
  // ../zero-protocol/src/protocol-version.ts
12087
- var PROTOCOL_VERSION = 6;
12302
+ var PROTOCOL_VERSION = 7;
12088
12303
  var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 2;
12089
12304
  assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
12090
12305
  var MIN_SERVER_SUPPORTED_PERMISSIONS_PROTOCOL = 4;
@@ -12149,7 +12364,10 @@ var pushBodySchema = valita_exports.object({
12149
12364
  clientGroupID: valita_exports.string(),
12150
12365
  mutations: valita_exports.array(mutationSchema),
12151
12366
  pushVersion: valita_exports.number(),
12152
- schemaVersion: valita_exports.number(),
12367
+ // For legacy (CRUD) mutations, the schema is tied to the client group /
12368
+ // sync connection. For custom mutations, schema versioning is delegated
12369
+ // to the custom protocol / api-server.
12370
+ schemaVersion: valita_exports.number().optional(),
12153
12371
  timestamp: valita_exports.number(),
12154
12372
  requestID: valita_exports.string()
12155
12373
  });
@@ -12792,6 +13010,7 @@ var MemorySource = class _MemorySource {
12792
13010
  #indexes = /* @__PURE__ */ new Map();
12793
13011
  #connections = [];
12794
13012
  #overlay;
13013
+ #splitEditOverlay;
12795
13014
  constructor(tableName, columns, primaryKey, primaryIndexData) {
12796
13015
  this.#tableName = tableName;
12797
13016
  this.#columns = columns;
@@ -12834,7 +13053,7 @@ var MemorySource = class _MemorySource {
12834
13053
  compareRows: connection.compareRows
12835
13054
  };
12836
13055
  }
12837
- connect(sort, filters) {
13056
+ connect(sort, filters, splitEditKeys) {
12838
13057
  const transformedFilters = transformFilters(filters);
12839
13058
  const input = {
12840
13059
  getSchema: () => schema,
@@ -12852,6 +13071,7 @@ var MemorySource = class _MemorySource {
12852
13071
  input,
12853
13072
  output: void 0,
12854
13073
  sort,
13074
+ splitEditKeys,
12855
13075
  compareRows: makeComparator(sort),
12856
13076
  filters: transformedFilters.filters ? {
12857
13077
  condition: transformedFilters.filters,
@@ -12905,10 +13125,9 @@ var MemorySource = class _MemorySource {
12905
13125
  return [...this.#indexes.keys()];
12906
13126
  }
12907
13127
  *#fetch(req, from) {
12908
- let overlay;
12909
- const callingConnectionNum = this.#connections.indexOf(from);
12910
- assert(callingConnectionNum !== -1, "Output not found");
12911
- const conn = this.#connections[callingConnectionNum];
13128
+ const callingConnectionIndex = this.#connections.indexOf(from);
13129
+ assert(callingConnectionIndex !== -1, "Output not found");
13130
+ const conn = this.#connections[callingConnectionIndex];
12912
13131
  const { sort: requestedSort } = conn;
12913
13132
  const indexSort = [];
12914
13133
  if (req.constraint) {
@@ -12922,11 +13141,6 @@ var MemorySource = class _MemorySource {
12922
13141
  const index = this.#getOrCreateIndex(indexSort, from);
12923
13142
  const { data, comparator: compare } = index;
12924
13143
  const comparator2 = (r1, r2) => compare(r1, r2) * (req.reverse ? -1 : 1);
12925
- if (this.#overlay) {
12926
- if (callingConnectionNum <= this.#overlay.outputIndex) {
12927
- overlay = this.#overlay;
12928
- }
12929
- }
12930
13144
  const startAt = req.start?.row;
12931
13145
  let scanStart;
12932
13146
  if (req.constraint) {
@@ -12949,7 +13163,9 @@ var MemorySource = class _MemorySource {
12949
13163
  startAt,
12950
13164
  generateRows(data, scanStart, req.reverse),
12951
13165
  req.constraint,
12952
- overlay,
13166
+ this.#overlay,
13167
+ this.#splitEditOverlay,
13168
+ callingConnectionIndex,
12953
13169
  comparator2,
12954
13170
  conn.filters?.predicate
12955
13171
  );
@@ -12969,56 +13185,18 @@ var MemorySource = class _MemorySource {
12969
13185
  *genPush(change) {
12970
13186
  const primaryIndex = this.#getPrimaryIndex();
12971
13187
  const { data } = primaryIndex;
12972
- switch (change.type) {
12973
- case "add":
12974
- assert(
12975
- !data.has(change.row),
12976
- () => `Row already exists ${JSON.stringify(change)}`
12977
- );
12978
- break;
12979
- case "remove":
12980
- assert(
12981
- data.has(change.row),
12982
- () => `Row not found ${JSON.stringify(change)}`
12983
- );
12984
- break;
12985
- case "edit":
12986
- assert(
12987
- data.has(change.oldRow),
12988
- () => `Row not found ${JSON.stringify(change)}`
12989
- );
12990
- break;
12991
- default:
12992
- unreachable(change);
12993
- }
12994
- const outputChange = change.type === "edit" ? {
12995
- type: change.type,
12996
- oldNode: {
12997
- row: change.oldRow,
12998
- relationships: {}
12999
- },
13000
- node: {
13001
- row: change.row,
13002
- relationships: {}
13003
- }
13004
- } : {
13005
- type: change.type,
13006
- node: {
13007
- row: change.row,
13008
- relationships: {}
13009
- }
13010
- };
13011
- for (const [
13012
- outputIndex,
13013
- { output, filters }
13014
- ] of this.#connections.entries()) {
13015
- if (output) {
13016
- this.#overlay = { outputIndex, change };
13017
- filterPush(outputChange, output, filters?.predicate);
13018
- yield;
13019
- }
13188
+ const exists = (row) => data.has(row);
13189
+ const setOverlay = (o) => this.#overlay = o;
13190
+ const setSplitEditOverlay = (o) => this.#splitEditOverlay = o;
13191
+ for (const x of genPush(
13192
+ change,
13193
+ exists,
13194
+ this.#connections.entries(),
13195
+ setOverlay,
13196
+ setSplitEditOverlay
13197
+ )) {
13198
+ yield x;
13020
13199
  }
13021
- this.#overlay = void 0;
13022
13200
  for (const { data: data2 } of this.#indexes.values()) {
13023
13201
  switch (change.type) {
13024
13202
  case "add": {
@@ -13058,6 +13236,89 @@ function* generateWithFilter(it, filter) {
13058
13236
  }
13059
13237
  }
13060
13238
  }
13239
+ function* genPush(change, exists, connections, setOverlay, setSplitEditOverlay) {
13240
+ switch (change.type) {
13241
+ case "add":
13242
+ assert(
13243
+ !exists(change.row),
13244
+ () => `Row already exists ${stringify(change)}`
13245
+ );
13246
+ break;
13247
+ case "remove":
13248
+ assert(exists(change.row), () => `Row not found ${stringify(change)}`);
13249
+ break;
13250
+ case "edit":
13251
+ assert(exists(change.oldRow), () => `Row not found ${stringify(change)}`);
13252
+ break;
13253
+ default:
13254
+ unreachable(change);
13255
+ }
13256
+ for (const [outputIndex, { output, splitEditKeys, filters }] of connections) {
13257
+ if (output) {
13258
+ let splitEdit = false;
13259
+ if (change.type === "edit" && splitEditKeys) {
13260
+ for (const key of splitEditKeys) {
13261
+ if (!valuesEqual(change.row[key], change.oldRow[key])) {
13262
+ splitEdit = true;
13263
+ break;
13264
+ }
13265
+ }
13266
+ }
13267
+ if (splitEdit) {
13268
+ assert(change.type === "edit");
13269
+ setSplitEditOverlay({
13270
+ outputIndex,
13271
+ change: {
13272
+ type: "remove",
13273
+ row: change.oldRow
13274
+ }
13275
+ });
13276
+ const outputRemove = {
13277
+ type: "remove",
13278
+ node: {
13279
+ row: change.oldRow,
13280
+ relationships: {}
13281
+ }
13282
+ };
13283
+ filterPush(outputRemove, output, filters?.predicate);
13284
+ yield;
13285
+ setSplitEditOverlay(void 0);
13286
+ setOverlay({ outputIndex, change });
13287
+ const outputAdd = {
13288
+ type: "add",
13289
+ node: {
13290
+ row: change.row,
13291
+ relationships: {}
13292
+ }
13293
+ };
13294
+ filterPush(outputAdd, output, filters?.predicate);
13295
+ yield;
13296
+ } else {
13297
+ setOverlay({ outputIndex, change });
13298
+ const outputChange = change.type === "edit" ? {
13299
+ type: change.type,
13300
+ oldNode: {
13301
+ row: change.oldRow,
13302
+ relationships: {}
13303
+ },
13304
+ node: {
13305
+ row: change.row,
13306
+ relationships: {}
13307
+ }
13308
+ } : {
13309
+ type: change.type,
13310
+ node: {
13311
+ row: change.row,
13312
+ relationships: {}
13313
+ }
13314
+ };
13315
+ filterPush(outputChange, output, filters?.predicate);
13316
+ yield;
13317
+ }
13318
+ }
13319
+ }
13320
+ setOverlay(void 0);
13321
+ }
13061
13322
  function* generateWithStart(nodes, start, compare) {
13062
13323
  if (!start) {
13063
13324
  yield* nodes;
@@ -13081,11 +13342,17 @@ function* generateWithStart(nodes, start, compare) {
13081
13342
  }
13082
13343
  }
13083
13344
  }
13084
- function* generateWithOverlay(startAt, rows, constraint, overlay, compare, filterPredicate) {
13345
+ function* generateWithOverlay(startAt, rows, constraint, overlay, splitEditOverlay, connectionIndex, compare, filterPredicate) {
13346
+ let overlayToApply = void 0;
13347
+ if (splitEditOverlay && splitEditOverlay.outputIndex === connectionIndex) {
13348
+ overlayToApply = splitEditOverlay;
13349
+ } else if (overlay && connectionIndex <= overlay.outputIndex) {
13350
+ overlayToApply = overlay;
13351
+ }
13085
13352
  const overlays = computeOverlays(
13086
13353
  startAt,
13087
13354
  constraint,
13088
- overlay,
13355
+ overlayToApply,
13089
13356
  compare,
13090
13357
  filterPredicate
13091
13358
  );
@@ -13209,6 +13476,12 @@ function* generateRows(data, scanStart, reverse) {
13209
13476
  scanStart
13210
13477
  );
13211
13478
  }
13479
+ function stringify(change) {
13480
+ return JSON.stringify(
13481
+ change,
13482
+ (_, v2) => typeof v2 === "bigint" ? v2.toString() : v2
13483
+ );
13484
+ }
13212
13485
 
13213
13486
  // ../zero-client/src/client/keys.ts
13214
13487
  var DESIRED_QUERIES_KEY_PREFIX = "d/";
@@ -13374,11 +13647,15 @@ var ZeroContext = class {
13374
13647
  #addQuery;
13375
13648
  #batchViewUpdates;
13376
13649
  #commitListeners = /* @__PURE__ */ new Set();
13650
+ slowMaterializeThreshold;
13651
+ lc;
13377
13652
  staticQueryParameters = void 0;
13378
- constructor(mainSources, addQuery, batchViewUpdates) {
13653
+ constructor(lc, mainSources, addQuery, batchViewUpdates, slowMaterializeThreshold) {
13379
13654
  this.#mainSources = mainSources;
13380
13655
  this.#addQuery = addQuery;
13381
13656
  this.#batchViewUpdates = batchViewUpdates;
13657
+ this.lc = lc;
13658
+ this.slowMaterializeThreshold = slowMaterializeThreshold;
13382
13659
  }
13383
13660
  getSource(name) {
13384
13661
  return this.#mainSources.getSource(name);
@@ -13386,9 +13663,29 @@ var ZeroContext = class {
13386
13663
  addServerQuery(ast, ttl, gotCallback) {
13387
13664
  return this.#addQuery(ast, ttl, gotCallback);
13388
13665
  }
13666
+ onQueryMaterialized(hash2, ast, duration) {
13667
+ if (this.slowMaterializeThreshold !== void 0 && duration > this.slowMaterializeThreshold) {
13668
+ this.lc.warn?.(
13669
+ "Slow query materialization (including server/network)",
13670
+ hash2,
13671
+ ast,
13672
+ duration
13673
+ );
13674
+ } else {
13675
+ this.lc.debug?.(
13676
+ "Materialized query (including server/network)",
13677
+ hash2,
13678
+ ast,
13679
+ duration
13680
+ );
13681
+ }
13682
+ }
13389
13683
  createStorage() {
13390
13684
  return new MemoryStorage();
13391
13685
  }
13686
+ decorateInput(input) {
13687
+ return input;
13688
+ }
13392
13689
  onTransactionCommit(cb) {
13393
13690
  this.#commitListeners.add(cb);
13394
13691
  return () => {
@@ -13681,11 +13978,16 @@ async function deleteImpl(tx, arg, schema, ivmBranch) {
13681
13978
  // ../zero-client/src/client/custom.ts
13682
13979
  var TransactionImpl = class {
13683
13980
  constructor(repTx, schema) {
13981
+ const castedRepTx = repTx;
13684
13982
  must(repTx.reason === "initial" || repTx.reason === "rebase");
13685
13983
  this.clientID = repTx.clientID;
13686
13984
  this.mutationID = repTx.mutationID;
13687
13985
  this.reason = repTx.reason === "initial" ? "optimistic" : "rebase";
13688
- this.mutate = makeSchemaCRUD(schema, repTx);
13986
+ this.mutate = makeSchemaCRUD(
13987
+ schema,
13988
+ repTx,
13989
+ castedRepTx[zeroData]
13990
+ );
13689
13991
  this.query = {};
13690
13992
  }
13691
13993
  clientID;
@@ -13701,14 +14003,14 @@ function makeReplicacheMutator(mutator, schema) {
13701
14003
  return mutator(tx, args);
13702
14004
  };
13703
14005
  }
13704
- function makeSchemaCRUD(schema, tx) {
14006
+ function makeSchemaCRUD(schema, tx, ivmBranch) {
13705
14007
  const mutate = {};
13706
14008
  for (const [name] of Object.entries(schema.tables)) {
13707
- mutate[name] = makeTableCRUD(schema, name, tx);
14009
+ mutate[name] = makeTableCRUD(schema, name, tx, ivmBranch);
13708
14010
  }
13709
14011
  return mutate;
13710
14012
  }
13711
- function makeTableCRUD(schema, tableName, tx) {
14013
+ function makeTableCRUD(schema, tableName, tx, ivmBranch) {
13712
14014
  const table2 = must(schema.tables[tableName]);
13713
14015
  const { primaryKey } = table2;
13714
14016
  return {
@@ -13716,25 +14018,25 @@ function makeTableCRUD(schema, tableName, tx) {
13716
14018
  tx,
13717
14019
  { op: "insert", tableName, primaryKey, value },
13718
14020
  schema,
13719
- void 0
14021
+ ivmBranch
13720
14022
  ),
13721
14023
  upsert: (value) => upsertImpl(
13722
14024
  tx,
13723
14025
  { op: "upsert", tableName, primaryKey, value },
13724
14026
  schema,
13725
- void 0
14027
+ ivmBranch
13726
14028
  ),
13727
14029
  update: (value) => updateImpl(
13728
14030
  tx,
13729
14031
  { op: "update", tableName, primaryKey, value },
13730
14032
  schema,
13731
- void 0
14033
+ ivmBranch
13732
14034
  ),
13733
14035
  delete: (id) => deleteImpl(
13734
14036
  tx,
13735
14037
  { op: "delete", tableName, primaryKey, value: id },
13736
14038
  schema,
13737
- void 0
14039
+ ivmBranch
13738
14040
  )
13739
14041
  };
13740
14042
  }
@@ -14038,7 +14340,7 @@ function makeMessage(message, context, logLevel) {
14038
14340
  }
14039
14341
 
14040
14342
  // ../zero-client/src/client/version.ts
14041
- var version2 = "0.17.2025030601";
14343
+ var version2 = "0.17.2025031100";
14042
14344
 
14043
14345
  // ../zero-client/src/client/log-options.ts
14044
14346
  var LevelFilterLogSink = class {
@@ -14407,7 +14709,7 @@ var QueryManager = class {
14407
14709
  }
14408
14710
  for (const [hash2, { normalized, ttl }] of this.#queries) {
14409
14711
  if (!existingQueryHashes.has(hash2)) {
14410
- patch.set(hash2, { op: "put", hash: hash2, ast: normalized, ttl });
14712
+ patch.set(hash2, { op: "put", hash: hash2, ast: normalized, ttl: parseTTL(ttl) });
14411
14713
  }
14412
14714
  }
14413
14715
  if (lastPatch) {
@@ -14435,7 +14737,7 @@ var QueryManager = class {
14435
14737
  entry = {
14436
14738
  normalized: serverAST,
14437
14739
  count: 1,
14438
- gotCallbacks: gotCallback === void 0 ? [] : [gotCallback],
14740
+ gotCallbacks: gotCallback ? [gotCallback] : [],
14439
14741
  ttl
14440
14742
  };
14441
14743
  this.#queries.set(astHash, entry);
@@ -14443,19 +14745,24 @@ var QueryManager = class {
14443
14745
  "changeDesiredQueries",
14444
14746
  {
14445
14747
  desiredQueriesPatch: [
14446
- { op: "put", hash: astHash, ast: serverAST, ttl }
14748
+ { op: "put", hash: astHash, ast: serverAST, ttl: parseTTL(ttl) }
14447
14749
  ]
14448
14750
  }
14449
14751
  ]);
14450
14752
  } else {
14451
14753
  ++entry.count;
14452
- if (ttl !== void 0 && (entry.ttl === void 0 || ttl > entry.ttl)) {
14754
+ if (compareTTL(ttl, entry.ttl) > 0) {
14453
14755
  entry.ttl = ttl;
14454
14756
  this.#send([
14455
14757
  "changeDesiredQueries",
14456
14758
  {
14457
14759
  desiredQueriesPatch: [
14458
- { op: "put", hash: astHash, ast: entry.normalized, ttl }
14760
+ {
14761
+ op: "put",
14762
+ hash: astHash,
14763
+ ast: entry.normalized,
14764
+ ttl: parseTTL(ttl)
14765
+ }
14459
14766
  ]
14460
14767
  }
14461
14768
  ]);
@@ -14473,11 +14780,10 @@ var QueryManager = class {
14473
14780
  return;
14474
14781
  }
14475
14782
  removed = true;
14476
- this.#remove(astHash, gotCallback);
14783
+ this.#remove(entry, astHash, gotCallback);
14477
14784
  };
14478
14785
  }
14479
- #remove(astHash, gotCallback) {
14480
- const entry = must(this.#queries.get(astHash));
14786
+ #remove(entry, astHash, gotCallback) {
14481
14787
  if (gotCallback) {
14482
14788
  const index = entry.gotCallbacks.indexOf(gotCallback);
14483
14789
  entry.gotCallbacks.splice(index, 1);
@@ -14974,7 +15280,7 @@ function updateNeededReloadReason(reason, serverErrMsg) {
14974
15280
  reasonMsg = "The server no longer supports this client's protocol version.";
14975
15281
  break;
14976
15282
  case "SchemaVersionNotSupported":
14977
- reasonMsg = "The server no longer supports this client's schema version.";
15283
+ reasonMsg = "Client and server schemas incompatible.";
14978
15284
  break;
14979
15285
  default:
14980
15286
  unreachable(type);
@@ -15001,6 +15307,7 @@ var Zero = class {
15001
15307
  #lc;
15002
15308
  #logOptions;
15003
15309
  #enableAnalytics;
15310
+ #clientSchema;
15004
15311
  #pokeHandler;
15005
15312
  #queryManager;
15006
15313
  #ivmMain;
@@ -15098,7 +15405,8 @@ var Zero = class {
15098
15405
  hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,
15099
15406
  schema,
15100
15407
  batchViewUpdates = (applyViewUpdates) => applyViewUpdates(),
15101
- maxRecentQueries = 0
15408
+ maxRecentQueries = 0,
15409
+ slowMaterializeThreshold = 5e3
15102
15410
  } = options;
15103
15411
  if (!userID) {
15104
15412
  throw new Error("ZeroOptions.userID must not be empty.");
@@ -15146,10 +15454,12 @@ var Zero = class {
15146
15454
  }
15147
15455
  }
15148
15456
  this.storageKey = storageKey ?? "";
15457
+ const { clientSchema: clientSchema2, hash: hash2 } = clientSchemaFrom(schema);
15458
+ this.#clientSchema = clientSchema2;
15149
15459
  const replicacheOptions = {
15150
- // The schema stored in IDB is dependent upon both the application schema
15460
+ // The schema stored in IDB is dependent upon both the ClientSchema
15151
15461
  // and the AST schema (i.e. PROTOCOL_VERSION).
15152
- schemaVersion: `${schema.version}.${PROTOCOL_VERSION}`,
15462
+ schemaVersion: `${PROTOCOL_VERSION}.${hash2}`,
15153
15463
  logLevel: logOptions.logLevel,
15154
15464
  logSinks: [logOptions.logSink],
15155
15465
  mutators: replicacheMutators,
@@ -15236,9 +15546,11 @@ var Zero = class {
15236
15546
  this.#lc
15237
15547
  );
15238
15548
  this.#zeroContext = new ZeroContext(
15549
+ this.#lc,
15239
15550
  this.#ivmMain,
15240
15551
  (ast, ttl, gotCallback) => this.#queryManager.add(ast, ttl, gotCallback),
15241
- batchViewUpdates
15552
+ batchViewUpdates,
15553
+ slowMaterializeThreshold
15242
15554
  );
15243
15555
  rep.experimentalWatch(
15244
15556
  (diff3) => this.#zeroContext.processChanges(diff3),
@@ -15446,10 +15758,14 @@ var Zero = class {
15446
15758
  case "error":
15447
15759
  return this.#handleErrorMessage(lc, downMessage);
15448
15760
  case "pong":
15761
+ resetBackoff();
15449
15762
  return this.#onPong();
15450
15763
  case "pokeStart":
15451
15764
  return this.#handlePokeStart(lc, downMessage);
15452
15765
  case "pokePart":
15766
+ if (downMessage[1].rowsPatch) {
15767
+ resetBackoff();
15768
+ }
15453
15769
  return this.#handlePokePart(lc, downMessage);
15454
15770
  case "pokeEnd":
15455
15771
  return this.#handlePokeEnd(lc, downMessage);
@@ -15583,11 +15899,15 @@ var Zero = class {
15583
15899
  }
15584
15900
  ]);
15585
15901
  } else if (this.#initConnectionQueries === void 0) {
15902
+ const clientSchema2 = this.#clientSchema;
15586
15903
  send(socket, [
15587
15904
  "initConnection",
15588
15905
  {
15589
15906
  desiredQueriesPatch: [...queriesPatch.values()],
15590
- deleted: skipEmptyDeletedClients(this.#deletedClients)
15907
+ deleted: skipEmptyDeletedClients(this.#deletedClients),
15908
+ // The clientSchema only needs to be sent for the very first request.
15909
+ // Henceforth it is stored with the CVR and verified automatically.
15910
+ ...this.#connectCookie === null ? { clientSchema: clientSchema2 } : {}
15591
15911
  }
15592
15912
  ]);
15593
15913
  this.#deletedClients = void 0;
@@ -15655,7 +15975,7 @@ var Zero = class {
15655
15975
  this.#connectCookie,
15656
15976
  this.clientID,
15657
15977
  await this.clientGroupID,
15658
- this.#options.schema.version,
15978
+ this.#clientSchema,
15659
15979
  this.userID,
15660
15980
  this.#rep.auth,
15661
15981
  this.#lastMutationIDReceived,
@@ -15751,7 +16071,6 @@ var Zero = class {
15751
16071
  );
15752
16072
  }
15753
16073
  #handlePokeStart(_lc, pokeMessage) {
15754
- resetBackoff();
15755
16074
  this.#abortPingTimeout();
15756
16075
  this.#pokeHandler.handlePokeStart(pokeMessage[1]);
15757
16076
  }
@@ -15836,8 +16155,6 @@ var Zero = class {
15836
16155
  clientGroupID: req.clientGroupID,
15837
16156
  mutations: [zeroM],
15838
16157
  pushVersion: req.pushVersion,
15839
- // Zero schema versions are always numbers.
15840
- schemaVersion: parseInt(req.schemaVersion),
15841
16158
  requestID
15842
16159
  }
15843
16160
  ];
@@ -16082,7 +16399,7 @@ var Zero = class {
16082
16399
  return this.#online;
16083
16400
  }
16084
16401
  /**
16085
- * Starts a a ping and waits for a pong.
16402
+ * Starts a ping and waits for a pong.
16086
16403
  *
16087
16404
  * If it takes too long to get a pong we disconnect and this returns
16088
16405
  * {@code PingResult.TimedOut}.
@@ -16130,14 +16447,13 @@ var Zero = class {
16130
16447
  return rv;
16131
16448
  }
16132
16449
  };
16133
- async function createSocket(rep, queryManager, deleteClientsManager, socketOrigin, baseCookie, clientID, clientGroupID, schemaVersion, userID, auth, lmid, wsid, debugPerf, lc, maxHeaderLength = 1024 * 8, additionalConnectParams) {
16450
+ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigin, baseCookie, clientID, clientGroupID, clientSchema2, userID, auth, lmid, wsid, debugPerf, lc, maxHeaderLength = 1024 * 8, additionalConnectParams) {
16134
16451
  const url = new URL(
16135
16452
  appendPath(socketOrigin, `/sync/v${PROTOCOL_VERSION}/connect`)
16136
16453
  );
16137
16454
  const { searchParams } = url;
16138
16455
  searchParams.set("clientID", clientID);
16139
16456
  searchParams.set("clientGroupID", clientGroupID);
16140
- searchParams.set("schemaVersion", schemaVersion.toString());
16141
16457
  searchParams.set("userID", userID);
16142
16458
  searchParams.set("baseCookie", baseCookie === null ? "" : String(baseCookie));
16143
16459
  searchParams.set("ts", String(performance.now()));
@@ -16165,7 +16481,10 @@ async function createSocket(rep, queryManager, deleteClientsManager, socketOrigi
16165
16481
  "initConnection",
16166
16482
  {
16167
16483
  desiredQueriesPatch: [...queriesPatch.values()],
16168
- deleted: skipEmptyDeletedClients(deletedClients)
16484
+ deleted: skipEmptyDeletedClients(deletedClients),
16485
+ // The clientSchema only needs to be sent for the very first request.
16486
+ // Henceforth it is stored with the CVR and verified automatically.
16487
+ ...baseCookie === null ? { clientSchema: clientSchema2 } : {}
16169
16488
  }
16170
16489
  ],
16171
16490
  auth
@@ -16240,6 +16559,7 @@ export {
16240
16559
  NOBODY_CAN,
16241
16560
  definePermissions,
16242
16561
  escapeLike,
16562
+ DEFAULT_TTL2 as DEFAULT_TTL,
16243
16563
  Zero
16244
16564
  };
16245
- //# sourceMappingURL=chunk-EENFDWT4.js.map
16565
+ //# sourceMappingURL=chunk-2TJNN7K4.js.map