@rocicorp/zero 0.26.0-canary.0 → 0.26.0-canary.10

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 (616) hide show
  1. package/README.md +1 -1
  2. package/out/analyze-query/src/bin-analyze.js +1 -1
  3. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  4. package/out/analyze-query/src/bin-transform.js +3 -1
  5. package/out/analyze-query/src/bin-transform.js.map +1 -1
  6. package/out/analyze-query/src/run-ast.d.ts.map +1 -1
  7. package/out/analyze-query/src/run-ast.js +2 -1
  8. package/out/analyze-query/src/run-ast.js.map +1 -1
  9. package/out/ast-to-zql/src/ast-to-zql.js +16 -9
  10. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  11. package/out/replicache/src/bg-interval.d.ts.map +1 -1
  12. package/out/replicache/src/bg-interval.js +3 -0
  13. package/out/replicache/src/bg-interval.js.map +1 -1
  14. package/out/replicache/src/persist/collect-idb-databases.d.ts +4 -4
  15. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  16. package/out/replicache/src/persist/collect-idb-databases.js +30 -24
  17. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  18. package/out/replicache/src/persist/idb-databases-store.d.ts +2 -1
  19. package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -1
  20. package/out/replicache/src/persist/idb-databases-store.js +1 -1
  21. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  22. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  23. package/out/replicache/src/persist/refresh.js +0 -8
  24. package/out/replicache/src/persist/refresh.js.map +1 -1
  25. package/out/replicache/src/process-scheduler.d.ts +23 -0
  26. package/out/replicache/src/process-scheduler.d.ts.map +1 -1
  27. package/out/replicache/src/process-scheduler.js +50 -1
  28. package/out/replicache/src/process-scheduler.js.map +1 -1
  29. package/out/replicache/src/replicache-impl.d.ts +8 -0
  30. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  31. package/out/replicache/src/replicache-impl.js +11 -2
  32. package/out/replicache/src/replicache-impl.js.map +1 -1
  33. package/out/shared/src/bigint-json.js +1 -1
  34. package/out/shared/src/browser-env.js +0 -4
  35. package/out/shared/src/browser-env.js.map +1 -1
  36. package/out/shared/src/custom-key-map.d.ts +4 -4
  37. package/out/shared/src/custom-key-map.d.ts.map +1 -1
  38. package/out/shared/src/custom-key-map.js.map +1 -1
  39. package/out/shared/src/falsy.d.ts +3 -0
  40. package/out/shared/src/falsy.d.ts.map +1 -0
  41. package/out/shared/src/iterables.d.ts +6 -8
  42. package/out/shared/src/iterables.d.ts.map +1 -1
  43. package/out/shared/src/iterables.js +13 -7
  44. package/out/shared/src/iterables.js.map +1 -1
  45. package/out/shared/src/options.d.ts +1 -0
  46. package/out/shared/src/options.d.ts.map +1 -1
  47. package/out/shared/src/options.js +5 -1
  48. package/out/shared/src/options.js.map +1 -1
  49. package/out/z2s/src/compiler.d.ts.map +1 -1
  50. package/out/z2s/src/compiler.js +23 -0
  51. package/out/z2s/src/compiler.js.map +1 -1
  52. package/out/zero/package.json.js +1 -1
  53. package/out/zero/src/adapters/drizzle.js +1 -2
  54. package/out/zero/src/adapters/prisma.d.ts +2 -0
  55. package/out/zero/src/adapters/prisma.d.ts.map +1 -0
  56. package/out/zero/src/adapters/prisma.js +6 -0
  57. package/out/zero/src/adapters/prisma.js.map +1 -0
  58. package/out/zero/src/pg.js +4 -7
  59. package/out/zero/src/react.js +3 -1
  60. package/out/zero/src/react.js.map +1 -1
  61. package/out/zero/src/server.js +5 -8
  62. package/out/zero/src/zero-cache-dev.js +9 -6
  63. package/out/zero/src/zero-cache-dev.js.map +1 -1
  64. package/out/zero-cache/src/auth/auth.d.ts +45 -0
  65. package/out/zero-cache/src/auth/auth.d.ts.map +1 -0
  66. package/out/zero-cache/src/auth/auth.js +179 -0
  67. package/out/zero-cache/src/auth/auth.js.map +1 -0
  68. package/out/zero-cache/src/auth/load-permissions.d.ts +3 -2
  69. package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
  70. package/out/zero-cache/src/auth/load-permissions.js +17 -9
  71. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  72. package/out/zero-cache/src/auth/read-authorizer.d.ts +3 -3
  73. package/out/zero-cache/src/auth/read-authorizer.d.ts.map +1 -1
  74. package/out/zero-cache/src/auth/read-authorizer.js +4 -4
  75. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  76. package/out/zero-cache/src/auth/write-authorizer.d.ts +6 -0
  77. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  78. package/out/zero-cache/src/auth/write-authorizer.js +19 -4
  79. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  80. package/out/zero-cache/src/config/zero-config.d.ts +53 -9
  81. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  82. package/out/zero-cache/src/config/zero-config.js +91 -20
  83. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  84. package/out/zero-cache/src/custom/fetch.d.ts +6 -3
  85. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  86. package/out/zero-cache/src/custom/fetch.js +142 -76
  87. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  88. package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
  89. package/out/zero-cache/src/custom-queries/transform-query.js +0 -1
  90. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  91. package/out/zero-cache/src/db/lite-tables.d.ts +16 -2
  92. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  93. package/out/zero-cache/src/db/lite-tables.js +34 -28
  94. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  95. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  96. package/out/zero-cache/src/db/migration-lite.js +9 -3
  97. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  98. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  99. package/out/zero-cache/src/db/migration.js +9 -3
  100. package/out/zero-cache/src/db/migration.js.map +1 -1
  101. package/out/zero-cache/src/db/pg-type-parser.d.ts +9 -1
  102. package/out/zero-cache/src/db/pg-type-parser.d.ts.map +1 -1
  103. package/out/zero-cache/src/db/pg-type-parser.js +13 -4
  104. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  105. package/out/zero-cache/src/db/specs.d.ts +4 -3
  106. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  107. package/out/zero-cache/src/db/specs.js +4 -1
  108. package/out/zero-cache/src/db/specs.js.map +1 -1
  109. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  110. package/out/zero-cache/src/db/transaction-pool.js +16 -12
  111. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  112. package/out/zero-cache/src/observability/events.d.ts.map +1 -1
  113. package/out/zero-cache/src/observability/events.js +15 -5
  114. package/out/zero-cache/src/observability/events.js.map +1 -1
  115. package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
  116. package/out/zero-cache/src/server/anonymous-otel-start.js +1 -0
  117. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  118. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  119. package/out/zero-cache/src/server/change-streamer.js +25 -7
  120. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  121. package/out/zero-cache/src/server/inspector-delegate.d.ts +1 -1
  122. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  123. package/out/zero-cache/src/server/inspector-delegate.js +13 -32
  124. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  125. package/out/zero-cache/src/server/main.js +2 -2
  126. package/out/zero-cache/src/server/main.js.map +1 -1
  127. package/out/zero-cache/src/server/priority-op.d.ts +8 -0
  128. package/out/zero-cache/src/server/priority-op.d.ts.map +1 -0
  129. package/out/zero-cache/src/server/priority-op.js +29 -0
  130. package/out/zero-cache/src/server/priority-op.js.map +1 -0
  131. package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
  132. package/out/zero-cache/src/server/runner/run-worker.js +7 -3
  133. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  134. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  135. package/out/zero-cache/src/server/syncer.js +20 -12
  136. package/out/zero-cache/src/server/syncer.js.map +1 -1
  137. package/out/zero-cache/src/services/analyze.d.ts +3 -3
  138. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  139. package/out/zero-cache/src/services/analyze.js +10 -4
  140. package/out/zero-cache/src/services/analyze.js.map +1 -1
  141. package/out/zero-cache/src/services/change-source/change-source.d.ts +19 -0
  142. package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -0
  143. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts +47 -0
  144. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -0
  145. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +426 -0
  146. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -0
  147. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts +55 -0
  148. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -0
  149. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +117 -0
  150. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -0
  151. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +9 -0
  152. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -0
  153. package/out/zero-cache/src/services/change-source/common/replica-schema.js +136 -0
  154. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -0
  155. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
  156. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  157. package/out/zero-cache/src/services/change-source/custom/change-source.js +20 -12
  158. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  159. package/out/zero-cache/src/services/change-source/custom/sync-schema.js +1 -1
  160. package/out/zero-cache/src/services/change-source/custom/sync-schema.js.map +1 -1
  161. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.d.ts +14 -0
  162. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.d.ts.map +1 -0
  163. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js +15 -0
  164. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -0
  165. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +19 -0
  166. package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -0
  167. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +205 -0
  168. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -0
  169. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -1
  170. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  171. package/out/zero-cache/src/services/change-source/pg/change-source.js +177 -40
  172. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  173. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +11 -0
  174. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  175. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +32 -28
  176. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  177. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts +12 -4
  178. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  179. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +20 -11
  180. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  181. package/out/zero-cache/src/services/change-source/pg/lsn.d.ts +3 -3
  182. package/out/zero-cache/src/services/change-source/pg/lsn.d.ts.map +1 -1
  183. package/out/zero-cache/src/services/change-source/pg/lsn.js +9 -4
  184. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  185. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +125 -180
  186. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  187. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +25 -40
  188. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  189. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  190. package/out/zero-cache/src/services/change-source/pg/schema/init.js +47 -11
  191. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  192. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +36 -90
  193. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  194. package/out/zero-cache/src/services/change-source/pg/schema/published.js +65 -14
  195. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  196. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +31 -36
  197. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  198. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +26 -18
  199. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  200. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +2 -2
  201. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
  202. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +2 -4
  203. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  204. package/out/zero-cache/src/services/change-source/pg/sync-schema.js +1 -1
  205. package/out/zero-cache/src/services/change-source/pg/sync-schema.js.map +1 -1
  206. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +213 -54
  207. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  208. package/out/zero-cache/src/services/change-source/protocol/current/data.js +157 -12
  209. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  210. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +267 -76
  211. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  212. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +7 -4
  213. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  214. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +24 -8
  215. package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
  216. package/out/zero-cache/src/services/change-source/protocol/current/status.js +15 -6
  217. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  218. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +31 -2
  219. package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
  220. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +14 -2
  221. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  222. package/out/zero-cache/src/services/change-source/protocol/current.js +18 -6
  223. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +3 -3
  224. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  225. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +40 -18
  226. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  227. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +2 -2
  228. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  229. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +3 -21
  230. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +32 -10
  232. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  233. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +89 -26
  234. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  235. package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
  236. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  237. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +1 -1
  238. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  239. package/out/zero-cache/src/services/change-streamer/forwarder.js +3 -4
  240. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  241. package/out/zero-cache/src/services/change-streamer/schema/init.d.ts.map +1 -1
  242. package/out/zero-cache/src/services/change-streamer/schema/init.js +8 -2
  243. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  244. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +14 -1
  245. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/change-streamer/schema/tables.js +38 -5
  247. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  248. package/out/zero-cache/src/services/change-streamer/storer.d.ts +12 -5
  249. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  250. package/out/zero-cache/src/services/change-streamer/storer.js +223 -27
  251. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  252. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +4 -3
  253. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  254. package/out/zero-cache/src/services/change-streamer/subscriber.js +22 -13
  255. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  256. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  257. package/out/zero-cache/src/services/heapz.js +1 -0
  258. package/out/zero-cache/src/services/heapz.js.map +1 -1
  259. package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
  260. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  261. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  262. package/out/zero-cache/src/services/litestream/commands.d.ts +1 -1
  263. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  264. package/out/zero-cache/src/services/litestream/commands.js +5 -2
  265. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  266. package/out/zero-cache/src/services/litestream/config.yml +1 -0
  267. package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
  268. package/out/zero-cache/src/services/mutagen/error.js +4 -1
  269. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  270. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +4 -4
  271. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  272. package/out/zero-cache/src/services/mutagen/mutagen.js +10 -24
  273. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  274. package/out/zero-cache/src/services/mutagen/pusher.d.ts +8 -6
  275. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  276. package/out/zero-cache/src/services/mutagen/pusher.js +142 -23
  277. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  278. package/out/zero-cache/src/services/replicator/change-processor.d.ts +1 -0
  279. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  280. package/out/zero-cache/src/services/replicator/change-processor.js +182 -68
  281. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  282. package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
  283. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  284. package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -1
  285. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  286. package/out/zero-cache/src/services/replicator/replication-status.js +14 -12
  287. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  288. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +42 -6
  289. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  290. package/out/zero-cache/src/services/replicator/schema/change-log.js +133 -68
  291. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  292. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.d.ts +12 -9
  293. package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts.map +1 -0
  294. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.js +56 -28
  295. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -0
  296. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +7 -1
  297. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  298. package/out/zero-cache/src/services/replicator/schema/replication-state.js +12 -3
  299. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  300. package/out/zero-cache/src/services/replicator/schema/table-metadata.d.ts +24 -0
  301. package/out/zero-cache/src/services/replicator/schema/table-metadata.d.ts.map +1 -0
  302. package/out/zero-cache/src/services/replicator/schema/table-metadata.js +57 -0
  303. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -0
  304. package/out/zero-cache/src/services/run-ast.d.ts +4 -4
  305. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  306. package/out/zero-cache/src/services/run-ast.js +4 -4
  307. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  308. package/out/zero-cache/src/services/running-state.d.ts +1 -0
  309. package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
  310. package/out/zero-cache/src/services/running-state.js +3 -0
  311. package/out/zero-cache/src/services/running-state.js.map +1 -1
  312. package/out/zero-cache/src/services/statz.d.ts +6 -0
  313. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  314. package/out/zero-cache/src/services/statz.js +110 -86
  315. package/out/zero-cache/src/services/statz.js.map +1 -1
  316. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +5 -6
  317. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  318. package/out/zero-cache/src/services/view-syncer/client-handler.js +5 -23
  319. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  320. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +1 -1
  321. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  322. package/out/zero-cache/src/services/view-syncer/cvr-store.js +361 -172
  323. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  324. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +1 -2
  325. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  326. package/out/zero-cache/src/services/view-syncer/cvr.js +392 -333
  327. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  328. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -2
  329. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  330. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +4 -4
  331. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  332. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +15 -23
  333. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  334. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +211 -123
  335. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  336. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
  337. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  338. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +25 -14
  339. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  340. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +19 -19
  341. package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
  342. package/out/zero-cache/src/services/view-syncer/schema/types.js +12 -11
  343. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  344. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +0 -2
  345. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  346. package/out/zero-cache/src/services/view-syncer/snapshotter.js +12 -13
  347. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  348. package/out/zero-cache/src/services/view-syncer/tracer.d.ts +2 -0
  349. package/out/zero-cache/src/services/view-syncer/tracer.d.ts.map +1 -0
  350. package/out/zero-cache/src/services/view-syncer/tracer.js +7 -0
  351. package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -0
  352. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +17 -12
  353. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  354. package/out/zero-cache/src/services/view-syncer/view-syncer.js +374 -344
  355. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  356. package/out/zero-cache/src/types/error-with-level.d.ts +1 -1
  357. package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -1
  358. package/out/zero-cache/src/types/error-with-level.js +1 -1
  359. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  360. package/out/zero-cache/src/types/lexi-version.d.ts +0 -1
  361. package/out/zero-cache/src/types/lexi-version.d.ts.map +1 -1
  362. package/out/zero-cache/src/types/lexi-version.js +4 -5
  363. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  364. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  365. package/out/zero-cache/src/types/lite.js +8 -2
  366. package/out/zero-cache/src/types/lite.js.map +1 -1
  367. package/out/zero-cache/src/types/pg-data-type.d.ts +2 -0
  368. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  369. package/out/zero-cache/src/types/pg-data-type.js +2 -0
  370. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  371. package/out/zero-cache/src/types/pg-types.js +3 -1
  372. package/out/zero-cache/src/types/pg-types.js.map +1 -1
  373. package/out/zero-cache/src/types/pg.d.ts +11 -2
  374. package/out/zero-cache/src/types/pg.d.ts.map +1 -1
  375. package/out/zero-cache/src/types/pg.js +21 -11
  376. package/out/zero-cache/src/types/pg.js.map +1 -1
  377. package/out/zero-cache/src/types/shards.js +1 -1
  378. package/out/zero-cache/src/types/shards.js.map +1 -1
  379. package/out/zero-cache/src/types/sql.d.ts +5 -0
  380. package/out/zero-cache/src/types/sql.d.ts.map +1 -1
  381. package/out/zero-cache/src/types/sql.js +5 -1
  382. package/out/zero-cache/src/types/sql.js.map +1 -1
  383. package/out/zero-cache/src/types/state-version.d.ts +29 -0
  384. package/out/zero-cache/src/types/state-version.d.ts.map +1 -0
  385. package/out/zero-cache/src/types/state-version.js +33 -0
  386. package/out/zero-cache/src/types/state-version.js.map +1 -0
  387. package/out/zero-cache/src/types/streams.d.ts +8 -1
  388. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  389. package/out/zero-cache/src/types/streams.js +22 -8
  390. package/out/zero-cache/src/types/streams.js.map +1 -1
  391. package/out/zero-cache/src/types/subscription.d.ts +1 -1
  392. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  393. package/out/zero-cache/src/types/subscription.js +2 -2
  394. package/out/zero-cache/src/types/subscription.js.map +1 -1
  395. package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
  396. package/out/zero-cache/src/types/websocket-handoff.js +7 -1
  397. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  398. package/out/zero-cache/src/workers/connect-params.d.ts +1 -1
  399. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  400. package/out/zero-cache/src/workers/connect-params.js +2 -3
  401. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  402. package/out/zero-cache/src/workers/connection.js +1 -1
  403. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  404. package/out/zero-cache/src/workers/replicator.js +3 -6
  405. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  406. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts +2 -2
  407. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  408. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +38 -21
  409. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  410. package/out/zero-cache/src/workers/syncer.d.ts +2 -1
  411. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  412. package/out/zero-cache/src/workers/syncer.js +48 -49
  413. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  414. package/out/zero-client/src/client/connection-manager.d.ts +11 -0
  415. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  416. package/out/zero-client/src/client/connection-manager.js +43 -3
  417. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  418. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  419. package/out/zero-client/src/client/connection.js +6 -3
  420. package/out/zero-client/src/client/connection.js.map +1 -1
  421. package/out/zero-client/src/client/context.js +1 -0
  422. package/out/zero-client/src/client/context.js.map +1 -1
  423. package/out/zero-client/src/client/error.d.ts +5 -1
  424. package/out/zero-client/src/client/error.d.ts.map +1 -1
  425. package/out/zero-client/src/client/error.js +4 -4
  426. package/out/zero-client/src/client/error.js.map +1 -1
  427. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  428. package/out/zero-client/src/client/mutator-proxy.js +15 -1
  429. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  430. package/out/zero-client/src/client/options.d.ts +25 -12
  431. package/out/zero-client/src/client/options.d.ts.map +1 -1
  432. package/out/zero-client/src/client/options.js.map +1 -1
  433. package/out/zero-client/src/client/query-manager.d.ts +4 -0
  434. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  435. package/out/zero-client/src/client/query-manager.js +7 -0
  436. package/out/zero-client/src/client/query-manager.js.map +1 -1
  437. package/out/zero-client/src/client/version.js +1 -1
  438. package/out/zero-client/src/client/zero-poke-handler.d.ts +5 -5
  439. package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
  440. package/out/zero-client/src/client/zero-poke-handler.js +15 -17
  441. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  442. package/out/zero-client/src/client/zero.d.ts +12 -8
  443. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  444. package/out/zero-client/src/client/zero.js +95 -12
  445. package/out/zero-client/src/client/zero.js.map +1 -1
  446. package/out/zero-client/src/mod.d.ts +2 -1
  447. package/out/zero-client/src/mod.d.ts.map +1 -1
  448. package/out/zero-protocol/src/ast.d.ts +1 -0
  449. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  450. package/out/zero-protocol/src/ast.js +7 -2
  451. package/out/zero-protocol/src/ast.js.map +1 -1
  452. package/out/zero-protocol/src/connect.d.ts +4 -0
  453. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  454. package/out/zero-protocol/src/connect.js +3 -1
  455. package/out/zero-protocol/src/connect.js.map +1 -1
  456. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  457. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  458. package/out/zero-protocol/src/protocol-version.js +1 -1
  459. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  460. package/out/zero-protocol/src/push.d.ts +26 -0
  461. package/out/zero-protocol/src/push.d.ts.map +1 -1
  462. package/out/zero-protocol/src/push.js +31 -2
  463. package/out/zero-protocol/src/push.js.map +1 -1
  464. package/out/zero-protocol/src/up.d.ts +5 -0
  465. package/out/zero-protocol/src/up.d.ts.map +1 -1
  466. package/out/zero-protocol/src/up.js +2 -0
  467. package/out/zero-protocol/src/up.js.map +1 -1
  468. package/out/zero-protocol/src/update-auth.d.ts +11 -0
  469. package/out/zero-protocol/src/update-auth.d.ts.map +1 -0
  470. package/out/zero-protocol/src/update-auth.js +13 -0
  471. package/out/zero-protocol/src/update-auth.js.map +1 -0
  472. package/out/zero-react/src/mod.d.ts +3 -1
  473. package/out/zero-react/src/mod.d.ts.map +1 -1
  474. package/out/zero-react/src/paging-reducer.d.ts +61 -0
  475. package/out/zero-react/src/paging-reducer.d.ts.map +1 -0
  476. package/out/zero-react/src/paging-reducer.js +77 -0
  477. package/out/zero-react/src/paging-reducer.js.map +1 -0
  478. package/out/zero-react/src/use-query.d.ts +14 -4
  479. package/out/zero-react/src/use-query.d.ts.map +1 -1
  480. package/out/zero-react/src/use-query.js +14 -13
  481. package/out/zero-react/src/use-query.js.map +1 -1
  482. package/out/zero-react/src/use-rows.d.ts +39 -0
  483. package/out/zero-react/src/use-rows.d.ts.map +1 -0
  484. package/out/zero-react/src/use-rows.js +130 -0
  485. package/out/zero-react/src/use-rows.js.map +1 -0
  486. package/out/zero-react/src/use-zero-virtualizer.d.ts +122 -0
  487. package/out/zero-react/src/use-zero-virtualizer.d.ts.map +1 -0
  488. package/out/zero-react/src/use-zero-virtualizer.js +342 -0
  489. package/out/zero-react/src/use-zero-virtualizer.js.map +1 -0
  490. package/out/zero-react/src/zero-provider.d.ts +5 -5
  491. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  492. package/out/zero-react/src/zero-provider.js +1 -1
  493. package/out/zero-react/src/zero-provider.js.map +1 -1
  494. package/out/zero-server/src/adapters/drizzle.d.ts +18 -18
  495. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  496. package/out/zero-server/src/adapters/drizzle.js +8 -22
  497. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  498. package/out/zero-server/src/adapters/pg.d.ts +19 -13
  499. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  500. package/out/zero-server/src/adapters/pg.js.map +1 -1
  501. package/out/zero-server/src/adapters/postgresjs.d.ts +19 -13
  502. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  503. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  504. package/out/zero-server/src/adapters/prisma.d.ts +66 -0
  505. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -0
  506. package/out/zero-server/src/adapters/prisma.js +63 -0
  507. package/out/zero-server/src/adapters/prisma.js.map +1 -0
  508. package/out/zero-server/src/custom.js +1 -15
  509. package/out/zero-server/src/custom.js.map +1 -1
  510. package/out/zero-server/src/mod.d.ts +9 -8
  511. package/out/zero-server/src/mod.d.ts.map +1 -1
  512. package/out/zero-server/src/process-mutations.d.ts +2 -1
  513. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  514. package/out/zero-server/src/process-mutations.js +39 -4
  515. package/out/zero-server/src/process-mutations.js.map +1 -1
  516. package/out/zero-server/src/push-processor.js +1 -1
  517. package/out/zero-server/src/push-processor.js.map +1 -1
  518. package/out/zero-server/src/schema.d.ts.map +1 -1
  519. package/out/zero-server/src/schema.js +4 -1
  520. package/out/zero-server/src/schema.js.map +1 -1
  521. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  522. package/out/zero-server/src/zql-database.js +18 -0
  523. package/out/zero-server/src/zql-database.js.map +1 -1
  524. package/out/zero-solid/src/mod.d.ts +1 -1
  525. package/out/zero-solid/src/mod.d.ts.map +1 -1
  526. package/out/zero-solid/src/solid-view.d.ts +42 -0
  527. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  528. package/out/zero-solid/src/solid-view.js +2 -1
  529. package/out/zero-solid/src/solid-view.js.map +1 -1
  530. package/out/zero-solid/src/use-query.d.ts +12 -3
  531. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  532. package/out/zero-solid/src/use-query.js +22 -5
  533. package/out/zero-solid/src/use-query.js.map +1 -1
  534. package/out/zero-solid/src/use-zero.d.ts +5 -5
  535. package/out/zero-solid/src/use-zero.d.ts.map +1 -1
  536. package/out/zero-solid/src/use-zero.js +1 -1
  537. package/out/zero-solid/src/use-zero.js.map +1 -1
  538. package/out/zero-types/src/default-types.d.ts +2 -0
  539. package/out/zero-types/src/default-types.d.ts.map +1 -1
  540. package/out/zql/src/builder/builder.d.ts.map +1 -1
  541. package/out/zql/src/builder/builder.js.map +1 -1
  542. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  543. package/out/zql/src/ivm/array-view.js +57 -6
  544. package/out/zql/src/ivm/array-view.js.map +1 -1
  545. package/out/zql/src/ivm/constraint.d.ts.map +1 -1
  546. package/out/zql/src/ivm/constraint.js +4 -1
  547. package/out/zql/src/ivm/constraint.js.map +1 -1
  548. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  549. package/out/zql/src/ivm/exists.js +4 -1
  550. package/out/zql/src/ivm/exists.js.map +1 -1
  551. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  552. package/out/zql/src/ivm/join-utils.js +8 -2
  553. package/out/zql/src/ivm/join-utils.js.map +1 -1
  554. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  555. package/out/zql/src/ivm/memory-source.js +12 -3
  556. package/out/zql/src/ivm/memory-source.js.map +1 -1
  557. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  558. package/out/zql/src/ivm/push-accumulated.js +25 -2
  559. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  560. package/out/zql/src/ivm/stream.d.ts.map +1 -1
  561. package/out/zql/src/ivm/stream.js +1 -1
  562. package/out/zql/src/ivm/stream.js.map +1 -1
  563. package/out/zql/src/ivm/take.d.ts.map +1 -1
  564. package/out/zql/src/ivm/take.js +24 -6
  565. package/out/zql/src/ivm/take.js.map +1 -1
  566. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  567. package/out/zql/src/ivm/union-fan-in.js +12 -3
  568. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  569. package/out/zql/src/ivm/view-apply-change.d.ts +50 -3
  570. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  571. package/out/zql/src/ivm/view-apply-change.js +358 -105
  572. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  573. package/out/zql/src/mutate/mutator-registry.d.ts +3 -3
  574. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  575. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  576. package/out/zql/src/mutate/mutator.js +4 -4
  577. package/out/zql/src/mutate/mutator.js.map +1 -1
  578. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  579. package/out/zql/src/planner/planner-builder.js.map +1 -1
  580. package/out/zql/src/query/create-builder.js +3 -5
  581. package/out/zql/src/query/create-builder.js.map +1 -1
  582. package/out/zql/src/query/expression.d.ts +7 -7
  583. package/out/zql/src/query/expression.d.ts.map +1 -1
  584. package/out/zql/src/query/expression.js +14 -7
  585. package/out/zql/src/query/expression.js.map +1 -1
  586. package/out/zql/src/query/query-delegate-base.js +1 -3
  587. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  588. package/out/zql/src/query/query-impl.d.ts +3 -4
  589. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  590. package/out/zql/src/query/query-impl.js +15 -15
  591. package/out/zql/src/query/query-impl.js.map +1 -1
  592. package/out/zql/src/query/query-registry.d.ts +3 -3
  593. package/out/zql/src/query/query-registry.d.ts.map +1 -1
  594. package/out/zql/src/query/query-registry.js +4 -4
  595. package/out/zql/src/query/query-registry.js.map +1 -1
  596. package/out/zql/src/query/query.d.ts +31 -8
  597. package/out/zql/src/query/query.d.ts.map +1 -1
  598. package/out/zqlite/src/resolve-scalar-subqueries.d.ts +55 -0
  599. package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -0
  600. package/out/zqlite/src/resolve-scalar-subqueries.js +139 -0
  601. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -0
  602. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  603. package/out/zqlite/src/table-source.d.ts.map +1 -1
  604. package/out/zqlite/src/table-source.js +1 -2
  605. package/out/zqlite/src/table-source.js.map +1 -1
  606. package/package.json +11 -9
  607. package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +0 -1
  608. package/out/zero-cache/src/services/change-source/column-metadata.js.map +0 -1
  609. package/out/zero-cache/src/services/change-source/replica-schema.d.ts +0 -7
  610. package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +0 -1
  611. package/out/zero-cache/src/services/change-source/replica-schema.js +0 -76
  612. package/out/zero-cache/src/services/change-source/replica-schema.js.map +0 -1
  613. package/out/zero-cache/src/types/schema-versions.d.ts +0 -12
  614. package/out/zero-cache/src/types/schema-versions.d.ts.map +0 -1
  615. package/out/zero-cache/src/types/schema-versions.js +0 -28
  616. package/out/zero-cache/src/types/schema-versions.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Documentation
