@rocicorp/zero 1.11.0-canary.1 → 1.11.0-canary.3

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 (102) hide show
  1. package/out/replicache/src/btree/read.d.ts +12 -1
  2. package/out/replicache/src/btree/read.d.ts.map +1 -1
  3. package/out/replicache/src/btree/read.js +24 -12
  4. package/out/replicache/src/btree/read.js.map +1 -1
  5. package/out/replicache/src/db/write.js.map +1 -1
  6. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  7. package/out/replicache/src/replicache-impl.js +10 -0
  8. package/out/replicache/src/replicache-impl.js.map +1 -1
  9. package/out/replicache/src/transactions.d.ts.map +1 -1
  10. package/out/replicache/src/transactions.js +1 -1
  11. package/out/replicache/src/transactions.js.map +1 -1
  12. package/out/zero/package.js +1 -1
  13. package/out/zero/package.js.map +1 -1
  14. package/out/zero-cache/src/config/zero-config.d.ts +2 -0
  15. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  16. package/out/zero-cache/src/config/zero-config.js +12 -4
  17. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  18. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  19. package/out/zero-cache/src/server/replicator.js +1 -1
  20. package/out/zero-cache/src/server/replicator.js.map +1 -1
  21. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  22. package/out/zero-cache/src/services/change-source/common/replica-schema.js +2 -39
  23. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  24. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +2 -2
  25. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  26. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +2 -2
  27. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  28. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +6 -6
  29. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  30. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  31. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  32. package/out/zero-cache/src/services/litestream/commands.js +3 -1
  33. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  34. package/out/zero-cache/src/services/litestream/config-v5.yml +3 -4
  35. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  36. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  37. package/out/zero-cache/src/services/replicator/incremental-sync.js +22 -5
  38. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  39. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  40. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +4 -4
  41. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  42. package/out/zero-cache/src/services/replicator/write-worker-client.js +2 -2
  43. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  44. package/out/zero-cache/src/services/replicator/write-worker.js +10 -4
  45. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  46. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  47. package/out/zero-cache/src/services/view-syncer/view-syncer.js +75 -27
  48. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  49. package/out/zero-cache/src/types/streams.d.ts +6 -6
  50. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  51. package/out/zero-cache/src/types/streams.js +6 -11
  52. package/out/zero-cache/src/types/streams.js.map +1 -1
  53. package/out/zero-client/src/client/context.d.ts +15 -0
  54. package/out/zero-client/src/client/context.d.ts.map +1 -1
  55. package/out/zero-client/src/client/context.js +44 -0
  56. package/out/zero-client/src/client/context.js.map +1 -1
  57. package/out/zero-client/src/client/inspector/lazy-inspector.js +2 -2
  58. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  59. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  60. package/out/zero-client/src/client/version.js +1 -1
  61. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  62. package/out/zero-client/src/client/zero-rep.js +2 -1
  63. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  64. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  65. package/out/zero-client/src/client/zero.js +48 -11
  66. package/out/zero-client/src/client/zero.js.map +1 -1
  67. package/out/zero-protocol/src/down.d.ts +29 -29
  68. package/out/zero-protocol/src/inspect-down.d.ts +81 -81
  69. package/out/zero-protocol/src/poke.d.ts +6 -6
  70. package/out/zero-react/src/use-query.d.ts.map +1 -1
  71. package/out/zero-react/src/use-query.js +24 -5
  72. package/out/zero-react/src/use-query.js.map +1 -1
  73. package/out/zero-solid/src/use-query.js +4 -1
  74. package/out/zero-solid/src/use-query.js.map +1 -1
  75. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  76. package/out/zql/src/ivm/array-view.js +5 -3
  77. package/out/zql/src/ivm/array-view.js.map +1 -1
  78. package/out/zql/src/ivm/deferred-input.d.ts +44 -0
  79. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -0
  80. package/out/zql/src/ivm/deferred-input.js +88 -0
  81. package/out/zql/src/ivm/deferred-input.js.map +1 -0
  82. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  83. package/out/zql/src/ivm/memory-source.js +5 -10
  84. package/out/zql/src/ivm/memory-source.js.map +1 -1
  85. package/out/zql/src/query/query-delegate-base.d.ts +6 -0
  86. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  87. package/out/zql/src/query/query-delegate-base.js +73 -10
  88. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  89. package/out/zql/src/query/query-delegate.d.ts +22 -0
  90. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  91. package/out/zql/src/query/query-impl.d.ts +12 -11
  92. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  93. package/out/zql/src/query/query-impl.js +383 -60
  94. package/out/zql/src/query/query-impl.js.map +1 -1
  95. package/out/zql/src/query/query-transitions.d.ts +171 -0
  96. package/out/zql/src/query/query-transitions.d.ts.map +1 -0
  97. package/out/zql/src/query/query-transitions.js +207 -0
  98. package/out/zql/src/query/query-transitions.js.map +1 -0
  99. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  100. package/out/zql/src/query/runnable-query-impl.js +21 -1
  101. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  102. package/package.json +1 -1
