@rocicorp/zero 1.5.0-canary.4 → 1.6.0-canary.0

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 (172) hide show
  1. package/out/analyze-query/src/analyze-cli.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  3. package/out/replicache/src/btree/node.d.ts +3 -0
  4. package/out/replicache/src/btree/node.d.ts.map +1 -1
  5. package/out/replicache/src/btree/node.js +114 -1
  6. package/out/replicache/src/btree/node.js.map +1 -1
  7. package/out/replicache/src/btree/write.d.ts +7 -0
  8. package/out/replicache/src/btree/write.d.ts.map +1 -1
  9. package/out/replicache/src/btree/write.js +50 -0
  10. package/out/replicache/src/btree/write.js.map +1 -1
  11. package/out/replicache/src/db/write.d.ts +8 -0
  12. package/out/replicache/src/db/write.d.ts.map +1 -1
  13. package/out/replicache/src/db/write.js +15 -0
  14. package/out/replicache/src/db/write.js.map +1 -1
  15. package/out/replicache/src/kv/sqlite-store.d.ts +2 -5
  16. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  17. package/out/replicache/src/kv/sqlite-store.js +21 -24
  18. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  19. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  20. package/out/replicache/src/replicache-impl.js.map +1 -1
  21. package/out/replicache/src/sync/patch.d.ts +15 -0
  22. package/out/replicache/src/sync/patch.d.ts.map +1 -1
  23. package/out/replicache/src/sync/patch.js +85 -26
  24. package/out/replicache/src/sync/patch.js.map +1 -1
  25. package/out/shared/src/testing.d.ts +3 -0
  26. package/out/shared/src/testing.d.ts.map +1 -0
  27. package/out/zero/package.js +5 -6
  28. package/out/zero/package.js.map +1 -1
  29. package/out/zero-cache/src/auth/write-authorizer.js +1 -1
  30. package/out/zero-cache/src/config/zero-config.d.ts +4 -0
  31. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  32. package/out/zero-cache/src/config/zero-config.js +8 -0
  33. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  34. package/out/zero-cache/src/server/inspector-delegate.d.ts +3 -2
  35. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  36. package/out/zero-cache/src/server/inspector-delegate.js +19 -9
  37. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  38. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  39. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  40. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  41. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +7 -6
  42. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  43. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  44. package/out/zero-cache/src/services/change-source/pg/change-source.js +49 -66
  45. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  46. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +0 -8
  47. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  48. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +22 -52
  49. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  50. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +57 -0
  51. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -0
  52. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +162 -0
  53. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -0
  54. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  55. package/out/zero-cache/src/services/change-source/pg/schema/init.js +18 -0
  56. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  57. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +17 -3
  58. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  59. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +43 -16
  60. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  61. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +2 -3
  62. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  63. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +5 -5
  64. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  65. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +10 -1
  66. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  67. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +13 -3
  68. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  69. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +6 -11
  70. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  71. package/out/zero-cache/src/services/change-streamer/change-streamer.js +0 -1
  72. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  73. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  74. package/out/zero-cache/src/services/change-streamer/forwarder.js +2 -2
  75. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  76. package/out/zero-cache/src/services/change-streamer/storer.d.ts +12 -5
  77. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  78. package/out/zero-cache/src/services/change-streamer/storer.js +43 -21
  79. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  80. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +4 -5
  81. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  82. package/out/zero-cache/src/services/change-streamer/subscriber.js +18 -16
  83. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  84. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  85. package/out/zero-cache/src/services/litestream/commands.js +3 -2
  86. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  87. package/out/zero-cache/src/services/litestream/config.yml +1 -0
  88. package/out/zero-cache/src/services/mutagen/pusher.d.ts +2 -2
  89. package/out/zero-cache/src/services/view-syncer/cvr-store.js +2 -2
  90. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  91. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +1 -1
  92. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  93. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  94. package/out/zero-cache/src/services/view-syncer/view-syncer.js +5 -6
  95. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  96. package/out/zero-cache/src/types/streams.d.ts +4 -0
  97. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  98. package/out/zero-cache/src/types/streams.js +13 -10
  99. package/out/zero-cache/src/types/streams.js.map +1 -1
  100. package/out/zero-cache/src/workers/connection.js +5 -5
  101. package/out/zero-cache/src/workers/connection.js.map +1 -1
  102. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  103. package/out/zero-client/src/client/inspector/inspector.js +15 -2
  104. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  105. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +9 -3
  106. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  107. package/out/zero-client/src/client/inspector/lazy-inspector.js +27 -6
  108. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  109. package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
  110. package/out/zero-client/src/client/inspector/query.js +3 -3
  111. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  112. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  113. package/out/zero-client/src/client/ivm-branch.js +16 -2
  114. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  115. package/out/zero-client/src/client/options.d.ts +12 -4
  116. package/out/zero-client/src/client/options.d.ts.map +1 -1
  117. package/out/zero-client/src/client/options.js.map +1 -1
  118. package/out/zero-client/src/client/query-manager.d.ts +8 -1
  119. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  120. package/out/zero-client/src/client/query-manager.js +28 -3
  121. package/out/zero-client/src/client/query-manager.js.map +1 -1
  122. package/out/zero-client/src/client/version.js +1 -1
  123. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  124. package/out/zero-client/src/client/zero.js +12 -11
  125. package/out/zero-client/src/client/zero.js.map +1 -1
  126. package/out/zero-protocol/src/down.d.ts +1 -1
  127. package/out/zero-protocol/src/inspect-down.d.ts +15 -4
  128. package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
  129. package/out/zero-protocol/src/inspect-down.js +11 -1
  130. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  131. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  132. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  133. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  134. package/out/zero-react/src/use-query.d.ts.map +1 -1
  135. package/out/zero-react/src/use-query.js.map +1 -1
  136. package/out/zero-react/src/zero-provider.d.ts +6 -0
  137. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  138. package/out/zero-react/src/zero-provider.js +21 -1
  139. package/out/zero-react/src/zero-provider.js.map +1 -1
  140. package/out/zero-solid/src/use-zero.d.ts +6 -0
  141. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  142. package/out/zero-solid/src/use-zero.js +24 -4
  143. package/out/zero-solid/src/use-zero.js.map +1 -1
  144. package/out/zql/src/builder/builder.d.ts.map +1 -1
  145. package/out/zql/src/builder/builder.js +18 -8
  146. package/out/zql/src/builder/builder.js.map +1 -1
  147. package/out/zql/src/ivm/cap.d.ts +32 -0
  148. package/out/zql/src/ivm/cap.d.ts.map +1 -0
  149. package/out/zql/src/ivm/cap.js +205 -0
  150. package/out/zql/src/ivm/cap.js.map +1 -0
  151. package/out/zql/src/ivm/constraint.d.ts.map +1 -1
  152. package/out/zql/src/ivm/constraint.js.map +1 -1
  153. package/out/zql/src/ivm/flipped-join.d.ts +9 -0
  154. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  155. package/out/zql/src/ivm/flipped-join.js +56 -69
  156. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  157. package/out/zql/src/ivm/memory-source.d.ts +24 -3
  158. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  159. package/out/zql/src/ivm/memory-source.js +162 -7
  160. package/out/zql/src/ivm/memory-source.js.map +1 -1
  161. package/out/zql/src/ivm/operator.d.ts +26 -0
  162. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  163. package/out/zql/src/ivm/operator.js.map +1 -1
  164. package/out/zql/src/ivm/take.js +2 -2
  165. package/out/zqlite/src/query-builder.d.ts +14 -2
  166. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  167. package/out/zqlite/src/query-builder.js +32 -1
  168. package/out/zqlite/src/query-builder.js.map +1 -1
  169. package/out/zqlite/src/table-source.d.ts.map +1 -1
  170. package/out/zqlite/src/table-source.js +4 -4
  171. package/out/zqlite/src/table-source.js.map +1 -1
  172. package/package.json +5 -6
@@ -4,6 +4,17 @@ declare const serverMetricsSchema: v.ObjectType<{
4
4
  'query-update-server': v.VariadicTupleType<[v.Type<number>], v.Type<number>, []>;
5
5
  }, undefined>;
6
6
  export type ServerMetrics = v.Infer<typeof serverMetricsSchema>;