4
4
 
5
- [https://zero.rocicorp.dev/docs/introduction](https://zero.rocicorp.dev/docs/introduction)
5
+ Read over the [docs](https://zero.rocicorp.dev/docs/introduction). For AI assistants: [llms.txt](https://zero.rocicorp.dev/llms.txt).
6
6
 
7
7
  ## Install
8
8
 
@@ -175,7 +175,7 @@ const clientSchema = clientSchemaFrom(schema).clientSchema;
175
175
  const sources = /* @__PURE__ */ new Map();
176
176
  const clientToServerMapper = clientToServer(schema.tables);
177
177
  const debug = new Debug();
178
- const tableSpecs = computeZqlSpecs(lc, db);
178
+ const tableSpecs = computeZqlSpecs(lc, db, { includeBackfillingColumns: false });
179
179
  class AnalyzeQueryDelegate extends QueryDelegateBase {
180
180
  debug = debug;
181
181
  defaultQueryComplete = true;
@@ -1 +1 @@
1
- {"version":3,"file":"bin-analyze.js","sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport chalk from 'chalk';\nimport fs from 'node:fs';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {testLogConfig} from '../../otel/src/test-log-config.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {PullRow, Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\nimport {explainQueries} from './explain-queries.ts';\nimport {runAst} from './run-ast.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: [`File path to the SQLite replica to test queries against.`],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n `Query to be analyzed in the form of: table.where(...).related(...).etc. `,\n `Only one of ast/query/hash should be provided.`,\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n `Hash of the query to be analyzed. This is used to look up the query in the database. `,\n `Only one of ast/query/hash should be provided.`,\n `You should run this script from the directory containing your .env file to reduce the amount of`,\n `configuration required. The .env file should contain the connection URL to the CVR database.`,\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n // the command line parses drops all text after the first newline\n // so we need to replace newlines with spaces\n // before parsing\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug();\nconst tableSpecs = computeZqlSpecs(lc, db);\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n\n getSource(serverTableName: string): Source | undefined {\n let source = sources.get(serverTableName);\n if (source) {\n return source;\n }\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n testLogConfig,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n\n sources.set(serverTableName, source);\n return source;\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n // the user likely has a transformed AST since the wire and storage formats are the transformed AST\n result = await runAst(lc, clientSchema, JSON.parse(config.ast), true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(lc, clientSchema, ast, false, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(lc, clientSchema, ast, true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(chalk.blue.bold('=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(chalk.bold(table + ':'), rows);\n }\n}\n\ncolorConsole.log(chalk.blue.bold('=== Query Stats: ===\\n'));\ncolorConsole.log(chalk.bold('total synced rows:'), result.syncedRowCount);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(chalk.blue.bold('=== JS Row Scan Values: ===\\n'));\n for (const source of sources.values()) {\n colorConsole.log(\n chalk.bold(`${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(chalk.blue.bold('\\n=== Rows Scanned (by SQLite): ===\\n'));\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(chalk.bold(`${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n chalk.bold('total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(chalk.blue.bold('\\n\\n=== Query Plans: ===\\n'));\nconst plans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(chalk.bold('query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n chalk.bold(source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n chalk.bold('Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n chalk.bold('time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return chalk.green(duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return chalk.yellow(duration.toFixed(2) + 'ms');\n }\n return chalk.red(duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return chalk.green(n.toString());\n } else if (n < 10000) {\n return chalk.yellow(n.toString());\n }\n return chalk.red(n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return chalk.yellow(row);\n }\n return chalk.red(row);\n }\n return chalk.green(row);\n}\n"],"names":["v.string","v.boolean","v"],"mappings":"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"}
1
+ {"version":3,"file":"bin-analyze.js","sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport chalk from 'chalk';\nimport fs from 'node:fs';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {testLogConfig} from '../../otel/src/test-log-config.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {PullRow, Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\nimport {explainQueries} from './explain-queries.ts';\nimport {runAst} from './run-ast.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: [`File path to the SQLite replica to test queries against.`],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n `Query to be analyzed in the form of: table.where(...).related(...).etc. `,\n `Only one of ast/query/hash should be provided.`,\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n `Hash of the query to be analyzed. This is used to look up the query in the database. `,\n `Only one of ast/query/hash should be provided.`,\n `You should run this script from the directory containing your .env file to reduce the amount of`,\n `configuration required. The .env file should contain the connection URL to the CVR database.`,\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n // the command line parses drops all text after the first newline\n // so we need to replace newlines with spaces\n // before parsing\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug();\nconst tableSpecs = computeZqlSpecs(lc, db, {includeBackfillingColumns: false});\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n\n getSource(serverTableName: string): Source | undefined {\n let source = sources.get(serverTableName);\n if (source) {\n return source;\n }\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n testLogConfig,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n\n sources.set(serverTableName, source);\n return source;\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n // the user likely has a transformed AST since the wire and storage formats are the transformed AST\n result = await runAst(lc, clientSchema, JSON.parse(config.ast), true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(lc, clientSchema, ast, false, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(lc, clientSchema, ast, true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(chalk.blue.bold('=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(chalk.bold(table + ':'), rows);\n }\n}\n\ncolorConsole.log(chalk.blue.bold('=== Query Stats: ===\\n'));\ncolorConsole.log(chalk.bold('total synced rows:'), result.syncedRowCount);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(chalk.blue.bold('=== JS Row Scan Values: ===\\n'));\n for (const source of sources.values()) {\n colorConsole.log(\n chalk.bold(`${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(chalk.blue.bold('\\n=== Rows Scanned (by SQLite): ===\\n'));\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(chalk.bold(`${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n chalk.bold('total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(chalk.blue.bold('\\n\\n=== Query Plans: ===\\n'));\nconst plans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(chalk.bold('query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n chalk.bold(source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n chalk.bold('Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n chalk.bold('time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return chalk.green(duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return chalk.yellow(duration.toFixed(2) + 'ms');\n }\n return chalk.red(duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return chalk.green(n.toString());\n } else if (n < 10000) {\n return chalk.yellow(n.toString());\n }\n return chalk.red(n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return chalk.yellow(row);\n }\n return chalk.red(row);\n }\n return chalk.green(row);\n}\n"],"names":["v.string","v.boolean","v"],"mappings":"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"}
@@ -36,7 +36,9 @@ const queryAst = transformAndHashQuery(
36
36
  "",
37
37
  rows[0].clientAST,
38
38
  permissions,
39
- {},
39
+ {
40
+ decoded: {}
41
+ },
40
42
  rows[0].internal
41
43
  ).transformedAst;
42
44
  console.log("\n=== AST ===\n");
@@ -1 +1 @@
1
- {"version":3,"file":"bin-transform.js","sources":["../../../../analyze-query/src/bin-transform.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {loadSchemaAndPermissions} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\n\nconst options = {\n cvr: {db: v.string()},\n schema: {\n type: v.string().default('./schema.ts'),\n desc: ['Path to the schema file.'],\n },\n app: appOptions,\n shard: shardOptions,\n hash: {\n type: v.string().optional(),\n desc: ['Hash of the query to fetch the AST for.'],\n },\n};\n\nconst config = parseOptions(options, {envNamePrefix: ZERO_ENV_VAR_PREFIX});\n\nconst lc = new LogContext('debug', {}, consoleLogSink);\nconst {permissions} = await loadSchemaAndPermissions(config.schema);\n\nconst cvrDB = pgClient(lc, config.cvr.db);\n\nconst rows =\n await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(upstreamSchema(getShardID(config)) + '/cvr')}.\"queries\" where \"queryHash\" = ${must(\n config.hash,\n )} limit 1;`;\n\nconst queryAst = transformAndHashQuery(\n lc,\n '',\n rows[0].clientAST,\n permissions,\n {},\n rows[0].internal,\n).transformedAst;\n\n// oxlint-disable no-console\nconsole.log('\\n=== AST ===\\n');\nconsole.log(JSON.stringify(queryAst, null, 2));\nconsole.log('\\n=== ZQL ===\\n');\nconsole.log(await formatOutput(queryAst.table + astToZQL(queryAst)));\n// oxlint-enable no-console\n\nawait cvrDB.end();\n"],"names":["v.string"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,UAAU;AAAA,EACd,KAAK,EAAC,IAAIA,SAAS;AAAA,EACnB,QAAQ;AAAA,IACN,MAAMA,OAAE,EAAS,QAAQ,aAAa;AAAA,IACtC,MAAM,CAAC,0BAA0B;AAAA,EAAA;AAAA,EAEnC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM,CAAC,yCAAyC;AAAA,EAAA;AAEpD;AAEA,MAAM,SAAS,aAAa,SAAS,EAAC,eAAe,qBAAoB;AAEzE,MAAM,KAAK,IAAI,WAAW,SAAS,CAAA,GAAI,cAAc;AACrD,MAAM,EAAC,YAAA,IAAe,MAAM,yBAAyB,OAAO,MAAM;AAElE,MAAM,QAAQ,SAAS,IAAI,OAAO,IAAI,EAAE;AAExC,MAAM,OACJ,MAAM,4CAA4C,MAAM,eAAe,WAAW,MAAM,CAAC,IAAI,MAAM,CAAC,kCAAkC;AAAA,EACpI,OAAO;AACT,CAAC;AAEH,MAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA,KAAK,CAAC,EAAE;AAAA,EACR;AAAA,EACA,CAAA;AAAA,EACA,KAAK,CAAC,EAAE;AACV,EAAE;AAGF,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7C,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,MAAM,aAAa,SAAS,QAAQ,SAAS,QAAQ,CAAC,CAAC;AAGnE,MAAM,MAAM,IAAA;"}
1
+ {"version":3,"file":"bin-transform.js","sources":["../../../../analyze-query/src/bin-transform.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {loadSchemaAndPermissions} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\n\nconst options = {\n cvr: {db: v.string()},\n schema: {\n type: v.string().default('./schema.ts'),\n desc: ['Path to the schema file.'],\n },\n app: appOptions,\n shard: shardOptions,\n hash: {\n type: v.string().optional(),\n desc: ['Hash of the query to fetch the AST for.'],\n },\n};\n\nconst config = parseOptions(options, {envNamePrefix: ZERO_ENV_VAR_PREFIX});\n\nconst lc = new LogContext('debug', {}, consoleLogSink);\nconst {permissions} = await loadSchemaAndPermissions(config.schema);\n\nconst cvrDB = pgClient(lc, config.cvr.db);\n\nconst rows =\n await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(upstreamSchema(getShardID(config)) + '/cvr')}.\"queries\" where \"queryHash\" = ${must(\n config.hash,\n )} limit 1;`;\n\nconst queryAst = transformAndHashQuery(\n lc,\n '',\n rows[0].clientAST,\n permissions,\n {\n type: 'jwt',\n raw: '',\n decoded: {},\n },\n rows[0].internal,\n).transformedAst;\n\n// oxlint-disable no-console\nconsole.log('\\n=== AST ===\\n');\nconsole.log(JSON.stringify(queryAst, null, 2));\nconsole.log('\\n=== ZQL ===\\n');\nconsole.log(await formatOutput(queryAst.table + astToZQL(queryAst)));\n// oxlint-enable no-console\n\nawait cvrDB.end();\n"],"names":["v.string"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,UAAU;AAAA,EACd,KAAK,EAAC,IAAIA,SAAS;AAAA,EACnB,QAAQ;AAAA,IACN,MAAMA,OAAE,EAAS,QAAQ,aAAa;AAAA,IACtC,MAAM,CAAC,0BAA0B;AAAA,EAAA;AAAA,EAEnC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM,CAAC,yCAAyC;AAAA,EAAA;AAEpD;AAEA,MAAM,SAAS,aAAa,SAAS,EAAC,eAAe,qBAAoB;AAEzE,MAAM,KAAK,IAAI,WAAW,SAAS,CAAA,GAAI,cAAc;AACrD,MAAM,EAAC,YAAA,IAAe,MAAM,yBAAyB,OAAO,MAAM;AAElE,MAAM,QAAQ,SAAS,IAAI,OAAO,IAAI,EAAE;AAExC,MAAM,OACJ,MAAM,4CAA4C,MAAM,eAAe,WAAW,MAAM,CAAC,IAAI,MAAM,CAAC,kCAAkC;AAAA,EACpI,OAAO;AACT,CAAC;AAEH,MAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA,KAAK,CAAC,EAAE;AAAA,EACR;AAAA,EACA;AAAA,IAGE,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ,KAAK,CAAC,EAAE;AACV,EAAE;AAGF,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7C,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,MAAM,aAAa,SAAS,QAAQ,SAAS,QAAQ,CAAC,CAAC;AAGnE,MAAM,MAAM,IAAA;"}
@@ -1 +1 @@
1
- {"version":3,"file":"run-ast.d.ts","sourceRoot":"","sources":["../../../../analyze-query/src/run-ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAMjD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAErE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iDAAiD,CAAC;AACxF,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,gCAAgC,CAAC;AAExD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAG3E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,oBAAoB,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9C,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,wBAAsB,MAAM,CAC1B,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,kBAAkB,CAAC,CA6F7B"}
1
+ {"version":3,"file":"run-ast.d.ts","sourceRoot":"","sources":["../../../../analyze-query/src/run-ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAErE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iDAAiD,CAAC;AACxF,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,gCAAgC,CAAC;AAExD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAG3E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,oBAAoB,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9C,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,wBAAsB,MAAM,CAC1B,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,kBAAkB,CAAC,CA8F7B"}
@@ -33,6 +33,7 @@ async function runAst(lc, clientSchema, ast, isTransformed, options) {
33
33
  "No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced."
34
34
  );
35
35
  }
36
+ const auth = { decoded: authData };
36
37
  ast = transformAndHashQuery(
37
38
  lc,
38
39
  "clientGroupIDForAnalyze",
@@ -41,7 +42,7 @@ async function runAst(lc, clientSchema, ast, isTransformed, options) {
41
42
  permissions,
42
43
  "Permissions are required when applyPermissions is true"
43
44
  ),
44
- authData,
45
+ auth,
45
46
  false
46
47
  ).transformedAst;
47
48
  result.afterPermissions = await formatOutput(ast.table + astToZQL(ast));
@@ -1 +1 @@
1
- {"version":3,"file":"run-ast.js","sources":["../../../../analyze-query/src/run-ast.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport type {LiteAndZqlSpec} from '../../zero-cache/src/db/specs.ts';\nimport {hydrate} from '../../zero-cache/src/services/view-syncer/pipeline-driver.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport {mapAST} from '../../zero-protocol/src/ast.ts';\nimport type {ClientSchema} from '../../zero-protocol/src/client-schema.ts';\nimport type {Row} from '../../zero-protocol/src/data.ts';\nimport {hashOfAST} from '../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../zero-schema/src/compiled-permissions.ts';\nimport type {NameMapper} from '../../zero-schema/src/name-mapper.ts';\nimport {\n buildPipeline,\n type BuilderDelegate,\n} from '../../zql/src/builder/builder.ts';\nimport type {Database} from '../../zqlite/src/db.ts';\n\nexport type RunAstOptions = {\n applyPermissions?: boolean | undefined;\n authData?: string | undefined;\n clientToServerMapper?: NameMapper | undefined;\n db: Database;\n host: BuilderDelegate;\n permissions?: PermissionsConfig | undefined;\n syncedRows?: boolean | undefined;\n tableSpecs: Map<string, LiteAndZqlSpec>;\n vendedRows?: boolean | undefined;\n};\n\nexport async function runAst(\n lc: LogContext,\n clientSchema: ClientSchema,\n ast: AST,\n isTransformed: boolean,\n options: RunAstOptions,\n): Promise<AnalyzeQueryResult> {\n const {clientToServerMapper, permissions, host} = options;\n const result: AnalyzeQueryResult = {\n warnings: [],\n syncedRows: undefined,\n syncedRowCount: 0,\n start: 0,\n end: 0,\n afterPermissions: undefined,\n readRows: undefined,\n readRowCountsByQuery: {},\n readRowCount: undefined,\n };\n\n if (!isTransformed) {\n // map the AST to server names if not already transformed\n ast = mapAST(ast, must(clientToServerMapper));\n }\n if (options.applyPermissions) {\n result.warnings.push(\n 'Permissions are deprecated and will be removed in an upcoming release. See: https://zero.rocicorp.dev/docs/auth.',\n );\n\n const authData = options.authData ? JSON.parse(options.authData) : {};\n if (!options.authData) {\n result.warnings.push(\n 'No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced.',\n );\n }\n ast = transformAndHashQuery(\n lc,\n 'clientGroupIDForAnalyze',\n ast,\n must(\n permissions,\n 'Permissions are required when applyPermissions is true',\n ),\n authData,\n false,\n ).transformedAst;\n result.afterPermissions = await formatOutput(ast.table + astToZQL(ast));\n }\n const pipeline = buildPipeline(ast, host, 'query-id');\n\n const start = performance.now();\n\n let syncedRowCount = 0;\n const rowsByTable: Record<string, Row[]> = {};\n const seenByTable: Set<string> = new Set();\n for (const rowChange of hydrate(pipeline, hashOfAST(ast), clientSchema)) {\n if (rowChange === 'yield') {\n continue;\n }\n assert(rowChange.type === 'add');\n\n let rows: Row[] = rowsByTable[rowChange.table];\n const s = rowChange.table + '.' + JSON.stringify(rowChange.row);\n if (seenByTable.has(s)) {\n continue; // skip duplicates\n }\n syncedRowCount++;\n seenByTable.add(s);\n if (options.syncedRows) {\n if (!rows) {\n rows = [];\n rowsByTable[rowChange.table] = rows;\n }\n rows.push(rowChange.row);\n }\n }\n\n const end = performance.now();\n if (options.syncedRows) {\n result.syncedRows = rowsByTable;\n }\n result.start = start;\n result.end = end;\n\n // Always include the count of synced and vended rows.\n result.syncedRowCount = syncedRowCount;\n result.readRowCountsByQuery = host.debug?.getVendedRowCounts() ?? {};\n let readRowCount = 0;\n for (const c of Object.values(result.readRowCountsByQuery)) {\n for (const v of Object.values(c)) {\n readRowCount += v;\n }\n }\n result.readRowCount = readRowCount;\n\n if (options.vendedRows) {\n result.readRows = host.debug?.getVendedRows();\n }\n return result;\n}\n"],"names":[],"mappings":";;;;;;;;;AAkCA,eAAsB,OACpB,IACA,cACA,KACA,eACA,SAC6B;AAC7B,QAAM,EAAC,sBAAsB,aAAa,KAAA,IAAQ;AAClD,QAAM,SAA6B;AAAA,IACjC,UAAU,CAAA;AAAA,IACV,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,KAAK;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,sBAAsB,CAAA;AAAA,IACtB,cAAc;AAAA,EAAA;AAGhB,MAAI,CAAC,eAAe;AAElB,UAAM,OAAO,KAAK,KAAK,oBAAoB,CAAC;AAAA,EAC9C;AACA,MAAI,QAAQ,kBAAkB;AAC5B,WAAO,SAAS;AAAA,MACd;AAAA,IAAA;AAGF,UAAM,WAAW,QAAQ,WAAW,KAAK,MAAM,QAAQ,QAAQ,IAAI,CAAA;AACnE,QAAI,CAAC,QAAQ,UAAU;AACrB,aAAO,SAAS;AAAA,QACd;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA,EACA;AACF,WAAO,mBAAmB,MAAM,aAAa,IAAI,QAAQ,SAAS,GAAG,CAAC;AAAA,EACxE;AACA,QAAM,WAAW,cAAc,KAAK,MAAM,UAAU;AAEpD,QAAM,QAAQ,YAAY,IAAA;AAE1B,MAAI,iBAAiB;AACrB,QAAM,cAAqC,CAAA;AAC3C,QAAM,kCAA+B,IAAA;AACrC,aAAW,aAAa,QAAQ,UAAU,UAAU,GAAG,GAAG,YAAY,GAAG;AACvE,QAAI,cAAc,SAAS;AACzB;AAAA,IACF;AACA,WAAO,UAAU,SAAS,KAAK;AAE/B,QAAI,OAAc,YAAY,UAAU,KAAK;AAC7C,UAAM,IAAI,UAAU,QAAQ,MAAM,KAAK,UAAU,UAAU,GAAG;AAC9D,QAAI,YAAY,IAAI,CAAC,GAAG;AACtB;AAAA,IACF;AACA;AACA,gBAAY,IAAI,CAAC;AACjB,QAAI,QAAQ,YAAY;AACtB,UAAI,CAAC,MAAM;AACT,eAAO,CAAA;AACP,oBAAY,UAAU,KAAK,IAAI;AAAA,MACjC;AACA,WAAK,KAAK,UAAU,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,MAAM,YAAY,IAAA;AACxB,MAAI,QAAQ,YAAY;AACtB,WAAO,aAAa;AAAA,EACtB;AACA,SAAO,QAAQ;AACf,SAAO,MAAM;AAGb,SAAO,iBAAiB;AACxB,SAAO,uBAAuB,KAAK,OAAO,mBAAA,KAAwB,CAAA;AAClE,MAAI,eAAe;AACnB,aAAW,KAAK,OAAO,OAAO,OAAO,oBAAoB,GAAG;AAC1D,eAAW,KAAK,OAAO,OAAO,CAAC,GAAG;AAChC,sBAAgB;AAAA,IAClB;AAAA,EACF;AACA,SAAO,eAAe;AAEtB,MAAI,QAAQ,YAAY;AACtB,WAAO,WAAW,KAAK,OAAO,cAAA;AAAA,EAChC;AACA,SAAO;AACT;"}
1
+ {"version":3,"file":"run-ast.js","sources":["../../../../analyze-query/src/run-ast.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {JWTAuth} from '../../zero-cache/src/auth/auth.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport type {LiteAndZqlSpec} from '../../zero-cache/src/db/specs.ts';\nimport {hydrate} from '../../zero-cache/src/services/view-syncer/pipeline-driver.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport {mapAST} from '../../zero-protocol/src/ast.ts';\nimport type {ClientSchema} from '../../zero-protocol/src/client-schema.ts';\nimport type {Row} from '../../zero-protocol/src/data.ts';\nimport {hashOfAST} from '../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../zero-schema/src/compiled-permissions.ts';\nimport type {NameMapper} from '../../zero-schema/src/name-mapper.ts';\nimport {\n buildPipeline,\n type BuilderDelegate,\n} from '../../zql/src/builder/builder.ts';\nimport type {Database} from '../../zqlite/src/db.ts';\n\nexport type RunAstOptions = {\n applyPermissions?: boolean | undefined;\n authData?: string | undefined;\n clientToServerMapper?: NameMapper | undefined;\n db: Database;\n host: BuilderDelegate;\n permissions?: PermissionsConfig | undefined;\n syncedRows?: boolean | undefined;\n tableSpecs: Map<string, LiteAndZqlSpec>;\n vendedRows?: boolean | undefined;\n};\n\nexport async function runAst(\n lc: LogContext,\n clientSchema: ClientSchema,\n ast: AST,\n isTransformed: boolean,\n options: RunAstOptions,\n): Promise<AnalyzeQueryResult> {\n const {clientToServerMapper, permissions, host} = options;\n const result: AnalyzeQueryResult = {\n warnings: [],\n syncedRows: undefined,\n syncedRowCount: 0,\n start: 0,\n end: 0,\n afterPermissions: undefined,\n readRows: undefined,\n readRowCountsByQuery: {},\n readRowCount: undefined,\n };\n\n if (!isTransformed) {\n // map the AST to server names if not already transformed\n ast = mapAST(ast, must(clientToServerMapper));\n }\n if (options.applyPermissions) {\n result.warnings.push(\n 'Permissions are deprecated and will be removed in an upcoming release. See: https://zero.rocicorp.dev/docs/auth.',\n );\n\n const authData = options.authData ? JSON.parse(options.authData) : {};\n if (!options.authData) {\n result.warnings.push(\n 'No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced.',\n );\n }\n const auth: JWTAuth = {type: 'jwt', raw: '', decoded: authData};\n ast = transformAndHashQuery(\n lc,\n 'clientGroupIDForAnalyze',\n ast,\n must(\n permissions,\n 'Permissions are required when applyPermissions is true',\n ),\n auth,\n false,\n ).transformedAst;\n result.afterPermissions = await formatOutput(ast.table + astToZQL(ast));\n }\n const pipeline = buildPipeline(ast, host, 'query-id');\n\n const start = performance.now();\n\n let syncedRowCount = 0;\n const rowsByTable: Record<string, Row[]> = {};\n const seenByTable: Set<string> = new Set();\n for (const rowChange of hydrate(pipeline, hashOfAST(ast), clientSchema)) {\n if (rowChange === 'yield') {\n continue;\n }\n assert(rowChange.type === 'add');\n\n let rows: Row[] = rowsByTable[rowChange.table];\n const s = rowChange.table + '.' + JSON.stringify(rowChange.row);\n if (seenByTable.has(s)) {\n continue; // skip duplicates\n }\n syncedRowCount++;\n seenByTable.add(s);\n if (options.syncedRows) {\n if (!rows) {\n rows = [];\n rowsByTable[rowChange.table] = rows;\n }\n rows.push(rowChange.row);\n }\n }\n\n const end = performance.now();\n if (options.syncedRows) {\n result.syncedRows = rowsByTable;\n }\n result.start = start;\n result.end = end;\n\n // Always include the count of synced and vended rows.\n result.syncedRowCount = syncedRowCount;\n result.readRowCountsByQuery = host.debug?.getVendedRowCounts() ?? {};\n let readRowCount = 0;\n for (const c of Object.values(result.readRowCountsByQuery)) {\n for (const v of Object.values(c)) {\n readRowCount += v;\n }\n }\n result.readRowCount = readRowCount;\n\n if (options.vendedRows) {\n result.readRows = host.debug?.getVendedRows();\n }\n return result;\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,eAAsB,OACpB,IACA,cACA,KACA,eACA,SAC6B;AAC7B,QAAM,EAAC,sBAAsB,aAAa,KAAA,IAAQ;AAClD,QAAM,SAA6B;AAAA,IACjC,UAAU,CAAA;AAAA,IACV,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,KAAK;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,sBAAsB,CAAA;AAAA,IACtB,cAAc;AAAA,EAAA;AAGhB,MAAI,CAAC,eAAe;AAElB,UAAM,OAAO,KAAK,KAAK,oBAAoB,CAAC;AAAA,EAC9C;AACA,MAAI,QAAQ,kBAAkB;AAC5B,WAAO,SAAS;AAAA,MACd;AAAA,IAAA;AAGF,UAAM,WAAW,QAAQ,WAAW,KAAK,MAAM,QAAQ,QAAQ,IAAI,CAAA;AACnE,QAAI,CAAC,QAAQ,UAAU;AACrB,aAAO,SAAS;AAAA,QACd;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,OAAgB,EAAuB,SAAS,SAAA;AACtD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA,EACA;AACF,WAAO,mBAAmB,MAAM,aAAa,IAAI,QAAQ,SAAS,GAAG,CAAC;AAAA,EACxE;AACA,QAAM,WAAW,cAAc,KAAK,MAAM,UAAU;AAEpD,QAAM,QAAQ,YAAY,IAAA;AAE1B,MAAI,iBAAiB;AACrB,QAAM,cAAqC,CAAA;AAC3C,QAAM,kCAA+B,IAAA;AACrC,aAAW,aAAa,QAAQ,UAAU,UAAU,GAAG,GAAG,YAAY,GAAG;AACvE,QAAI,cAAc,SAAS;AACzB;AAAA,IACF;AACA,WAAO,UAAU,SAAS,KAAK;AAE/B,QAAI,OAAc,YAAY,UAAU,KAAK;AAC7C,UAAM,IAAI,UAAU,QAAQ,MAAM,KAAK,UAAU,UAAU,GAAG;AAC9D,QAAI,YAAY,IAAI,CAAC,GAAG;AACtB;AAAA,IACF;AACA;AACA,gBAAY,IAAI,CAAC;AACjB,QAAI,QAAQ,YAAY;AACtB,UAAI,CAAC,MAAM;AACT,eAAO,CAAA;AACP,oBAAY,UAAU,KAAK,IAAI;AAAA,MACjC;AACA,WAAK,KAAK,UAAU,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,MAAM,YAAY,IAAA;AACxB,MAAI,QAAQ,YAAY;AACtB,WAAO,aAAa;AAAA,EACtB;AACA,SAAO,QAAQ;AACf,SAAO,MAAM;AAGb,SAAO,iBAAiB;AACxB,SAAO,uBAAuB,KAAK,OAAO,mBAAA,KAAwB,CAAA;AAClE,MAAI,eAAe;AACnB,aAAW,KAAK,OAAO,OAAO,OAAO,oBAAoB,GAAG;AAC1D,eAAW,KAAK,OAAO,OAAO,CAAC,GAAG;AAChC,sBAAgB;AAAA,IAClB;AAAA,EACF;AACA,SAAO,eAAe;AAEtB,MAAI,QAAQ,YAAY;AACtB,WAAO,WAAW,KAAK,OAAO,cAAA;AAAA,EAChC;AACA,SAAO;AACT;"}
@@ -77,37 +77,44 @@ function transformExistsCondition(condition, prefix, args) {
77
77
  const relationship = extractRelationshipName(related);
78
78
  const nextSubquery = getNextExistsSubquery(related);
79
79
  const hasSubQueryProps = nextSubquery.where || nextSubquery.related && nextSubquery.related.length > 0 || nextSubquery.orderBy || nextSubquery.limit;
80
+ const optionParts = [];
81
+ if (condition.flip !== void 0) {
82
+ optionParts.push(`flip: ${condition.flip}`);
83
+ }
84
+ if (condition.scalar !== void 0) {
85
+ optionParts.push(`scalar: ${condition.scalar}`);
86
+ }
87
+ const optionsStr = optionParts.length > 0 ? `, {${optionParts.join(", ")}}` : "";
80
88
  if (op === "EXISTS") {
81
- const flipped = condition.flip ? ", {flip: true}" : "";
82
89
  if (!hasSubQueryProps) {
83
90
  if (prefix === ".where") {
84
- return `.whereExists('${relationship}'${flipped})`;
91
+ return `.whereExists('${relationship}'${optionsStr})`;
85
92
  }
86
93
  args.add("exists");
87
- return `exists('${relationship}'${flipped})`;
94
+ return `exists('${relationship}'${optionsStr})`;
88
95
  }
89
96
  if (prefix === ".where") {
90
- return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;
97
+ return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;
91
98
  }
92
99
  args.add("exists");
93
- return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;
100
+ return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;
94
101
  }
95
102
  if (hasSubQueryProps) {
96
103
  if (prefix === ".where") {
97
104
  return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(
98
105
  nextSubquery
99
- )})))`;
106
+ )}${optionsStr})))`;
100
107
  }
101
108
  args.add("not");
102
109
  args.add("exists");
103
- return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}))`;
110
+ return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr}))`;
104
111
  }
105
112
  if (prefix === ".where") {
106
- return `.where(({exists, not}) => not(exists('${relationship}')))`;
113
+ return `.where(({exists, not}) => not(exists('${relationship}'${optionsStr})))`;
107
114
  }
108
115
  args.add("not");
109
116
  args.add("exists");
110
- return `not(exists('${relationship}')))`;
117
+ return `not(exists('${relationship}'${optionsStr})))`;
111
118
  }