@@ -90,7 +90,21 @@ var ViewSyncerService = class {
90
90
  #stopped = resolver();
91
91
  #initialized = resolver();
92
92
  #cvr;
93
- #pipelinesSynced = false;
93
+ /**
94
+ * Indicates whether the query pipelines have completed initial catch-up and
95
+ * hydration with the CVR snapshot, and are ready for steady-state operation.
96
+ *
97
+ * - When `false`: The syncer is in its initial catch-up phase. The replica
98
+ * advances without diffs until it reaches `cvr.version.stateVersion`,
99
+ * after which `#maybeHydratePipelines` hydrates queries.
100
+ * - When `true`: Pipelines are fully populated and in steady-state; replica
101
+ * changes advance incrementally via `#advancePipelines`, and client query
102
+ * updates are processed via `#syncQueryPipelineSet`.
103
+ *
104
+ * Resets to `false` if `#advancePipelines` returns a `ResetPipelinesSignal`
105
+ * and pipelines must be reset and rehydrated.
106
+ */
107
+ #pipelinesHydrated = false;
94
108
  #servedVersion = null;
95
109
  #e2eServingLagTracker = new E2EServingLagTracker();
96
110
  #expiredQueriesTimer = 0;
@@ -213,26 +227,18 @@ var ViewSyncerService = class {
213
227
  lc.info?.(`resetting CVR: ${message}`);
214
228
  throw new ClientNotFoundError(message);
215
229
  }
216
- if (this.#pipelinesSynced) {
230
+ if (this.#pipelinesHydrated) {
217
231
  const result = await this.#advancePipelines(lc, cvr);
218
232
  if (result === "success") return;
219
233
  lc.info?.(`resetting pipelines: ${result.message}`);
220
234
  this.#pipelineResets.add(1, { reason: result.reason });
221
235
  this.#pipelines.reset(clientSchema);
222
- this.#pipelinesSynced = false;
236
+ this.#pipelinesHydrated = false;
223
237
  this.connContextManager.setSharedRetransformReady(false);
224
238
  }
225
- const version = this.#pipelines.advanceWithoutDiff();
226
- const cvrVer = versionString(cvr.version);
227
- if (version < cvr.version.stateVersion) {
228
- lc.debug?.(`replica@${version} is behind cvr@${cvrVer}`);
229
- return;
230
- }
231
- lc.info?.(`init pipelines@${version} (cvr@${cvrVer})`);
232
- const driftedQueryIDs = await this.#hydrateUnchangedQueries(lc, cvr);
233
- await this.#syncQueryPipelineSet(lc, cvr, "missing", void 0, driftedQueryIDs);
234
- this.#pipelinesSynced = true;
235
- this.connContextManager.setSharedRetransformReady(true);
239
+ const backgroundConnCtx = this.connContextManager.getBackgroundConnectionContext();
240
+ if (backgroundConnCtx) await this.#maybeHydratePipelines(lc, cvr, backgroundConnCtx);
241
+ else lc.info?.("No validated background connection; deferring pipeline init");
236
242
  });
237
243
  }
238
244
  if (this.#drainCoordinator.shouldDrain()) this.#drainCoordinator.drainNextIn(this.#totalHydrationTimeMs());
@@ -246,11 +252,52 @@ var ViewSyncerService = class {
246
252
  this.#stopped.resolve();
247
253
  }
248
254
  }