7
+ /**
8
+ * Per-query server metrics sent with each query row in the inspector protocol.
9
+ * `query-hydration-server-ms` is a plain number (milliseconds) since each
10
+ * query is typically hydrated only once. `query-update-server` is a TDigest
11
+ * histogram since queries receive many incremental updates.
12
+ */
13
+ declare const queryServerMetricsSchema: v.ObjectType<{
14
+ 'query-hydration-server-ms': v.Optional<number>;
15
+ 'query-update-server': v.VariadicTupleType<[v.Type<number>], v.Type<number>, []>;
16
+ }, undefined>;
17
+ export type QueryServerMetrics = v.Infer<typeof queryServerMetricsSchema>;
7
18
  declare const inspectQueryRowSchema: v.ObjectType<{
8
19
  clientID: v.Type<string>;
9
20
  queryID: v.Type<string>;
@@ -16,7 +27,7 @@ declare const inspectQueryRowSchema: v.ObjectType<{
16
27
  inactivatedAt: v.Type<number | null>;
17
28
  rowCount: v.Type<number>;
18
29
  metrics: v.Optional<{
19
- 'query-materialization-server': [number, ...number[]];
30
+ 'query-hydration-server-ms'?: number | undefined;
20
31
  'query-update-server': [number, ...number[]];
21
32
  } | null>;
22
33
  }, undefined>;
@@ -37,7 +48,7 @@ export declare const inspectQueriesDownSchema: v.ObjectType<Omit<{
37
48
  inactivatedAt: v.Type<number | null>;
38
49
  rowCount: v.Type<number>;
39
50
  metrics: v.Optional<{
40
- 'query-materialization-server': [number, ...number[]];
51
+ 'query-hydration-server-ms'?: number | undefined;
41
52
  'query-update-server': [number, ...number[]];
42
53
  } | null>;
43
54
  }, undefined>>;
@@ -210,7 +221,7 @@ export declare const inspectDownBodySchema: v.UnionType<[v.ObjectType<Omit<{
210
221
  inactivatedAt: v.Type<number | null>;
211
222
  rowCount: v.Type<number>;
212
223
  metrics: v.Optional<{
213
- 'query-materialization-server': [number, ...number[]];
224
+ 'query-hydration-server-ms'?: number | undefined;
214
225
  'query-update-server': [number, ...number[]];
215
226
  } | null>;
216
227
  }, undefined>>;
@@ -373,7 +384,7 @@ export declare const inspectDownMessageSchema: v.TupleType<[v.Type<"inspect">, v
373
384
  inactivatedAt: v.Type<number | null>;
374
385
  rowCount: v.Type<number>;
375
386
  metrics: v.Optional<{
376
- 'query-materialization-server': [number, ...number[]];
387
+ 'query-hydration-server-ms'?: number | undefined;
377
388
  'query-update-server': [number, ...number[]];
378
389
  } | null>;
379
390
  }, undefined>>;
@@ -1 +1 @@
1
- {"version":3,"file":"inspect-down.d.ts","sourceRoot":"","sources":["../../../../zero-protocol/src/inspect-down.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,CAAC,MAAM,4BAA4B,CAAC;AAIhD,QAAA,MAAM,mBAAmB;;;aAGvB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;aAgBzB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMpE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;aAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;;;;aAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;aAGnC,CAAC;AAEH,eAAO,MAAM,8BAA8B;;;;;aAGzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC;AAEF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAGxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;aAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAOjC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"inspect-down.d.ts","sourceRoot":"","sources":["../../../../zero-protocol/src/inspect-down.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,CAAC,MAAM,4BAA4B,CAAC;AAIhD,QAAA,MAAM,mBAAmB;;;aAGvB,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;;GAKG;AACH,QAAA,MAAM,wBAAwB;;;aAG5B,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;aAgBzB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAMpE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;aAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;;;;aAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,wBAAwB;;;;;aAGnC,CAAC;AAEH,eAAO,MAAM,8BAA8B;;;;;aAGzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAC5C,OAAO,8BAA8B,CACtC,CAAC;AAEF,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAGxC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAC3C,OAAO,6BAA6B,CACrC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;aAGjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAOjC,CAAC;AAEF,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGnC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -8,6 +8,16 @@ var serverMetricsSchema = valita_exports.object({
8
8
  "query-materialization-server": tdigestSchema,
9
9
  "query-update-server": tdigestSchema
10
10
  });
11
+ /**
12
+ * Per-query server metrics sent with each query row in the inspector protocol.
13
+ * `query-hydration-server-ms` is a plain number (milliseconds) since each
14
+ * query is typically hydrated only once. `query-update-server` is a TDigest
15
+ * histogram since queries receive many incremental updates.
16
+ */
17
+ var queryServerMetricsSchema = valita_exports.object({
18
+ "query-hydration-server-ms": valita_exports.number().optional(),
19
+ "query-update-server": tdigestSchema
20
+ });
11
21
  var inspectQueryRowSchema = valita_exports.object({
12
22
  clientID: valita_exports.string(),
13
23
  queryID: valita_exports.string(),
@@ -19,7 +29,7 @@ var inspectQueryRowSchema = valita_exports.object({
19
29
  ttl: valita_exports.number(),
20
30
  inactivatedAt: valita_exports.number().nullable(),
21
31
  rowCount: valita_exports.number(),
22
- metrics: serverMetricsSchema.nullable().optional()
32
+ metrics: queryServerMetricsSchema.nullable().optional()
23
33
  });
24
34
  var inspectBaseDownSchema = valita_exports.object({ id: valita_exports.string() });
25
35
  var inspectQueriesDownSchema = inspectBaseDownSchema.extend({
@@ -1 +1 @@
1
- {"version":3,"file":"inspect-down.js","names":[],"sources":["../../../../zero-protocol/src/inspect-down.ts"],"sourcesContent":["import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport {tdigestSchema} from '../../shared/src/tdigest-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {analyzeQueryResultSchema} from './analyze-query-result.ts';\nimport {astSchema} from './ast.ts';\n\nconst serverMetricsSchema = v.object({\n 'query-materialization-server': tdigestSchema,\n 'query-update-server': tdigestSchema,\n});\n\nexport type ServerMetrics = v.Infer<typeof serverMetricsSchema>;\n\nconst inspectQueryRowSchema = v.object({\n clientID: v.string(),\n queryID: v.string(),\n // This is the server return AST for custom queries\n // TODO: Return server generated AST\n ast: astSchema.nullable(),\n // not null for custom queries\n name: v.string().nullable(),\n // not null for custom queries\n args: v.readonlyArray(jsonSchema).nullable(),\n got: v.boolean(),\n deleted: v.boolean(),\n ttl: v.number(),\n inactivatedAt: v.number().nullable(),\n rowCount: v.number(),\n metrics: serverMetricsSchema.nullable().optional(),\n});\n\nexport type InspectQueryRow = v.Infer<typeof inspectQueryRowSchema>;\n\nconst inspectBaseDownSchema = v.object({\n id: v.string(),\n});\n\nexport const inspectQueriesDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('queries'),\n value: v.array(inspectQueryRowSchema),\n});\n\nexport type InspectQueriesDown = v.Infer<typeof inspectQueriesDownSchema>;\n\nexport const inspectMetricsDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('metrics'),\n value: serverMetricsSchema,\n});\n\nexport type InspectMetricsDown = v.Infer<typeof inspectMetricsDownSchema>;\n\nexport const inspectVersionDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('version'),\n value: v.string(),\n});\n\nexport const inspectAuthenticatedDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('authenticated'),\n value: v.boolean(),\n});\n\nexport type InspectAuthenticatedDown = v.Infer<\n typeof inspectAuthenticatedDownSchema\n>;\n\nexport const inspectAnalyzeQueryDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('analyze-query'),\n value: analyzeQueryResultSchema,\n});\n\nexport type InspectAnalyzeQueryDown = v.Infer<\n typeof inspectAnalyzeQueryDownSchema\n>;\n\nexport const inspectErrorDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('error'),\n value: v.string(),\n});\n\nexport type InspectErrorDown = v.Infer<typeof inspectErrorDownSchema>;\n\nexport const inspectDownBodySchema = v.union(\n inspectQueriesDownSchema,\n inspectMetricsDownSchema,\n inspectVersionDownSchema,\n inspectAuthenticatedDownSchema,\n inspectAnalyzeQueryDownSchema,\n inspectErrorDownSchema,\n);\n\nexport const inspectDownMessageSchema = v.tuple([\n v.literal('inspect'),\n inspectDownBodySchema,\n]);\n\nexport type InspectDownMessage = v.Infer<typeof inspectDownMessageSchema>;\n\nexport type InspectDownBody = v.Infer<typeof inspectDownBodySchema>;\n"],"mappings":";;;;;;AAMA,IAAM,sBAAsB,eAAE,OAAO;CACnC,gCAAgC;CAChC,uBAAuB;CACxB,CAAC;AAIF,IAAM,wBAAwB,eAAE,OAAO;CACrC,UAAU,eAAE,QAAQ;CACpB,SAAS,eAAE,QAAQ;CAGnB,KAAK,UAAU,UAAU;CAEzB,MAAM,eAAE,QAAQ,CAAC,UAAU;CAE3B,MAAM,cAAgB,WAAW,CAAC,UAAU;CAC5C,KAAK,eAAE,SAAS;CAChB,SAAS,eAAE,SAAS;CACpB,KAAK,eAAE,QAAQ;CACf,eAAe,eAAE,QAAQ,CAAC,UAAU;CACpC,UAAU,eAAE,QAAQ;CACpB,SAAS,oBAAoB,UAAU,CAAC,UAAU;CACnD,CAAC;AAIF,IAAM,wBAAwB,eAAE,OAAO,EACrC,IAAI,eAAE,QAAQ,EACf,CAAC;AAEF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO,eAAE,MAAM,sBAAsB;CACtC,CAAC;AAIF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO;CACR,CAAC;AAIF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO,eAAE,QAAQ;CAClB,CAAC;AAEF,IAAa,iCAAiC,sBAAsB,OAAO;CACzE,IAAI,eAAE,QAAQ,gBAAgB;CAC9B,OAAO,eAAE,SAAS;CACnB,CAAC;AAMF,IAAa,gCAAgC,sBAAsB,OAAO;CACxE,IAAI,eAAE,QAAQ,gBAAgB;CAC9B,OAAO;CACR,CAAC;AAMF,IAAa,yBAAyB,sBAAsB,OAAO;CACjE,IAAI,eAAE,QAAQ,QAAQ;CACtB,OAAO,eAAE,QAAQ;CAClB,CAAC;AAIF,IAAa,wBAAwB,eAAE,MACrC,0BACA,0BACA,0BACA,gCACA,+BACA,uBACD;AAED,IAAa,2BAA2B,eAAE,MAAM,CAC9C,eAAE,QAAQ,UAAU,EACpB,sBACD,CAAC"}
1
+ {"version":3,"file":"inspect-down.js","names":[],"sources":["../../../../zero-protocol/src/inspect-down.ts"],"sourcesContent":["import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport {tdigestSchema} from '../../shared/src/tdigest-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {analyzeQueryResultSchema} from './analyze-query-result.ts';\nimport {astSchema} from './ast.ts';\n\nconst serverMetricsSchema = v.object({\n 'query-materialization-server': tdigestSchema,\n 'query-update-server': tdigestSchema,\n});\n\nexport type ServerMetrics = v.Infer<typeof serverMetricsSchema>;\n\n/**\n * Per-query server metrics sent with each query row in the inspector protocol.\n * `query-hydration-server-ms` is a plain number (milliseconds) since each\n * query is typically hydrated only once. `query-update-server` is a TDigest\n * histogram since queries receive many incremental updates.\n */\nconst queryServerMetricsSchema = v.object({\n 'query-hydration-server-ms': v.number().optional(),\n 'query-update-server': tdigestSchema,\n});\n\nexport type QueryServerMetrics = v.Infer<typeof queryServerMetricsSchema>;\n\nconst inspectQueryRowSchema = v.object({\n clientID: v.string(),\n queryID: v.string(),\n // This is the server return AST for custom queries\n // TODO: Return server generated AST\n ast: astSchema.nullable(),\n // not null for custom queries\n name: v.string().nullable(),\n // not null for custom queries\n args: v.readonlyArray(jsonSchema).nullable(),\n got: v.boolean(),\n deleted: v.boolean(),\n ttl: v.number(),\n inactivatedAt: v.number().nullable(),\n rowCount: v.number(),\n metrics: queryServerMetricsSchema.nullable().optional(),\n});\n\nexport type InspectQueryRow = v.Infer<typeof inspectQueryRowSchema>;\n\nconst inspectBaseDownSchema = v.object({\n id: v.string(),\n});\n\nexport const inspectQueriesDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('queries'),\n value: v.array(inspectQueryRowSchema),\n});\n\nexport type InspectQueriesDown = v.Infer<typeof inspectQueriesDownSchema>;\n\nexport const inspectMetricsDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('metrics'),\n value: serverMetricsSchema,\n});\n\nexport type InspectMetricsDown = v.Infer<typeof inspectMetricsDownSchema>;\n\nexport const inspectVersionDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('version'),\n value: v.string(),\n});\n\nexport const inspectAuthenticatedDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('authenticated'),\n value: v.boolean(),\n});\n\nexport type InspectAuthenticatedDown = v.Infer<\n typeof inspectAuthenticatedDownSchema\n>;\n\nexport const inspectAnalyzeQueryDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('analyze-query'),\n value: analyzeQueryResultSchema,\n});\n\nexport type InspectAnalyzeQueryDown = v.Infer<\n typeof inspectAnalyzeQueryDownSchema\n>;\n\nexport const inspectErrorDownSchema = inspectBaseDownSchema.extend({\n op: v.literal('error'),\n value: v.string(),\n});\n\nexport type InspectErrorDown = v.Infer<typeof inspectErrorDownSchema>;\n\nexport const inspectDownBodySchema = v.union(\n inspectQueriesDownSchema,\n inspectMetricsDownSchema,\n inspectVersionDownSchema,\n inspectAuthenticatedDownSchema,\n inspectAnalyzeQueryDownSchema,\n inspectErrorDownSchema,\n);\n\nexport const inspectDownMessageSchema = v.tuple([\n v.literal('inspect'),\n inspectDownBodySchema,\n]);\n\nexport type InspectDownMessage = v.Infer<typeof inspectDownMessageSchema>;\n\nexport type InspectDownBody = v.Infer<typeof inspectDownBodySchema>;\n"],"mappings":";;;;;;AAMA,IAAM,sBAAsB,eAAE,OAAO;CACnC,gCAAgC;CAChC,uBAAuB;CACxB,CAAC;;;;;;;AAUF,IAAM,2BAA2B,eAAE,OAAO;CACxC,6BAA6B,eAAE,QAAQ,CAAC,UAAU;CAClD,uBAAuB;CACxB,CAAC;AAIF,IAAM,wBAAwB,eAAE,OAAO;CACrC,UAAU,eAAE,QAAQ;CACpB,SAAS,eAAE,QAAQ;CAGnB,KAAK,UAAU,UAAU;CAEzB,MAAM,eAAE,QAAQ,CAAC,UAAU;CAE3B,MAAM,cAAgB,WAAW,CAAC,UAAU;CAC5C,KAAK,eAAE,SAAS;CAChB,SAAS,eAAE,SAAS;CACpB,KAAK,eAAE,QAAQ;CACf,eAAe,eAAE,QAAQ,CAAC,UAAU;CACpC,UAAU,eAAE,QAAQ;CACpB,SAAS,yBAAyB,UAAU,CAAC,UAAU;CACxD,CAAC;AAIF,IAAM,wBAAwB,eAAE,OAAO,EACrC,IAAI,eAAE,QAAQ,EACf,CAAC;AAEF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO,eAAE,MAAM,sBAAsB;CACtC,CAAC;AAIF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO;CACR,CAAC;AAIF,IAAa,2BAA2B,sBAAsB,OAAO;CACnE,IAAI,eAAE,QAAQ,UAAU;CACxB,OAAO,eAAE,QAAQ;CAClB,CAAC;AAEF,IAAa,iCAAiC,sBAAsB,OAAO;CACzE,IAAI,eAAE,QAAQ,gBAAgB;CAC9B,OAAO,eAAE,SAAS;CACnB,CAAC;AAMF,IAAa,gCAAgC,sBAAsB,OAAO;CACxE,IAAI,eAAE,QAAQ,gBAAgB;CAC9B,OAAO;CACR,CAAC;AAMF,IAAa,yBAAyB,sBAAsB,OAAO;CACjE,IAAI,eAAE,QAAQ,QAAQ;CACtB,OAAO,eAAE,QAAQ;CAClB,CAAC;AAIF,IAAa,wBAAwB,eAAE,MACrC,0BACA,0BACA,0BACA,gCACA,+BACA,uBACD;AAED,IAAa,2BAA2B,eAAE,MAAM,CAC9C,eAAE,QAAQ,UAAU,EACpB,sBACD,CAAC"}
@@ -10,7 +10,7 @@
10
10
  * release. The server (`zero-cache`) must be deployed before clients start
11
11
  * running the new code.
12
12
  */
13
- export declare const PROTOCOL_VERSION = 50;
13
+ export declare const PROTOCOL_VERSION = 51;
14
14
  /**
15
15
  * The minimum server-supported sync protocol version (i.e. the version
16
16
  * declared in the "/sync/v{#}/connect" URL). The contract for
@@ -1 +1 @@
1
- {"version":3,"file":"protocol-version.d.ts","sourceRoot":"","sources":["../../../../zero-protocol/src/protocol-version.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AA6CH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;;;;GASG;AACH,eAAO,MAAM,kCAAkC,KAAK,CAAC"}
1
+ {"version":3,"file":"protocol-version.d.ts","sourceRoot":"","sources":["../../../../zero-protocol/src/protocol-version.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AA8CH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;;;;GASG;AACH,eAAO,MAAM,kCAAkC,KAAK,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol-version.js","names":[],"sources":["../../../../zero-protocol/src/protocol-version.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\n\n/**\n * The current `PROTOCOL_VERSION` of the code.\n *\n * The `PROTOCOL_VERSION` encompasses both the wire-protocol of the `/sync/...`\n * connection between the browser and `zero-cache`, as well as the format of\n * the `AST` objects stored in both components (i.e. IDB and CVR).\n *\n * A change in the `AST` schema (e.g. new functionality added) must be\n * accompanied by an increment of the `PROTOCOL_VERSION` and a new major\n * release. The server (`zero-cache`) must be deployed before clients start\n * running the new code.\n */\n// History:\n// -- Version 5 adds support for `pokeEnd.cookie`. (0.14)\n// -- Version 6 makes `pokeStart.cookie` optional. (0.16)\n// -- Version 7 introduces the initConnection.clientSchema field. (0.17)\n// -- Version 8 drops support for Version 5 (0.18).\n// -- Version 11 adds inspect queries. (0.18)\n// -- Version 12 adds 'timestamp' and 'date' types to the ClientSchema ValueType. (not shipped, reversed by version 14)\n// -- Version 14 removes 'timestamp' and 'date' types from the ClientSchema ValueType. (0.18)\n// -- Version 15 adds a `userPushParams` field to `initConnection` (0.19)\n// -- Version 16 adds a new error type (alreadyProcessed) to mutation responses (0.19)\n// -- Version 17 deprecates `AST` in downstream query puts. It was never used anyway. (0.21)\n// -- Version 18 adds `name` and `args` to the `queries-patch` protocol (0.21)\n// -- Version 19 adds `activeClients` to the `initConnection` protocol (0.22)\n// -- Version 20 changes inspector down message (0.22)\n// -- Version 21 removes `AST` in downstream query puts which was deprecated in Version 17, removes support for versions < 18 (0.22)\n// -- Version 22 adds an optional 'userQueryParams' field to `initConnection` (0.22)\n// -- Version 23 add `mutationResults` to poke (0.22)\n// -- Version 24 adds `ackMutationResults` to upstream (0.22).\n// -- version 25 modifies `mutationsResults` to include `del` patches (0.22)\n// -- version 26 adds inspect/metrics and adds metrics to inspect/query (0.23)\n// -- version 27 adds inspect/version (0.23)\n// -- version 28 adds more inspect/metrics (0.23)\n// -- version 29 adds error responses for custom queries (0.23)\n// -- version 30 adds an optional primaryKey to the ClientSchema (0.24)\n// -- version 31 adds admin password authentication to inspector RPC calls (0.24)\n// -- version 32 adds analyze-query to the inspector RPC calls (0.24)\n// -- version 33 adds `flip` to CorrelatedSubquery (0.25)\n// -- version 34 moves `flip` from CorrelatedSubquery to CorrelatedSubqueryCondition (0.25)\n// -- version 35 adds `readRows`, `readRowCountsByQuery` and `readRowCount` to analyze-query result (0.25)\n// -- version 36 changes inspector analyze-query and adds error response to RPC (0.25)\n// -- version 37 adds `elapsed` to AnalyzeQueryResult (0.25)\n// -- version 38 adds structured push/transform error responses (0.25)\n// -- version 39 removes per-transform error types and adds `message` to app error (0.25)\n// -- version 40 adds `dbRowScansByQuery` to AnalyzeQueryResult (0.25)\n// -- version 41 makes ClientSchema.primaryKey required (0.25)\n// -- version 42 adds planner events to AnalyzeQueryResult (0.25)\n// -- version 43 renames `plans` to `sqlitePlans`, `plannerEvents` to `joinPlans`, and `plannerDebug` option to `joinPlans` (0.25)\n// -- version 44 adds profileID to connection URL (0.25)\n// -- version 45 adds userPushHeaders and userQueryHeaders to initConnection (0.25)\n// -- version 46 adds scalarSubquery condition type to AST\n// -- version 47 adds optional auth token to push body\n// -- version 48 adds updateAuth\n// -- version 49 adds `scalar` to CorrelatedSubqueryCondition, removes scalarSubquery\n// -- version 50 adds OTEL headers to push and query messages\nexport const PROTOCOL_VERSION = 50;\n\n/**\n * The minimum server-supported sync protocol version (i.e. the version\n * declared in the \"/sync/v{#}/connect\" URL). The contract for\n * backwards compatibility is that a `zero-cache` supports the current\n * `PROTOCOL_VERSION` and at least the previous one (i.e. `PROTOCOL_VERSION - 1`)\n * if not earlier ones as well. This corresponds to supporting clients running\n * the current release and the previous (major) release. Any client connections\n * from protocol versions before `MIN_SERVER_SUPPORTED_PROTOCOL_VERSION` are\n * closed with a `VersionNotSupported` error.\n */\nexport const MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 30;\n\nassert(\n MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION,\n 'MIN_SERVER_SUPPORTED_SYNC_PROTOCOL must be less than PROTOCOL_VERSION',\n);\n"],"mappings":";AAwEA,OAAA,MAEE,wEACD"}
1
+ {"version":3,"file":"protocol-version.js","names":[],"sources":["../../../../zero-protocol/src/protocol-version.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\n\n/**\n * The current `PROTOCOL_VERSION` of the code.\n *\n * The `PROTOCOL_VERSION` encompasses both the wire-protocol of the `/sync/...`\n * connection between the browser and `zero-cache`, as well as the format of\n * the `AST` objects stored in both components (i.e. IDB and CVR).\n *\n * A change in the `AST` schema (e.g. new functionality added) must be\n * accompanied by an increment of the `PROTOCOL_VERSION` and a new major\n * release. The server (`zero-cache`) must be deployed before clients start\n * running the new code.\n */\n// History:\n// -- Version 5 adds support for `pokeEnd.cookie`. (0.14)\n// -- Version 6 makes `pokeStart.cookie` optional. (0.16)\n// -- Version 7 introduces the initConnection.clientSchema field. (0.17)\n// -- Version 8 drops support for Version 5 (0.18).\n// -- Version 11 adds inspect queries. (0.18)\n// -- Version 12 adds 'timestamp' and 'date' types to the ClientSchema ValueType. (not shipped, reversed by version 14)\n// -- Version 14 removes 'timestamp' and 'date' types from the ClientSchema ValueType. (0.18)\n// -- Version 15 adds a `userPushParams` field to `initConnection` (0.19)\n// -- Version 16 adds a new error type (alreadyProcessed) to mutation responses (0.19)\n// -- Version 17 deprecates `AST` in downstream query puts. It was never used anyway. (0.21)\n// -- Version 18 adds `name` and `args` to the `queries-patch` protocol (0.21)\n// -- Version 19 adds `activeClients` to the `initConnection` protocol (0.22)\n// -- Version 20 changes inspector down message (0.22)\n// -- Version 21 removes `AST` in downstream query puts which was deprecated in Version 17, removes support for versions < 18 (0.22)\n// -- Version 22 adds an optional 'userQueryParams' field to `initConnection` (0.22)\n// -- Version 23 add `mutationResults` to poke (0.22)\n// -- Version 24 adds `ackMutationResults` to upstream (0.22).\n// -- version 25 modifies `mutationsResults` to include `del` patches (0.22)\n// -- version 26 adds inspect/metrics and adds metrics to inspect/query (0.23)\n// -- version 27 adds inspect/version (0.23)\n// -- version 28 adds more inspect/metrics (0.23)\n// -- version 29 adds error responses for custom queries (0.23)\n// -- version 30 adds an optional primaryKey to the ClientSchema (0.24)\n// -- version 31 adds admin password authentication to inspector RPC calls (0.24)\n// -- version 32 adds analyze-query to the inspector RPC calls (0.24)\n// -- version 33 adds `flip` to CorrelatedSubquery (0.25)\n// -- version 34 moves `flip` from CorrelatedSubquery to CorrelatedSubqueryCondition (0.25)\n// -- version 35 adds `readRows`, `readRowCountsByQuery` and `readRowCount` to analyze-query result (0.25)\n// -- version 36 changes inspector analyze-query and adds error response to RPC (0.25)\n// -- version 37 adds `elapsed` to AnalyzeQueryResult (0.25)\n// -- version 38 adds structured push/transform error responses (0.25)\n// -- version 39 removes per-transform error types and adds `message` to app error (0.25)\n// -- version 40 adds `dbRowScansByQuery` to AnalyzeQueryResult (0.25)\n// -- version 41 makes ClientSchema.primaryKey required (0.25)\n// -- version 42 adds planner events to AnalyzeQueryResult (0.25)\n// -- version 43 renames `plans` to `sqlitePlans`, `plannerEvents` to `joinPlans`, and `plannerDebug` option to `joinPlans` (0.25)\n// -- version 44 adds profileID to connection URL (0.25)\n// -- version 45 adds userPushHeaders and userQueryHeaders to initConnection (0.25)\n// -- version 46 adds scalarSubquery condition type to AST\n// -- version 47 adds optional auth token to push body\n// -- version 48 adds updateAuth\n// -- version 49 adds `scalar` to CorrelatedSubqueryCondition, removes scalarSubquery\n// -- version 50 adds OTEL headers to push and query messages\n// -- version 51 changes inspector metrics fields\nexport const PROTOCOL_VERSION = 51;\n\n/**\n * The minimum server-supported sync protocol version (i.e. the version\n * declared in the \"/sync/v{#}/connect\" URL). The contract for\n * backwards compatibility is that a `zero-cache` supports the current\n * `PROTOCOL_VERSION` and at least the previous one (i.e. `PROTOCOL_VERSION - 1`)\n * if not earlier ones as well. This corresponds to supporting clients running\n * the current release and the previous (major) release. Any client connections\n * from protocol versions before `MIN_SERVER_SUPPORTED_PROTOCOL_VERSION` are\n * closed with a `VersionNotSupported` error.\n */\nexport const MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 30;\n\nassert(\n MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION,\n 'MIN_SERVER_SUPPORTED_SYNC_PROTOCOL must be less than PROTOCOL_VERSION',\n);\n"],"mappings":";AAyEA,OAAA,MAEE,wEACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-query.d.ts","sourceRoot":"","sources":["../../../../zero-react/src/use-query.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"use-query.d.ts","sourceRoot":"","sources":["../../../../zero-react/src/use-query.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-query.js","names":["#views","#onDematerialized","#query","#reactInternals","#zero","#singular","#ttl","#snapshot","#materializeIfNeeded","#retry","#complete","#completeResolver","#nonEmpty","#nonEmptyResolver","#view","#onData","#destroyTimer"],"sources":["../../../../zero-react/src/use-query.tsx"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport React, {useSyncExternalStore} from 'react';\nimport {\n type Immutable,\n addContextToQuery,\n asQueryInternals,\n deepClone,\n DEFAULT_TTL_MS,\n} from './bindings.ts';\nimport {useZero} from './zero-provider.tsx';\nimport type {\n AnyMutatorRegistry,\n BaseDefaultContext,\n BaseDefaultSchema,\n CustomMutatorDefs,\n DefaultContext,\n DefaultSchema,\n ErroredQuery,\n Falsy,\n HumanReadable,\n PullRow,\n Query,\n QueryErrorDetails,\n QueryOrQueryRequest,\n QueryResultDetails,\n ReadonlyJSONValue,\n ResultType,\n TTL,\n TypedView,\n Zero,\n} from './zero.ts';\n\nexport type QueryResult<TReturn> = readonly [\n HumanReadable<TReturn>,\n QueryResultDetails & {},\n];\n\n/**\n * Result type for \"maybe queries\" - queries that may be falsy.\n * The data value can be undefined when the query is falsy/disabled.\n */\nexport type MaybeQueryResult<TReturn> = readonly [\n HumanReadable<TReturn> | undefined,\n QueryResultDetails & {},\n];\n\nexport type UseQueryOptions = {\n enabled?: boolean | undefined;\n /**\n * Time to live (TTL) in seconds. Controls how long query results are cached\n * after the query is removed. During this time, Zero continues to sync the query.\n * Default is 'never'.\n */\n ttl?: TTL | undefined;\n};\n\nexport type UseSuspenseQueryOptions = UseQueryOptions & {\n /**\n * Whether to suspend until:\n * - 'partial': the query has partial results (partial array or defined\n * value for singular results) which may be of result type 'unknown',\n * or the query result type is 'complete' (in which case results may be\n * empty). This is useful for suspending until there are partial\n * optimistic local results, or the query has completed loading from the\n * server.\n * - 'complete': the query result type is 'complete'.\n *\n * Default is 'partial'.\n */\n suspendUntil?: 'complete' | 'partial';\n};\n\nconst reactUse = (React as {use?: (p: Promise<unknown>) => void}).use;\nconst suspend: (p: Promise<unknown>) => void = reactUse\n ? reactUse\n : p => {\n throw p;\n };\n\n// Overload 1: Query\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn>;\n\n// Overload 2: Maybe query\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseQueryOptions | boolean,\n): MaybeQueryResult<TReturn>;\n\n// Implementation\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn> | MaybeQueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({enabled = true, ttl = DEFAULT_TTL_MS} = options);\n }\n\n const zero = useZero<TSchema, undefined, TContext>();\n\n // When query is falsy, use disabled subscriber/snapshot to maintain hook order\n const q = query ? addContextToQuery(query, zero.context) : undefined;\n const view = q ? viewStore.getView(zero, q, enabled, ttl) : undefined;\n\n // https://react.dev/reference/react/useSyncExternalStore\n // Always call useSyncExternalStore to maintain consistent hook order\n return useSyncExternalStore(\n view?.subscribeReactInternals ?? disabledSubscriber,\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n );\n}\n\n// Overload 1: Query\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n options?: UseSuspenseQueryOptions | boolean,\n): QueryResult<TReturn>;\n\n// Overload 2: Maybe query\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseSuspenseQueryOptions | boolean,\n): MaybeQueryResult<TReturn>;\n\n// Implementation\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseSuspenseQueryOptions | boolean,\n): QueryResult<TReturn> | MaybeQueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n let suspendUntil: 'complete' | 'partial' = 'partial';\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({\n enabled = true,\n ttl = DEFAULT_TTL_MS,\n suspendUntil = 'complete',\n } = options);\n }\n\n const zero = useZero<TSchema, undefined, TContext>();\n\n // When query is falsy, use disabled subscriber/snapshot to maintain hook order\n const q = query ? addContextToQuery(query, zero.context) : undefined;\n const view = q ? viewStore.getView(zero, q, enabled, ttl) : undefined;\n\n // https://react.dev/reference/react/useSyncExternalStore\n // Always call useSyncExternalStore to maintain consistent hook order\n const snapshot = useSyncExternalStore(\n view?.subscribeReactInternals ?? disabledSubscriber,\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n );\n\n if (view && enabled) {\n if (suspendUntil === 'complete' && !view.complete) {\n suspend(view.waitForComplete());\n }\n\n if (suspendUntil === 'partial' && !view.nonEmpty) {\n suspend(view.waitForNonEmpty());\n }\n }\n\n return snapshot;\n}\n\nconst emptyArray: unknown[] = [];\nconst disabledSubscriber = () => () => {};\n\nconst resultTypeUnknown = {type: 'unknown'} as const;\nconst resultTypeComplete = {type: 'complete'} as const;\nconst resultTypeError = {type: 'error'} as const;\n\nconst disabledQuerySnapshot = [undefined, resultTypeUnknown] as const;\nconst getDisabledSnapshot = () => disabledQuerySnapshot;\n\nconst emptySnapshotSingularUnknown = [undefined, resultTypeUnknown] as const;\nconst emptySnapshotSingularComplete = [undefined, resultTypeComplete] as const;\nconst emptySnapshotSingularErrorUnknown = [undefined, resultTypeError] as const;\nconst emptySnapshotPluralUnknown = [emptyArray, resultTypeUnknown] as const;\nconst emptySnapshotPluralComplete = [emptyArray, resultTypeComplete] as const;\nconst emptySnapshotErrorUnknown = [emptyArray, resultTypeError] as const;\n\nfunction getDefaultSnapshot<TReturn>(singular: boolean): QueryResult<TReturn> {\n return (\n singular ? emptySnapshotSingularUnknown : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n}\n\n/**\n * Returns a new snapshot or one of the empty predefined ones. Returning the\n * predefined ones is important to prevent unnecessary re-renders in React.\n */\nfunction getSnapshot<TReturn>(\n singular: boolean,\n data: HumanReadable<TReturn>,\n resultType: ResultType,\n retryFn: () => void,\n error?: ErroredQuery,\n): QueryResult<TReturn> {\n if (singular && data === undefined) {\n switch (resultType) {\n case 'error':\n if (error) {\n return [\n undefined,\n makeError(retryFn, error),\n ] as unknown as QueryResult<TReturn>;\n }\n return emptySnapshotSingularErrorUnknown as unknown as QueryResult<TReturn>;\n case 'complete':\n return emptySnapshotSingularComplete as unknown as QueryResult<TReturn>;\n case 'unknown':\n return emptySnapshotSingularUnknown as unknown as QueryResult<TReturn>;\n }\n }\n\n if (!singular && (data as unknown[]).length === 0) {\n switch (resultType) {\n case 'error':\n if (error) {\n return [\n emptyArray,\n makeError(retryFn, error),\n ] as unknown as QueryResult<TReturn>;\n }\n return emptySnapshotErrorUnknown as unknown as QueryResult<TReturn>;\n case 'complete':\n return emptySnapshotPluralComplete as unknown as QueryResult<TReturn>;\n case 'unknown':\n return emptySnapshotPluralUnknown as unknown as QueryResult<TReturn>;\n }\n }\n\n switch (resultType) {\n case 'error':\n if (error) {\n return [data, makeError(retryFn, error)];\n }\n return [\n data,\n makeError(retryFn, {\n error: 'app',\n id: 'unknown',\n name: 'unknown',\n message: 'An unknown error occurred',\n }),\n ];\n case 'complete':\n return [data, resultTypeComplete];\n case 'unknown':\n return [data, resultTypeUnknown];\n }\n}\n\nfunction makeError(retry: () => void, error: ErroredQuery): QueryErrorDetails {\n const message = error.message ?? 'An unknown error occurred';\n return {\n type: 'error',\n retry,\n refetch: retry,\n error: {\n type: error.error,\n message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n}\n\ndeclare const TESTING: boolean;\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyViewWrapper = ViewWrapper<any, any, any, any, any>;\n\nconst allViews = new WeakMap<ViewStore, Map<string, AnyViewWrapper>>();\n\nexport function getAllViewsSizeForTesting(store: ViewStore): number {\n if (TESTING) {\n return allViews.get(store)?.size ?? 0;\n }\n return 0;\n}\n\n/**\n * A global store of all active views.\n *\n * React subscribes and unsubscribes to these views\n * via `useSyncExternalStore`.\n *\n * Managing views through `useEffect` or `useLayoutEffect` causes\n * inconsistencies because effects run after render.\n *\n * For example, if useQuery used use*Effect in the component below:\n * ```ts\n * function Foo({issueID}) {\n * const issue = useQuery(z.query.issue.where('id', issueID).one());\n * if (issue?.id !== undefined && issue.id !== issueID) {\n * console.log('MISMATCH!', issue.id, issueID);\n * }\n * }\n * ```\n *\n * `MISMATCH` will be printed whenever the `issueID` prop changes.\n *\n * This is because the component will render once with\n * the old state returned from `useQuery`. Then the effect inside\n * `useQuery` will run. The component will render again with the new\n * state. This inconsistent transition can cause unexpected results.\n *\n * Emulating `useEffect` via `useState` and `if` causes resource leaks.\n * That is:\n *\n * ```ts\n * function useQuery(q) {\n * const [oldHash, setOldHash] = useState();\n * if (hash(q) !== oldHash) {\n * // make new view\n * }\n *\n * useEffect(() => {\n * return () => view.destroy();\n * }, []);\n * }\n * ```\n *\n * I'm not sure why but in strict mode the cleanup function\n * fails to be called for the first instance of the view and only\n * cleans up later instances.\n *\n * Swapping `useState` to `useRef` has similar problems.\n */\nexport class ViewStore {\n #views = new Map<string, AnyViewWrapper>();\n\n constructor() {\n if (TESTING) {\n allViews.set(this, this.#views);\n }\n }\n\n getView<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends BaseDefaultSchema,\n TReturn,\n MD extends CustomMutatorDefs | undefined,\n TContext extends BaseDefaultContext,\n >(\n zero: Zero<TSchema, MD, TContext>,\n q: Query<TTable, TSchema, TReturn>,\n enabled: boolean,\n ttl: TTL,\n ): {\n getSnapshot: () => QueryResult<TReturn>;\n subscribeReactInternals: (internals: () => void) => () => void;\n updateTTL: (ttl: TTL) => void;\n waitForComplete: () => Promise<void>;\n waitForNonEmpty: () => Promise<void>;\n complete: boolean;\n nonEmpty: boolean;\n } {\n const qi = asQueryInternals(q);\n\n if (!enabled) {\n return {\n getSnapshot: () => getDefaultSnapshot(qi.format.singular),\n subscribeReactInternals: disabledSubscriber,\n updateTTL: () => {},\n waitForComplete: () => Promise.resolve(),\n waitForNonEmpty: () => Promise.resolve(),\n complete: false,\n nonEmpty: false,\n };\n }\n\n const hash = qi.hash() + zero.clientID;\n let existing = this.#views.get(hash);\n if (!existing) {\n existing = new ViewWrapper(q, zero, ttl, view => {\n const currentView = this.#views.get(hash);\n if (currentView && currentView !== view) {\n // we replaced the view with a new one already.\n return;\n }\n this.#views.delete(hash);\n });\n this.#views.set(hash, existing);\n } else {\n existing.updateTTL(ttl);\n }\n return existing as ViewWrapper<TTable, TSchema, TReturn, MD, TContext>;\n }\n}\n\nconst viewStore = new ViewStore();\n\n/**\n * This wraps and ref counts a view.\n *\n * The only signal we have from React as to whether or not it is\n * done with a view is when it calls `unsubscribe`.\n *\n * In non-strict-mode we can clean up the view as soon\n * as the listener count goes to 0.\n *\n * In strict-mode, the listener count will go to 0 then a\n * new listener for the same view is immediately added back.\n *\n * This is why the `onMaterialized` and `onDematerialized` callbacks exist --\n * they allow a view which React is still referencing to be added\n * back into the store when React re-subscribes to it.\n *\n * This wrapper also exists to deal with the various\n * `useSyncExternalStore` caveats that cause excessive\n * re-renders and materializations.\n *\n * See: https://react.dev/reference/react/useSyncExternalStore#caveats\n * Especially:\n * 1. The store snapshot returned by getSnapshot must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.\n * 2. If a different subscribe function is passed during a re-render, React will re-subscribe to the store using the newly passed subscribe function. You can prevent this by declaring subscribe outside the component.\n */\nclass ViewWrapper<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends BaseDefaultSchema,\n TReturn,\n MD extends AnyMutatorRegistry | CustomMutatorDefs | undefined,\n TContext extends BaseDefaultContext,\n> {\n #view: TypedView<HumanReadable<TReturn>> | undefined;\n readonly #onDematerialized;\n readonly #query: Query<TTable, TSchema, TReturn>;\n #snapshot: QueryResult<TReturn>;\n readonly #reactInternals: Set<() => void> = new Set();\n #ttl: TTL;\n #complete = false;\n #completeResolver = resolver<void>();\n #nonEmpty = false;\n #nonEmptyResolver = resolver<void>();\n readonly #zero: Pick<Zero<TSchema, undefined, TContext>, 'materialize'>;\n readonly #singular: boolean;\n #destroyTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n query: Query<TTable, TSchema, TReturn>,\n zero: Pick<Zero<TSchema, undefined, TContext>, 'materialize'>,\n ttl: TTL,\n onDematerialized: (\n view: ViewWrapper<TTable, TSchema, TReturn, MD, TContext>,\n ) => void,\n ) {\n this.#query = query;\n this.#zero = zero;\n this.#ttl = ttl;\n this.#onDematerialized = onDematerialized;\n const {singular} = asQueryInternals(query).format;\n this.#singular = singular;\n this.#snapshot = getDefaultSnapshot(singular);\n this.#materializeIfNeeded();\n }\n\n #onData = (\n snap: Immutable<HumanReadable<TReturn>>,\n resultType: ResultType,\n error?: ErroredQuery,\n ) => {\n const data =\n snap === undefined\n ? snap\n : (deepClone(snap as ReadonlyJSONValue) as HumanReadable<TReturn>);\n this.#snapshot = getSnapshot(\n this.#singular,\n data,\n resultType,\n this.#retry,\n error,\n );\n if (resultType === 'complete' || resultType === 'error') {\n this.#complete = true;\n this.#completeResolver.resolve();\n this.#nonEmpty = true;\n this.#nonEmptyResolver.resolve();\n }\n\n if (\n this.#singular\n ? this.#snapshot[0] !== undefined\n : (this.#snapshot[0] as unknown[]).length !== 0\n ) {\n this.#nonEmpty = true;\n this.#nonEmptyResolver.resolve();\n }\n\n for (const internals of this.#reactInternals) {\n internals();\n }\n };\n\n /**\n * Called by the user to force a retry of the query\n * in the case the query errored.\n */\n #retry = () => {\n this.#view?.destroy();\n this.#view = undefined;\n this.#materializeIfNeeded();\n };\n\n #materializeIfNeeded = () => {\n if (this.#view) {\n return;\n }\n this.#view = this.#zero.materialize(this.#query, {\n ttl: this.#ttl,\n });\n this.#view.addListener(this.#onData);\n };\n\n getSnapshot = () => this.#snapshot;\n\n subscribeReactInternals = (internals: () => void): (() => void) => {\n this.#reactInternals.add(internals);\n // Cancel any pending destroy timer from a previous unsubscribe.\n // Without this, rapid unsub/resub cycles accumulate stale timers\n // that can fire during a gap between unsubscribe and resubscribe,\n // destroying the view even though it was actively used.\n if (this.#destroyTimer !== undefined) {\n clearTimeout(this.#destroyTimer);\n this.#destroyTimer = undefined;\n }\n this.#materializeIfNeeded();\n return () => {\n this.#reactInternals.delete(internals);\n\n // only schedule a cleanup task if we have no listeners left\n if (this.#reactInternals.size === 0) {\n this.#destroyTimer = setTimeout(() => {\n this.#destroyTimer = undefined;\n\n // We already destroyed the view\n if (this.#view === undefined) {\n return;\n }\n\n // Someone re-registered a listener on this view before the timeout elapsed.\n // This happens often in strict-mode which forces a component\n // to mount, unmount, remount.\n if (this.#reactInternals.size > 0) {\n return;\n }\n\n this.#view.destroy();\n this.#view = undefined;\n this.#complete = false;\n this.#completeResolver = resolver();\n this.#nonEmpty = false;\n this.#nonEmptyResolver = resolver();\n this.#onDematerialized(this);\n }, 10);\n }\n };\n };\n\n updateTTL(ttl: TTL): void {\n this.#ttl = ttl;\n this.#view?.updateTTL(ttl);\n }\n\n get complete() {\n return this.#complete;\n }\n\n waitForComplete(): Promise<void> {\n return this.#completeResolver.promise;\n }\n\n get nonEmpty() {\n return this.#nonEmpty;\n }\n\n waitForNonEmpty(): Promise<void> {\n return this.#nonEmptyResolver.promise;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-query.js","names":["#views","#onDematerialized","#query","#reactInternals","#zero","#singular","#ttl","#snapshot","#materializeIfNeeded","#retry","#complete","#completeResolver","#nonEmpty","#nonEmptyResolver","#view","#onData","#destroyTimer"],"sources":["../../../../zero-react/src/use-query.tsx"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport React, {useSyncExternalStore} from 'react';\nimport {TESTING} from '../../shared/src/testing.ts';\nimport {\n type Immutable,\n addContextToQuery,\n asQueryInternals,\n deepClone,\n DEFAULT_TTL_MS,\n} from './bindings.ts';\nimport {useZero} from './zero-provider.tsx';\nimport type {\n AnyMutatorRegistry,\n BaseDefaultContext,\n BaseDefaultSchema,\n CustomMutatorDefs,\n DefaultContext,\n DefaultSchema,\n ErroredQuery,\n Falsy,\n HumanReadable,\n PullRow,\n Query,\n QueryErrorDetails,\n QueryOrQueryRequest,\n QueryResultDetails,\n ReadonlyJSONValue,\n ResultType,\n TTL,\n TypedView,\n Zero,\n} from './zero.ts';\n\nexport type QueryResult<TReturn> = readonly [\n HumanReadable<TReturn>,\n QueryResultDetails & {},\n];\n\n/**\n * Result type for \"maybe queries\" - queries that may be falsy.\n * The data value can be undefined when the query is falsy/disabled.\n */\nexport type MaybeQueryResult<TReturn> = readonly [\n HumanReadable<TReturn> | undefined,\n QueryResultDetails & {},\n];\n\nexport type UseQueryOptions = {\n enabled?: boolean | undefined;\n /**\n * Time to live (TTL) in seconds. Controls how long query results are cached\n * after the query is removed. During this time, Zero continues to sync the query.\n * Default is 'never'.\n */\n ttl?: TTL | undefined;\n};\n\nexport type UseSuspenseQueryOptions = UseQueryOptions & {\n /**\n * Whether to suspend until:\n * - 'partial': the query has partial results (partial array or defined\n * value for singular results) which may be of result type 'unknown',\n * or the query result type is 'complete' (in which case results may be\n * empty). This is useful for suspending until there are partial\n * optimistic local results, or the query has completed loading from the\n * server.\n * - 'complete': the query result type is 'complete'.\n *\n * Default is 'partial'.\n */\n suspendUntil?: 'complete' | 'partial';\n};\n\nconst reactUse = (React as {use?: (p: Promise<unknown>) => void}).use;\nconst suspend: (p: Promise<unknown>) => void = reactUse\n ? reactUse\n : p => {\n throw p;\n };\n\n// Overload 1: Query\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn>;\n\n// Overload 2: Maybe query\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseQueryOptions | boolean,\n): MaybeQueryResult<TReturn>;\n\n// Implementation\nexport function useQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseQueryOptions | boolean,\n): QueryResult<TReturn> | MaybeQueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({enabled = true, ttl = DEFAULT_TTL_MS} = options);\n }\n\n const zero = useZero<TSchema, undefined, TContext>();\n\n // When query is falsy, use disabled subscriber/snapshot to maintain hook order\n const q = query ? addContextToQuery(query, zero.context) : undefined;\n const view = q ? viewStore.getView(zero, q, enabled, ttl) : undefined;\n\n // https://react.dev/reference/react/useSyncExternalStore\n // Always call useSyncExternalStore to maintain consistent hook order\n return useSyncExternalStore(\n view?.subscribeReactInternals ?? disabledSubscriber,\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n );\n}\n\n// Overload 1: Query\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n options?: UseSuspenseQueryOptions | boolean,\n): QueryResult<TReturn>;\n\n// Overload 2: Maybe query\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseSuspenseQueryOptions | boolean,\n): MaybeQueryResult<TReturn>;\n\n// Implementation\nexport function useSuspenseQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends BaseDefaultSchema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext extends BaseDefaultContext = DefaultContext,\n>(\n query:\n | QueryOrQueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Falsy,\n options?: UseSuspenseQueryOptions | boolean,\n): QueryResult<TReturn> | MaybeQueryResult<TReturn> {\n let enabled = true;\n let ttl: TTL = DEFAULT_TTL_MS;\n let suspendUntil: 'complete' | 'partial' = 'partial';\n if (typeof options === 'boolean') {\n enabled = options;\n } else if (options) {\n ({\n enabled = true,\n ttl = DEFAULT_TTL_MS,\n suspendUntil = 'complete',\n } = options);\n }\n\n const zero = useZero<TSchema, undefined, TContext>();\n\n // When query is falsy, use disabled subscriber/snapshot to maintain hook order\n const q = query ? addContextToQuery(query, zero.context) : undefined;\n const view = q ? viewStore.getView(zero, q, enabled, ttl) : undefined;\n\n // https://react.dev/reference/react/useSyncExternalStore\n // Always call useSyncExternalStore to maintain consistent hook order\n const snapshot = useSyncExternalStore(\n view?.subscribeReactInternals ?? disabledSubscriber,\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n view?.getSnapshot ??\n (getDisabledSnapshot as () => MaybeQueryResult<TReturn>),\n );\n\n if (view && enabled) {\n if (suspendUntil === 'complete' && !view.complete) {\n suspend(view.waitForComplete());\n }\n\n if (suspendUntil === 'partial' && !view.nonEmpty) {\n suspend(view.waitForNonEmpty());\n }\n }\n\n return snapshot;\n}\n\nconst emptyArray: unknown[] = [];\nconst disabledSubscriber = () => () => {};\n\nconst resultTypeUnknown = {type: 'unknown'} as const;\nconst resultTypeComplete = {type: 'complete'} as const;\nconst resultTypeError = {type: 'error'} as const;\n\nconst disabledQuerySnapshot = [undefined, resultTypeUnknown] as const;\nconst getDisabledSnapshot = () => disabledQuerySnapshot;\n\nconst emptySnapshotSingularUnknown = [undefined, resultTypeUnknown] as const;\nconst emptySnapshotSingularComplete = [undefined, resultTypeComplete] as const;\nconst emptySnapshotSingularErrorUnknown = [undefined, resultTypeError] as const;\nconst emptySnapshotPluralUnknown = [emptyArray, resultTypeUnknown] as const;\nconst emptySnapshotPluralComplete = [emptyArray, resultTypeComplete] as const;\nconst emptySnapshotErrorUnknown = [emptyArray, resultTypeError] as const;\n\nfunction getDefaultSnapshot<TReturn>(singular: boolean): QueryResult<TReturn> {\n return (\n singular ? emptySnapshotSingularUnknown : emptySnapshotPluralUnknown\n ) as QueryResult<TReturn>;\n}\n\n/**\n * Returns a new snapshot or one of the empty predefined ones. Returning the\n * predefined ones is important to prevent unnecessary re-renders in React.\n */\nfunction getSnapshot<TReturn>(\n singular: boolean,\n data: HumanReadable<TReturn>,\n resultType: ResultType,\n retryFn: () => void,\n error?: ErroredQuery,\n): QueryResult<TReturn> {\n if (singular && data === undefined) {\n switch (resultType) {\n case 'error':\n if (error) {\n return [\n undefined,\n makeError(retryFn, error),\n ] as unknown as QueryResult<TReturn>;\n }\n return emptySnapshotSingularErrorUnknown as unknown as QueryResult<TReturn>;\n case 'complete':\n return emptySnapshotSingularComplete as unknown as QueryResult<TReturn>;\n case 'unknown':\n return emptySnapshotSingularUnknown as unknown as QueryResult<TReturn>;\n }\n }\n\n if (!singular && (data as unknown[]).length === 0) {\n switch (resultType) {\n case 'error':\n if (error) {\n return [\n emptyArray,\n makeError(retryFn, error),\n ] as unknown as QueryResult<TReturn>;\n }\n return emptySnapshotErrorUnknown as unknown as QueryResult<TReturn>;\n case 'complete':\n return emptySnapshotPluralComplete as unknown as QueryResult<TReturn>;\n case 'unknown':\n return emptySnapshotPluralUnknown as unknown as QueryResult<TReturn>;\n }\n }\n\n switch (resultType) {\n case 'error':\n if (error) {\n return [data, makeError(retryFn, error)];\n }\n return [\n data,\n makeError(retryFn, {\n error: 'app',\n id: 'unknown',\n name: 'unknown',\n message: 'An unknown error occurred',\n }),\n ];\n case 'complete':\n return [data, resultTypeComplete];\n case 'unknown':\n return [data, resultTypeUnknown];\n }\n}\n\nfunction makeError(retry: () => void, error: ErroredQuery): QueryErrorDetails {\n const message = error.message ?? 'An unknown error occurred';\n return {\n type: 'error',\n retry,\n refetch: retry,\n error: {\n type: error.error,\n message,\n ...(error.details ? {details: error.details} : {}),\n },\n };\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyViewWrapper = ViewWrapper<any, any, any, any, any>;\n\nconst allViews = new WeakMap<ViewStore, Map<string, AnyViewWrapper>>();\n\nexport function getAllViewsSizeForTesting(store: ViewStore): number {\n if (TESTING) {\n return allViews.get(store)?.size ?? 0;\n }\n return 0;\n}\n\n/**\n * A global store of all active views.\n *\n * React subscribes and unsubscribes to these views\n * via `useSyncExternalStore`.\n *\n * Managing views through `useEffect` or `useLayoutEffect` causes\n * inconsistencies because effects run after render.\n *\n * For example, if useQuery used use*Effect in the component below:\n * ```ts\n * function Foo({issueID}) {\n * const issue = useQuery(z.query.issue.where('id', issueID).one());\n * if (issue?.id !== undefined && issue.id !== issueID) {\n * console.log('MISMATCH!', issue.id, issueID);\n * }\n * }\n * ```\n *\n * `MISMATCH` will be printed whenever the `issueID` prop changes.\n *\n * This is because the component will render once with\n * the old state returned from `useQuery`. Then the effect inside\n * `useQuery` will run. The component will render again with the new\n * state. This inconsistent transition can cause unexpected results.\n *\n * Emulating `useEffect` via `useState` and `if` causes resource leaks.\n * That is:\n *\n * ```ts\n * function useQuery(q) {\n * const [oldHash, setOldHash] = useState();\n * if (hash(q) !== oldHash) {\n * // make new view\n * }\n *\n * useEffect(() => {\n * return () => view.destroy();\n * }, []);\n * }\n * ```\n *\n * I'm not sure why but in strict mode the cleanup function\n * fails to be called for the first instance of the view and only\n * cleans up later instances.\n *\n * Swapping `useState` to `useRef` has similar problems.\n */\nexport class ViewStore {\n #views = new Map<string, AnyViewWrapper>();\n\n constructor() {\n if (TESTING) {\n allViews.set(this, this.#views);\n }\n }\n\n getView<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends BaseDefaultSchema,\n TReturn,\n MD extends CustomMutatorDefs | undefined,\n TContext extends BaseDefaultContext,\n >(\n zero: Zero<TSchema, MD, TContext>,\n q: Query<TTable, TSchema, TReturn>,\n enabled: boolean,\n ttl: TTL,\n ): {\n getSnapshot: () => QueryResult<TReturn>;\n subscribeReactInternals: (internals: () => void) => () => void;\n updateTTL: (ttl: TTL) => void;\n waitForComplete: () => Promise<void>;\n waitForNonEmpty: () => Promise<void>;\n complete: boolean;\n nonEmpty: boolean;\n } {\n const qi = asQueryInternals(q);\n\n if (!enabled) {\n return {\n getSnapshot: () => getDefaultSnapshot(qi.format.singular),\n subscribeReactInternals: disabledSubscriber,\n updateTTL: () => {},\n waitForComplete: () => Promise.resolve(),\n waitForNonEmpty: () => Promise.resolve(),\n complete: false,\n nonEmpty: false,\n };\n }\n\n const hash = qi.hash() + zero.clientID;\n let existing = this.#views.get(hash);\n if (!existing) {\n existing = new ViewWrapper(q, zero, ttl, view => {\n const currentView = this.#views.get(hash);\n if (currentView && currentView !== view) {\n // we replaced the view with a new one already.\n return;\n }\n this.#views.delete(hash);\n });\n this.#views.set(hash, existing);\n } else {\n existing.updateTTL(ttl);\n }\n return existing as ViewWrapper<TTable, TSchema, TReturn, MD, TContext>;\n }\n}\n\nconst viewStore = new ViewStore();\n\n/**\n * This wraps and ref counts a view.\n *\n * The only signal we have from React as to whether or not it is\n * done with a view is when it calls `unsubscribe`.\n *\n * In non-strict-mode we can clean up the view as soon\n * as the listener count goes to 0.\n *\n * In strict-mode, the listener count will go to 0 then a\n * new listener for the same view is immediately added back.\n *\n * This is why the `onMaterialized` and `onDematerialized` callbacks exist --\n * they allow a view which React is still referencing to be added\n * back into the store when React re-subscribes to it.\n *\n * This wrapper also exists to deal with the various\n * `useSyncExternalStore` caveats that cause excessive\n * re-renders and materializations.\n *\n * See: https://react.dev/reference/react/useSyncExternalStore#caveats\n * Especially:\n * 1. The store snapshot returned by getSnapshot must be immutable. If the underlying store has mutable data, return a new immutable snapshot if the data has changed. Otherwise, return a cached last snapshot.\n * 2. If a different subscribe function is passed during a re-render, React will re-subscribe to the store using the newly passed subscribe function. You can prevent this by declaring subscribe outside the component.\n */\nclass ViewWrapper<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends BaseDefaultSchema,\n TReturn,\n MD extends AnyMutatorRegistry | CustomMutatorDefs | undefined,\n TContext extends BaseDefaultContext,\n> {\n #view: TypedView<HumanReadable<TReturn>> | undefined;\n readonly #onDematerialized;\n readonly #query: Query<TTable, TSchema, TReturn>;\n #snapshot: QueryResult<TReturn>;\n readonly #reactInternals: Set<() => void> = new Set();\n #ttl: TTL;\n #complete = false;\n #completeResolver = resolver<void>();\n #nonEmpty = false;\n #nonEmptyResolver = resolver<void>();\n readonly #zero: Pick<Zero<TSchema, undefined, TContext>, 'materialize'>;\n readonly #singular: boolean;\n #destroyTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(\n query: Query<TTable, TSchema, TReturn>,\n zero: Pick<Zero<TSchema, undefined, TContext>, 'materialize'>,\n ttl: TTL,\n onDematerialized: (\n view: ViewWrapper<TTable, TSchema, TReturn, MD, TContext>,\n ) => void,\n ) {\n this.#query = query;\n this.#zero = zero;\n this.#ttl = ttl;\n this.#onDematerialized = onDematerialized;\n const {singular} = asQueryInternals(query).format;\n this.#singular = singular;\n this.#snapshot = getDefaultSnapshot(singular);\n this.#materializeIfNeeded();\n }\n\n #onData = (\n snap: Immutable<HumanReadable<TReturn>>,\n resultType: ResultType,\n error?: ErroredQuery,\n ) => {\n const data =\n snap === undefined\n ? snap\n : (deepClone(snap as ReadonlyJSONValue) as HumanReadable<TReturn>);\n this.#snapshot = getSnapshot(\n this.#singular,\n data,\n resultType,\n this.#retry,\n error,\n );\n if (resultType === 'complete' || resultType === 'error') {\n this.#complete = true;\n this.#completeResolver.resolve();\n this.#nonEmpty = true;\n this.#nonEmptyResolver.resolve();\n }\n\n if (\n this.#singular\n ? this.#snapshot[0] !== undefined\n : (this.#snapshot[0] as unknown[]).length !== 0\n ) {\n this.#nonEmpty = true;\n this.#nonEmptyResolver.resolve();\n }\n\n for (const internals of this.#reactInternals) {\n internals();\n }\n };\n\n /**\n * Called by the user to force a retry of the query\n * in the case the query errored.\n */\n #retry = () => {\n this.#view?.destroy();\n this.#view = undefined;\n this.#materializeIfNeeded();\n };\n\n #materializeIfNeeded = () => {\n if (this.#view) {\n return;\n }\n this.#view = this.#zero.materialize(this.#query, {\n ttl: this.#ttl,\n });\n this.#view.addListener(this.#onData);\n };\n\n getSnapshot = () => this.#snapshot;\n\n subscribeReactInternals = (internals: () => void): (() => void) => {\n this.#reactInternals.add(internals);\n // Cancel any pending destroy timer from a previous unsubscribe.\n // Without this, rapid unsub/resub cycles accumulate stale timers\n // that can fire during a gap between unsubscribe and resubscribe,\n // destroying the view even though it was actively used.\n if (this.#destroyTimer !== undefined) {\n clearTimeout(this.#destroyTimer);\n this.#destroyTimer = undefined;\n }\n this.#materializeIfNeeded();\n return () => {\n this.#reactInternals.delete(internals);\n\n // only schedule a cleanup task if we have no listeners left\n if (this.#reactInternals.size === 0) {\n this.#destroyTimer = setTimeout(() => {\n this.#destroyTimer = undefined;\n\n // We already destroyed the view\n if (this.#view === undefined) {\n return;\n }\n\n // Someone re-registered a listener on this view before the timeout elapsed.\n // This happens often in strict-mode which forces a component\n // to mount, unmount, remount.\n if (this.#reactInternals.size > 0) {\n return;\n }\n\n this.#view.destroy();\n this.#view = undefined;\n this.#complete = false;\n this.#completeResolver = resolver();\n this.#nonEmpty = false;\n this.#nonEmptyResolver = resolver();\n this.#onDematerialized(this);\n }, 10);\n }\n };\n };\n\n updateTTL(ttl: TTL): void {\n this.#ttl = ttl;\n this.#view?.updateTTL(ttl);\n }\n\n get complete() {\n return this.#complete;\n }\n\n waitForComplete(): Promise<void> {\n return this.#completeResolver.promise;\n }\n\n get nonEmpty() {\n return this.#nonEmpty;\n }\n\n waitForNonEmpty(): Promise<void> {\n return this.#nonEmptyResolver.promise;\n }\n}\n"],"mappings":"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"}
@@ -17,6 +17,12 @@ export declare function createUseZero<S extends BaseDefaultSchema = DefaultSchem
17
17
  export type ZeroProviderProps<S extends BaseDefaultSchema = DefaultSchema, MD extends CustomMutatorDefs | undefined = undefined, Context extends BaseDefaultContext = DefaultContext> = (ZeroOptions<S, MD, Context> | {
18
18
  zero: Zero<S, MD, Context>;
19
19
  }) & {
20
+ /**
21
+ * Called after ZeroProvider constructs a new Zero instance.
22
+ *
23
+ * This runs only when the provider creates Zero from options, and is not
24
+ * called when an existing instance is passed with `zero`.
25
+ */
20
26
  init?: (zero: Zero<S, MD, Context>) => void;
21
27
  children: ReactNode;
22
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"zero-provider.d.ts","sourceRoot":"","sources":["../../../../zero-react/src/zero-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAGnB,eAAO,MAAM,WAAW,0DAEvB,CAAC;AAEF,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAMxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,gCAGpD;AAED,MAAM,MAAM,iBAAiB,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,IACjD,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG;IAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;CAAC,CAAC,GAAG;IACjE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,EAAC,EAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,uDA8D9D"}
1
+ {"version":3,"file":"zero-provider.d.ts","sourceRoot":"","sources":["../../../../zero-react/src/zero-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAGnB,eAAO,MAAM,WAAW,0DAEvB,CAAC;AAEF,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAMxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,gCAGpD;AAED,MAAM,MAAM,iBAAiB,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,IACjD,CAAC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG;IAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;CAAC,CAAC,GAAG;IACjE;;;;;OAKG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,EAAC,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,EAAC,EAAE,iBAAiB,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,uDA4F9D"}
@@ -27,18 +27,37 @@ function createUseZero() {
27
27
  function ZeroProvider({ children, init, ...props }) {
28
28
  const isExternalZero = "zero" in props;
29
29
  const [zero, setZero] = useState(isExternalZero ? props.zero : void 0);
30
+ const [rotationGeneration, setRotationGeneration] = useState(0);
30
31
  const auth = "auth" in props ? props.auth : void 0;
31
32
  const hasAuth = typeof auth === "string";
32
33
  const prevAuthRef = useRef(auth);
34
+ const rotationPendingRef = useRef(false);
35
+ const scheduleRotation = () => {
36
+ if (rotationPendingRef.current) return;
37
+ rotationPendingRef.current = true;
38
+ setRotationGeneration((gen) => gen + 1);
39
+ };
33
40
  useEffect(() => {
34
41
  if (isExternalZero) {
42
+ rotationPendingRef.current = false;
35
43
  setZero(props.zero);
36
44
  return;
37
45
  }
38
- const z = new Zero(props);
46
+ const z = new Zero({
47
+ ...props,
48
+ onClientStateNotFound: () => {
49
+ if (rotationPendingRef.current) return;
50
+ if (props.onClientStateNotFound) try {
51
+ props.onClientStateNotFound();
52
+ return;
53
+ } catch {}
54
+ scheduleRotation();
55
+ }
56
+ });
39
57
  prevAuthRef.current = auth;
40
58
  init?.(z);
41
59
  setZero(z);
60
+ rotationPendingRef.current = false;
42
61
  return () => {
43
62
  z.close();
44
63
  setZero(void 0);
@@ -46,6 +65,7 @@ function ZeroProvider({ children, init, ...props }) {
46
65
  }, [
47
66
  hasAuth,
48
67
  init,
68
+ rotationGeneration,
49
69
  ...useMemo(() => Object.entries(props).filter(([key]) => key !== "auth").sort(([a], [b]) => stringCompare(a, b)).map(([_, value]) => value), [props])
50
70
  ]);
51
71
  useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"zero-provider.js","names":[],"sources":["../../../../zero-react/src/zero-provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {stringCompare} from '../../shared/src/string-compare.ts';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\n// oxlint-disable-next-line no-explicit-any\nexport const ZeroContext = createContext<Zero<any, any, any> | undefined>(\n undefined,\n);\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD, Context>;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport type ZeroProviderProps<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n> = (ZeroOptions<S, MD, Context> | {zero: Zero<S, MD, Context>}) & {\n init?: (zero: Zero<S, MD, Context>) => void;\n children: ReactNode;\n};\n\nexport function ZeroProvider<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>({children, init, ...props}: ZeroProviderProps<S, MD, Context>) {\n const isExternalZero = 'zero' in props;\n\n const [zero, setZero] = useState<Zero<S, MD, Context> | undefined>(\n isExternalZero ? props.zero : undefined,\n );\n\n const auth = 'auth' in props ? props.auth : undefined;\n const hasAuth = typeof auth === 'string';\n const prevAuthRef = useRef<typeof auth>(auth);\n\n const keysWithoutAuth = useMemo(\n () =>\n Object.entries(props)\n .filter(([key]) => key !== 'auth')\n .sort(([a], [b]) => stringCompare(a, b))\n .map(([_, value]) => value),\n [props],\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if (isExternalZero) {\n setZero(props.zero);\n return;\n }\n\n const z = new Zero(props);\n prevAuthRef.current = auth;\n init?.(z);\n setZero(z);\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n // we intentionally don't include auth in the dependency array\n // to avoid closing zero when auth changes\n }, [hasAuth, init, ...keysWithoutAuth]);\n\n useEffect(() => {\n if (!zero || isExternalZero) return;\n\n const prevAuth = prevAuthRef.current;\n const authChanged = auth !== prevAuth;\n\n if (authChanged) {\n prevAuthRef.current = auth;\n\n if (typeof prevAuth === 'string' && typeof auth === 'string') {\n void zero.connection.connect({auth});\n }\n }\n }, [auth, zero]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n"],"mappings":";;;;;;AAqBA,IAAa,cAAc,cACzB,KAAA,EACD;AAED,SAAgB,UAIU;CACxB,MAAM,OAAO,WAAW,YAAY;AACpC,KAAI,SAAS,KAAA,EACX,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;;;;;;;;;;;;AAcT,SAAgB,gBAIZ;AACF,cAAa,SAAyB;;AAYxC,SAAgB,aAId,EAAC,UAAU,MAAM,GAAG,SAA2C;CAC/D,MAAM,iBAAiB,UAAU;CAEjC,MAAM,CAAC,MAAM,WAAW,SACtB,iBAAiB,MAAM,OAAO,KAAA,EAC/B;CAED,MAAM,OAAO,UAAU,QAAQ,MAAM,OAAO,KAAA;CAC5C,MAAM,UAAU,OAAO,SAAS;CAChC,MAAM,cAAc,OAAoB,KAAK;AAgB7C,iBAAgB;AACd,MAAI,gBAAgB;AAClB,WAAQ,MAAM,KAAK;AACnB;;EAGF,MAAM,IAAI,IAAI,KAAK,MAAM;AACzB,cAAY,UAAU;AACtB,SAAO,EAAE;AACT,UAAQ,EAAE;AAEV,eAAa;AACN,KAAE,OAAO;AACd,WAAQ,KAAA,EAAU;;IAInB;EAAC;EAAS;EAAM,GA/BK,cAEpB,OAAO,QAAQ,MAAM,CAClB,QAAQ,CAAC,SAAS,QAAQ,OAAO,CACjC,MAAM,CAAC,IAAI,CAAC,OAAO,cAAc,GAAG,EAAE,CAAC,CACvC,KAAK,CAAC,GAAG,WAAW,MAAM,EAC/B,CAAC,MAAM,CACR;EAwBqC,CAAC;AAEvC,iBAAgB;AACd,MAAI,CAAC,QAAQ,eAAgB;EAE7B,MAAM,WAAW,YAAY;AAG7B,MAFoB,SAAS,UAEZ;AACf,eAAY,UAAU;AAEtB,OAAI,OAAO,aAAa,YAAY,OAAO,SAAS,SAC7C,MAAK,WAAW,QAAQ,EAAC,MAAK,CAAC;;IAGvC,CAAC,MAAM,KAAK,CAAC;AAEhB,QACE,QAAQ,oBAAC,YAAY,UAAb;EAAsB,OAAO;EAAO;EAAgC,CAAA"}
1
+ {"version":3,"file":"zero-provider.js","names":[],"sources":["../../../../zero-react/src/zero-provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {stringCompare} from '../../shared/src/string-compare.ts';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\n// oxlint-disable-next-line no-explicit-any\nexport const ZeroContext = createContext<Zero<any, any, any> | undefined>(\n undefined,\n);\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD, Context>;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport type ZeroProviderProps<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n> = (ZeroOptions<S, MD, Context> | {zero: Zero<S, MD, Context>}) & {\n /**\n * Called after ZeroProvider constructs a new Zero instance.\n *\n * This runs only when the provider creates Zero from options, and is not\n * called when an existing instance is passed with `zero`.\n */\n init?: (zero: Zero<S, MD, Context>) => void;\n children: ReactNode;\n};\n\nexport function ZeroProvider<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>({children, init, ...props}: ZeroProviderProps<S, MD, Context>) {\n const isExternalZero = 'zero' in props;\n\n const [zero, setZero] = useState<Zero<S, MD, Context> | undefined>(\n isExternalZero ? props.zero : undefined,\n );\n const [rotationGeneration, setRotationGeneration] = useState(0);\n\n const auth = 'auth' in props ? props.auth : undefined;\n const hasAuth = typeof auth === 'string';\n const prevAuthRef = useRef<typeof auth>(auth);\n const rotationPendingRef = useRef(false);\n\n const scheduleRotation = () => {\n if (rotationPendingRef.current) {\n return;\n }\n rotationPendingRef.current = true;\n setRotationGeneration(gen => gen + 1);\n };\n\n const keysWithoutAuth = useMemo(\n () =>\n Object.entries(props)\n .filter(([key]) => key !== 'auth')\n .sort(([a], [b]) => stringCompare(a, b))\n .map(([_, value]) => value),\n [props],\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if (isExternalZero) {\n rotationPendingRef.current = false;\n setZero(props.zero);\n return;\n }\n\n const z = new Zero({\n ...props,\n onClientStateNotFound: () => {\n if (rotationPendingRef.current) {\n return;\n }\n\n if (props.onClientStateNotFound) {\n try {\n props.onClientStateNotFound();\n return;\n } catch {\n // rotate since zero client is now closed\n }\n }\n\n scheduleRotation();\n },\n });\n prevAuthRef.current = auth;\n init?.(z);\n setZero(z);\n rotationPendingRef.current = false;\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n // we intentionally don't include auth in the dependency array\n // to avoid closing zero when auth changes\n }, [hasAuth, init, rotationGeneration, ...keysWithoutAuth]);\n\n useEffect(() => {\n if (!zero || isExternalZero) return;\n\n const prevAuth = prevAuthRef.current;\n const authChanged = auth !== prevAuth;\n\n if (authChanged) {\n prevAuthRef.current = auth;\n\n if (typeof prevAuth === 'string' && typeof auth === 'string') {\n void zero.connection.connect({auth});\n }\n }\n }, [auth, zero]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n"],"mappings":";;;;;;AAqBA,IAAa,cAAc,cACzB,KAAA,EACD;AAED,SAAgB,UAIU;CACxB,MAAM,OAAO,WAAW,YAAY;AACpC,KAAI,SAAS,KAAA,EACX,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;;;;;;;;;;;;AAcT,SAAgB,gBAIZ;AACF,cAAa,SAAyB;;AAkBxC,SAAgB,aAId,EAAC,UAAU,MAAM,GAAG,SAA2C;CAC/D,MAAM,iBAAiB,UAAU;CAEjC,MAAM,CAAC,MAAM,WAAW,SACtB,iBAAiB,MAAM,OAAO,KAAA,EAC/B;CACD,MAAM,CAAC,oBAAoB,yBAAyB,SAAS,EAAE;CAE/D,MAAM,OAAO,UAAU,QAAQ,MAAM,OAAO,KAAA;CAC5C,MAAM,UAAU,OAAO,SAAS;CAChC,MAAM,cAAc,OAAoB,KAAK;CAC7C,MAAM,qBAAqB,OAAO,MAAM;CAExC,MAAM,yBAAyB;AAC7B,MAAI,mBAAmB,QACrB;AAEF,qBAAmB,UAAU;AAC7B,yBAAsB,QAAO,MAAM,EAAE;;AAiBvC,iBAAgB;AACd,MAAI,gBAAgB;AAClB,sBAAmB,UAAU;AAC7B,WAAQ,MAAM,KAAK;AACnB;;EAGF,MAAM,IAAI,IAAI,KAAK;GACjB,GAAG;GACH,6BAA6B;AAC3B,QAAI,mBAAmB,QACrB;AAGF,QAAI,MAAM,sBACR,KAAI;AACF,WAAM,uBAAuB;AAC7B;YACM;AAKV,sBAAkB;;GAErB,CAAC;AACF,cAAY,UAAU;AACtB,SAAO,EAAE;AACT,UAAQ,EAAE;AACV,qBAAmB,UAAU;AAE7B,eAAa;AACN,KAAE,OAAO;AACd,WAAQ,KAAA,EAAU;;IAInB;EAAC;EAAS;EAAM;EAAoB,GAnDf,cAEpB,OAAO,QAAQ,MAAM,CAClB,QAAQ,CAAC,SAAS,QAAQ,OAAO,CACjC,MAAM,CAAC,IAAI,CAAC,OAAO,cAAc,GAAG,EAAE,CAAC,CACvC,KAAK,CAAC,GAAG,WAAW,MAAM,EAC/B,CAAC,MAAM,CACR;EA4CyD,CAAC;AAE3D,iBAAgB;AACd,MAAI,CAAC,QAAQ,eAAgB;EAE7B,MAAM,WAAW,YAAY;AAG7B,MAFoB,SAAS,UAEZ;AACf,eAAY,UAAU;AAEtB,OAAI,OAAO,aAAa,YAAY,OAAO,SAAS,SAC7C,MAAK,WAAW,QAAQ,EAAC,MAAK,CAAC;;IAGvC,CAAC,MAAM,KAAK,CAAC;AAEhB,QACE,QAAQ,oBAAC,YAAY,UAAb;EAAsB,OAAO;EAAO;EAAgC,CAAA"}
@@ -19,6 +19,12 @@ export declare function useZero<S extends BaseDefaultSchema = DefaultSchema, MD
19
19
  export declare function createUseZero<S extends BaseDefaultSchema = DefaultSchema, MD extends CustomMutatorDefs | undefined = undefined, Context extends BaseDefaultContext = DefaultContext>(): () => () => Zero<S, MD, Context>;
20
20
  export declare function ZeroProvider<S extends BaseDefaultSchema = DefaultSchema, MD extends CustomMutatorDefs | undefined = undefined, Context extends BaseDefaultContext = DefaultContext>(props: {
21
21
  children: JSX.Element;
22
+ /**
23
+ * Called after ZeroProvider constructs a new Zero instance.
24
+ *
25
+ * This runs only when the provider creates Zero from options, and is not
26
+ * called when an existing instance is passed with `zero`.
27
+ */
22
28
  init?: (zero: Zero<S, MD, Context>) => void;
23
29
  } & ({
24
30
  zero: Zero<S, MD, Context>;
@@ -1 +1 @@
1
- {"version":3,"file":"use-zero.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/use-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,GAAG,EACT,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAOnB;;GAEG;AACH,wBAAgB,UAAU,CACxB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAM5D;AAED,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,sCAGpD;AAED,wBAAgB,YAAY,CAC1B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EAEnD,KAAK,EAAE;IACL,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC7C,GAAG,CACA;IACE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;CAC5B,GACD,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAC9B,eAoDF"}
1
+ {"version":3,"file":"use-zero.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/use-zero.ts"],"names":[],"mappings":"AAAA,OAAO,EAWL,KAAK,GAAG,EACT,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,IAAI,EACJ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,WAAW,EACjB,MAAM,WAAW,CAAC;AAOnB;;GAEG;AACH,wBAAgB,UAAU,CACxB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EACnD,OAAO,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAM5D;AAED,wBAAgB,OAAO,CACrB,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,KAChD,MAAM,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAO9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,sCAGpD;AAED,wBAAgB,YAAY,CAC1B,CAAC,SAAS,iBAAiB,GAAG,aAAa,EAC3C,EAAE,SAAS,iBAAiB,GAAG,SAAS,GAAG,SAAS,EACpD,OAAO,SAAS,kBAAkB,GAAG,cAAc,EAEnD,KAAK,EAAE;IACL,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC;IACtB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAC7C,GAAG,CACA;IACE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;CAC5B,GACD,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAC9B,eAiFF"}
@@ -1,6 +1,6 @@
1
1
  import { Zero } from "../../zero-client/src/client/zero.js";
2
2
  import "./zero.js";
3
- import { batch, createContext, createEffect, createMemo, onCleanup, splitProps, untrack, useContext } from "solid-js";
3
+ import { batch, createContext, createEffect, createMemo, createSignal, onCleanup, splitProps, untrack, useContext } from "solid-js";
4
4
  //#region ../zero-solid/src/use-zero.ts
5
5
  var ZeroContext = createContext(void 0);
6
6
  /**
@@ -33,20 +33,40 @@ function createUseZero() {
33
33
  }
34
34
  function ZeroProvider(props) {
35
35
  let prevAuth = "auth" in props ? props.auth : void 0;
36
+ const [rotationGeneration, setRotationGeneration] = createSignal(0);
36
37
  const auth = createMemo(() => "auth" in props ? props.auth : void 0);
37
38
  const hasAuth = createMemo(() => typeof auth() === "string");
38
39
  const zero = createMemo(() => {
40
+ rotationGeneration();
39
41
  if ("zero" in props) return props.zero;
40
42
  hasAuth();
41
- const [, options] = splitProps(props, ["children", "auth"]);
43
+ const [local, options] = splitProps(props, [
44
+ "children",
45
+ "auth",
46
+ "init"
47
+ ]);
42
48
  const authValue = untrack(auth);
43
49
  prevAuth = authValue;
50
+ let rotationRequested = false;
51
+ const scheduleRotation = () => {
52
+ if (rotationRequested) return;
53
+ rotationRequested = true;
54
+ setRotationGeneration((gen) => gen + 1);
55
+ };
44
56
  const createdZero = new Zero({
45
57
  ...options,
46
58
  ...authValue !== void 0 ? { auth: authValue } : {},
47
- batchViewUpdates: batch
59
+ batchViewUpdates: batch,
60
+ onClientStateNotFound: () => {
61
+ if (rotationRequested) return;
62
+ if (options.onClientStateNotFound) try {
63
+ options.onClientStateNotFound();
64
+ return;
65
+ } catch {}
66
+ scheduleRotation();
67
+ }
48
68
  });
49
- options.init?.(createdZero);
69
+ local.init?.(createdZero);
50
70
  onCleanup(() => createdZero.close());
51
71
  return createdZero;
52
72
  });
@@ -1 +1 @@
1
- {"version":3,"file":"use-zero.js","names":[],"sources":["../../../../zero-solid/src/use-zero.ts"],"sourcesContent":["import {\n batch,\n createContext,\n createEffect,\n createMemo,\n onCleanup,\n splitProps,\n untrack,\n useContext,\n type Accessor,\n type JSX,\n} from 'solid-js';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\nconst ZeroContext = createContext<\n // oxlint-disable-next-line no-explicit-any\n Accessor<Zero<any, any, any>> | undefined\n>(undefined);\n\n/**\n * @deprecated Use {@linkcode ZeroProvider} instead of managing your own Zero instance.\n */\nexport function createZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(options: ZeroOptions<S, MD, Context>): Zero<S, MD, Context> {\n const opts = {\n ...options,\n batchViewUpdates: batch,\n };\n return new Zero<S, MD, Context>(opts);\n}\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): () => Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport function ZeroProvider<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(\n props: {\n children: JSX.Element;\n init?: (zero: Zero<S, MD, Context>) => void;\n } & (\n | {\n zero: Zero<S, MD, Context>;\n }\n | ZeroOptions<S, MD, Context>\n ),\n) {\n let prevAuth = 'auth' in props ? props.auth : undefined;\n\n const auth = createMemo(() => ('auth' in props ? props.auth : undefined));\n const hasAuth = createMemo(() => typeof auth() === 'string');\n\n const zero = createMemo(() => {\n if ('zero' in props) {\n return props.zero;\n }\n\n hasAuth();\n\n const [, options] = splitProps(props, ['children', 'auth']);\n\n const authValue = untrack(auth);\n prevAuth = authValue;\n const createdZero = new Zero({\n ...options,\n ...(authValue !== undefined ? {auth: authValue} : {}),\n batchViewUpdates: batch,\n });\n options.init?.(createdZero);\n onCleanup(() => createdZero.close());\n return createdZero;\n });\n\n createEffect(() => {\n const currentZero = zero();\n if (!currentZero || 'zero' in props) {\n return;\n }\n\n const currentAuth = auth();\n\n if (currentAuth !== prevAuth) {\n const previousAuth = prevAuth;\n prevAuth = currentAuth;\n\n if (typeof previousAuth === 'string' && typeof currentAuth === 'string') {\n void currentZero.connection.connect({auth: currentAuth});\n }\n }\n });\n\n return ZeroContext.Provider({\n value: zero,\n get children() {\n return props.children;\n },\n });\n}\n"],"mappings":";;;;AAsBA,IAAM,cAAc,cAGlB,KAAA,EAAU;;;;AAKZ,SAAgB,WAId,SAA4D;AAK5D,QAAO,IAAI,KAJE;EACX,GAAG;EACH,kBAAkB;EACnB,CACoC;;AAGvC,SAAgB,UAIgB;CAC9B,MAAM,OAAO,WAAW,YAAY;AAEpC,KAAI,SAAS,KAAA,EACX,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;;;;;;;;;;;;AAcT,SAAgB,gBAIZ;AACF,cAAa,SAAyB;;AAGxC,SAAgB,aAKd,OASA;CACA,IAAI,WAAW,UAAU,QAAQ,MAAM,OAAO,KAAA;CAE9C,MAAM,OAAO,iBAAkB,UAAU,QAAQ,MAAM,OAAO,KAAA,EAAW;CACzE,MAAM,UAAU,iBAAiB,OAAO,MAAM,KAAK,SAAS;CAE5D,MAAM,OAAO,iBAAiB;AAC5B,MAAI,UAAU,MACZ,QAAO,MAAM;AAGf,WAAS;EAET,MAAM,GAAG,WAAW,WAAW,OAAO,CAAC,YAAY,OAAO,CAAC;EAE3D,MAAM,YAAY,QAAQ,KAAK;AAC/B,aAAW;EACX,MAAM,cAAc,IAAI,KAAK;GAC3B,GAAG;GACH,GAAI,cAAc,KAAA,IAAY,EAAC,MAAM,WAAU,GAAG,EAAE;GACpD,kBAAkB;GACnB,CAAC;AACF,UAAQ,OAAO,YAAY;AAC3B,kBAAgB,YAAY,OAAO,CAAC;AACpC,SAAO;GACP;AAEF,oBAAmB;EACjB,MAAM,cAAc,MAAM;AAC1B,MAAI,CAAC,eAAe,UAAU,MAC5B;EAGF,MAAM,cAAc,MAAM;AAE1B,MAAI,gBAAgB,UAAU;GAC5B,MAAM,eAAe;AACrB,cAAW;AAEX,OAAI,OAAO,iBAAiB,YAAY,OAAO,gBAAgB,SACxD,aAAY,WAAW,QAAQ,EAAC,MAAM,aAAY,CAAC;;GAG5D;AAEF,QAAO,YAAY,SAAS;EAC1B,OAAO;EACP,IAAI,WAAW;AACb,UAAO,MAAM;;EAEhB,CAAC"}
1
+ {"version":3,"file":"use-zero.js","names":[],"sources":["../../../../zero-solid/src/use-zero.ts"],"sourcesContent":["import {\n batch,\n createContext,\n createEffect,\n createMemo,\n createSignal,\n onCleanup,\n splitProps,\n untrack,\n useContext,\n type Accessor,\n type JSX,\n} from 'solid-js';\nimport {\n Zero,\n type BaseDefaultContext,\n type BaseDefaultSchema,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type ZeroOptions,\n} from './zero.ts';\n\nconst ZeroContext = createContext<\n // oxlint-disable-next-line no-explicit-any\n Accessor<Zero<any, any, any>> | undefined\n>(undefined);\n\n/**\n * @deprecated Use {@linkcode ZeroProvider} instead of managing your own Zero instance.\n */\nexport function createZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(options: ZeroOptions<S, MD, Context>): Zero<S, MD, Context> {\n const opts = {\n ...options,\n batchViewUpdates: batch,\n };\n return new Zero<S, MD, Context>(opts);\n}\n\nexport function useZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(): () => Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport function ZeroProvider<\n S extends BaseDefaultSchema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context extends BaseDefaultContext = DefaultContext,\n>(\n props: {\n children: JSX.Element;\n /**\n * Called after ZeroProvider constructs a new Zero instance.\n *\n * This runs only when the provider creates Zero from options, and is not\n * called when an existing instance is passed with `zero`.\n */\n init?: (zero: Zero<S, MD, Context>) => void;\n } & (\n | {\n zero: Zero<S, MD, Context>;\n }\n | ZeroOptions<S, MD, Context>\n ),\n) {\n let prevAuth = 'auth' in props ? props.auth : undefined;\n const [rotationGeneration, setRotationGeneration] = createSignal(0);\n\n const auth = createMemo(() => ('auth' in props ? props.auth : undefined));\n const hasAuth = createMemo(() => typeof auth() === 'string');\n\n const zero = createMemo(() => {\n rotationGeneration();\n\n if ('zero' in props) {\n return props.zero;\n }\n\n hasAuth();\n\n const [local, options] = splitProps(props, ['children', 'auth', 'init']);\n\n const authValue = untrack(auth);\n prevAuth = authValue;\n let rotationRequested = false;\n\n const scheduleRotation = () => {\n if (rotationRequested) {\n return;\n }\n rotationRequested = true;\n setRotationGeneration(gen => gen + 1);\n };\n\n const createdZero = new Zero({\n ...options,\n ...(authValue !== undefined ? {auth: authValue} : {}),\n batchViewUpdates: batch,\n onClientStateNotFound: () => {\n if (rotationRequested) {\n return;\n }\n\n if (options.onClientStateNotFound) {\n try {\n options.onClientStateNotFound();\n return;\n } catch {\n // rotate since zero client is now closed\n }\n }\n\n scheduleRotation();\n },\n });\n local.init?.(createdZero);\n onCleanup(() => createdZero.close());\n return createdZero;\n });\n\n createEffect(() => {\n const currentZero = zero();\n if (!currentZero || 'zero' in props) {\n return;\n }\n\n const currentAuth = auth();\n\n if (currentAuth !== prevAuth) {\n const previousAuth = prevAuth;\n prevAuth = currentAuth;\n\n if (typeof previousAuth === 'string' && typeof currentAuth === 'string') {\n void currentZero.connection.connect({auth: currentAuth});\n }\n }\n });\n\n return ZeroContext.Provider({\n value: zero,\n get children() {\n return props.children;\n },\n });\n}\n"],"mappings":";;;;AAuBA,IAAM,cAAc,cAGlB,KAAA,EAAU;;;;AAKZ,SAAgB,WAId,SAA4D;AAK5D,QAAO,IAAI,KAJE;EACX,GAAG;EACH,kBAAkB;EACnB,CACoC;;AAGvC,SAAgB,UAIgB;CAC9B,MAAM,OAAO,WAAW,YAAY;AAEpC,KAAI,SAAS,KAAA,EACX,OAAM,IAAI,MAAM,6CAA6C;AAE/D,QAAO;;;;;;;;;;;;;AAcT,SAAgB,gBAIZ;AACF,cAAa,SAAyB;;AAGxC,SAAgB,aAKd,OAeA;CACA,IAAI,WAAW,UAAU,QAAQ,MAAM,OAAO,KAAA;CAC9C,MAAM,CAAC,oBAAoB,yBAAyB,aAAa,EAAE;CAEnE,MAAM,OAAO,iBAAkB,UAAU,QAAQ,MAAM,OAAO,KAAA,EAAW;CACzE,MAAM,UAAU,iBAAiB,OAAO,MAAM,KAAK,SAAS;CAE5D,MAAM,OAAO,iBAAiB;AAC5B,sBAAoB;AAEpB,MAAI,UAAU,MACZ,QAAO,MAAM;AAGf,WAAS;EAET,MAAM,CAAC,OAAO,WAAW,WAAW,OAAO;GAAC;GAAY;GAAQ;GAAO,CAAC;EAExE,MAAM,YAAY,QAAQ,KAAK;AAC/B,aAAW;EACX,IAAI,oBAAoB;EAExB,MAAM,yBAAyB;AAC7B,OAAI,kBACF;AAEF,uBAAoB;AACpB,0BAAsB,QAAO,MAAM,EAAE;;EAGvC,MAAM,cAAc,IAAI,KAAK;GAC3B,GAAG;GACH,GAAI,cAAc,KAAA,IAAY,EAAC,MAAM,WAAU,GAAG,EAAE;GACpD,kBAAkB;GAClB,6BAA6B;AAC3B,QAAI,kBACF;AAGF,QAAI,QAAQ,sBACV,KAAI;AACF,aAAQ,uBAAuB;AAC/B;YACM;AAKV,sBAAkB;;GAErB,CAAC;AACF,QAAM,OAAO,YAAY;AACzB,kBAAgB,YAAY,OAAO,CAAC;AACpC,SAAO;GACP;AAEF,oBAAmB;EACjB,MAAM,cAAc,MAAM;AAC1B,MAAI,CAAC,eAAe,UAAU,MAC5B;EAGF,MAAM,cAAc,MAAM;AAE1B,MAAI,gBAAgB,UAAU;GAC5B,MAAM,eAAe;AACrB,cAAW;AAEX,OAAI,OAAO,iBAAiB,YAAY,OAAO,gBAAgB,SACxD,aAAY,WAAW,QAAQ,EAAC,MAAM,aAAY,CAAC;;GAG5D;AAEF,QAAO,YAAY,SAAS;EAC1B,OAAO;EACP,IAAI,WAAW;AACb,UAAO,MAAM;;EAEhB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/builder/builder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../../../../zql/src/builder/builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,6BAA6B,CAAC;AAE3D,OAAO,KAAK,EACV,GAAG,EAGH,SAAS,EAIT,WAAW,EAEX,QAAQ,EAIT,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAK1E,OAAO,EAEL,KAAK,WAAW,EACjB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,KAAK,EAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,EAAC,MAAM,EAAE,WAAW,EAAC,MAAM,kBAAkB,CAAC;AAK1D,OAAO,KAAK,EAAC,mBAAmB,EAAC,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAkB,KAAK,mBAAmB,EAAC,MAAM,aAAa,CAAC;AAEtE,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,cAAc,CAAC,EAAE,GAAG,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClD,KAAK,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IAElC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAE/C;;;;OAIG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;IAEjD;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAErC,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAEjD,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IAElD,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAEnE,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,KAAK,CAAC;IAEhE;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,SAAS,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,GAAG,EACR,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,mBAAmB,EAC/B,EAAE,CAAC,EAAE,UAAU,EACf,YAAY,CAAC,EAAE,YAAY,GAC1B,KAAK,CAWP;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,GAAG,EACR,qBAAqB,EAAE,qBAAqB,GAAG,SAAS,OAsDzD;AAyBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,CAsB5D;AAkSD,wBAAgB,OAAO,CACrB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,WAAW,EACtB,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,GACX,WAAW,CAsCb;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,WAAW,6EAa7D;AAED,wBAAgB,8BAA8B,CAC5C,SAAS,EAAE,SAAS,GACnB,SAAS,IAAI,mBAAmB,CAQlC;AAuHD,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,UAAU,GACb,IAAI,CAgBN;AA8CD,wBAAgB,0CAA0C,CACxD,IAAI,EAAE,SAAS,GACd,OAAO,CAWT;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,SAAS,SAAS,EAAE,EAChC,SAAS,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,OAAO,uCAYrC"}
@@ -1,19 +1,20 @@
1
1
  import { assert, unreachable } from "../../../shared/src/asserts.js";
2
2
  import { must } from "../../../shared/src/must.js";
3
+ import { completeOrdering } from "../query/complete-ordering.js";
4
+ import { Take } from "../ivm/take.js";
5
+ import { Cap } from "../ivm/cap.js";
3
6
  import { buildFilterPipeline } from "../ivm/filter-operators.js";
4
7
  import { Exists } from "../ivm/exists.js";
5
8
  import { FanIn } from "../ivm/fan-in.js";
6
9
  import { FanOut } from "../ivm/fan-out.js";
7
10
  import { Filter } from "../ivm/filter.js";
11
+ import { createPredicate } from "./filter.js";
8
12
  import { FlippedJoin } from "../ivm/flipped-join.js";
9
13
  import { Join } from "../ivm/join.js";
10
14
  import { Skip } from "../ivm/skip.js";
11
- import { completeOrdering } from "../query/complete-ordering.js";
12
- import { Take } from "../ivm/take.js";
13
15
  import { UnionFanIn } from "../ivm/union-fan-in.js";
14
16
  import { UnionFanOut } from "../ivm/union-fan-out.js";
15
17
  import { planQuery } from "../planner/planner-builder.js";
16
- import { createPredicate } from "./filter.js";
17
18
  //#region ../zql/src/builder/builder.ts
18
19
  /**
19
20
  * Builds a pipeline from an AST. Caller must provide a delegate to create source
@@ -112,7 +113,7 @@ function assertNoNotExists(condition) {
112
113
  default: unreachable(condition);
113
114
  }
114
115
  }
115
- function buildPipelineInternal(ast, delegate, queryID, name, partitionKey) {
116
+ function buildPipelineInternal(ast, delegate, queryID, name, partitionKey, isNonFlippedExistsChild) {
116
117
  const source = delegate.getSource(ast.table);
117
118
  if (!source) throw new Error(`Source not found: ${ast.table}`);
118
119
  ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
@@ -125,7 +126,11 @@ function buildPipelineInternal(ast, delegate, queryID, name, partitionKey) {
125
126
  for (const key of csq.related.correlation.parentField) splitEditKeys.add(key);
126
127
  }
127
128
  if (ast.related) for (const csq of ast.related) for (const key of csq.correlation.parentField) splitEditKeys.add(key);
128
- const conn = source.connect(must(ast.orderBy), ast.where, splitEditKeys, delegate.debug);
129
+ if (isNonFlippedExistsChild) {
130
+ assert(ast.start === void 0, "EXISTS subqueries must not have start");
131
+ assert(ast.related === void 0, "EXISTS subqueries must not have related");
132
+ }
133
+ const conn = source.connect(isNonFlippedExistsChild ? void 0 : must(ast.orderBy), ast.where, splitEditKeys, delegate.debug);
129
134
  let end = delegate.decorateSourceInput(conn, queryID);
130
135
  end = delegate.decorateInput(end, `${name}:source(${ast.table})`);
131
136
  const { fullyAppliedFilters } = conn;
@@ -142,7 +147,12 @@ function buildPipelineInternal(ast, delegate, queryID, name, partitionKey) {
142
147
  }
143
148
  }, delegate, queryID, end, name, true);
144
149
  if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) end = applyWhere(end, ast.where, delegate, name);
145
- if (ast.limit !== void 0) {
150
+ if (ast.limit !== void 0) if (isNonFlippedExistsChild) {
151
+ const capName = `${name}:cap`;
152
+ const cap = new Cap(end, delegate.createStorage(capName), ast.limit, partitionKey);
153
+ delegate.addEdge(end, cap);
154
+ end = delegate.decorateInput(cap, capName);
155
+ } else {
146
156
  const takeName = `${name}:take`;
147
157
  const take = new Take(end, delegate.createStorage(takeName), ast.limit, partitionKey);
148
158
  delegate.addEdge(end, take);
@@ -192,7 +202,7 @@ function applyFilterWithFlips(input, condition, delegate, name) {
192
202
  }
193
203
  case "correlatedSubquery": {
194
204
  const sq = condition.related;
195
- const child = buildPipelineInternal(sq.subquery, delegate, "", `${name}.${sq.subquery.alias}`, sq.correlation.childField);
205
+ const child = buildPipelineInternal(sq.subquery, delegate, "", `${name}.${sq.subquery.alias}`, sq.correlation.childField, false);
196
206
  const flippedJoin = new FlippedJoin({
197
207
  parent: end,
198
208
  child,
@@ -275,7 +285,7 @@ function valuePosName(left) {
275
285
  function applyCorrelatedSubQuery(sq, delegate, queryID, end, name, fromCondition) {
276
286
  if (sq.subquery.limit === 0 && fromCondition) return end;
277
287
  assert(sq.subquery.alias, "Subquery must have an alias");
278
- const child = buildPipelineInternal(sq.subquery, delegate, queryID, `${name}.${sq.subquery.alias}`, sq.correlation.childField);
288
+ const child = buildPipelineInternal(sq.subquery, delegate, queryID, `${name}.${sq.subquery.alias}`, sq.correlation.childField, fromCondition);
279
289
  const joinName = `${name}:join(${sq.subquery.alias})`;
280
290
  const join = new Join({
281
291
  parent: end,