112
119
  function getNextExistsSubquery(related) {
113
120
  if (related.subquery.where?.type === "correlatedSubquery" && related.subquery.where.related.subquery.alias?.includes(
@@ -1 +1 @@
1
- {"version":3,"file":"ast-to-zql.js","sources":["../../../../ast-to-zql/src/ast-to-zql.ts"],"sourcesContent":["import {unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralReference,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {SUBQ_PREFIX} from '../../zero-protocol/src/ast.ts';\n\n/**\n * Converts an AST to the equivalent query builder code.\n * This is useful for debugging and understanding queries.\n *\n * @example\n * ```\n * const ast = query.issue.where('id', '=', 123)[astSymbol];\n * console.log(astToZQL(ast)); // outputs: .where('id', '=', 123)\n * ```\n */\nexport function astToZQL(ast: AST): string {\n let code = '';\n\n // Handle where conditions\n if (ast.where) {\n code += transformCondition(ast.where, '.where', new Set());\n }\n\n // Handle related subqueries\n if (ast.related && ast.related.length > 0) {\n for (const related of ast.related) {\n if (related.hidden) {\n const nestedRelated = related.subquery.related?.[0];\n if (nestedRelated) {\n code += transformRelated(nestedRelated);\n }\n } else {\n code += transformRelated(related);\n }\n }\n }\n\n // Handle orderBy\n if (ast.orderBy && ast.orderBy.length > 0) {\n code += transformOrder(ast.orderBy);\n }\n\n // Handle limit\n if (ast.limit !== undefined) {\n code += `.limit(${ast.limit})`;\n }\n\n // Handle start\n if (ast.start) {\n const {row, exclusive} = ast.start;\n code += `.start(${JSON.stringify(row)}${\n exclusive ? '' : ', { inclusive: true }'\n })`;\n }\n\n return code;\n}\n\ntype Args = Set<string>;\n\ntype Prefix = '.where' | 'cmp';\n\nfunction transformCondition(\n condition: Condition,\n prefix: Prefix,\n args: Args,\n): string {\n switch (condition.type) {\n case 'simple':\n return transformSimpleCondition(condition, prefix);\n case 'and':\n case 'or':\n return transformLogicalCondition(condition, prefix, args);\n case 'correlatedSubquery':\n return transformExistsCondition(condition, prefix, args);\n default:\n unreachable(condition);\n }\n}\n\nfunction transformSimpleCondition(\n condition: SimpleCondition,\n prefix: Prefix,\n): string {\n const {left, op, right} = condition;\n\n const leftCode = transformValuePosition(left);\n const rightCode = transformValuePosition(right);\n\n // Handle the shorthand form for equals\n if (op === '=') {\n return `${prefix}(${leftCode}, ${rightCode})`;\n }\n\n return `${prefix}(${leftCode}, '${op}', ${rightCode})`;\n}\n\nfunction transformLogicalCondition(\n condition: Conjunction | Disjunction,\n prefix: Prefix,\n args: Args,\n): string {\n const {type, conditions} = condition;\n\n // For single condition, no need for logical operator\n if (conditions.length === 1) {\n return transformCondition(conditions[0], prefix, args);\n }\n\n // Generate multiple where calls for top-level AND conditions\n if (type === 'and') {\n const parts = conditions.map(c => transformCondition(c, prefix, args));\n // Simply concatenate the where conditions\n if (prefix === '.where') {\n return parts.join('');\n }\n args.add('and');\n return 'and(' + parts.join(', ') + ')';\n }\n\n args = new Set<string>();\n\n // Handle nested conditions with a callback for OR conditions and nested ANDs/ORs\n const conditionsCode = conditions\n .map(c => transformCondition(c, 'cmp', args))\n .join(', ');\n\n args.add('cmp');\n args.add(type);\n const argsCode = [...args].sort().join(', ');\n\n return `.where(({${argsCode}}) => ${type}(${conditionsCode}))`;\n}\n\nfunction transformExistsCondition(\n condition: CorrelatedSubqueryCondition,\n prefix: '.where' | 'cmp',\n args: Set<string>,\n): string {\n const {related, op} = condition;\n const relationship = extractRelationshipName(related);\n\n const nextSubquery = getNextExistsSubquery(related);\n\n // Check if subquery has additional properties\n const hasSubQueryProps =\n nextSubquery.where ||\n (nextSubquery.related && nextSubquery.related.length > 0) ||\n nextSubquery.orderBy ||\n nextSubquery.limit;\n\n if (op === 'EXISTS') {\n const flipped = condition.flip ? ', {flip: true}' : '';\n if (!hasSubQueryProps) {\n if (prefix === '.where') {\n return `.whereExists('${relationship}'${flipped})`;\n }\n args.add('exists');\n return `exists('${relationship}'${flipped})`;\n }\n\n if (prefix === '.where') {\n return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;\n }\n prefix satisfies 'cmp';\n args.add('exists');\n return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;\n }\n\n op satisfies 'NOT EXISTS';\n\n if (hasSubQueryProps) {\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(\n nextSubquery,\n )})))`;\n }\n prefix satisfies 'cmp';\n args.add('not');\n args.add('exists');\n return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}))`;\n }\n\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}')))`;\n }\n args.add('not');\n args.add('exists');\n\n return `not(exists('${relationship}')))`;\n}\n\n// If the `exists` is applied against a junction edge, both hops will have the same alias and both hops will be exists conditions.\nfunction getNextExistsSubquery(related: CorrelatedSubquery): AST {\n if (\n related.subquery.where?.type === 'correlatedSubquery' &&\n related.subquery.where.related.subquery.alias?.includes(\n SUBQ_PREFIX + 'zhidden_',\n )\n ) {\n return getNextExistsSubquery(related.subquery.where.related);\n }\n\n return related.subquery;\n}\n\nfunction extractRelationshipName(related: CorrelatedSubquery): string {\n const alias = must(related.subquery.alias);\n return alias.startsWith(SUBQ_PREFIX)\n ? alias.substring(SUBQ_PREFIX.length)\n : alias;\n}\n\nfunction transformRelated(related: CorrelatedSubquery): string {\n const {alias} = related.subquery;\n if (!alias) return '';\n\n const relationship = alias;\n let code = `.related('${relationship}'`;\n\n // If the subquery has additional filters or configurations\n if (\n related.subquery.where ||\n (related.subquery.related && related.subquery.related.length > 0) ||\n related.subquery.orderBy ||\n related.subquery.limit\n ) {\n code += ', q => q' + astToZQL(related.subquery);\n }\n\n code += ')';\n return code;\n}\n\nfunction transformOrder(orderBy: Ordering): string {\n let code = '';\n for (const [field, direction] of orderBy) {\n code += `.orderBy('${field}', '${direction}')`;\n }\n return code;\n}\n\nfunction transformValuePosition(value: ValuePosition): string {\n switch (value.type) {\n case 'literal':\n return transformLiteral(value);\n case 'column':\n return `'${value.name}'`;\n case 'static':\n return transformParameter(value);\n default:\n unreachable(value);\n }\n}\n\nfunction transformLiteral(literal: LiteralReference): string {\n if (literal.value === null) {\n return 'null';\n }\n if (Array.isArray(literal.value)) {\n return JSON.stringify(literal.value);\n }\n if (typeof literal.value === 'string') {\n return `'${literal.value.replace(/'/g, \"\\\\'\")}'`;\n }\n return String(literal.value);\n}\n\nfunction transformParameter(param: Parameter): string {\n const fieldStr = Array.isArray(param.field)\n ? `[${param.field.map(f => `'${f}'`).join(', ')}]`\n : `'${param.field}'`;\n\n return `authParam(${fieldStr})`;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ast-to-zql.js","sources":["../../../../ast-to-zql/src/ast-to-zql.ts"],"sourcesContent":["import {unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralReference,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {SUBQ_PREFIX} from '../../zero-protocol/src/ast.ts';\n\n/**\n * Converts an AST to the equivalent query builder code.\n * This is useful for debugging and understanding queries.\n *\n * @example\n * ```\n * const ast = query.issue.where('id', '=', 123)[astSymbol];\n * console.log(astToZQL(ast)); // outputs: .where('id', '=', 123)\n * ```\n */\nexport function astToZQL(ast: AST): string {\n let code = '';\n\n // Handle where conditions\n if (ast.where) {\n code += transformCondition(ast.where, '.where', new Set());\n }\n\n // Handle related subqueries\n if (ast.related && ast.related.length > 0) {\n for (const related of ast.related) {\n if (related.hidden) {\n const nestedRelated = related.subquery.related?.[0];\n if (nestedRelated) {\n code += transformRelated(nestedRelated);\n }\n } else {\n code += transformRelated(related);\n }\n }\n }\n\n // Handle orderBy\n if (ast.orderBy && ast.orderBy.length > 0) {\n code += transformOrder(ast.orderBy);\n }\n\n // Handle limit\n if (ast.limit !== undefined) {\n code += `.limit(${ast.limit})`;\n }\n\n // Handle start\n if (ast.start) {\n const {row, exclusive} = ast.start;\n code += `.start(${JSON.stringify(row)}${\n exclusive ? '' : ', { inclusive: true }'\n })`;\n }\n\n return code;\n}\n\ntype Args = Set<string>;\n\ntype Prefix = '.where' | 'cmp';\n\nfunction transformCondition(\n condition: Condition,\n prefix: Prefix,\n args: Args,\n): string {\n switch (condition.type) {\n case 'simple':\n return transformSimpleCondition(condition, prefix);\n case 'and':\n case 'or':\n return transformLogicalCondition(condition, prefix, args);\n case 'correlatedSubquery':\n return transformExistsCondition(condition, prefix, args);\n default:\n unreachable(condition);\n }\n}\n\nfunction transformSimpleCondition(\n condition: SimpleCondition,\n prefix: Prefix,\n): string {\n const {left, op, right} = condition;\n\n const leftCode = transformValuePosition(left);\n const rightCode = transformValuePosition(right);\n\n // Handle the shorthand form for equals\n if (op === '=') {\n return `${prefix}(${leftCode}, ${rightCode})`;\n }\n\n return `${prefix}(${leftCode}, '${op}', ${rightCode})`;\n}\n\nfunction transformLogicalCondition(\n condition: Conjunction | Disjunction,\n prefix: Prefix,\n args: Args,\n): string {\n const {type, conditions} = condition;\n\n // For single condition, no need for logical operator\n if (conditions.length === 1) {\n return transformCondition(conditions[0], prefix, args);\n }\n\n // Generate multiple where calls for top-level AND conditions\n if (type === 'and') {\n const parts = conditions.map(c => transformCondition(c, prefix, args));\n // Simply concatenate the where conditions\n if (prefix === '.where') {\n return parts.join('');\n }\n args.add('and');\n return 'and(' + parts.join(', ') + ')';\n }\n\n args = new Set<string>();\n\n // Handle nested conditions with a callback for OR conditions and nested ANDs/ORs\n const conditionsCode = conditions\n .map(c => transformCondition(c, 'cmp', args))\n .join(', ');\n\n args.add('cmp');\n args.add(type);\n const argsCode = [...args].sort().join(', ');\n\n return `.where(({${argsCode}}) => ${type}(${conditionsCode}))`;\n}\n\nfunction transformExistsCondition(\n condition: CorrelatedSubqueryCondition,\n prefix: '.where' | 'cmp',\n args: Set<string>,\n): string {\n const {related, op} = condition;\n const relationship = extractRelationshipName(related);\n\n const nextSubquery = getNextExistsSubquery(related);\n\n // Check if subquery has additional properties\n const hasSubQueryProps =\n nextSubquery.where ||\n (nextSubquery.related && nextSubquery.related.length > 0) ||\n nextSubquery.orderBy ||\n nextSubquery.limit;\n\n // Build options string for flip and scalar\n const optionParts: string[] = [];\n if (condition.flip !== undefined) {\n optionParts.push(`flip: ${condition.flip}`);\n }\n if (condition.scalar !== undefined) {\n optionParts.push(`scalar: ${condition.scalar}`);\n }\n const optionsStr =\n optionParts.length > 0 ? `, {${optionParts.join(', ')}}` : '';\n\n if (op === 'EXISTS') {\n if (!hasSubQueryProps) {\n if (prefix === '.where') {\n return `.whereExists('${relationship}'${optionsStr})`;\n }\n args.add('exists');\n return `exists('${relationship}'${optionsStr})`;\n }\n\n if (prefix === '.where') {\n return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;\n }\n prefix satisfies 'cmp';\n args.add('exists');\n return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;\n }\n\n op satisfies 'NOT EXISTS';\n\n if (hasSubQueryProps) {\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(\n nextSubquery,\n )}${optionsStr})))`;\n }\n prefix satisfies 'cmp';\n args.add('not');\n args.add('exists');\n return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr}))`;\n }\n\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}'${optionsStr})))`;\n }\n args.add('not');\n args.add('exists');\n\n return `not(exists('${relationship}'${optionsStr})))`;\n}\n\n// If the `exists` is applied against a junction edge, both hops will have the same alias and both hops will be exists conditions.\nfunction getNextExistsSubquery(related: CorrelatedSubquery): AST {\n if (\n related.subquery.where?.type === 'correlatedSubquery' &&\n related.subquery.where.related.subquery.alias?.includes(\n SUBQ_PREFIX + 'zhidden_',\n )\n ) {\n return getNextExistsSubquery(related.subquery.where.related);\n }\n\n return related.subquery;\n}\n\nfunction extractRelationshipName(related: CorrelatedSubquery): string {\n const alias = must(related.subquery.alias);\n return alias.startsWith(SUBQ_PREFIX)\n ? alias.substring(SUBQ_PREFIX.length)\n : alias;\n}\n\nfunction transformRelated(related: CorrelatedSubquery): string {\n const {alias} = related.subquery;\n if (!alias) return '';\n\n const relationship = alias;\n let code = `.related('${relationship}'`;\n\n // If the subquery has additional filters or configurations\n if (\n related.subquery.where ||\n (related.subquery.related && related.subquery.related.length > 0) ||\n related.subquery.orderBy ||\n related.subquery.limit\n ) {\n code += ', q => q' + astToZQL(related.subquery);\n }\n\n code += ')';\n return code;\n}\n\nfunction transformOrder(orderBy: Ordering): string {\n let code = '';\n for (const [field, direction] of orderBy) {\n code += `.orderBy('${field}', '${direction}')`;\n }\n return code;\n}\n\nfunction transformValuePosition(value: ValuePosition): string {\n switch (value.type) {\n case 'literal':\n return transformLiteral(value);\n case 'column':\n return `'${value.name}'`;\n case 'static':\n return transformParameter(value);\n default:\n unreachable(value);\n }\n}\n\nfunction transformLiteral(literal: LiteralReference): string {\n if (literal.value === null) {\n return 'null';\n }\n if (Array.isArray(literal.value)) {\n return JSON.stringify(literal.value);\n }\n if (typeof literal.value === 'string') {\n return `'${literal.value.replace(/'/g, \"\\\\'\")}'`;\n }\n return String(literal.value);\n}\n\nfunction transformParameter(param: Parameter): string {\n const fieldStr = Array.isArray(param.field)\n ? `[${param.field.map(f => `'${f}'`).join(', ')}]`\n : `'${param.field}'`;\n\n return `authParam(${fieldStr})`;\n}\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"bg-interval.d.ts","sourceRoot":"","sources":["../../../../replicache/src/bg-interval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAIjD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,MAAM,EACrB,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAEN"}
1
+ {"version":3,"file":"bg-interval.d.ts","sourceRoot":"","sources":["../../../../replicache/src/bg-interval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAKjD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,MAAM,EACrB,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAEN"}
@@ -1,5 +1,6 @@
1
1
  import { AbortError } from "../../shared/src/abort-error.js";
2
2
  import { sleep } from "../../shared/src/sleep.js";
3
+ import { IDBNotFoundError } from "./kv/idb-store.js";
3
4
  function initBgIntervalProcess(processName, process, delayMs, lc, signal) {
4
5
  void runBgIntervalProcess(processName, process, delayMs, lc, signal);
5
6
  }
@@ -24,6 +25,8 @@ async function runBgIntervalProcess(processName, process, delayMs, lc, signal) {
24
25
  } catch (e) {
25
26
  if (signal.aborted) {
26
27
  lc.debug?.("Error running most likely due to close.", e);
28
+ } else if (e instanceof IDBNotFoundError) {
29
+ lc.info?.("IndexedDB was deleted externally.", e);
27
30
  } else {
28
31
  lc.error?.("Error running.", e);
29
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"bg-interval.js","sources":["../../../../replicache/src/bg-interval.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n"],"names":[],"mappings":";;AAIO,SAAS,sBACd,aACA,SACA,SACA,IACA,QACM;AACN,OAAK,qBAAqB,aAAa,SAAS,SAAS,IAAI,MAAM;AACrE;AAEA,eAAe,qBACb,aACA,SACA,SACA,IACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB;AAAA,EACF;AACA,OAAK,GAAG,YAAY,qBAAqB,WAAW;AACpD,KAAG,QAAQ,UAAU;AACrB,SAAO,CAAC,OAAO,SAAS;AACtB,QAAI;AACF,YAAM,MAAM,QAAA,GAAW,MAAM;AAAA,IAC/B,SAAS,GAAG;AACV,UAAI,EAAE,aAAa,aAAa;AAC9B,cAAM;AAAA,MACR;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,SAAG,QAAQ,SAAS;AACpB,UAAI;AACF,cAAM,QAAA;AAAA,MACR,SAAS,GAAG;AACV,YAAI,OAAO,SAAS;AAClB,aAAG,QAAQ,2CAA2C,CAAC;AAAA,QACzD,OAAO;AACL,aAAG,QAAQ,kBAAkB,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,KAAG,QAAQ,UAAU;AACvB;"}
1
+ {"version":3,"file":"bg-interval.js","sources":["../../../../replicache/src/bg-interval.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\nimport {IDBNotFoundError} from './kv/idb-store.ts';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else if (e instanceof IDBNotFoundError) {\n lc.info?.('IndexedDB was deleted externally.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n"],"names":[],"mappings":";;;AAKO,SAAS,sBACd,aACA,SACA,SACA,IACA,QACM;AACN,OAAK,qBAAqB,aAAa,SAAS,SAAS,IAAI,MAAM;AACrE;AAEA,eAAe,qBACb,aACA,SACA,SACA,IACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB;AAAA,EACF;AACA,OAAK,GAAG,YAAY,qBAAqB,WAAW;AACpD,KAAG,QAAQ,UAAU;AACrB,SAAO,CAAC,OAAO,SAAS;AACtB,QAAI;AACF,YAAM,MAAM,QAAA,GAAW,MAAM;AAAA,IAC/B,SAAS,GAAG;AACV,UAAI,EAAE,aAAa,aAAa;AAC9B,cAAM;AAAA,MACR;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,SAAG,QAAQ,SAAS;AACpB,UAAI;AACF,cAAM,QAAA;AAAA,MACR,SAAS,GAAG;AACV,YAAI,OAAO,SAAS;AAClB,aAAG,QAAQ,2CAA2C,CAAC;AAAA,QACzD,WAAW,aAAa,kBAAkB;AACxC,aAAG,OAAO,qCAAqC,CAAC;AAAA,QAClD,OAAO;AACL,aAAG,QAAQ,kBAAkB,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,KAAG,QAAQ,UAAU;AACvB;"}
@@ -1,6 +1,6 @@
1
1
  import type { LogContext, LogLevel, LogSink } from '@rocicorp/logger';
2
2
  import type { Store } from '../dag/store.ts';
3
- import type { DropStore, StoreProvider } from '../kv/store.ts';
3
+ import type { CreateStore, StoreProvider } from '../kv/store.ts';
4
4
  import type { OnClientsDeleted } from './clients.ts';
5
5
  import { IDBDatabasesStore } from './idb-databases-store.ts';
6
6
  /**
@@ -11,12 +11,12 @@ export declare const COLLECT_IDB_INTERVAL: number;
11
11
  * We delay the initial collection to prevent doing it at startup.
12
12
  */
13
13
  export declare const INITIAL_COLLECT_IDB_DELAY: number;
14
- export declare function initCollectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, kvDropStore: DropStore, collectInterval: number, initialCollectDelay: number, maxAge: number, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, lc: LogContext, signal: AbortSignal): void;
14
+ export declare function initCollectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, kvStoreProvider: StoreProvider, collectInterval: number, initialCollectDelay: number, maxAge: number, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, lc: LogContext, signal: AbortSignal): void;
15
15
  /**
16
16
  * Collects IDB databases that are no longer needed.
17
17
  */
18
- export declare function collectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, now: number, maxAge: number, kvDropStore: DropStore, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, newDagStore?: typeof defaultNewDagStore): Promise<void>;
19
- declare function defaultNewDagStore(name: string): Store;
18
+ export declare function collectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, now: number, maxAge: number, kvStoreProvider: StoreProvider, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, newDagStore?: typeof defaultNewDagStore): Promise<void>;
19
+ declare function defaultNewDagStore(name: string, kvCreateStore: CreateStore): Store;
20
20
  /**
21
21
  * Options for `dropDatabase` and `dropAllDatabases`.
22
22
  */
@@ -1 +1 @@
1
- {"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAKpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAa3C,OAAO,KAAK,EAAC,SAAS,EAAE,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAO7D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,SAAS,EACtB,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAwBN;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,SAAS,EACtB,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,4BAAqB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA+Df;AAsCD,iBAAS,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAG/C;AAyCD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,iBAU5E;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CASD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,mBAAmB;aArBvD,MAAM,EAAE;YACT,OAAO,EAAE;GAsBlB"}
1
+ {"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAKpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAY3C,OAAO,KAAK,EAAC,WAAW,EAAa,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,aAAa,EAC9B,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAwBN;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,aAAa,EAC9B,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,4BAAqB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmEf;AAsCD,iBAAS,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,GAAG,KAAK,CAG3E;AAmCD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,iBAU5E;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CASD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,mBAAmB;aArBvD,MAAM,EAAE;YACT,OAAO,EAAE;GAsBlB"}
@@ -5,7 +5,6 @@ import { addDeletedClients, mergeDeletedClients, normalizeDeletedClients, getDel
5
5
  import { Latest, DD31, V6, V7 } from "../format-version-enum.js";
6
6
  import { getKVStoreProvider } from "../get-kv-store-provider.js";
7
7
  import { newRandomHash, assertHash } from "../hash.js";
8
- import { IDBStore } from "../kv/idb-store.js";
9
8
  import { createLogContext } from "../log-options.js";
10
9
  import { withWrite, withRead } from "../with-transactions.js";
11
10
  import { getClientGroups, clientGroupHasPendingMutations } from "./client-groups.js";
@@ -13,7 +12,7 @@ import { getClients } from "./clients.js";
13
12
  import { IDBDatabasesStore } from "./idb-databases-store.js";
14
13
  const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1e3;
15
14
  const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1e3;
16
- function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval, initialCollectDelay, maxAge, enableMutationRecovery, onClientsDeleted, lc, signal) {
15
+ function initCollectIDBDatabases(idbDatabasesStore, kvStoreProvider, collectInterval, initialCollectDelay, maxAge, enableMutationRecovery, onClientsDeleted, lc, signal) {
17
16
  let initial = true;
18
17
  initBgIntervalProcess(
19
18
  "CollectIDBDatabases",
@@ -22,7 +21,7 @@ function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval
22
21
  idbDatabasesStore,
23
22
  Date.now(),
24
23
  maxAge,
25
- kvDropStore,
24
+ kvStoreProvider,
26
25
  enableMutationRecovery,
27
26
  onClientsDeleted
28
27
  );
@@ -38,7 +37,7 @@ function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval
38
37
  signal
39
38
  );
40
39
  }
41
- async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore, enableMutationRecovery, onClientsDeleted, newDagStore = defaultNewDagStore) {
40
+ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvStoreProvider, enableMutationRecovery, onClientsDeleted, newDagStore = defaultNewDagStore) {
42
41
  const databases = await idbDatabasesStore.getDatabases();
43
42
  const dbs = Object.values(databases);
44
43
  const collectResults = await Promise.all(
@@ -50,6 +49,7 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
50
49
  now,
51
50
  maxAge,
52
51
  enableMutationRecovery,
52
+ kvStoreProvider.create,
53
53
  newDagStore
54
54
  )
55
55
  ]
@@ -69,7 +69,7 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
69
69
  const { errors } = await dropDatabases(
70
70
  idbDatabasesStore,
71
71
  dbNamesToRemove,
72
- kvDropStore
72
+ kvStoreProvider.drop
73
73
  );
74
74
  if (errors.length) {
75
75
  throw errors[0];
@@ -77,16 +77,19 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
77
77
  if (deletedClientsToRemove.length > 0) {
78
78
  let allDeletedClients = deletedClientsToRemove;
79
79
  for (const name of dbNamesToKeep) {
80
- await withWrite(newDagStore(name), async (dagWrite) => {
81
- const newDeletedClients = await addDeletedClients(
82
- dagWrite,
83
- deletedClientsToRemove
84
- );
85
- allDeletedClients = mergeDeletedClients(
86
- allDeletedClients,
87
- newDeletedClients
88
- );
89
- });
80
+ await withWrite(
81
+ newDagStore(name, kvStoreProvider.create),
82
+ async (dagWrite) => {
83
+ const newDeletedClients = await addDeletedClients(
84
+ dagWrite,
85
+ deletedClientsToRemove
86
+ );
87
+ allDeletedClients = mergeDeletedClients(
88
+ allDeletedClients,
89
+ newDeletedClients
90
+ );
91
+ }
92
+ );
90
93
  }
91
94
  const normalizedDeletedClients = normalizeDeletedClients(allDeletedClients);
92
95
  await onClientsDeleted(normalizedDeletedClients);
@@ -114,24 +117,22 @@ async function dropDatabases(idbDatabasesStore, namesToRemove, kvDropStore) {
114
117
  }
115
118
  return { dropped, errors };
116
119
  }
117
- function defaultNewDagStore(name) {
118
- const perKvStore = new IDBStore(name);
120
+ function defaultNewDagStore(name, kvCreateStore) {
121
+ const perKvStore = kvCreateStore(name);
119
122
  return new StoreImpl(perKvStore, newRandomHash, assertHash);
120
123
  }
121
- function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, newDagStore) {
124
+ function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, kvCreateStore, newDagStore) {
122
125
  if (db.replicacheFormatVersion > Latest) {
123
126
  return [false];
124
127
  }
125
- assert(db.lastOpenedTimestampMS !== void 0);
126
- if (now - db.lastOpenedTimestampMS < maxAge) {
127
- return [false];
128
- }
129
128
  assert(
130
129
  db.replicacheFormatVersion === DD31 || db.replicacheFormatVersion === V6 || db.replicacheFormatVersion === V7
131
130
  );
132
131
  return canDatabaseBeCollectedAndGetDeletedClientIDs(
133
132
  enableMutationRecovery,
134
- newDagStore(db.name)
133
+ newDagStore(db.name, kvCreateStore),
134
+ now,
135
+ maxAge
135
136
  );
136
137
  }
137
138
  async function dropDatabase(dbName, opts) {
@@ -155,7 +156,7 @@ async function dropAllDatabases(opts) {
155
156
  const dbNames = Object.values(databases).map((db) => db.name);
156
157
  return dropDatabases(store, dbNames, kvStoreProvider.drop);
157
158
  }
158
- function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, perdag) {
159
+ function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, perdag, now, maxAge) {
159
160
  return withRead(perdag, async (read) => {
160
161
  if (enableMutationRecovery) {
161
162
  const clientGroups = await getClientGroups(read);
@@ -166,6 +167,11 @@ function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, pe
166
167
  }
167
168
  }
168
169
  const clients = await getClients(read);
170
+ for (const [, client] of clients) {
171
+ if (now - client.heartbeatTimestampMs < maxAge) {
172
+ return [false];
173
+ }
174
+ }
169
175
  const existingDeletedClients = await getDeletedClients(read);
170
176
  const deletedClients = [...existingDeletedClients];
171
177
  for (const [clientID, client] of clients) {