255
+ /**
256
+ * Ensures that query pipelines are hydrated and ready for steady-state
257
+ * operation.
258
+ *
259
+ * Preconditions:
260
+ * 1. Must be called from within the `#lock`.
261
+ * 2. The caller must provide an active, validated `ConnectionContext` for
262
+ * evaluating custom query transforms and permissions.
263
+ *
264
+ * Readiness prerequisites:
265
+ * - The underlying `QueryPipelineDriver` must be initialized with the schema
266
+ * (i.e. `this.#pipelines.initialized()` is true).
267
+ * - The SQLite replica must have caught up to at least the CVR's
268
+ * `stateVersion` (`version >= cvr.version.stateVersion`).
269
+ *
270
+ * If either prerequisite is not met, this method returns early as a no-op,
271
+ * waiting for the replica to catch up or the driver to initialize.
272
+ *
273
+ * Once ready:
274
+ * - Hydrates unchanged queries from the CVR snapshot without full row diffing.
275
+ * - Syncs missing, errored, or drifted queries via `#syncQueryPipelineSet`.
276
+ * - Sets `#pipelinesHydrated = true` and enables shared retransformations.
277
+ */
278
+ async #maybeHydratePipelines(lc, cvr, connCtx) {
279
+ if (!this.#pipelines.initialized()) return;
280
+ const version = this.#pipelines.advanceWithoutDiff();
281
+ const cvrVer = versionString(cvr.version);
282
+ if (version < cvr.version.stateVersion) {
283
+ lc.debug?.(`replica@${version} is behind cvr@${cvrVer}`);
284
+ return;
285
+ }
286
+ lc.info?.(`init pipelines@${version} (cvr@${cvrVer})`);
287
+ const driftedQueryIDs = await this.#hydrateUnchangedQueries(lc, cvr, connCtx);
288
+ await this.#syncQueryPipelineSet(lc, cvr, "missing", connCtx, driftedQueryIDs);
289
+ this.#pipelinesHydrated = true;
290
+ this.connContextManager.setSharedRetransformReady(true);
291
+ }
249
292
  #removeExpiredQueries = async (lc, cvr) => {
250
293
  if (hasExpiredQueries(cvr)) {
251
294
  lc = lc.withContext("method", "#removeExpiredQueries");
252
295
  lc.debug?.("Queries have expired");
253
- if (this.#pipelinesSynced) await this.#syncQueryPipelineSet(lc, cvr, "missing", void 0);
296
+ if (this.#pipelinesHydrated) {
297
+ const connCtx = this.connContextManager.getBackgroundConnectionContext();
298
+ if (connCtx) await this.#syncQueryPipelineSet(lc, cvr, "missing", connCtx);
299
+ else lc.info?.("No validated background connection to remove expired queries; deferring");
300
+ }
254
301
  }
255
302
  this.#scheduleExpireEviction(lc, cvr);
256
303
  };
@@ -466,7 +513,7 @@ var ViewSyncerService = class {
466
513
  }
467
514
  lc.debug?.("Auth changed, re-validating and re-transforming queries");
468
515
  const connCtx = this.connContextManager.mustGetConnectionContext(selector);
469
- if (!this.#pipelinesSynced) {
516
+ if (!this.#pipelinesHydrated) {
470
517
  if (!await this.#validateConnection(connCtx)) return;
471
518
  }
472
519
  return await this.#handleConfigUpdate(lc, clientID, {}, cvr, "all", void 0, connCtx);
@@ -528,7 +575,8 @@ var ViewSyncerService = class {
528
575
  await pokers.end(newCVR.version);
529
576
  });
530
577
  }
531
- if (this.#pipelinesSynced) await this.#syncQueryPipelineSet(lc, this.#cvr, customQueryTransformMode, connCtx);
578
+ if (!this.#pipelinesHydrated) await this.#maybeHydratePipelines(lc, this.#cvr, connCtx);
579
+ else await this.#syncQueryPipelineSet(lc, this.#cvr, customQueryTransformMode, connCtx);
532
580
  return this.#cvr;
533
581
  }
534
582
  /**
@@ -651,7 +699,7 @@ var ViewSyncerService = class {
651
699
  *
652
700
  * This must be called from within the #lock.
653
701
  */
654
- async #hydrateUnchangedQueries(lc, cvr) {
702
+ async #hydrateUnchangedQueries(lc, cvr, connCtx) {
655
703
  assert(this.#pipelines.initialized(), "pipelines must be initialized");
656
704
  const dbVersion = this.#pipelines.currentVersion();
657
705
  const cvrVersion = cvr.version;
@@ -676,17 +724,16 @@ var ViewSyncerService = class {
676
724
  let customHashMismatchCount = 0;
677
725
  let otherHashMismatchCount = 0;
678
726
  if (customQueries.size > 0 && !this.#customQueryTransformer) lc.warn?.("Custom/named queries were requested but no `ZERO_QUERY_URL` is configured for Zero Cache.");
679
- const backgroundContext = this.connContextManager.mustGetBackgroundConnectionContext();
680
727
  const customQueryTransformer = this.#customQueryTransformer;
681
728
  if (customQueryTransformer && customQueries.size > 0) {
682
- const transformedCustomQueries = await this.#runPriorityOp(lc, "#hydrateUnchangedQueries transforming custom queries", () => customQueryTransformer.transform(backgroundContext, customQueries.values()));
683
- if (transformedCustomQueries.kind === "success" && !transformedCustomQueries.cached) this.connContextManager.validateConnection(backgroundContext, backgroundContext.revision, transformedCustomQueries.validation);
729
+ const transformedCustomQueries = await this.#runPriorityOp(lc, "#hydrateUnchangedQueries transforming custom queries", () => customQueryTransformer.transform(connCtx, customQueries.values()));
730
+ if (transformedCustomQueries.kind === "success" && !transformedCustomQueries.cached) this.connContextManager.validateConnection(connCtx, connCtx.revision, transformedCustomQueries.validation);
684
731
  if (Array.isArray(transformedCustomQueries.result)) for (const q of transformedCustomQueries.result) if ("error" in q) customErrorCount++;
685
732
  else if (q.transformationHash !== customQueries.get(q.id)?.transformationHash) customHashMismatchCount++;
686
733
  else transformedQueries.push(q);
687
734
  }
688
735
  for (const q of otherQueries) {
689
- const transformed = transformAndHashQuery(lc, q.id, q.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, backgroundContext.auth?.type === "jwt" ? backgroundContext.auth : void 0, q.type === "internal");
736
+ const transformed = transformAndHashQuery(lc, q.id, q.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, connCtx.auth?.type === "jwt" ? connCtx.auth : void 0, q.type === "internal");
690
737
  if (transformed.transformationHash === q.transformationHash) transformedQueries.push(transformed);
691
738
  else otherHashMismatchCount++;
692
739
  }
@@ -832,7 +879,6 @@ var ViewSyncerService = class {
832
879
  const customQueries = /* @__PURE__ */ new Map();
833
880
  const otherQueries = [];
834
881
  const transformedQueries = [];
835
- const resolvedConnCtx = connCtx ?? this.connContextManager.mustGetBackgroundConnectionContext();
836
882
  for (const [id, query] of cvrQueryEntires) if (query.type === "custom") {
837
883
  assert(id === query.id, "custom query id mismatch");
838
884
  customQueries.set(id, query);
@@ -842,7 +888,7 @@ var ViewSyncerService = class {
842
888
  });
843
889
  for (const { id, query: origQuery } of otherQueries) {
844
890
  assert(id === origQuery.id, "query id mismatch");
845
- const transformed = transformAndHashQuery(lc, origQuery.id, origQuery.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, resolvedConnCtx.auth?.type === "jwt" ? resolvedConnCtx.auth : void 0, origQuery.type === "internal");
891
+ const transformed = transformAndHashQuery(lc, origQuery.id, origQuery.ast, must(this.#pipelines.currentPermissions()).permissions ?? { tables: {} }, connCtx.auth?.type === "jwt" ? connCtx.auth : void 0, origQuery.type === "internal");
846
892
  transformedQueries.push({
847
893
  id,
848
894
  origQuery,
@@ -857,10 +903,10 @@ var ViewSyncerService = class {
857
903
  const transformStart = performance.now();
858
904
  let transformedCustomQueries;
859
905
  try {
860
- transformedCustomQueries = await this.#runPriorityOp(lc, "#syncQueryPipelineSet transforming custom queries", () => customQueryTransformer.transform(resolvedConnCtx, customQueriesToTransform));
906
+ transformedCustomQueries = await this.#runPriorityOp(lc, "#syncQueryPipelineSet transforming custom queries", () => customQueryTransformer.transform(connCtx, customQueriesToTransform));
861
907
  if (transformedCustomQueries.kind === "failed") throw new ProtocolErrorWithLevel(transformedCustomQueries.result, "warn");
862
908
  else {
863
- if (!transformedCustomQueries.cached) this.connContextManager.validateConnection(resolvedConnCtx, resolvedConnCtx.revision, transformedCustomQueries.validation);
909
+ if (!transformedCustomQueries.cached) this.connContextManager.validateConnection(connCtx, connCtx.revision, transformedCustomQueries.validation);
864
910
  this.#queryTransformations.add(1, { result: "success" });
865
911
  }
866
912
  } catch (e) {
@@ -1156,7 +1202,9 @@ var ViewSyncerService = class {
1156
1202
  *
1157
1203
  * Must be called from within the #lock.
1158
1204
  *
1159
- * Returns false if the advancement failed due to a schema change.
1205
+ * Returns 'success' if changes were successfully processed and poked,
1206
+ * or a `ResetPipelinesSignal` if advancement aborted (e.g. schema change,
1207
+ * timeout) and pipelines need to be reset and rehydrated.
1160
1208
  */
1161
1209
  #advancePipelines(lc, cvr) {
1162
1210
  return startAsyncSpan(tracer, "vs.#advancePipelines", async (span) => {