@rocicorp/zero 1.12.0-canary.3 → 1.12.0-canary.4

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 (785) hide show
  1. package/out/_virtual/{_@oxc-project_runtime@0.130.0/helpers → _@oxc-project_runtime@0.154.0/helpers/esm}/usingCtx.js +2 -2
  2. package/out/analyze-query/src/analyze-cli.js +4 -3
  3. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  4. package/out/analyze-query/src/bin-analyze.js +5 -3
  5. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  6. package/out/analyze-query/src/bin-transform.js +3 -2
  7. package/out/analyze-query/src/bin-transform.js.map +1 -1
  8. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  9. package/out/ast-to-zql/src/bin.js +3 -2
  10. package/out/ast-to-zql/src/bin.js.map +1 -1
  11. package/out/ast-to-zql/src/format.js.map +1 -1
  12. package/out/datadog/src/datadog-log-sink.js +5 -4
  13. package/out/datadog/src/datadog-log-sink.js.map +1 -1
  14. package/out/otel/src/log-options.js.map +1 -1
  15. package/out/replicache/src/btree/node.js +13 -11
  16. package/out/replicache/src/btree/node.js.map +1 -1
  17. package/out/replicache/src/btree/read.js +4 -2
  18. package/out/replicache/src/btree/read.js.map +1 -1
  19. package/out/replicache/src/btree/splice.js.map +1 -1
  20. package/out/replicache/src/btree/write.js +9 -5
  21. package/out/replicache/src/btree/write.js.map +1 -1
  22. package/out/replicache/src/config.js +1 -2
  23. package/out/replicache/src/connection-loop.js.map +1 -1
  24. package/out/replicache/src/dag/chunk.js +1 -1
  25. package/out/replicache/src/dag/gc.js.map +1 -1
  26. package/out/replicache/src/dag/lazy-store.js +8 -7
  27. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  28. package/out/replicache/src/dag/store-impl.js +1 -1
  29. package/out/replicache/src/dag/store-impl.js.map +1 -1
  30. package/out/replicache/src/dag/visitor.js.map +1 -1
  31. package/out/replicache/src/db/commit.js +5 -3
  32. package/out/replicache/src/db/commit.js.map +1 -1
  33. package/out/replicache/src/db/read.js +1 -1
  34. package/out/replicache/src/db/read.js.map +1 -1
  35. package/out/replicache/src/db/rebase.js.map +1 -1
  36. package/out/replicache/src/db/write.js +5 -2
  37. package/out/replicache/src/db/write.js.map +1 -1
  38. package/out/replicache/src/deleted-clients.js +3 -2
  39. package/out/replicache/src/deleted-clients.js.map +1 -1
  40. package/out/replicache/src/expo-sqlite.js +1 -2
  41. package/out/replicache/src/frozen-json.js +1 -1
  42. package/out/replicache/src/frozen-json.js.map +1 -1
  43. package/out/replicache/src/get-default-puller.js +1 -1
  44. package/out/replicache/src/hash.js +1 -1
  45. package/out/replicache/src/hash.js.map +1 -1
  46. package/out/replicache/src/impl.js +1 -2
  47. package/out/replicache/src/index-defs.js +5 -3
  48. package/out/replicache/src/index-defs.js.map +1 -1
  49. package/out/replicache/src/kv/expo-sqlite/store.js +1 -1
  50. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  51. package/out/replicache/src/kv/idb-store.js +1 -1
  52. package/out/replicache/src/kv/idb-store.js.map +1 -1
  53. package/out/replicache/src/kv/mem-fallback-store.js +1 -1
  54. package/out/replicache/src/kv/mem-fallback-store.js.map +1 -1
  55. package/out/replicache/src/kv/mem-store.js.map +1 -1
  56. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  57. package/out/replicache/src/kv/op-sqlite/types.js.map +1 -1
  58. package/out/replicache/src/kv/read-impl.js.map +1 -1
  59. package/out/replicache/src/kv/sqlite-store.js +1 -1
  60. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  61. package/out/replicache/src/kv/write-impl-base.js +4 -1
  62. package/out/replicache/src/kv/write-impl-base.js.map +1 -1
  63. package/out/replicache/src/kv/write-impl.js.map +1 -1
  64. package/out/replicache/src/log-options.js +2 -1
  65. package/out/replicache/src/log-options.js.map +1 -1
  66. package/out/replicache/src/make-idb-name.js +1 -1
  67. package/out/replicache/src/new-client-channel.js +9 -7
  68. package/out/replicache/src/new-client-channel.js.map +1 -1
  69. package/out/replicache/src/on-persist-channel.js +1 -1
  70. package/out/replicache/src/on-persist-channel.js.map +1 -1
  71. package/out/replicache/src/op-sqlite.js +1 -2
  72. package/out/replicache/src/pending-mutations.js +2 -1
  73. package/out/replicache/src/pending-mutations.js.map +1 -1
  74. package/out/replicache/src/persist/client-gc.js +2 -2
  75. package/out/replicache/src/persist/client-gc.js.map +1 -1
  76. package/out/replicache/src/persist/client-group-gc.js +2 -2
  77. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  78. package/out/replicache/src/persist/client-groups.js +1 -1
  79. package/out/replicache/src/persist/client-groups.js.map +1 -1
  80. package/out/replicache/src/persist/clients.js +1 -1
  81. package/out/replicache/src/persist/clients.js.map +1 -1
  82. package/out/replicache/src/persist/collect-idb-databases.js +5 -4
  83. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  84. package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
  85. package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
  86. package/out/replicache/src/persist/heartbeat.js +2 -2
  87. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  88. package/out/replicache/src/persist/idb-databases-store.js +1 -1
  89. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  90. package/out/replicache/src/persist/make-client-id.js +1 -1
  91. package/out/replicache/src/persist/make-client-id.js.map +1 -1
  92. package/out/replicache/src/persist/persist.js +3 -2
  93. package/out/replicache/src/persist/persist.js.map +1 -1
  94. package/out/replicache/src/persist/refresh.js +8 -5
  95. package/out/replicache/src/persist/refresh.js.map +1 -1
  96. package/out/replicache/src/process-scheduler.js.map +1 -1
  97. package/out/replicache/src/replicache-impl.js +3 -3
  98. package/out/replicache/src/replicache-impl.js.map +1 -1
  99. package/out/replicache/src/scan-iterator.js.map +1 -1
  100. package/out/replicache/src/scan-options.js +7 -6
  101. package/out/replicache/src/scan-options.js.map +1 -1
  102. package/out/replicache/src/sqlite.js +1 -2
  103. package/out/replicache/src/subscriptions.js +1 -1
  104. package/out/replicache/src/subscriptions.js.map +1 -1
  105. package/out/replicache/src/sync/diff.js +3 -1
  106. package/out/replicache/src/sync/diff.js.map +1 -1
  107. package/out/replicache/src/sync/ids.js.map +1 -1
  108. package/out/replicache/src/sync/patch.js +2 -4
  109. package/out/replicache/src/sync/patch.js.map +1 -1
  110. package/out/replicache/src/sync/pull.js +3 -1
  111. package/out/replicache/src/sync/pull.js.map +1 -1
  112. package/out/replicache/src/sync/push.js.map +1 -1
  113. package/out/replicache/src/sync/request-id.js +1 -1
  114. package/out/replicache/src/sync/request-id.js.map +1 -1
  115. package/out/replicache/src/transactions.js +1 -1
  116. package/out/replicache/src/transactions.js.map +1 -1
  117. package/out/shared/src/arrays.js +4 -1
  118. package/out/shared/src/arrays.js.map +1 -1
  119. package/out/shared/src/asserts.js +1 -1
  120. package/out/shared/src/bigint-json.d.ts +9 -0
  121. package/out/shared/src/bigint-json.d.ts.map +1 -1
  122. package/out/shared/src/bigint-json.js +27 -2
  123. package/out/shared/src/bigint-json.js.map +1 -1
  124. package/out/shared/src/broadcast-channel.js +1 -1
  125. package/out/shared/src/btree-set.js +11 -8
  126. package/out/shared/src/btree-set.js.map +1 -1
  127. package/out/shared/src/cache.js.map +1 -1
  128. package/out/shared/src/config.js +1 -1
  129. package/out/shared/src/custom-key-map.js.map +1 -1
  130. package/out/shared/src/custom-key-set.js.map +1 -1
  131. package/out/shared/src/deep-clone.js +1 -1
  132. package/out/shared/src/document-visible.js.map +1 -1
  133. package/out/shared/src/dotenv.js.map +1 -1
  134. package/out/shared/src/error.js +1 -1
  135. package/out/shared/src/error.js.map +1 -1
  136. package/out/shared/src/hash.js +2 -2
  137. package/out/shared/src/hash.js.map +1 -1
  138. package/out/shared/src/iterables.js.map +1 -1
  139. package/out/shared/src/json-schema.js.map +1 -1
  140. package/out/shared/src/json.js.map +1 -1
  141. package/out/shared/src/logging-test-utils.js +1 -1
  142. package/out/shared/src/logging.js +1 -1
  143. package/out/shared/src/logging.js.map +1 -1
  144. package/out/shared/src/navigator.js +1 -1
  145. package/out/shared/src/options.js +9 -12
  146. package/out/shared/src/options.js.map +1 -1
  147. package/out/shared/src/promise-race.js.map +1 -1
  148. package/out/shared/src/queue.js.map +1 -1
  149. package/out/shared/src/record-proxy.js.map +1 -1
  150. package/out/shared/src/ring-buffer.js.map +1 -1
  151. package/out/shared/src/size-of-value.js +7 -10
  152. package/out/shared/src/size-of-value.js.map +1 -1
  153. package/out/shared/src/sorted-entries.js.map +1 -1
  154. package/out/shared/src/tdigest-schema.js.map +1 -1
  155. package/out/shared/src/tdigest.js.map +1 -1
  156. package/out/shared/src/valita.js +1 -1
  157. package/out/shared/src/valita.js.map +1 -1
  158. package/out/z2s/src/compiler.js +2 -4
  159. package/out/z2s/src/compiler.js.map +1 -1
  160. package/out/z2s/src/sql.js +1 -1
  161. package/out/z2s/src/sql.js.map +1 -1
  162. package/out/zero/package.js +212 -189
  163. package/out/zero/package.js.map +1 -1
  164. package/out/zero/src/adapters/drizzle.js +1 -2
  165. package/out/zero/src/adapters/kysely.js +1 -2
  166. package/out/zero/src/adapters/pg.js +1 -2
  167. package/out/zero/src/adapters/postgresjs.js +1 -2
  168. package/out/zero/src/adapters/prisma.js +1 -2
  169. package/out/zero/src/analyze.js +1 -2
  170. package/out/zero/src/change-protocol/v0.js +1 -2
  171. package/out/zero/src/expo-sqlite.js +1 -2
  172. package/out/zero/src/op-sqlite.js +1 -2
  173. package/out/zero/src/react-native.js.map +1 -1
  174. package/out/zero/src/sqlite.js +1 -2
  175. package/out/zero/src/zero-cache-dev.js +10 -9
  176. package/out/zero/src/zero-cache-dev.js.map +1 -1
  177. package/out/zero/src/zero-out.js +2 -1
  178. package/out/zero/src/zero-out.js.map +1 -1
  179. package/out/zero-cache/src/auth/auth.js +1 -1
  180. package/out/zero-cache/src/auth/auth.js.map +1 -1
  181. package/out/zero-cache/src/auth/jwt.js +4 -1
  182. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  183. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  184. package/out/zero-cache/src/auth/read-authorizer.js +3 -2
  185. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  186. package/out/zero-cache/src/auth/write-authorizer.js +5 -16
  187. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  188. package/out/zero-cache/src/config/network.js +1 -1
  189. package/out/zero-cache/src/config/network.js.map +1 -1
  190. package/out/zero-cache/src/config/server-context.js.map +1 -1
  191. package/out/zero-cache/src/config/zero-config.d.ts +5 -0
  192. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  193. package/out/zero-cache/src/config/zero-config.js +13 -2
  194. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  195. package/out/zero-cache/src/custom/fetch.js +1 -1
  196. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  197. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  198. package/out/zero-cache/src/db/create.js.map +1 -1
  199. package/out/zero-cache/src/db/index-predicate.js.map +1 -1
  200. package/out/zero-cache/src/db/lite-tables.d.ts +2 -2
  201. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  202. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  203. package/out/zero-cache/src/db/migration-lite.js +1 -1
  204. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  205. package/out/zero-cache/src/db/migration.js +5 -3
  206. package/out/zero-cache/src/db/migration.js.map +1 -1
  207. package/out/zero-cache/src/db/pg-copy-binary.js +4 -3
  208. package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
  209. package/out/zero-cache/src/db/pg-copy.js +0 -1
  210. package/out/zero-cache/src/db/pg-copy.js.map +1 -1
  211. package/out/zero-cache/src/db/pg-to-lite.js +1 -1
  212. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  213. package/out/zero-cache/src/db/run-transaction.js.map +1 -1
  214. package/out/zero-cache/src/db/specs.js +7 -5
  215. package/out/zero-cache/src/db/specs.js.map +1 -1
  216. package/out/zero-cache/src/db/sqlite-corruption.js.map +1 -1
  217. package/out/zero-cache/src/db/statements.d.ts.map +1 -1
  218. package/out/zero-cache/src/db/statements.js +9 -2
  219. package/out/zero-cache/src/db/statements.js.map +1 -1
  220. package/out/zero-cache/src/db/transaction-pool.js +5 -3
  221. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  222. package/out/zero-cache/src/db/warmup.js.map +1 -1
  223. package/out/zero-cache/src/observability/events.js.map +1 -1
  224. package/out/zero-cache/src/observability/log-throttle.js.map +1 -1
  225. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  226. package/out/zero-cache/src/scripts/deploy-permissions.js +4 -2
  227. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  228. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  229. package/out/zero-cache/src/server/anonymous-otel-start.js +2 -1
  230. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  231. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  232. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  233. package/out/zero-cache/src/server/logging.js +1 -1
  234. package/out/zero-cache/src/server/logging.js.map +1 -1
  235. package/out/zero-cache/src/server/main.js.map +1 -1
  236. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  237. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  238. package/out/zero-cache/src/server/reaper.js +2 -2
  239. package/out/zero-cache/src/server/reaper.js.map +1 -1
  240. package/out/zero-cache/src/server/replicator.js.map +1 -1
  241. package/out/zero-cache/src/server/runner/run-worker.js +2 -1
  242. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  243. package/out/zero-cache/src/server/runner/runtime.js +2 -1
  244. package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
  245. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  246. package/out/zero-cache/src/server/shadow-syncer.js +1 -1
  247. package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
  248. package/out/zero-cache/src/server/slot-keeper.js.map +1 -1
  249. package/out/zero-cache/src/server/syncer-assigner.js.map +1 -1
  250. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  251. package/out/zero-cache/src/server/syncer.js +6 -1
  252. package/out/zero-cache/src/server/syncer.js.map +1 -1
  253. package/out/zero-cache/src/server/worker-dispatcher.js +1 -1
  254. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  255. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  256. package/out/zero-cache/src/services/analyze.js +1 -1
  257. package/out/zero-cache/src/services/analyze.js.map +1 -1
  258. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
  259. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  260. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  261. package/out/zero-cache/src/services/change-source/common/init-cleanup.js.map +1 -1
  262. package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
  263. package/out/zero-cache/src/services/change-source/common/replica-schema.js +3 -3
  264. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  265. package/out/zero-cache/src/services/change-source/custom/change-source.js +3 -3
  266. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  267. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
  268. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +3 -3
  269. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  270. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +1 -1
  271. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -1
  272. package/out/zero-cache/src/services/change-source/pg/change-source.js +4 -6
  273. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  274. package/out/zero-cache/src/services/change-source/pg/decommission.js +2 -1
  275. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  276. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +5 -3
  277. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  278. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
  279. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
  280. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +3 -2
  281. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  282. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  283. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +2 -2
  284. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -1
  285. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js +1 -1
  286. package/out/zero-cache/src/services/change-source/pg/replication-slot-health.js.map +1 -1
  287. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +3 -3
  288. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  289. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +1 -1
  290. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  291. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +13 -12
  292. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  293. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  294. package/out/zero-cache/src/services/change-source/pg/schema/published.js +1 -1
  295. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  296. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -1
  297. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +9 -6
  298. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  299. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +1 -1
  300. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  301. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js +1 -1
  302. package/out/zero-cache/src/services/change-source/protocol/backfill-progress.js.map +1 -1
  303. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  304. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  305. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  306. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  307. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  308. package/out/zero-cache/src/services/change-source/protocol/current.js +1 -1
  309. package/out/zero-cache/src/services/change-source/protocol/mod.js +1 -2
  310. package/out/zero-cache/src/services/change-streamer/backfill-state-tracker.js.map +1 -1
  311. package/out/zero-cache/src/services/change-streamer/backfill-state.js +1 -1
  312. package/out/zero-cache/src/services/change-streamer/backfill-state.js.map +1 -1
  313. package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
  314. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  315. package/out/zero-cache/src/services/change-streamer/broadcast.js +1 -1
  316. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  317. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +1 -1
  318. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  319. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +2 -3
  320. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  321. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +2 -2
  322. package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -1
  323. package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -1
  324. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +5 -3
  325. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  326. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +21 -21
  327. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  328. package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
  329. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  330. package/out/zero-cache/src/services/change-streamer/drain-tracker.js.map +1 -1
  331. package/out/zero-cache/src/services/change-streamer/forwarder.js +11 -10
  332. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  333. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js +1 -1
  334. package/out/zero-cache/src/services/change-streamer/litestream-sync-requester.js.map +1 -1
  335. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js +3 -3
  336. package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -1
  337. package/out/zero-cache/src/services/change-streamer/replica-poller.js +1 -1
  338. package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -1
  339. package/out/zero-cache/src/services/change-streamer/restore-admission.js +12 -1
  340. package/out/zero-cache/src/services/change-streamer/restore-admission.js.map +1 -1
  341. package/out/zero-cache/src/services/change-streamer/schema/init.js +1 -1
  342. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  343. package/out/zero-cache/src/services/change-streamer/schema/tables.js +1 -1
  344. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  345. package/out/zero-cache/src/services/change-streamer/snapshot-message.js +1 -1
  346. package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -1
  347. package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -1
  348. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +1 -1
  349. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -1
  350. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js +2 -2
  351. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-comparator.js.map +1 -1
  352. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -1
  353. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js.map +1 -1
  354. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -1
  355. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +4 -6
  356. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -1
  357. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +1 -3
  358. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  359. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  360. package/out/zero-cache/src/services/change-streamer/storer.js +2 -2
  361. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  362. package/out/zero-cache/src/services/change-streamer/subscribe.js +1 -1
  363. package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -1
  364. package/out/zero-cache/src/services/change-streamer/subscriber.js +2 -2
  365. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  366. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +0 -1
  367. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  368. package/out/zero-cache/src/services/heapz.js +2 -1
  369. package/out/zero-cache/src/services/heapz.js.map +1 -1
  370. package/out/zero-cache/src/services/http-service.js.map +1 -1
  371. package/out/zero-cache/src/services/life-cycle.js +1 -1
  372. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  373. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +4 -2
  374. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
  375. package/out/zero-cache/src/services/litestream/commands.js +1 -1
  376. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  377. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +2 -2
  378. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -1
  379. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -1
  380. package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
  381. package/out/zero-cache/src/services/litestream/restore-progress.js.map +1 -1
  382. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -1
  383. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  384. package/out/zero-cache/src/services/mutagen/pusher.js +3 -2
  385. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  386. package/out/zero-cache/src/services/plannerz.js +4 -3
  387. package/out/zero-cache/src/services/plannerz.js.map +1 -1
  388. package/out/zero-cache/src/services/profz.js +5 -3
  389. package/out/zero-cache/src/services/profz.js.map +1 -1
  390. package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -1
  391. package/out/zero-cache/src/services/replicator/change-log-db.js +3 -2
  392. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  393. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +1 -1
  394. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  395. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  396. package/out/zero-cache/src/services/replicator/drain-handler.js.map +1 -1
  397. package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
  398. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  399. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  400. package/out/zero-cache/src/services/replicator/replication-status.js +4 -3
  401. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  402. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  403. package/out/zero-cache/src/services/replicator/reporter/recorder.js +1 -1
  404. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  405. package/out/zero-cache/src/services/replicator/reporter/report-schema.js +1 -1
  406. package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
  407. package/out/zero-cache/src/services/replicator/schema/backfilling.js +1 -1
  408. package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -1
  409. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +19 -7
  410. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  411. package/out/zero-cache/src/services/replicator/schema/change-log.js +31 -15
  412. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  413. package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
  414. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  415. package/out/zero-cache/src/services/replicator/schema/replication-state.js +10 -7
  416. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  417. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
  418. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +1 -1
  419. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  420. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +1 -1
  421. package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -1
  422. package/out/zero-cache/src/services/replicator/write-worker-client.js +1 -1
  423. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  424. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  425. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  426. package/out/zero-cache/src/services/runner.js.map +1 -1
  427. package/out/zero-cache/src/services/running-state.js.map +1 -1
  428. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
  429. package/out/zero-cache/src/services/statz.js +2 -1
  430. package/out/zero-cache/src/services/statz.js.map +1 -1
  431. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +2 -2
  432. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  433. package/out/zero-cache/src/services/view-syncer/advancement-metrics.js.map +1 -1
  434. package/out/zero-cache/src/services/view-syncer/batch-pacer.js.map +1 -1
  435. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  436. package/out/zero-cache/src/services/view-syncer/client-handler.js +24 -3
  437. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  438. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts +15 -2
  439. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
  440. package/out/zero-cache/src/services/view-syncer/client-schema.js +46 -6
  441. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  442. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  443. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +2 -2
  444. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  445. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  446. package/out/zero-cache/src/services/view-syncer/cvr-store.js +10 -5
  447. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  448. package/out/zero-cache/src/services/view-syncer/cvr.js +12 -4
  449. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  450. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js +1 -1
  451. package/out/zero-cache/src/services/view-syncer/deferred-writes-budget.js.map +1 -1
  452. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  453. package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -1
  454. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -1
  455. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +2 -2
  456. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -1
  457. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +5 -3
  458. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  459. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  460. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +8 -5
  461. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  462. package/out/zero-cache/src/services/view-syncer/plan-warnings.js.map +1 -1
  463. package/out/zero-cache/src/services/view-syncer/push-cost.js.map +1 -1
  464. package/out/zero-cache/src/services/view-syncer/push-cutoff.js.map +1 -1
  465. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  466. package/out/zero-cache/src/services/view-syncer/query-shape.js.map +1 -1
  467. package/out/zero-cache/src/services/view-syncer/query-stats.js +1 -1
  468. package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -1
  469. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  470. package/out/zero-cache/src/services/view-syncer/schema/cvr.js +1 -1
  471. package/out/zero-cache/src/services/view-syncer/schema/types.js +1 -1
  472. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  473. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +7 -1
  474. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +1 -1
  475. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +8 -1
  476. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  477. package/out/zero-cache/src/services/view-syncer/snapshotter.js +6 -5
  478. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  479. package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
  480. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  481. package/out/zero-cache/src/services/view-syncer/view-syncer.js +13 -9
  482. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  483. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  484. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  485. package/out/zero-cache/src/types/lite.js +1 -1
  486. package/out/zero-cache/src/types/lite.js.map +1 -1
  487. package/out/zero-cache/src/types/pg-data-type.js +1 -1
  488. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  489. package/out/zero-cache/src/types/pg.js +6 -4
  490. package/out/zero-cache/src/types/pg.js.map +1 -1
  491. package/out/zero-cache/src/types/poke-chunk.js +2 -2
  492. package/out/zero-cache/src/types/poke-chunk.js.map +1 -1
  493. package/out/zero-cache/src/types/processes.js +1 -1
  494. package/out/zero-cache/src/types/processes.js.map +1 -1
  495. package/out/zero-cache/src/types/profiler.js.map +1 -1
  496. package/out/zero-cache/src/types/row-key.js.map +1 -1
  497. package/out/zero-cache/src/types/sql.js.map +1 -1
  498. package/out/zero-cache/src/types/streams.js +10 -9
  499. package/out/zero-cache/src/types/streams.js.map +1 -1
  500. package/out/zero-cache/src/types/strings.js.map +1 -1
  501. package/out/zero-cache/src/types/subscription.js.map +1 -1
  502. package/out/zero-cache/src/types/timeout.js +1 -1
  503. package/out/zero-cache/src/types/websocket-handoff.js +1 -1
  504. package/out/zero-cache/src/types/ws.js +1 -1
  505. package/out/zero-cache/src/workers/connection.js +5 -6
  506. package/out/zero-cache/src/workers/connection.js.map +1 -1
  507. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  508. package/out/zero-cache/src/workers/replicator.js +5 -4
  509. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  510. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  511. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +9 -1
  512. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  513. package/out/zero-cache/src/workers/syncer.js +4 -4
  514. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  515. package/out/zero-client/src/client/active-clients-manager.js +1 -1
  516. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  517. package/out/zero-client/src/client/bindings.js +11 -11
  518. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  519. package/out/zero-client/src/client/connection.js +1 -1
  520. package/out/zero-client/src/client/connection.js.map +1 -1
  521. package/out/zero-client/src/client/context.js.map +1 -1
  522. package/out/zero-client/src/client/crud-impl.js +1 -1
  523. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  524. package/out/zero-client/src/client/crud.js +1 -1
  525. package/out/zero-client/src/client/crud.js.map +1 -1
  526. package/out/zero-client/src/client/custom.js +1 -1
  527. package/out/zero-client/src/client/custom.js.map +1 -1
  528. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  529. package/out/zero-client/src/client/enable-analytics.js +1 -1
  530. package/out/zero-client/src/client/enable-analytics.js.map +1 -1
  531. package/out/zero-client/src/client/error.js.map +1 -1
  532. package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
  533. package/out/zero-client/src/client/inspector/client.js.map +1 -1
  534. package/out/zero-client/src/client/inspector/html-dialog-prompt.js +1 -1
  535. package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
  536. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  537. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  538. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  539. package/out/zero-client/src/client/ivm-branch.js +1 -3
  540. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  541. package/out/zero-client/src/client/keys.js +2 -1
  542. package/out/zero-client/src/client/keys.js.map +1 -1
  543. package/out/zero-client/src/client/log-options.js.map +1 -1
  544. package/out/zero-client/src/client/make-replicache-mutators.js +5 -3
  545. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  546. package/out/zero-client/src/client/metrics.js +3 -5
  547. package/out/zero-client/src/client/metrics.js.map +1 -1
  548. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  549. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  550. package/out/zero-client/src/client/options.js.map +1 -1
  551. package/out/zero-client/src/client/query-manager.js +2 -2
  552. package/out/zero-client/src/client/query-manager.js.map +1 -1
  553. package/out/zero-client/src/client/reload-error-handler.js +4 -3
  554. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  555. package/out/zero-client/src/client/version.js +1 -1
  556. package/out/zero-client/src/client/zero-poke-handler.js +1 -1
  557. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  558. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  559. package/out/zero-client/src/client/zero.js +19 -11
  560. package/out/zero-client/src/client/zero.js.map +1 -1
  561. package/out/zero-client/src/mod.js +23 -23
  562. package/out/zero-client/src/util/nanoid.js.map +1 -1
  563. package/out/zero-permissions/src/permissions.js +3 -2
  564. package/out/zero-permissions/src/permissions.js.map +1 -1
  565. package/out/zero-pg/src/mod.js +9 -9
  566. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  567. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  568. package/out/zero-protocol/src/application-error.js.map +1 -1
  569. package/out/zero-protocol/src/ast.js +19 -9
  570. package/out/zero-protocol/src/ast.js.map +1 -1
  571. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  572. package/out/zero-protocol/src/client-schema.js +1 -1
  573. package/out/zero-protocol/src/client-schema.js.map +1 -1
  574. package/out/zero-protocol/src/close-connection.js +1 -1
  575. package/out/zero-protocol/src/close-connection.js.map +1 -1
  576. package/out/zero-protocol/src/connect.js +1 -1
  577. package/out/zero-protocol/src/connect.js.map +1 -1
  578. package/out/zero-protocol/src/custom-queries.js +1 -1
  579. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  580. package/out/zero-protocol/src/data.js +4 -2
  581. package/out/zero-protocol/src/data.js.map +1 -1
  582. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  583. package/out/zero-protocol/src/down.d.ts +27 -27
  584. package/out/zero-protocol/src/down.js.map +1 -1
  585. package/out/zero-protocol/src/error.js.map +1 -1
  586. package/out/zero-protocol/src/inspect-down.d.ts +81 -81
  587. package/out/zero-protocol/src/inspect-down.js +1 -1
  588. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  589. package/out/zero-protocol/src/inspect-up.js +1 -1
  590. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  591. package/out/zero-protocol/src/mutate-server.js +1 -1
  592. package/out/zero-protocol/src/mutate-server.js.map +1 -1
  593. package/out/zero-protocol/src/mutation-id.js.map +1 -1
  594. package/out/zero-protocol/src/mutation.js +1 -1
  595. package/out/zero-protocol/src/mutation.js.map +1 -1
  596. package/out/zero-protocol/src/mutations-patch.js +1 -1
  597. package/out/zero-protocol/src/mutations-patch.js.map +1 -1
  598. package/out/zero-protocol/src/ping.js +1 -1
  599. package/out/zero-protocol/src/ping.js.map +1 -1
  600. package/out/zero-protocol/src/poke.d.ts +6 -6
  601. package/out/zero-protocol/src/poke.js +1 -1
  602. package/out/zero-protocol/src/poke.js.map +1 -1
  603. package/out/zero-protocol/src/pong.js +1 -1
  604. package/out/zero-protocol/src/pong.js.map +1 -1
  605. package/out/zero-protocol/src/primary-key.js.map +1 -1
  606. package/out/zero-protocol/src/protocol-version.js +1 -0
  607. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  608. package/out/zero-protocol/src/pull.js +1 -1
  609. package/out/zero-protocol/src/pull.js.map +1 -1
  610. package/out/zero-protocol/src/push.js +1 -1
  611. package/out/zero-protocol/src/push.js.map +1 -1
  612. package/out/zero-protocol/src/queries-patch.js +1 -1
  613. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  614. package/out/zero-protocol/src/query-hash-visitor.js.map +1 -1
  615. package/out/zero-protocol/src/query-hash.js +2 -2
  616. package/out/zero-protocol/src/query-server.js +1 -1
  617. package/out/zero-protocol/src/query-server.js.map +1 -1
  618. package/out/zero-protocol/src/row-patch.js.map +1 -1
  619. package/out/zero-protocol/src/up.d.ts +60 -60
  620. package/out/zero-protocol/src/up.js.map +1 -1
  621. package/out/zero-protocol/src/update-auth.js.map +1 -1
  622. package/out/zero-protocol/src/version.js.map +1 -1
  623. package/out/zero-react/src/bindings.js +11 -11
  624. package/out/zero-react/src/mod.js +5 -5
  625. package/out/zero-react/src/use-query.js +1 -1
  626. package/out/zero-react/src/use-query.js.map +1 -1
  627. package/out/zero-react/src/zero-provider.d.ts +1 -1
  628. package/out/zero-react/src/zero-provider.d.ts.map +1 -1
  629. package/out/zero-react/src/zero-provider.js +2 -1
  630. package/out/zero-react/src/zero-provider.js.map +1 -1
  631. package/out/zero-react/src/zero.js +23 -23
  632. package/out/zero-schema/src/builder/schema-builder.js +3 -2
  633. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  634. package/out/zero-schema/src/builder/table-builder.js +1 -1
  635. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  636. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  637. package/out/zero-schema/src/name-mapper.js +7 -5
  638. package/out/zero-schema/src/name-mapper.js.map +1 -1
  639. package/out/zero-schema/src/schema-config.js +1 -1
  640. package/out/zero-schema/src/schema-config.js.map +1 -1
  641. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  642. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  643. package/out/zero-server/src/adapters/pg.js.map +1 -1
  644. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  645. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  646. package/out/zero-server/src/closable-db-transaction.js.map +1 -1
  647. package/out/zero-server/src/custom.js +1 -1
  648. package/out/zero-server/src/custom.js.map +1 -1
  649. package/out/zero-server/src/mod.js +8 -8
  650. package/out/zero-server/src/process-mutations.js.map +1 -1
  651. package/out/zero-server/src/push-processor.js.map +1 -1
  652. package/out/zero-server/src/queries/process-queries.js +2 -1
  653. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  654. package/out/zero-server/src/schema.js +7 -7
  655. package/out/zero-server/src/schema.js.map +1 -1
  656. package/out/zero-server/src/zql-database.js.map +1 -1
  657. package/out/zero-solid/src/bindings.js +11 -11
  658. package/out/zero-solid/src/mod.js +5 -5
  659. package/out/zero-solid/src/solid-view.js +1 -1
  660. package/out/zero-solid/src/solid-view.js.map +1 -1
  661. package/out/zero-solid/src/use-connection-state.js +2 -1
  662. package/out/zero-solid/src/use-connection-state.js.map +1 -1
  663. package/out/zero-solid/src/use-query.js.map +1 -1
  664. package/out/zero-solid/src/use-zero-online.js +2 -1
  665. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  666. package/out/zero-solid/src/use-zero.js +3 -2
  667. package/out/zero-solid/src/use-zero.js.map +1 -1
  668. package/out/zero-solid/src/zero.js +23 -23
  669. package/out/zero-types/src/name-mapper.js.map +1 -1
  670. package/out/zql/src/builder/builder.js +15 -13
  671. package/out/zql/src/builder/builder.js.map +1 -1
  672. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +1 -1
  673. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  674. package/out/zql/src/builder/like.js +0 -1
  675. package/out/zql/src/builder/like.js.map +1 -1
  676. package/out/zql/src/ivm/array-view.js.map +1 -1
  677. package/out/zql/src/ivm/cap.js.map +1 -1
  678. package/out/zql/src/ivm/constraint.js +1 -1
  679. package/out/zql/src/ivm/constraint.js.map +1 -1
  680. package/out/zql/src/ivm/data.js.map +1 -1
  681. package/out/zql/src/ivm/deferred-input.js.map +1 -1
  682. package/out/zql/src/ivm/exists.js +20 -18
  683. package/out/zql/src/ivm/exists.js.map +1 -1
  684. package/out/zql/src/ivm/fan-in.js.map +1 -1
  685. package/out/zql/src/ivm/fan-out.js.map +1 -1
  686. package/out/zql/src/ivm/filter-operators.js +1 -1
  687. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  688. package/out/zql/src/ivm/filter-push.js.map +1 -1
  689. package/out/zql/src/ivm/filter.js.map +1 -1
  690. package/out/zql/src/ivm/flipped-join.js +1 -3
  691. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  692. package/out/zql/src/ivm/join-index-tap.js.map +1 -1
  693. package/out/zql/src/ivm/join-index.js.map +1 -1
  694. package/out/zql/src/ivm/join-utils.js +11 -13
  695. package/out/zql/src/ivm/join-utils.js.map +1 -1
  696. package/out/zql/src/ivm/join.js.map +1 -1
  697. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  698. package/out/zql/src/ivm/memory-source.js +26 -22
  699. package/out/zql/src/ivm/memory-source.js.map +1 -1
  700. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  701. package/out/zql/src/ivm/operator.js +2 -2
  702. package/out/zql/src/ivm/push-accumulated.js +0 -1
  703. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  704. package/out/zql/src/ivm/skip-yields.js.map +1 -1
  705. package/out/zql/src/ivm/skip.js.map +1 -1
  706. package/out/zql/src/ivm/take-gate.js.map +1 -1
  707. package/out/zql/src/ivm/take.js +1 -1
  708. package/out/zql/src/ivm/take.js.map +1 -1
  709. package/out/zql/src/ivm/union-fan-in.js +1 -1
  710. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  711. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  712. package/out/zql/src/ivm/view-apply-change.js +1 -1
  713. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  714. package/out/zql/src/mutate/crud.js +3 -2
  715. package/out/zql/src/mutate/crud.js.map +1 -1
  716. package/out/zql/src/planner/planner-builder.js +1 -1
  717. package/out/zql/src/planner/planner-builder.js.map +1 -1
  718. package/out/zql/src/planner/planner-connection.js.map +1 -1
  719. package/out/zql/src/planner/planner-debug.js.map +1 -1
  720. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  721. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  722. package/out/zql/src/planner/planner-filter.js.map +1 -1
  723. package/out/zql/src/planner/planner-graph.js +1 -5
  724. package/out/zql/src/planner/planner-graph.js.map +1 -1
  725. package/out/zql/src/planner/planner-join.js +1 -1
  726. package/out/zql/src/planner/planner-join.js.map +1 -1
  727. package/out/zql/src/planner/planner-source.js.map +1 -1
  728. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  729. package/out/zql/src/query/create-builder.js +2 -1
  730. package/out/zql/src/query/create-builder.js.map +1 -1
  731. package/out/zql/src/query/expression.js +1 -1
  732. package/out/zql/src/query/expression.js.map +1 -1
  733. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  734. package/out/zql/src/query/named.js +2 -1
  735. package/out/zql/src/query/named.js.map +1 -1
  736. package/out/zql/src/query/query-delegate-base.js +1 -1
  737. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  738. package/out/zql/src/query/query-impl.js +3 -2
  739. package/out/zql/src/query/query-impl.js.map +1 -1
  740. package/out/zql/src/query/query-registry.js +1 -1
  741. package/out/zql/src/query/query-registry.js.map +1 -1
  742. package/out/zql/src/query/query-transitions.js +1 -1
  743. package/out/zql/src/query/query-transitions.js.map +1 -1
  744. package/out/zql/src/query/runnable-query-impl.js +3 -2
  745. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  746. package/out/zql/src/query/static-query.js.map +1 -1
  747. package/out/zql/src/query/ttl.js +8 -8
  748. package/out/zql/src/query/ttl.js.map +1 -1
  749. package/out/zql/src/query/validate-input.js.map +1 -1
  750. package/out/zqlite/src/database-storage.d.ts +27 -8
  751. package/out/zqlite/src/database-storage.d.ts.map +1 -1
  752. package/out/zqlite/src/database-storage.js +190 -53
  753. package/out/zqlite/src/database-storage.js.map +1 -1
  754. package/out/zqlite/src/db.d.ts +47 -1
  755. package/out/zqlite/src/db.d.ts.map +1 -1
  756. package/out/zqlite/src/db.js +121 -21
  757. package/out/zqlite/src/db.js.map +1 -1
  758. package/out/zqlite/src/explain-queries.js.map +1 -1
  759. package/out/zqlite/src/fetch-sql.js.map +1 -1
  760. package/out/zqlite/src/index-usage.js.map +1 -1
  761. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  762. package/out/zqlite/src/internal/sql.js.map +1 -1
  763. package/out/zqlite/src/internal/statement-cache.d.ts +7 -0
  764. package/out/zqlite/src/internal/statement-cache.d.ts.map +1 -1
  765. package/out/zqlite/src/internal/statement-cache.js +11 -4
  766. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  767. package/out/zqlite/src/mod.js +5 -5
  768. package/out/zqlite/src/pending-delta.js.map +1 -1
  769. package/out/zqlite/src/query-builder.js +1 -1
  770. package/out/zqlite/src/query-builder.js.map +1 -1
  771. package/out/zqlite/src/query-delegate.js.map +1 -1
  772. package/out/zqlite/src/resolve-scalar-subqueries.js +2 -5
  773. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  774. package/out/zqlite/src/sqlite-cost-model.js +3 -2
  775. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  776. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  777. package/out/zqlite/src/table-source.d.ts +11 -0
  778. package/out/zqlite/src/table-source.d.ts.map +1 -1
  779. package/out/zqlite/src/table-source.js +62 -25
  780. package/out/zqlite/src/table-source.js.map +1 -1
  781. package/package.json +17 -15
  782. package/out/otel/src/maybe-time.d.ts +0 -3
  783. package/out/otel/src/maybe-time.d.ts.map +0 -1
  784. package/out/otel/src/maybe-time.js +0 -15
  785. package/out/otel/src/maybe-time.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"query-delegate-base.js","names":[],"sources":["../../../../../zql/src/query/query-delegate-base.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {buildPipeline} from '../builder/builder.ts';\nimport {ArrayView} from '../ivm/array-view.ts';\nimport {DeferredInput} from '../ivm/deferred-input.ts';\nimport type {FilterInput} from '../ivm/filter-operators.ts';\nimport {MemoryStorage} from '../ivm/memory-storage.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport type {MetricMap} from './metrics-delegate.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {\n AttachPipeline,\n CommitListener,\n GotCallback,\n QueryDelegate,\n} from './query-delegate.ts';\nimport {asQueryInternals, type QueryInternals} from './query-internals.ts';\nimport type {\n HumanReadable,\n MaterializeOptions,\n PreloadOptions,\n Query,\n RunOptions,\n} from './query.ts';\nimport {DEFAULT_PRELOAD_TTL_MS, DEFAULT_TTL_MS, type TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\n/**\n * Base class that provides default implementations for common QueryDelegate methods.\n * Subclasses can override specific methods as needed.\n */\nexport abstract class QueryDelegateBase implements QueryDelegate {\n /**\n * Default implementation that just calls applyViewUpdates synchronously.\n * Override if you need custom batching behavior (e.g., SolidJS).\n */\n batchViewUpdates<T>(applyViewUpdates: () => T): T {\n return applyViewUpdates();\n }\n\n /**\n * Default implementation returns MemoryStorage.\n * Override if you need custom storage.\n */\n createStorage(): Storage {\n return new MemoryStorage();\n }\n\n /**\n * Default implementation calls materializeImpl.\n * Override if you need custom materialization behavior.\n */\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: undefined,\n options?: MaterializeOptions,\n ): TypedView<HumanReadable<TReturn>>;\n\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T;\n\n /**\n * Materialize a query into a custom view using a provided factory function.\n */\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T;\n\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T {\n return materializeImpl(query, this, factory, options);\n }\n\n /**\n * Default implementation calls runImpl.\n * Override if you need custom query execution (e.g., TestPGQueryDelegate).\n */\n run<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n return runImpl(query, this, options);\n }\n\n /**\n * Default implementation calls preloadImpl.\n * Override if you need custom preload behavior.\n */\n preload<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n options?: PreloadOptions,\n ): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n return preloadImpl(query, this, options);\n }\n\n /**\n * Default no-op implementation for decorateSourceInput.\n * Override if you need to wrap or instrument source inputs.\n */\n decorateSourceInput(input: SourceInput, _queryID: string): Input {\n return input;\n }\n\n /**\n * Default no-op implementation for decorateInput.\n * Override if you need to wrap or instrument inputs.\n */\n decorateInput(input: Input, _name: string): Input {\n return input;\n }\n\n /**\n * Default no-op implementation for decorateFilterInput.\n * Override if you need to wrap or instrument filter inputs.\n */\n decorateFilterInput(input: FilterInput, _name: string): FilterInput {\n return input;\n }\n\n /**\n * Default no-op implementation for addEdge.\n * Override if you need to track graph edges (e.g., visualization).\n */\n addEdge(_source: InputBase, _dest: InputBase): void {\n // No-op\n }\n\n /**\n * Default no-op implementation for addMetric.\n * Override if you need to collect metrics.\n */\n addMetric<K extends keyof MetricMap>(\n _metric: K,\n _value: number,\n ..._args: MetricMap[K]\n ): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to track server queries (e.g., ZeroContext, test delegates).\n */\n addServerQuery(_ast: AST, _ttl: TTL, _gotCallback?: GotCallback): () => void {\n return () => {};\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to track custom queries (e.g., ZeroContext, test delegates).\n */\n addCustomQuery(\n _ast: AST,\n _customQueryID: CustomQueryID,\n _ttl: TTL,\n _gotCallback?: GotCallback,\n ): () => void {\n return () => {};\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to handle query updates.\n */\n updateServerQuery(_ast: AST, _ttl: TTL): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to handle custom query updates.\n */\n updateCustomQuery(_customQueryID: CustomQueryID, _ttl: TTL): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to flush query changes.\n */\n flushQueryChanges(): void {\n // No-op\n }\n\n /**\n * Called when a transaction commits. Override to add custom behavior.\n * Default implementation returns a no-op cleanup function.\n */\n onTransactionCommit(_cb: CommitListener): () => void {\n return () => {};\n }\n\n /**\n * Validates run options. Override to add custom validation.\n * Default implementation is a no-op.\n */\n assertValidRunOptions(_options?: RunOptions): void {\n // No-op\n }\n\n abstract readonly defaultQueryComplete: boolean;\n\n /**\n * Default: pipelines can always be built immediately. Override (together\n * with `onPipelinesReady`) to defer pipeline construction.\n */\n get pipelinesReady(): boolean {\n return true;\n }\n\n onPipelinesReady(_attach: AttachPipeline): () => void {\n throw new Error(\n 'onPipelinesReady called on a delegate whose pipelines are always ready',\n );\n }\n\n // BuilderDelegate methods - must be implemented\n abstract getSource(name: string): Source | undefined;\n}\n\n// oxlint-disable-next-line require-await\nexport async function runImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n options?: RunOptions,\n): Promise<HumanReadable<TReturn>> {\n delegate.assertValidRunOptions(options);\n const v: TypedView<HumanReadable<TReturn>> = materializeImpl(\n query,\n delegate,\n undefined,\n {\n ttl: options?.ttl,\n },\n );\n if (options?.type === 'complete' || options?.type === 'cached') {\n // 'cached' is satisfied by a result the server confirmed on a previous\n // connection, or by this connection confirming it, whichever comes first.\n const acceptCached = options.type === 'cached';\n return new Promise(resolve => {\n v.addListener((data, type) => {\n if (type === 'complete' || (acceptCached && type === 'cached')) {\n v.destroy();\n resolve(data as HumanReadable<TReturn>);\n } else if (type === 'error') {\n v.destroy();\n resolve(Promise.reject(data));\n }\n });\n });\n }\n\n options?.type satisfies 'unknown' | undefined;\n\n // A snapshot of what the view holds right now. While the delegate's\n // pipelines are not ready the view is deferred and this is empty; 'unknown'\n // has never waited for the local data, so it does not wait for that either.\n const ret = v.data;\n v.destroy();\n return ret;\n}\n\nexport function preloadImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n options?: PreloadOptions,\n): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n} {\n const qi = asQueryInternals(query);\n const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;\n const completeResolver = resolver<void>();\n const cachedResolver = resolver<void>();\n const {promise: complete} = completeResolver;\n const {promise: cached} = cachedResolver;\n // A caller may ignore either promise; a query error must not surface as an\n // unhandled rejection through the one nobody awaits.\n void complete.catch(() => {});\n void cached.catch(() => {});\n const {customQueryID, ast} = qi;\n const gotCallback: GotCallback = (got, error) => {\n if (error) {\n // The query cannot be satisfied; neither waiter should hang.\n cachedResolver.reject(error);\n completeResolver.reject(error);\n return;\n }\n // Only a server confirmation on this connection resolves `complete`;\n // `cached` is also satisfied by one from a previous connection.\n if (got === true) {\n cachedResolver.resolve();\n completeResolver.resolve();\n } else if (got === 'cached') {\n cachedResolver.resolve();\n }\n };\n const cleanup = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n if (delegate.defaultQueryComplete) {\n // A delegate whose results are complete from the start (a server-side\n // one) has no got callback to drive the waiters.\n cachedResolver.resolve();\n completeResolver.resolve();\n }\n return {\n cleanup,\n complete,\n cached,\n };\n}\n\nexport function materializeImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n factory: ViewFactory<\n TTable,\n TSchema,\n TReturn,\n T\n // oxlint-disable-next-line no-explicit-any\n > = arrayViewFactory as any,\n options?: MaterializeOptions,\n): T {\n let ttl: TTL = options?.ttl ?? DEFAULT_TTL_MS;\n\n const qi = asQueryInternals(query);\n const {ast, format, customQueryID} = qi;\n\n const queryID = customQueryID\n ? hashOfNameAndArgs(customQueryID.name, customQueryID.args)\n : hashOfAST(qi.ast);\n const queryCompleteResolver = resolver<true>();\n // When the delegate cannot build pipelines yet, the view starts over an\n // empty DeferredInput and is hydrated later. A view must not report\n // `complete` until it has actually been hydrated, so completion is gated on\n // both the server's \"got\" and the pipeline being attached.\n const deferPipeline = !delegate.pipelinesReady;\n let attached = !deferPipeline;\n // The last got report: `true` once the server confirmed the query on this\n // connection, `'cached'` while the store holds a previous connection's\n // confirmed result, `false` otherwise.\n let got: boolean | 'cached' = delegate.defaultQueryComplete;\n let queryComplete: boolean | ErroredQuery = attached && got === true;\n const updateTTL = customQueryID\n ? (newTTL: TTL) => delegate.updateCustomQuery(customQueryID, newTTL)\n : (newTTL: TTL) => delegate.updateServerQuery(ast, newTTL);\n\n // Completion, and the end-to-end metric, require both the server's \"got\"\n // and the pipeline being attached: until then the view is still empty.\n const maybeResolveComplete = () => {\n if (attached && got === true && queryComplete !== true) {\n delegate.addMetric(\n 'query-materialization-end-to-end',\n performance.now() - t0,\n queryID,\n ast,\n );\n queryComplete = true;\n queryCompleteResolver.resolve(true);\n }\n };\n\n // The view, seen as its optional hooks. Only views that implement\n // `markCached`/`unmarkCached` (e.g. ArrayView) surface 'cached'; for any\n // other factory the optional calls are no-ops. The registration path can\n // report 'cached' synchronously, before the view below exists, so this\n // stays undefined until then and the mark is applied afterwards.\n let viewHooks: OptionalViewHooks | undefined;\n\n // Like 'complete', 'cached' is a claim about the rows the view holds, so it\n // waits for the view to exist and its pipeline to be attached. Once the\n // server has confirmed the query on this connection, 'complete' supersedes\n // it and the mark is skipped.\n const maybeMarkCached = () => {\n // Only while the query is still incomplete: 'complete' supersedes the\n // mark, and an error that arrived before attach must not be preceded by\n // a 'cached' notification.\n if (attached && got === 'cached' && queryComplete === false) {\n viewHooks?.markCached?.();\n }\n };\n\n let destroyed = false;\n const gotCallback: GotCallback = (value, error) => {\n if (destroyed) {\n // The delegate may keep this callback registered for a while after\n // destroy (removals are deferred while mutations are pending); a dead\n // view must not be driven, nor its listeners fired.\n return;\n }\n if (error) {\n queryCompleteResolver.reject(error);\n queryComplete = error;\n return;\n }\n\n got = value;\n if (got === 'cached') {\n maybeMarkCached();\n } else if (got === false) {\n // The got key was deleted (eviction) before the server confirmed the\n // query on this connection.\n viewHooks?.unmarkCached?.();\n } else {\n maybeResolveComplete();\n }\n };\n\n let removeCommitObserver: (() => void) | undefined;\n let removePendingAttach: (() => void) | undefined;\n const onDestroy = () => {\n destroyed = true;\n removePendingAttach?.();\n removePendingAttach = undefined;\n input.destroy();\n removeCommitObserver?.();\n removeAddedQuery();\n };\n\n const t0 = performance.now();\n\n const removeAddedQuery = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n\n const deferred = deferPipeline\n ? newDeferredInput(ast, delegate, queryID)\n : undefined;\n // No type annotation here: annotating this as `Input` widens it enough that\n // the view type loses the pipeline's concrete schema, and `Zero.run` then\n // stops rejecting a query built from a schema with legacy queries enabled\n // (custom.test.ts covers that rejection).\n const input = deferred ?? buildPipeline(ast, delegate, queryID);\n\n const view = delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(\n query,\n input,\n format,\n onDestroy,\n cb => {\n removeCommitObserver = delegate.onTransactionCommit(cb);\n },\n queryComplete || queryCompleteResolver.promise,\n updateTTL,\n ),\n );\n\n if (!deferred) {\n delegate.addMetric(\n 'query-materialization-client',\n performance.now() - t0,\n queryID,\n );\n } else {\n // Registered after the factory ran so a throwing factory leaves nothing\n // behind.\n removePendingAttach = delegate.onPipelinesReady(() => {\n removePendingAttach = undefined;\n if (deferred.destroyed) {\n return () => {};\n }\n const t1 = performance.now();\n try {\n viewHooks?.holdData?.();\n deferred.attach();\n } catch (e) {\n // Surface the failure on this view and let the delegate decide how\n // to log it. Other pending pipelines are unaffected.\n const error: ErroredQuery = {\n error: 'app',\n id: queryID,\n name: customQueryID?.name ?? '',\n message: e instanceof Error ? e.message : String(e),\n };\n queryComplete = error;\n queryCompleteResolver.reject(error);\n throw e;\n }\n const hydrateMs = performance.now() - t1;\n // The view holds its rows now but must not say so yet: the delegate\n // releases every view hydrated in the same batch together.\n return () => {\n if (destroyed) {\n return;\n }\n attached = true;\n viewHooks?.releaseData?.();\n delegate.addMetric('query-materialization-client', hydrateMs, queryID);\n maybeResolveComplete();\n maybeMarkCached();\n };\n });\n }\n\n viewHooks = view as OptionalViewHooks;\n maybeMarkCached();\n\n return view as T;\n}\n\n/**\n * Creates the placeholder input for a query whose pipeline cannot be built yet.\n *\n * `Input.getSchema()` is unconditional, so the placeholder needs the schema up\n * front. It is captured by building a pipeline and immediately destroying it:\n * building only connects to the sources, while the indexes and rows -- the\n * expensive part this deferral exists to postpone -- are read on the first\n * fetch. Measured at ~5us against ~500us for a single 100 row fetch.\n *\n * Building here also means a query that cannot be built at all (an unknown\n * table, `not(exists())` on the client) still throws from `materialize()`,\n * as it did before hydration was deferred.\n */\nfunction newDeferredInput(\n ast: AST,\n delegate: QueryDelegate,\n queryID: string,\n): DeferredInput {\n const build = () => buildPipeline(ast, delegate, queryID);\n const probe = build();\n try {\n return new DeferredInput(probe.getSchema(), build);\n } finally {\n probe.destroy();\n }\n}\n\n/**\n * Optional methods `materialize` calls on a view when it has them (ArrayView\n * does). See {@link ViewFactory} for what a custom view needs to know.\n */\ntype OptionalViewHooks = {\n // Surface the 'cached' result type. Views without these never show it.\n markCached?: (() => void) | undefined;\n unmarkCached?: (() => void) | undefined;\n // Keep showing the current snapshot until `releaseData()` (or the next\n // flush), and notify nobody until that flush, so a deferred view does not\n // show rows ahead of its release.\n holdData?: (() => void) | undefined;\n // Called at the release: show the hydrated rows through `data` again, but\n // leave notifying listeners to the flush that follows all the releases.\n releaseData?: (() => void) | undefined;\n};\n\nfunction arrayViewFactory<\n TTable extends string,\n TSchema extends Schema,\n TReturn,\n>(\n _query: QueryInternals<TTable, TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n): TypedView<HumanReadable<TReturn>> {\n const v = new ArrayView<HumanReadable<TReturn>>(\n input,\n format,\n queryComplete,\n updateTTL,\n );\n v.onDestroy = onDestroy;\n onTransactionCommit(() => v.flush());\n return v;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query-delegate-base.js","names":["hashOfNameAndArgs"],"sources":["../../../../../zql/src/query/query-delegate-base.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {buildPipeline} from '../builder/builder.ts';\nimport {ArrayView} from '../ivm/array-view.ts';\nimport {DeferredInput} from '../ivm/deferred-input.ts';\nimport type {FilterInput} from '../ivm/filter-operators.ts';\nimport {MemoryStorage} from '../ivm/memory-storage.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport type {MetricMap} from './metrics-delegate.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {\n AttachPipeline,\n CommitListener,\n GotCallback,\n QueryDelegate,\n} from './query-delegate.ts';\nimport {asQueryInternals, type QueryInternals} from './query-internals.ts';\nimport type {\n HumanReadable,\n MaterializeOptions,\n PreloadOptions,\n Query,\n RunOptions,\n} from './query.ts';\nimport {DEFAULT_PRELOAD_TTL_MS, DEFAULT_TTL_MS, type TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\n/**\n * Base class that provides default implementations for common QueryDelegate methods.\n * Subclasses can override specific methods as needed.\n */\nexport abstract class QueryDelegateBase implements QueryDelegate {\n /**\n * Default implementation that just calls applyViewUpdates synchronously.\n * Override if you need custom batching behavior (e.g., SolidJS).\n */\n batchViewUpdates<T>(applyViewUpdates: () => T): T {\n return applyViewUpdates();\n }\n\n /**\n * Default implementation returns MemoryStorage.\n * Override if you need custom storage.\n */\n createStorage(): Storage {\n return new MemoryStorage();\n }\n\n /**\n * Default implementation calls materializeImpl.\n * Override if you need custom materialization behavior.\n */\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: undefined,\n options?: MaterializeOptions,\n ): TypedView<HumanReadable<TReturn>>;\n\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T;\n\n /**\n * Materialize a query into a custom view using a provided factory function.\n */\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T;\n\n materialize<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n >(\n query: Query<TTable, TSchema, TReturn>,\n factory?: ViewFactory<TTable, TSchema, TReturn, T>,\n options?: MaterializeOptions,\n ): T {\n return materializeImpl(query, this, factory, options);\n }\n\n /**\n * Default implementation calls runImpl.\n * Override if you need custom query execution (e.g., TestPGQueryDelegate).\n */\n run<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n return runImpl(query, this, options);\n }\n\n /**\n * Default implementation calls preloadImpl.\n * Override if you need custom preload behavior.\n */\n preload<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n >(\n query: Query<TTable, TSchema, TReturn>,\n options?: PreloadOptions,\n ): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n return preloadImpl(query, this, options);\n }\n\n /**\n * Default no-op implementation for decorateSourceInput.\n * Override if you need to wrap or instrument source inputs.\n */\n decorateSourceInput(input: SourceInput, _queryID: string): Input {\n return input;\n }\n\n /**\n * Default no-op implementation for decorateInput.\n * Override if you need to wrap or instrument inputs.\n */\n decorateInput(input: Input, _name: string): Input {\n return input;\n }\n\n /**\n * Default no-op implementation for decorateFilterInput.\n * Override if you need to wrap or instrument filter inputs.\n */\n decorateFilterInput(input: FilterInput, _name: string): FilterInput {\n return input;\n }\n\n /**\n * Default no-op implementation for addEdge.\n * Override if you need to track graph edges (e.g., visualization).\n */\n addEdge(_source: InputBase, _dest: InputBase): void {\n // No-op\n }\n\n /**\n * Default no-op implementation for addMetric.\n * Override if you need to collect metrics.\n */\n addMetric<K extends keyof MetricMap>(\n _metric: K,\n _value: number,\n ..._args: MetricMap[K]\n ): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to track server queries (e.g., ZeroContext, test delegates).\n */\n addServerQuery(_ast: AST, _ttl: TTL, _gotCallback?: GotCallback): () => void {\n return () => {};\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to track custom queries (e.g., ZeroContext, test delegates).\n */\n addCustomQuery(\n _ast: AST,\n _customQueryID: CustomQueryID,\n _ttl: TTL,\n _gotCallback?: GotCallback,\n ): () => void {\n return () => {};\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to handle query updates.\n */\n updateServerQuery(_ast: AST, _ttl: TTL): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to handle custom query updates.\n */\n updateCustomQuery(_customQueryID: CustomQueryID, _ttl: TTL): void {\n // No-op\n }\n\n /**\n * Default no-op implementation.\n * Override if you need to flush query changes.\n */\n flushQueryChanges(): void {\n // No-op\n }\n\n /**\n * Called when a transaction commits. Override to add custom behavior.\n * Default implementation returns a no-op cleanup function.\n */\n onTransactionCommit(_cb: CommitListener): () => void {\n return () => {};\n }\n\n /**\n * Validates run options. Override to add custom validation.\n * Default implementation is a no-op.\n */\n assertValidRunOptions(_options?: RunOptions): void {\n // No-op\n }\n\n abstract readonly defaultQueryComplete: boolean;\n\n /**\n * Default: pipelines can always be built immediately. Override (together\n * with `onPipelinesReady`) to defer pipeline construction.\n */\n get pipelinesReady(): boolean {\n return true;\n }\n\n onPipelinesReady(_attach: AttachPipeline): () => void {\n throw new Error(\n 'onPipelinesReady called on a delegate whose pipelines are always ready',\n );\n }\n\n // BuilderDelegate methods - must be implemented\n abstract getSource(name: string): Source | undefined;\n}\n\n// oxlint-disable-next-line require-await\nexport async function runImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n options?: RunOptions,\n): Promise<HumanReadable<TReturn>> {\n delegate.assertValidRunOptions(options);\n const v: TypedView<HumanReadable<TReturn>> = materializeImpl(\n query,\n delegate,\n undefined,\n {\n ttl: options?.ttl,\n },\n );\n if (options?.type === 'complete' || options?.type === 'cached') {\n // 'cached' is satisfied by a result the server confirmed on a previous\n // connection, or by this connection confirming it, whichever comes first.\n const acceptCached = options.type === 'cached';\n return new Promise(resolve => {\n v.addListener((data, type) => {\n if (type === 'complete' || (acceptCached && type === 'cached')) {\n v.destroy();\n resolve(data as HumanReadable<TReturn>);\n } else if (type === 'error') {\n v.destroy();\n resolve(Promise.reject(data));\n }\n });\n });\n }\n\n options?.type satisfies 'unknown' | undefined;\n\n // A snapshot of what the view holds right now. While the delegate's\n // pipelines are not ready the view is deferred and this is empty; 'unknown'\n // has never waited for the local data, so it does not wait for that either.\n const ret = v.data;\n v.destroy();\n return ret;\n}\n\nexport function preloadImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n options?: PreloadOptions,\n): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n} {\n const qi = asQueryInternals(query);\n const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;\n const completeResolver = resolver<void>();\n const cachedResolver = resolver<void>();\n const {promise: complete} = completeResolver;\n const {promise: cached} = cachedResolver;\n // A caller may ignore either promise; a query error must not surface as an\n // unhandled rejection through the one nobody awaits.\n void complete.catch(() => {});\n void cached.catch(() => {});\n const {customQueryID, ast} = qi;\n const gotCallback: GotCallback = (got, error) => {\n if (error) {\n // The query cannot be satisfied; neither waiter should hang.\n cachedResolver.reject(error);\n completeResolver.reject(error);\n return;\n }\n // Only a server confirmation on this connection resolves `complete`;\n // `cached` is also satisfied by one from a previous connection.\n if (got === true) {\n cachedResolver.resolve();\n completeResolver.resolve();\n } else if (got === 'cached') {\n cachedResolver.resolve();\n }\n };\n const cleanup = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n if (delegate.defaultQueryComplete) {\n // A delegate whose results are complete from the start (a server-side\n // one) has no got callback to drive the waiters.\n cachedResolver.resolve();\n completeResolver.resolve();\n }\n return {\n cleanup,\n complete,\n cached,\n };\n}\n\nexport function materializeImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n T,\n>(\n query: Query<TTable, TSchema, TReturn>,\n delegate: QueryDelegate,\n factory: ViewFactory<\n TTable,\n TSchema,\n TReturn,\n T\n // oxlint-disable-next-line no-explicit-any\n > = arrayViewFactory as any,\n options?: MaterializeOptions,\n): T {\n let ttl: TTL = options?.ttl ?? DEFAULT_TTL_MS;\n\n const qi = asQueryInternals(query);\n const {ast, format, customQueryID} = qi;\n\n const queryID = customQueryID\n ? hashOfNameAndArgs(customQueryID.name, customQueryID.args)\n : hashOfAST(qi.ast);\n const queryCompleteResolver = resolver<true>();\n // When the delegate cannot build pipelines yet, the view starts over an\n // empty DeferredInput and is hydrated later. A view must not report\n // `complete` until it has actually been hydrated, so completion is gated on\n // both the server's \"got\" and the pipeline being attached.\n const deferPipeline = !delegate.pipelinesReady;\n let attached = !deferPipeline;\n // The last got report: `true` once the server confirmed the query on this\n // connection, `'cached'` while the store holds a previous connection's\n // confirmed result, `false` otherwise.\n let got: boolean | 'cached' = delegate.defaultQueryComplete;\n let queryComplete: boolean | ErroredQuery = attached && got === true;\n const updateTTL = customQueryID\n ? (newTTL: TTL) => delegate.updateCustomQuery(customQueryID, newTTL)\n : (newTTL: TTL) => delegate.updateServerQuery(ast, newTTL);\n\n // Completion, and the end-to-end metric, require both the server's \"got\"\n // and the pipeline being attached: until then the view is still empty.\n const maybeResolveComplete = () => {\n if (attached && got === true && queryComplete !== true) {\n delegate.addMetric(\n 'query-materialization-end-to-end',\n performance.now() - t0,\n queryID,\n ast,\n );\n queryComplete = true;\n queryCompleteResolver.resolve(true);\n }\n };\n\n // The view, seen as its optional hooks. Only views that implement\n // `markCached`/`unmarkCached` (e.g. ArrayView) surface 'cached'; for any\n // other factory the optional calls are no-ops. The registration path can\n // report 'cached' synchronously, before the view below exists, so this\n // stays undefined until then and the mark is applied afterwards.\n let viewHooks: OptionalViewHooks | undefined;\n\n // Like 'complete', 'cached' is a claim about the rows the view holds, so it\n // waits for the view to exist and its pipeline to be attached. Once the\n // server has confirmed the query on this connection, 'complete' supersedes\n // it and the mark is skipped.\n const maybeMarkCached = () => {\n // Only while the query is still incomplete: 'complete' supersedes the\n // mark, and an error that arrived before attach must not be preceded by\n // a 'cached' notification.\n if (attached && got === 'cached' && queryComplete === false) {\n viewHooks?.markCached?.();\n }\n };\n\n let destroyed = false;\n const gotCallback: GotCallback = (value, error) => {\n if (destroyed) {\n // The delegate may keep this callback registered for a while after\n // destroy (removals are deferred while mutations are pending); a dead\n // view must not be driven, nor its listeners fired.\n return;\n }\n if (error) {\n queryCompleteResolver.reject(error);\n queryComplete = error;\n return;\n }\n\n got = value;\n if (got === 'cached') {\n maybeMarkCached();\n } else if (got === false) {\n // The got key was deleted (eviction) before the server confirmed the\n // query on this connection.\n viewHooks?.unmarkCached?.();\n } else {\n maybeResolveComplete();\n }\n };\n\n let removeCommitObserver: (() => void) | undefined;\n let removePendingAttach: (() => void) | undefined;\n const onDestroy = () => {\n destroyed = true;\n removePendingAttach?.();\n removePendingAttach = undefined;\n input.destroy();\n removeCommitObserver?.();\n removeAddedQuery();\n };\n\n const t0 = performance.now();\n\n const removeAddedQuery = customQueryID\n ? delegate.addCustomQuery(ast, customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n\n const deferred = deferPipeline\n ? newDeferredInput(ast, delegate, queryID)\n : undefined;\n // No type annotation here: annotating this as `Input` widens it enough that\n // the view type loses the pipeline's concrete schema, and `Zero.run` then\n // stops rejecting a query built from a schema with legacy queries enabled\n // (custom.test.ts covers that rejection).\n const input = deferred ?? buildPipeline(ast, delegate, queryID);\n\n const view = delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(\n query,\n input,\n format,\n onDestroy,\n cb => {\n removeCommitObserver = delegate.onTransactionCommit(cb);\n },\n queryComplete || queryCompleteResolver.promise,\n updateTTL,\n ),\n );\n\n if (!deferred) {\n delegate.addMetric(\n 'query-materialization-client',\n performance.now() - t0,\n queryID,\n );\n } else {\n // Registered after the factory ran so a throwing factory leaves nothing\n // behind.\n removePendingAttach = delegate.onPipelinesReady(() => {\n removePendingAttach = undefined;\n if (deferred.destroyed) {\n return () => {};\n }\n const t1 = performance.now();\n try {\n viewHooks?.holdData?.();\n deferred.attach();\n } catch (e) {\n // Surface the failure on this view and let the delegate decide how\n // to log it. Other pending pipelines are unaffected.\n const error: ErroredQuery = {\n error: 'app',\n id: queryID,\n name: customQueryID?.name ?? '',\n message: e instanceof Error ? e.message : String(e),\n };\n queryComplete = error;\n queryCompleteResolver.reject(error);\n throw e;\n }\n const hydrateMs = performance.now() - t1;\n // The view holds its rows now but must not say so yet: the delegate\n // releases every view hydrated in the same batch together.\n return () => {\n if (destroyed) {\n return;\n }\n attached = true;\n viewHooks?.releaseData?.();\n delegate.addMetric('query-materialization-client', hydrateMs, queryID);\n maybeResolveComplete();\n maybeMarkCached();\n };\n });\n }\n\n viewHooks = view as OptionalViewHooks;\n maybeMarkCached();\n\n return view as T;\n}\n\n/**\n * Creates the placeholder input for a query whose pipeline cannot be built yet.\n *\n * `Input.getSchema()` is unconditional, so the placeholder needs the schema up\n * front. It is captured by building a pipeline and immediately destroying it:\n * building only connects to the sources, while the indexes and rows -- the\n * expensive part this deferral exists to postpone -- are read on the first\n * fetch. Measured at ~5us against ~500us for a single 100 row fetch.\n *\n * Building here also means a query that cannot be built at all (an unknown\n * table, `not(exists())` on the client) still throws from `materialize()`,\n * as it did before hydration was deferred.\n */\nfunction newDeferredInput(\n ast: AST,\n delegate: QueryDelegate,\n queryID: string,\n): DeferredInput {\n const build = () => buildPipeline(ast, delegate, queryID);\n const probe = build();\n try {\n return new DeferredInput(probe.getSchema(), build);\n } finally {\n probe.destroy();\n }\n}\n\n/**\n * Optional methods `materialize` calls on a view when it has them (ArrayView\n * does). See {@link ViewFactory} for what a custom view needs to know.\n */\ntype OptionalViewHooks = {\n // Surface the 'cached' result type. Views without these never show it.\n markCached?: (() => void) | undefined;\n unmarkCached?: (() => void) | undefined;\n // Keep showing the current snapshot until `releaseData()` (or the next\n // flush), and notify nobody until that flush, so a deferred view does not\n // show rows ahead of its release.\n holdData?: (() => void) | undefined;\n // Called at the release: show the hydrated rows through `data` again, but\n // leave notifying listeners to the flush that follows all the releases.\n releaseData?: (() => void) | undefined;\n};\n\nfunction arrayViewFactory<\n TTable extends string,\n TSchema extends Schema,\n TReturn,\n>(\n _query: QueryInternals<TTable, TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n): TypedView<HumanReadable<TReturn>> {\n const v = new ArrayView<HumanReadable<TReturn>>(\n input,\n format,\n queryComplete,\n updateTTL,\n );\n v.onDestroy = onDestroy;\n onTransactionCommit(() => v.flush());\n return v;\n}\n"],"mappings":"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"}
@@ -454,7 +454,8 @@ function astID(ast) {
454
454
  */
455
455
  var whereKeys = /* @__PURE__ */ new Map();
456
456
  function whereKey(column, op) {
457
- return getOrInsertComputed(getOrInsertComputed(whereKeys, column, newMap), op, (op) => `where:${column}:${op}`);
457
+ const byOp = getOrInsertComputed(whereKeys, column, newMap);
458
+ return getOrInsertComputed(byOp, op, (op) => `where:${column}:${op}`);
458
459
  }
459
460
  var relatedKeys = /* @__PURE__ */ new Map();
460
461
  var newRelatedKey = (relationship) => `related:${relationship}`;
@@ -588,6 +589,6 @@ function isTwoHop(r) {
588
589
  return r.length === 2;
589
590
  }
590
591
  //#endregion
591
- export { QueryImpl, newQuery, newQueryImpl };
592
+ export { QueryImpl, asQueryImpl, newQuery, newQueryImpl };
592
593
 
593
594
  //# sourceMappingURL=query-impl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-impl.js","names":["#schema","#tableName","#ast","#system","#currentJunction","#newQuery","#transitions","#record","#parent","#derive","#hash","#canonicalize","#byHash","#sameAs","#deriveBounded","#expressionBuilder","#exists"],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {\n deepEqual,\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport {getOrInsertComputed, newMap} from '../../../shared/src/map.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type NormalizedAST,\n type Parameter,\n type LiteralValue,\n type SimpleCondition,\n type SimpleOperator,\n type System,\n insertRelated,\n normalizeAST,\n normalizeCondition,\n normalizedRelated,\n SUBQ_PREFIX,\n tableAST,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfQueryInternals} from '../../../zero-protocol/src/query-hash-visitor.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport {\n HashIndex,\n Transitions,\n type Delta,\n type TransitionValue,\n} from './query-transitions.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryInternal(\n schema,\n table,\n tableAST(table),\n defaultFormat,\n 'client',\n );\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // This is the entry point for ASTs that were not built by QueryImpl, so\n // normalize it here to establish the invariant that #ast is normalized.\n return newQueryInternal(schema, tableName, normalizeAST(ast), format, system);\n}\n\n/**\n * Root queries are interned per schema so that two `createBuilder(schema)` calls\n * hand out the same starting point, and therefore share the whole transition\n * tree below it. Only cleared entries accumulate here, at most one per\n * system/table pair, so no sweeping is needed.\n */\nconst rootsBySchema = new WeakMap<\n Schema,\n Map<string, WeakRef<QueryImpl<any, any, any>>>\n>();\n\n/**\n * Whether this is the AST `tableAST(tableName)` produces -- the whole table,\n * nothing else. A normalized AST carries every field, so this cannot be a key\n * count; each one has to be checked.\n */\nfunction isRootAST(ast: NormalizedAST, tableName: string): boolean {\n return (\n ast.table === tableName &&\n ast.schema === undefined &&\n ast.alias === undefined &&\n ast.where === undefined &&\n ast.related === undefined &&\n ast.start === undefined &&\n ast.limit === undefined &&\n ast.orderBy === undefined\n );\n}\n\nfunction newQueryInternal<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // Callers that hand in a pre-built AST -- benchmarks and the integration-test\n // harnesses -- are not roots and are not interned.\n const interned = format === defaultFormat && isRootAST(ast, tableName);\n const key = `${system}:${tableName}`;\n let roots: Map<string, WeakRef<QueryImpl<any, any, any>>> | undefined;\n\n if (interned) {\n roots = rootsBySchema.get(schema);\n const existing = roots?.get(key)?.deref();\n if (existing) {\n return existing as QueryImpl<TTable, TSchema, TReturn>;\n }\n }\n\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n const created = inner<TTable, TReturn>(\n tableName,\n ast,\n format,\n undefined,\n undefined,\n );\n\n if (interned) {\n if (!roots) {\n roots = new Map();\n rootsBySchema.set(schema, roots);\n }\n roots.set(key, new WeakRef(created));\n }\n\n return created;\n}\n\n/**\n * The AST of a QueryImpl is always normalized. Each step builds its AST in\n * normalized form rather than normalizing afterwards: a normalized AST has\n * every field, so spreading one and replacing a field keeps the field order\n * intact, and only the field a step actually changes needs normalizing (the\n * conditions of a `where`, the position of a new `related`). The ASTs that\n * come in from the outside are normalized by {@link newQueryImpl}, which is\n * what the `NormalizedAST` of the AST it holds stands for.\n */\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: NormalizedAST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n /**\n * The query this one was derived from, held *strongly*, and the queries\n * derived from this one, held *weakly*. This is the arrangement V8 uses for\n * hidden-class transitions, and it is what makes interning stable: as long as\n * a query is reachable its whole ancestor spine is too, so re-deriving it from\n * the root yields the same instance. See `query-transitions.ts`.\n */\n #parent: QueryImpl<any, any, any> | undefined;\n #transitions: Transitions<QueryImpl<any, any, any>> | undefined;\n\n /**\n * The second level of interning, keyed by hash; see `HashIndex`. Set on the\n * root only, which is what scopes it to one schema and one delegate.\n */\n #byHash: HashIndex<QueryImpl<any, any, any>> | undefined;\n\n /**\n * Memoized because a query is interned: the same node serves every rebuild of\n * a chain, so building this once rather than per `where(fn)` call takes the\n * whole thing -- the builder and the bound `#exists` -- off the repeat path.\n */\n #expressionBuilder: ExpressionBuilder<TTable, TSchema> | undefined;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n /**\n * Interns a transition whose key space is finite and schema-derived; see\n * {@link Transitions.storeBounded}. Used for the base sub-query handed to\n * a `related`/`exists` callback, which is determined entirely by the\n * relationship name.\n */\n #deriveBounded<T>(key: string, build: () => T): T {\n const existing = this.#transitions?.lookupBounded(key);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, undefined, undefined, build(), true);\n }\n\n /**\n * Interns the result of applying a builder operation to this query.\n *\n * `key` names the operation and `value` carries its varying argument, kept\n * apart so the key stays a string V8 has already hashed. When the two do not\n * settle it, `delta` carries the rest and is compared with `deepEqual`. Only\n * the delta is compared, never the whole AST: this query is already canonical,\n * so two of its children are equal exactly when the operations that produced\n * them are.\n *\n * `T` is deliberately unconstrained so that the contextual return type at each\n * call site still drives `#newQuery`'s inference, exactly as it did when the\n * call sites returned `this.#newQuery(...)` directly.\n */\n #derive<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n build: () => T,\n ): T {\n const existing = this.#transitions?.lookup(key, value, delta);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, value, delta, build(), false);\n }\n\n #record<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n created: T,\n bounded: boolean,\n ): T {\n const q = created as unknown as QueryImpl<any, any, any>;\n q.#parent = this;\n const transitions = (this.#transitions ??= new Transitions());\n if (bounded) {\n transitions.storeBounded(key, q);\n } else {\n transitions.store(key, value, delta, q);\n }\n return created;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#derive('nameAndArgs', name, args, () =>\n this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n ),\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfQueryInternals(\n this.#ast,\n this.format,\n this.#system,\n this.#currentJunction,\n this.customQueryID?.name,\n this.customQueryID?.args,\n );\n this.#canonicalize();\n }\n return this.#hash;\n }\n\n /**\n * Folds this query into its root's hash index, now that its hash is known.\n *\n * If an equal query is already indexed, the transition that produced this\n * one is re-pointed at it, so the next rebuild along this path yields that\n * instance rather than a second copy. This query itself is left alone: its\n * identity has already been handed out. Content is verified with `#sameAs`\n * before anything is redirected, so a hash collision costs nothing worse\n * than a missed unification.\n */\n #canonicalize(): void {\n const parent = this.#parent;\n if (parent === undefined) {\n // A root has no path to redirect and is its own canonical form.\n return;\n }\n let root = parent;\n while (root.#parent !== undefined) {\n root = root.#parent;\n }\n const index = (root.#byHash ??= new HashIndex());\n const existing = index.get(this.#hash);\n if (existing === undefined) {\n index.set(this.#hash, this);\n } else if (existing !== this && this.#sameAs(existing)) {\n parent.#transitions?.replace(this, existing);\n }\n }\n\n /**\n * Whether `other` is interchangeable with this query: everything `hash()`\n * covers, compared structurally. Schema and delegate are not compared. Both\n * are fixed by the root, and this only ever compares queries under one root.\n */\n #sameAs(other: QueryImpl<any, any, any>): boolean {\n return (\n this.#system === other.#system &&\n this.#currentJunction === other.#currentJunction &&\n this.customQueryID?.name === other.customQueryID?.name &&\n deepEqual(this.customQueryID?.args, other.customQueryID?.args) &&\n deepEqual(this.format, other.format) &&\n deepEqual(this.#ast, other.#ast)\n );\n }\n\n one(): Query<TTable, TSchema, TReturn | undefined> {\n return this.#derive('one', undefined, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit: 1},\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n whereExists(\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n }\n\n related(\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n // Intern the base handed to the callback too. A deterministic callback\n // then walks the same interned chain and hands back the *same* sub-query,\n // which makes the comparison below a pointer compare.\n const q: AnyQuery = this.#deriveBounded(\n `relatedBase:${relationship}`,\n () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n // Keyed by the sub-query's identity. Each query owns its AST object, so\n // this distinguishes even `q.one()` from `q.limit(1)`, whose ASTs are\n // structurally equal but whose formats differ. Comparing them as a delta\n // instead would put every sibling under one key and scan.\n return this.#derive(\n relatedKey(relationship),\n astID(subQuery.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#deriveBounded(`relatedBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n ),\n );\n\n // Bound to consts so the `isCompoundKey` narrowing survives into the\n // closure below; TypeScript drops narrowing of property accesses there.\n const {sourceField: firstSource, destField: firstDest} = firstRelation;\n const {sourceField: secondSource, destField: secondDest} = secondRelation;\n assert(isCompoundKey(firstSource), 'Invalid relationship');\n assert(isCompoundKey(firstDest), 'Invalid relationship');\n assert(isCompoundKey(secondSource), 'Invalid relationship');\n assert(isCompoundKey(secondDest), 'Invalid relationship');\n\n return this.#derive(\n relatedKey(relationship),\n astID(sq.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: firstSource,\n childField: firstDest,\n },\n hidden: true,\n subquery: {\n ...tableAST(junctionSchema, relationship),\n // A single subquery is sorted.\n related: [\n normalizedRelated({\n correlation: {\n parentField: secondSource,\n childField: secondDest,\n },\n subquery: sq.#ast,\n system: this.#system,\n }),\n ],\n },\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n // The declared return is the *bottom* of the pinned dimension, which is\n // assignable to every `where` overload's declared return. The overloads\n // refine `TPinned` for callers only; a single non-generic implementation\n // signature cannot express that refinement.\n where(\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn, any> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n const twoArg = arguments.length === 2;\n const op = (twoArg ? '=' : opOrValue) as SimpleOperator;\n const raw = twoArg ? opOrValue : value;\n\n // Comparing a column to a primitive is by far the most common thing anyone\n // does with a query, and the transition it names is fully determined by\n // (column, op, value) -- so check for it before building anything. On a hit\n // this returns without allocating the `Condition` at all. Objects are\n // excluded, which covers both parameter references and `IN` arrays; `cmp`\n // maps a missing value to null, so this must too.\n if (raw === null || typeof raw !== 'object') {\n const hit = this.#transitions?.lookup(\n whereKey(fieldOrExpressionFactory, op),\n (raw ?? null) as TransitionValue,\n undefined,\n );\n if (hit !== undefined) {\n return hit as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n }\n\n cond = twoArg\n ? cmp(fieldOrExpressionFactory, opOrValue)\n : cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n // The delta is the condition as built here, *before* it is merged with the\n // existing where and normalized. Both steps are deterministic and the\n // existing where is fixed by this query, so an equal `cond` always produces\n // an equal result.\n //\n // A simple comparison against a column splits cleanly: the column and\n // operator come from a small fixed set and give a memoized, stable key,\n // while the compared value -- the part that varies per call -- is handed\n // through as the transition value and never concatenated into a string.\n let key: string;\n let tValue: TransitionValue;\n let delta: Delta = cond;\n if (cond.type === 'simple' && cond.left.type === 'column') {\n key = whereKey(cond.left.name, cond.op);\n const right = cond.right;\n tValue =\n right.type === 'literal' && isPrimitive(right.value)\n ? right.value\n : rightTag(right);\n delta = undefined;\n } else {\n // A sub-query an `exists` correlates to is itself interned, so its\n // identity settles that part of the tree without walking it.\n const exact = condKey(cond);\n if (exact === undefined) {\n key = treeKey(cond);\n } else {\n key = 'where:tree';\n tValue = exact;\n delta = undefined;\n }\n }\n\n return this.#derive(key, tValue, delta, () => {\n const existingWhere = this.#ast.where;\n const merged = existingWhere ? and(existingWhere, cond) : cond;\n return this.#newQuery(\n this.#tableName,\n {...this.#ast, where: normalizeCondition(simplifyCondition(merged))},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }) as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n\n start(\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> {\n // The row is an object, so it is encoded to a string to serve as the\n // lookup key. Property order is part of that string.\n return this.#derive(\n opts?.inclusive ? 'start:inclusive' : 'start:exclusive',\n valueTag(row as ReadonlyJSONValue),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n limit(limit: number): Query<TTable, TSchema, TReturn> {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#derive('limit', limit, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n orderBy<TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#derive(\n direction === 'asc' ? 'orderBy:asc' : 'orderBy:desc',\n field as string,\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [\n ...(this.#ast.orderBy ?? []),\n [field as string, direction],\n ],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n #exists(\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#deriveBounded(`existsBase:${relationship}`, () =>\n this.#newQuery(\n destTableName,\n tableAST(destTableName, `${SUBQ_PREFIX}${relationship}`),\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery,\n ),\n );\n // Give the sub-query's AST an id so the enclosing `where` can key on it\n // exactly rather than comparing the sub-tree.\n astID(subQuery.#ast);\n // Unlike the entries of `related`, the correlated subqueries of a\n // condition keep the order their fields are written in: normalization\n // does not reorder them either.\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#deriveBounded(`existsJunctionBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, `${SUBQ_PREFIX}zhidden_${relationship}`),\n defaultFormat,\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n ...tableAST(junctionSchema, `${SUBQ_PREFIX}${relationship}`),\n // A single condition needs no flattening or sorting, but the node\n // itself still has to be rebuilt into the canonical field order.\n where: normalizeCondition({\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n }),\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n get ast(): NormalizedAST {\n return this.#ast;\n }\n\n expressionBuilder(): ExpressionBuilder<TTable, TSchema> {\n // Built on demand rather than held as an eagerly initialized field: a field\n // would cost a closure on every query constructed, where this costs one only\n // for queries that actually use an expression factory.\n return (this.#expressionBuilder ??= new ExpressionBuilder<TTable, TSchema>(\n this.#exists.bind(this) as ConstructorParameters<\n typeof ExpressionBuilder<TTable, TSchema>\n >[0],\n ));\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\n/**\n * A stable id per query AST.\n *\n * Every `QueryImpl` allocates its own AST object, so these are one-to-one with\n * queries, and interning makes the object identity stable across rebuilds. That\n * lets a `related` or `exists` transition key on *which* sub-query it points at\n * rather than comparing the sub-tree.\n *\n * Assigned only where it is needed. A `WeakMap.set` costs on the order of a\n * hundred nanoseconds, so doing this for every query rather than for the few\n * that are sub-queries was one of the largest single costs of building a query\n * from cold. ASTs that never pass through here -- including the junction AST a\n * two-hop `exists` builds inline -- are absent, and fall back to a delta.\n */\nconst astIDs = new WeakMap<AST, number>();\nlet nextASTID = 0;\n\nconst newASTID = () => ++nextASTID;\n\nfunction astID(ast: AST): number {\n return getOrInsertComputed(astIDs, ast, newASTID);\n}\n\n/**\n * Memoized transition keys.\n *\n * A transition key must be a string V8 has already hashed, or the `Map` lookup\n * has to hash it from scratch -- measured at ~148ns against ~10ns, which dwarfs\n * everything else a lookup does. Both tables are keyed by schema-derived names,\n * so they are bounded by the schema.\n */\nconst whereKeys = new Map<string, Map<string, string>>();\n\nfunction whereKey(column: string, op: string): string {\n const byOp = getOrInsertComputed(whereKeys, column, newMap);\n return getOrInsertComputed(byOp, op, op => `where:${column}:${op}`);\n}\n\nconst relatedKeys = new Map<string, string>();\n\nconst newRelatedKey = (relationship: string) => `related:${relationship}`;\n\nfunction relatedKey(relationship: string): string {\n return getOrInsertComputed(relatedKeys, relationship, newRelatedKey);\n}\n\nfunction isPrimitive(v: LiteralValue): v is string | number | boolean | null {\n return v === null || typeof v !== 'object';\n}\n\n/**\n * Folds a JSON value into a self-delimiting token: a string is\n * length-prefixed, a number is terminated, an array or object is\n * count-prefixed and encodes its members recursively, and the rest are fixed\n * width. Tokens can therefore be concatenated into a key with no way for one\n * to run into the next, and the leading tag keeps `'1'` and `1` apart.\n *\n * Not `JSON.stringify`: it writes `Infinity`, `NaN` and `null` all as `null`,\n * and this token is trusted as exact, so a nested value that serialized like\n * another's would hand back a query with the wrong value in its AST. Numbers\n * are written the way `String` writes them, which keeps those apart. An\n * `undefined` property is skipped, as `deepEqual` would skip it; property\n * order is part of the encoding, so an object spelled in another order\n * interns separately.\n */\nfunction valueTag(v: ReadonlyJSONValue): string {\n switch (typeof v) {\n case 'string':\n return `:s${enc(v)}`;\n case 'number':\n return `:n${v};`;\n case 'boolean':\n return v ? ':t' : ':f';\n default: {\n if (v === null) {\n return ':z';\n }\n if (Array.isArray(v)) {\n let out = `:a${v.length}:`;\n for (const e of v) {\n out += valueTag(e);\n }\n return out;\n }\n // `Array.isArray` does not narrow a readonly array out of the union.\n const o = v as ReadonlyJSONObject;\n let body = '';\n let n = 0;\n for (const key in o) {\n const e = o[key];\n if (e !== undefined && Object.hasOwn(o, key)) {\n body += enc(key) + valueTag(e);\n n++;\n }\n }\n return `:o${n}:${body}`;\n }\n }\n}\n\n/**\n * Folds the right-hand side of a simple condition into a transition value, so\n * that the transition is exact and the lookup needs no comparison at all.\n *\n * Arrays (`IN`) and parameter references are encoded in full: that is one\n * pass over a small value, where leaving them in the delta would instead cost\n * a `deepEqual` over the whole condition for every sibling a lookup walks\n * past.\n */\nfunction rightTag(right: SimpleCondition['right']): string {\n if (right.type !== 'literal') {\n return `:p${valueTag(right as unknown as ReadonlyJSONValue)}`;\n }\n return valueTag(right.value);\n}\n\n/**\n * Length-prefixes a free-form string so it can be concatenated into a key\n * without a separator being ambiguous with the content.\n */\nfunction enc(s: string): string {\n return `${s.length}:${s}`;\n}\n\n/** Encodes an optional boolean without collapsing `undefined` into `false`. */\nfunction tri(b: boolean | undefined): string {\n return b === undefined ? '-' : b ? 't' : 'f';\n}\n\n/**\n * An exact key for a whole condition tree, or `undefined` for a shape we cannot\n * encode (which falls back to {@link treeKey} plus a delta).\n *\n * Everything variable-length is length-prefixed, so distinct trees cannot\n * produce the same string and the key needs no `deepEqual` to back it up. That\n * matters because the alternative -- one coarse bucket per shape -- turns N\n * sibling conditions off the same parent into an N-deep scan of tree\n * comparisons, which measured far slower than not interning at all.\n */\nfunction condKey(cond: Condition): string | undefined {\n switch (cond.type) {\n case 'simple': {\n if (cond.left.type !== 'column') {\n return undefined;\n }\n return `S${enc(cond.left.name)}${enc(cond.op)}${rightTag(cond.right)}`;\n }\n case 'correlatedSubquery': {\n const id = astIDs.get(cond.related.subquery);\n return id === undefined\n ? undefined\n : `E${id}:${enc(cond.op)}${tri(cond.flip)}${tri(cond.scalar)}`;\n }\n case 'and':\n case 'or': {\n let out = `${cond.type === 'and' ? 'A' : 'O'}${cond.conditions.length}:`;\n for (const c of cond.conditions) {\n const k = condKey(c);\n if (k === undefined) {\n return undefined;\n }\n out += k;\n }\n return out;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * A coarse bucket key for the conditions {@link condKey} cannot encode --\n * a two-hop `exists`, whose junction AST is built inline and so has no identity\n * of its own. Reads only the top of the tree, so it is cheap; the delta tells\n * apart what shares it.\n */\nfunction treeKey(cond: Condition): string {\n switch (cond.type) {\n case 'correlatedSubquery':\n return `where:e:${cond.related.subquery.alias}:${cond.op}`;\n case 'and':\n case 'or':\n return `where:${cond.type}:${cond.conditions.length}`;\n default:\n return 'where:*';\n }\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"query-impl.js","names":[],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {\n deepEqual,\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport {getOrInsertComputed, newMap} from '../../../shared/src/map.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type NormalizedAST,\n type Parameter,\n type LiteralValue,\n type SimpleCondition,\n type SimpleOperator,\n type System,\n insertRelated,\n normalizeAST,\n normalizeCondition,\n normalizedRelated,\n SUBQ_PREFIX,\n tableAST,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfQueryInternals} from '../../../zero-protocol/src/query-hash-visitor.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport {\n HashIndex,\n Transitions,\n type Delta,\n type TransitionValue,\n} from './query-transitions.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryInternal(\n schema,\n table,\n tableAST(table),\n defaultFormat,\n 'client',\n );\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // This is the entry point for ASTs that were not built by QueryImpl, so\n // normalize it here to establish the invariant that #ast is normalized.\n return newQueryInternal(schema, tableName, normalizeAST(ast), format, system);\n}\n\n/**\n * Root queries are interned per schema so that two `createBuilder(schema)` calls\n * hand out the same starting point, and therefore share the whole transition\n * tree below it. Only cleared entries accumulate here, at most one per\n * system/table pair, so no sweeping is needed.\n */\nconst rootsBySchema = new WeakMap<\n Schema,\n Map<string, WeakRef<QueryImpl<any, any, any>>>\n>();\n\n/**\n * Whether this is the AST `tableAST(tableName)` produces -- the whole table,\n * nothing else. A normalized AST carries every field, so this cannot be a key\n * count; each one has to be checked.\n */\nfunction isRootAST(ast: NormalizedAST, tableName: string): boolean {\n return (\n ast.table === tableName &&\n ast.schema === undefined &&\n ast.alias === undefined &&\n ast.where === undefined &&\n ast.related === undefined &&\n ast.start === undefined &&\n ast.limit === undefined &&\n ast.orderBy === undefined\n );\n}\n\nfunction newQueryInternal<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n // Callers that hand in a pre-built AST -- benchmarks and the integration-test\n // harnesses -- are not roots and are not interned.\n const interned = format === defaultFormat && isRootAST(ast, tableName);\n const key = `${system}:${tableName}`;\n let roots: Map<string, WeakRef<QueryImpl<any, any, any>>> | undefined;\n\n if (interned) {\n roots = rootsBySchema.get(schema);\n const existing = roots?.get(key)?.deref();\n if (existing) {\n return existing as QueryImpl<TTable, TSchema, TReturn>;\n }\n }\n\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n const created = inner<TTable, TReturn>(\n tableName,\n ast,\n format,\n undefined,\n undefined,\n );\n\n if (interned) {\n if (!roots) {\n roots = new Map();\n rootsBySchema.set(schema, roots);\n }\n roots.set(key, new WeakRef(created));\n }\n\n return created;\n}\n\n/**\n * The AST of a QueryImpl is always normalized. Each step builds its AST in\n * normalized form rather than normalizing afterwards: a normalized AST has\n * every field, so spreading one and replacing a field keeps the field order\n * intact, and only the field a step actually changes needs normalizing (the\n * conditions of a `where`, the position of a new `related`). The ASTs that\n * come in from the outside are normalized by {@link newQueryImpl}, which is\n * what the `NormalizedAST` of the AST it holds stands for.\n */\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: NormalizedAST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n /**\n * The query this one was derived from, held *strongly*, and the queries\n * derived from this one, held *weakly*. This is the arrangement V8 uses for\n * hidden-class transitions, and it is what makes interning stable: as long as\n * a query is reachable its whole ancestor spine is too, so re-deriving it from\n * the root yields the same instance. See `query-transitions.ts`.\n */\n #parent: QueryImpl<any, any, any> | undefined;\n #transitions: Transitions<QueryImpl<any, any, any>> | undefined;\n\n /**\n * The second level of interning, keyed by hash; see `HashIndex`. Set on the\n * root only, which is what scopes it to one schema and one delegate.\n */\n #byHash: HashIndex<QueryImpl<any, any, any>> | undefined;\n\n /**\n * Memoized because a query is interned: the same node serves every rebuild of\n * a chain, so building this once rather than per `where(fn)` call takes the\n * whole thing -- the builder and the bound `#exists` -- off the repeat path.\n */\n #expressionBuilder: ExpressionBuilder<TTable, TSchema> | undefined;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: NormalizedAST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n /**\n * Interns a transition whose key space is finite and schema-derived; see\n * {@link Transitions.storeBounded}. Used for the base sub-query handed to\n * a `related`/`exists` callback, which is determined entirely by the\n * relationship name.\n */\n #deriveBounded<T>(key: string, build: () => T): T {\n const existing = this.#transitions?.lookupBounded(key);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, undefined, undefined, build(), true);\n }\n\n /**\n * Interns the result of applying a builder operation to this query.\n *\n * `key` names the operation and `value` carries its varying argument, kept\n * apart so the key stays a string V8 has already hashed. When the two do not\n * settle it, `delta` carries the rest and is compared with `deepEqual`. Only\n * the delta is compared, never the whole AST: this query is already canonical,\n * so two of its children are equal exactly when the operations that produced\n * them are.\n *\n * `T` is deliberately unconstrained so that the contextual return type at each\n * call site still drives `#newQuery`'s inference, exactly as it did when the\n * call sites returned `this.#newQuery(...)` directly.\n */\n #derive<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n build: () => T,\n ): T {\n const existing = this.#transitions?.lookup(key, value, delta);\n if (existing !== undefined) {\n return existing as T;\n }\n return this.#record(key, value, delta, build(), false);\n }\n\n #record<T>(\n key: string,\n value: TransitionValue,\n delta: Delta,\n created: T,\n bounded: boolean,\n ): T {\n const q = created as unknown as QueryImpl<any, any, any>;\n q.#parent = this;\n const transitions = (this.#transitions ??= new Transitions());\n if (bounded) {\n transitions.storeBounded(key, q);\n } else {\n transitions.store(key, value, delta, q);\n }\n return created;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n cached: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#derive('nameAndArgs', name, args, () =>\n this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n ),\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfQueryInternals(\n this.#ast,\n this.format,\n this.#system,\n this.#currentJunction,\n this.customQueryID?.name,\n this.customQueryID?.args,\n );\n this.#canonicalize();\n }\n return this.#hash;\n }\n\n /**\n * Folds this query into its root's hash index, now that its hash is known.\n *\n * If an equal query is already indexed, the transition that produced this\n * one is re-pointed at it, so the next rebuild along this path yields that\n * instance rather than a second copy. This query itself is left alone: its\n * identity has already been handed out. Content is verified with `#sameAs`\n * before anything is redirected, so a hash collision costs nothing worse\n * than a missed unification.\n */\n #canonicalize(): void {\n const parent = this.#parent;\n if (parent === undefined) {\n // A root has no path to redirect and is its own canonical form.\n return;\n }\n let root = parent;\n while (root.#parent !== undefined) {\n root = root.#parent;\n }\n const index = (root.#byHash ??= new HashIndex());\n const existing = index.get(this.#hash);\n if (existing === undefined) {\n index.set(this.#hash, this);\n } else if (existing !== this && this.#sameAs(existing)) {\n parent.#transitions?.replace(this, existing);\n }\n }\n\n /**\n * Whether `other` is interchangeable with this query: everything `hash()`\n * covers, compared structurally. Schema and delegate are not compared. Both\n * are fixed by the root, and this only ever compares queries under one root.\n */\n #sameAs(other: QueryImpl<any, any, any>): boolean {\n return (\n this.#system === other.#system &&\n this.#currentJunction === other.#currentJunction &&\n this.customQueryID?.name === other.customQueryID?.name &&\n deepEqual(this.customQueryID?.args, other.customQueryID?.args) &&\n deepEqual(this.format, other.format) &&\n deepEqual(this.#ast, other.#ast)\n );\n }\n\n one(): Query<TTable, TSchema, TReturn | undefined> {\n return this.#derive('one', undefined, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit: 1},\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n whereExists(\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n }\n\n related(\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n // Intern the base handed to the callback too. A deterministic callback\n // then walks the same interned chain and hands back the *same* sub-query,\n // which makes the comparison below a pointer compare.\n const q: AnyQuery = this.#deriveBounded(\n `relatedBase:${relationship}`,\n () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n // Keyed by the sub-query's identity. Each query owns its AST object, so\n // this distinguishes even `q.one()` from `q.limit(1)`, whose ASTs are\n // structurally equal but whose formats differ. Comparing them as a delta\n // instead would put every sibling under one key and scan.\n return this.#derive(\n relatedKey(relationship),\n astID(subQuery.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#deriveBounded(`relatedBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, relationship),\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n ),\n );\n\n // Bound to consts so the `isCompoundKey` narrowing survives into the\n // closure below; TypeScript drops narrowing of property accesses there.\n const {sourceField: firstSource, destField: firstDest} = firstRelation;\n const {sourceField: secondSource, destField: secondDest} = secondRelation;\n assert(isCompoundKey(firstSource), 'Invalid relationship');\n assert(isCompoundKey(firstDest), 'Invalid relationship');\n assert(isCompoundKey(secondSource), 'Invalid relationship');\n assert(isCompoundKey(secondDest), 'Invalid relationship');\n\n return this.#derive(\n relatedKey(relationship),\n astID(sq.#ast),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: insertRelated(this.#ast.related, {\n correlation: {\n parentField: firstSource,\n childField: firstDest,\n },\n hidden: true,\n subquery: {\n ...tableAST(junctionSchema, relationship),\n // A single subquery is sorted.\n related: [\n normalizedRelated({\n correlation: {\n parentField: secondSource,\n childField: secondDest,\n },\n subquery: sq.#ast,\n system: this.#system,\n }),\n ],\n },\n system: this.#system,\n }),\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ),\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n // The declared return is the *bottom* of the pinned dimension, which is\n // assignable to every `where` overload's declared return. The overloads\n // refine `TPinned` for callers only; a single non-generic implementation\n // signature cannot express that refinement.\n where(\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn, any> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n const twoArg = arguments.length === 2;\n const op = (twoArg ? '=' : opOrValue) as SimpleOperator;\n const raw = twoArg ? opOrValue : value;\n\n // Comparing a column to a primitive is by far the most common thing anyone\n // does with a query, and the transition it names is fully determined by\n // (column, op, value) -- so check for it before building anything. On a hit\n // this returns without allocating the `Condition` at all. Objects are\n // excluded, which covers both parameter references and `IN` arrays; `cmp`\n // maps a missing value to null, so this must too.\n if (raw === null || typeof raw !== 'object') {\n const hit = this.#transitions?.lookup(\n whereKey(fieldOrExpressionFactory, op),\n (raw ?? null) as TransitionValue,\n undefined,\n );\n if (hit !== undefined) {\n return hit as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n }\n\n cond = twoArg\n ? cmp(fieldOrExpressionFactory, opOrValue)\n : cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n // The delta is the condition as built here, *before* it is merged with the\n // existing where and normalized. Both steps are deterministic and the\n // existing where is fixed by this query, so an equal `cond` always produces\n // an equal result.\n //\n // A simple comparison against a column splits cleanly: the column and\n // operator come from a small fixed set and give a memoized, stable key,\n // while the compared value -- the part that varies per call -- is handed\n // through as the transition value and never concatenated into a string.\n let key: string;\n let tValue: TransitionValue;\n let delta: Delta = cond;\n if (cond.type === 'simple' && cond.left.type === 'column') {\n key = whereKey(cond.left.name, cond.op);\n const right = cond.right;\n tValue =\n right.type === 'literal' && isPrimitive(right.value)\n ? right.value\n : rightTag(right);\n delta = undefined;\n } else {\n // A sub-query an `exists` correlates to is itself interned, so its\n // identity settles that part of the tree without walking it.\n const exact = condKey(cond);\n if (exact === undefined) {\n key = treeKey(cond);\n } else {\n key = 'where:tree';\n tValue = exact;\n delta = undefined;\n }\n }\n\n return this.#derive(key, tValue, delta, () => {\n const existingWhere = this.#ast.where;\n const merged = existingWhere ? and(existingWhere, cond) : cond;\n return this.#newQuery(\n this.#tableName,\n {...this.#ast, where: normalizeCondition(simplifyCondition(merged))},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }) as unknown as Query<TTable, TSchema, TReturn, any>;\n }\n\n start(\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> {\n // The row is an object, so it is encoded to a string to serve as the\n // lookup key. Property order is part of that string.\n return this.#derive(\n opts?.inclusive ? 'start:inclusive' : 'start:exclusive',\n valueTag(row as ReadonlyJSONValue),\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n limit(limit: number): Query<TTable, TSchema, TReturn> {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#derive('limit', limit, undefined, () =>\n this.#newQuery(\n this.#tableName,\n {...this.#ast, limit},\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n orderBy<TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#derive(\n direction === 'asc' ? 'orderBy:asc' : 'orderBy:desc',\n field as string,\n undefined,\n () =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [\n ...(this.#ast.orderBy ?? []),\n [field as string, direction],\n ],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n ),\n );\n }\n\n #exists(\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#deriveBounded(`existsBase:${relationship}`, () =>\n this.#newQuery(\n destTableName,\n tableAST(destTableName, `${SUBQ_PREFIX}${relationship}`),\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ) as AnyQuery,\n ),\n );\n // Give the sub-query's AST an id so the enclosing `where` can key on it\n // exactly rather than comparing the sub-tree.\n astID(subQuery.#ast);\n // Unlike the entries of `related`, the correlated subqueries of a\n // condition keep the order their fields are written in: normalization\n // does not reorder them either.\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#deriveBounded(`existsJunctionBase:${relationship}`, () =>\n this.#newQuery(\n destSchema,\n tableAST(destSchema, `${SUBQ_PREFIX}zhidden_${relationship}`),\n defaultFormat,\n this.customQueryID,\n relationship,\n ),\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n ...tableAST(junctionSchema, `${SUBQ_PREFIX}${relationship}`),\n // A single condition needs no flattening or sorting, but the node\n // itself still has to be rebuilt into the canonical field order.\n where: normalizeCondition({\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n }),\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n }\n\n get ast(): NormalizedAST {\n return this.#ast;\n }\n\n expressionBuilder(): ExpressionBuilder<TTable, TSchema> {\n // Built on demand rather than held as an eagerly initialized field: a field\n // would cost a closure on every query constructed, where this costs one only\n // for queries that actually use an expression factory.\n return (this.#expressionBuilder ??= new ExpressionBuilder<TTable, TSchema>(\n this.#exists.bind(this) as ConstructorParameters<\n typeof ExpressionBuilder<TTable, TSchema>\n >[0],\n ));\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\n/**\n * A stable id per query AST.\n *\n * Every `QueryImpl` allocates its own AST object, so these are one-to-one with\n * queries, and interning makes the object identity stable across rebuilds. That\n * lets a `related` or `exists` transition key on *which* sub-query it points at\n * rather than comparing the sub-tree.\n *\n * Assigned only where it is needed. A `WeakMap.set` costs on the order of a\n * hundred nanoseconds, so doing this for every query rather than for the few\n * that are sub-queries was one of the largest single costs of building a query\n * from cold. ASTs that never pass through here -- including the junction AST a\n * two-hop `exists` builds inline -- are absent, and fall back to a delta.\n */\nconst astIDs = new WeakMap<AST, number>();\nlet nextASTID = 0;\n\nconst newASTID = () => ++nextASTID;\n\nfunction astID(ast: AST): number {\n return getOrInsertComputed(astIDs, ast, newASTID);\n}\n\n/**\n * Memoized transition keys.\n *\n * A transition key must be a string V8 has already hashed, or the `Map` lookup\n * has to hash it from scratch -- measured at ~148ns against ~10ns, which dwarfs\n * everything else a lookup does. Both tables are keyed by schema-derived names,\n * so they are bounded by the schema.\n */\nconst whereKeys = new Map<string, Map<string, string>>();\n\nfunction whereKey(column: string, op: string): string {\n const byOp = getOrInsertComputed(whereKeys, column, newMap);\n return getOrInsertComputed(byOp, op, op => `where:${column}:${op}`);\n}\n\nconst relatedKeys = new Map<string, string>();\n\nconst newRelatedKey = (relationship: string) => `related:${relationship}`;\n\nfunction relatedKey(relationship: string): string {\n return getOrInsertComputed(relatedKeys, relationship, newRelatedKey);\n}\n\nfunction isPrimitive(v: LiteralValue): v is string | number | boolean | null {\n return v === null || typeof v !== 'object';\n}\n\n/**\n * Folds a JSON value into a self-delimiting token: a string is\n * length-prefixed, a number is terminated, an array or object is\n * count-prefixed and encodes its members recursively, and the rest are fixed\n * width. Tokens can therefore be concatenated into a key with no way for one\n * to run into the next, and the leading tag keeps `'1'` and `1` apart.\n *\n * Not `JSON.stringify`: it writes `Infinity`, `NaN` and `null` all as `null`,\n * and this token is trusted as exact, so a nested value that serialized like\n * another's would hand back a query with the wrong value in its AST. Numbers\n * are written the way `String` writes them, which keeps those apart. An\n * `undefined` property is skipped, as `deepEqual` would skip it; property\n * order is part of the encoding, so an object spelled in another order\n * interns separately.\n */\nfunction valueTag(v: ReadonlyJSONValue): string {\n switch (typeof v) {\n case 'string':\n return `:s${enc(v)}`;\n case 'number':\n return `:n${v};`;\n case 'boolean':\n return v ? ':t' : ':f';\n default: {\n if (v === null) {\n return ':z';\n }\n if (Array.isArray(v)) {\n let out = `:a${v.length}:`;\n for (const e of v) {\n out += valueTag(e);\n }\n return out;\n }\n // `Array.isArray` does not narrow a readonly array out of the union.\n const o = v as ReadonlyJSONObject;\n let body = '';\n let n = 0;\n for (const key in o) {\n const e = o[key];\n if (e !== undefined && Object.hasOwn(o, key)) {\n body += enc(key) + valueTag(e);\n n++;\n }\n }\n return `:o${n}:${body}`;\n }\n }\n}\n\n/**\n * Folds the right-hand side of a simple condition into a transition value, so\n * that the transition is exact and the lookup needs no comparison at all.\n *\n * Arrays (`IN`) and parameter references are encoded in full: that is one\n * pass over a small value, where leaving them in the delta would instead cost\n * a `deepEqual` over the whole condition for every sibling a lookup walks\n * past.\n */\nfunction rightTag(right: SimpleCondition['right']): string {\n if (right.type !== 'literal') {\n return `:p${valueTag(right as unknown as ReadonlyJSONValue)}`;\n }\n return valueTag(right.value);\n}\n\n/**\n * Length-prefixes a free-form string so it can be concatenated into a key\n * without a separator being ambiguous with the content.\n */\nfunction enc(s: string): string {\n return `${s.length}:${s}`;\n}\n\n/** Encodes an optional boolean without collapsing `undefined` into `false`. */\nfunction tri(b: boolean | undefined): string {\n return b === undefined ? '-' : b ? 't' : 'f';\n}\n\n/**\n * An exact key for a whole condition tree, or `undefined` for a shape we cannot\n * encode (which falls back to {@link treeKey} plus a delta).\n *\n * Everything variable-length is length-prefixed, so distinct trees cannot\n * produce the same string and the key needs no `deepEqual` to back it up. That\n * matters because the alternative -- one coarse bucket per shape -- turns N\n * sibling conditions off the same parent into an N-deep scan of tree\n * comparisons, which measured far slower than not interning at all.\n */\nfunction condKey(cond: Condition): string | undefined {\n switch (cond.type) {\n case 'simple': {\n if (cond.left.type !== 'column') {\n return undefined;\n }\n return `S${enc(cond.left.name)}${enc(cond.op)}${rightTag(cond.right)}`;\n }\n case 'correlatedSubquery': {\n const id = astIDs.get(cond.related.subquery);\n return id === undefined\n ? undefined\n : `E${id}:${enc(cond.op)}${tri(cond.flip)}${tri(cond.scalar)}`;\n }\n case 'and':\n case 'or': {\n let out = `${cond.type === 'and' ? 'A' : 'O'}${cond.conditions.length}:`;\n for (const c of cond.conditions) {\n const k = condKey(c);\n if (k === undefined) {\n return undefined;\n }\n out += k;\n }\n return out;\n }\n default:\n return undefined;\n }\n}\n\n/**\n * A coarse bucket key for the conditions {@link condKey} cannot encode --\n * a two-hop `exists`, whose junction AST is built inline and so has no identity\n * of its own. Reads only the top of the tree, so it is cheap; the delta tells\n * apart what shares it.\n */\nfunction treeKey(cond: Condition): string {\n switch (cond.type) {\n case 'correlatedSubquery':\n return `where:e:${cond.related.subquery.alias}:${cond.op}`;\n case 'and':\n case 'or':\n return `where:${cond.type}:${cond.conditions.length}`;\n default:\n return 'where:*';\n }\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
@@ -102,6 +102,6 @@ function mustGetQuery(queries, name) {
102
102
  return query;
103
103
  }
104
104
  //#endregion
105
- export { addContextToQuery, defineQueries, defineQueriesWithType, defineQuery, defineQueryWithType, getQuery, isQuery, isQueryDefinition, isQueryRegistry, mustGetQuery };
105
+ export { addContextToQuery, createQuery, defineQueries, defineQueriesWithType, defineQuery, defineQueryWithType, getQuery, isQuery, isQueryDefinition, isQueryRegistry, mustGetQuery };
106
106
 
107
107
  //# sourceMappingURL=query-registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"query-registry.js","names":[],"sources":["../../../../../zql/src/query/query-registry.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\nimport {\n deepMerge,\n isPlainObject,\n type DeepMerge,\n} from '../../../shared/src/deep-merge.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {getValueAtPath} from '../../../shared/src/object-traversal.ts';\nimport type {\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n IsUnknown,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport type {PullRow, Query} from './query.ts';\nimport {validateInput} from './validate-input.ts';\n\n// ----------------------------------------------------------------------------\n// CustomQuery and QueryRequest types\n// ----------------------------------------------------------------------------\n\nexport type CustomQueryTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'Query' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * CustomQuery is returned from defineQueries. It is a callable that captures\n * args and can be turned into a Query via {@link QueryRequest}.\n */\nexport type CustomQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined = TInput,\n TSchema extends Schema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext = DefaultContext,\n> = {\n readonly 'queryName': string;\n readonly 'fn': QueryExecutionFunction<TTable, TInput, TReturn, TContext>;\n readonly '~': CustomQueryTypes<TTable, TInput, TSchema, TReturn, TContext>;\n} & CustomQueryCallable<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n\ntype CustomQueryCallable<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = [TInput] extends [undefined]\n ? () => QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n : undefined extends TInput\n ? {\n (): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n (\n args?: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n }\n : {\n (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n };\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyCustomQuery = CustomQuery<string, any, any, Schema, any, any>;\n\nexport function isQuery<S extends Schema>(\n value: unknown,\n // oxlint-disable-next-line no-explicit-any\n): value is CustomQuery<string, any, any, S, any, any> {\n return (\n typeof value === 'function' &&\n typeof (value as {queryName?: unknown}).queryName === 'string' &&\n typeof (value as {fn?: unknown}).fn === 'function'\n );\n}\n\nexport type QueryRequestTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'QueryRequest' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\nexport type QueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = {\n readonly 'query': CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n readonly 'args': TInput;\n readonly '~': QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n};\n\n/**\n * A shared type that can be a query request or a query builder.\n *\n * If it is a query request, it will be converted to a {@link Query} using the context.\n * Otherwise, it will be returned as is.\n */\nexport type QueryOrQueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> =\n | QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Query<TTable, TSchema, TReturn>;\n\n/**\n * Converts a query request to a {@link Query} using the context,\n * or returns the query as is.\n *\n * @param query - The query request or query builder to convert\n * @param context - The context to use to convert the query request\n */\nexport const addContextToQuery = <\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n context: TContext,\n): Query<TTable, TSchema, TReturn> =>\n 'query' in query ? query.query.fn({ctx: context, args: query.args}) : query;\n\n// ----------------------------------------------------------------------------\n// QueryRegistry types\n// ----------------------------------------------------------------------------\n\nexport function isQueryRegistry(obj: unknown): obj is AnyQueryRegistry {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as unknown as {['~']: string})?.['~'] === 'QueryRegistry'\n );\n}\n\nexport type QueryRegistryTypes<TSchema extends Schema> = 'QueryRegistry' & {\n readonly $schema: TSchema;\n};\n\nexport type QueryRegistry<\n QD extends QueryDefinitions,\n S extends Schema,\n> = ToQueryTree<QD, S> & {\n ['~']: QueryRegistryTypes<S>;\n};\n\nexport type AnyQueryRegistry = {\n ['~']: QueryRegistryTypes<Schema>;\n [key: string]: unknown;\n};\n\ntype ToQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? // pull types from the phantom property\n CustomQuery<\n QD[K]['~']['$tableName'],\n QD[K]['~']['$input'],\n QD[K]['~']['$output'],\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? ToQueryTree<QD[K], S>\n : never;\n};\n\nexport type FromQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? CustomQuery<\n QD[K]['~']['$tableName'],\n // intentionally left as generic to avoid variance issues\n ReadonlyJSONValue | undefined,\n ReadonlyJSONValue | undefined,\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? FromQueryTree<QD[K], S>\n : never;\n}[keyof QD];\n\nexport type QueryDefinitions = {\n readonly [key: string]: AnyQueryDefinition | QueryDefinitions;\n};\n\n// ----------------------------------------------------------------------------\n// defineQuery\n// ----------------------------------------------------------------------------\n\nexport type QueryDefinitionTypes<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput,\n TReturn,\n TContext,\n> = 'QueryDefinition' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * A query definition is the return type of `defineQuery()`.\n */\nexport type QueryDefinition<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext = DefaultContext,\n> = {\n readonly 'fn': QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>;\n readonly 'validator': StandardSchemaV1<TInput, TOutput> | undefined;\n readonly '~': QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >;\n};\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryDefinition = QueryDefinition<any, any, any, any, any>;\n\nexport function isQueryDefinition(f: unknown): f is AnyQueryDefinition {\n return (\n typeof f === 'object' &&\n f !== null &&\n (f as {['~']?: unknown})['~'] === 'QueryDefinition'\n );\n}\n\nexport type QueryDefinitionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (options: {args: TInput; ctx: TContext}) => Query<TTable, Schema, TReturn>;\n\nexport type QueryExecutionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (\n options: QueryExecutionOptions<TInput, TContext>,\n) => Query<TTable, Schema, TReturn>;\n\ntype QueryExecutionOptions<\n TInput extends ReadonlyJSONValue | undefined,\n TContext,\n> = undefined extends TInput\n ? IsUnknown<TContext> extends true\n ? {args?: TInput | undefined; ctx?: TContext | undefined}\n : {args?: TInput | undefined; ctx: TContext}\n : IsUnknown<TContext> extends true\n ? {args: TInput; ctx?: TContext | undefined}\n : {args: TInput; ctx: TContext};\n\n/**\n * Defines a query to be used with {@link defineQueries}.\n *\n * The query function receives an object with `args` (the query arguments) and\n * `ctx` (the context). It should return a {@link Query} built using a builder\n * created from {@link createBuilder}.\n *\n * Note: A query defined with `defineQuery` must be passed to\n * {@link defineQueries} to be usable. The query name is derived from its\n * position in the `defineQueries` object.\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * // Simple query with no arguments\n * allIssues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n *\n * // Query with typed arguments\n * issueById: defineQuery(({args}: {args: {id: string}}) =>\n * builder.issue.where('id', args.id).one(),\n * ),\n *\n * // Query with validation using a Standard Schema validator (e.g., Zod)\n * issuesByStatus: defineQuery(\n * z.object({status: z.enum(['open', 'closed'])}),\n * ({args}) => builder.issue.where('status', args.status),\n * ),\n *\n * // Query using context\n * myIssues: defineQuery(({ctx}: {ctx: {userID: string}}) =>\n * builder.issue.where('creatorID', ctx.userID),\n * ),\n * });\n * ```\n *\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} that can be passed to {@link defineQueries}.\n *\n * @overload\n * @param validator - A Standard Schema validator for the arguments.\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} with validated arguments.\n */\n// Overload for no validator parameter with default inference for untyped functions\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n queryFn: QueryDefinitionFunction<TTable, TInput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TInput, TReturn, TContext>;\n\n// Overload for validator parameter - Input and Output can be different\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n\n// Implementation\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validatorOrQueryFn:\n | StandardSchemaV1<TInput, TOutput>\n | QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n queryFn?: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext> {\n // Handle different parameter patterns\n let validator: StandardSchemaV1<TInput, TOutput> | undefined;\n let actualQueryFn: QueryDefinitionFunction<\n TTable,\n TOutput,\n TReturn,\n TContext\n >;\n\n if ('~standard' in validatorOrQueryFn) {\n // defineQuery(validator, queryFn) - with validator\n validator = validatorOrQueryFn;\n actualQueryFn = must(queryFn);\n } else {\n // defineQuery(queryFn) - no validator\n validator = undefined;\n actualQueryFn = validatorOrQueryFn;\n }\n\n const queryDefinition: QueryDefinition<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n > = {\n 'fn': actualQueryFn,\n 'validator': validator,\n '~': 'QueryDefinition' as unknown as QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >,\n };\n return queryDefinition;\n}\n\n/**\n * Returns a typed version of {@link defineQuery} with the schema and context\n * types pre-specified. This enables better type inference when defining\n * queries.\n *\n * @example\n * ```ts\n * const zql = createBuilder(schema);\n *\n * // With both Schema and Context types\n * const defineAppQuery = defineQueryWithType<AppSchema, AppContext>();\n * const myQuery = defineAppQuery(({ctx}) =>\n * zql.issue.where('userID', ctx.userID),\n * );\n *\n * // With just Context type (Schema inferred)\n * const defineAppQuery = defineQueryWithType<AppContext>();\n * ```\n *\n * @typeParam S - The Zero schema type.\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with types\n * pre-bound.\n */\nexport function defineQueryWithType<\n S extends Schema,\n C = unknown,\n>(): TypedDefineQuery<S, C>;\n\n/**\n * Returns a typed version of {@link defineQuery} with the context type\n * pre-specified.\n *\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with the context\n * type pre-bound.\n */\nexport function defineQueryWithType<C>(): TypedDefineQuery<Schema, C>;\n\nexport function defineQueryWithType() {\n return defineQuery;\n}\n\n/**\n * The return type of defineQueryWithType. A function matching the\n * defineQuery overloads but with Schema and Context pre-bound.\n */\ntype TypedDefineQuery<TSchema extends Schema, TContext> = {\n // Without validator\n <\n TArgs extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n queryFn: QueryDefinitionFunction<TTable, TArgs, TReturn, TContext>,\n ): QueryDefinition<TTable, TArgs, TArgs, TReturn, TContext>;\n\n // With validator\n <\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n ): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n};\n\n// ----------------------------------------------------------------------------\n// createQuery\n// ----------------------------------------------------------------------------\n\nexport function createQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n name: string,\n definition: QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>,\n): CustomQuery<TTable, TInput, TOutput, TSchema, TReturn, TContext> {\n const {validator} = definition;\n\n const fn: QueryExecutionFunction<\n TTable,\n TInput,\n TReturn,\n TContext\n > = options => {\n const validatedArgs = validator\n ? validateInput(name, options.args, validator, 'query')\n : (options.args as unknown as TOutput);\n\n return asQueryInternals(\n definition.fn({\n args: validatedArgs,\n ctx: options.ctx as TContext,\n }),\n ).nameAndArgs(\n name,\n // TODO(arv): Get rid of the array?\n // Send original input args to server (not transformed output)\n options.args === undefined ? [] : [options.args],\n );\n };\n\n const query = (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext> => ({\n args,\n '~': 'QueryRequest' as QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n 'query': query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n });\n\n query.queryName = name;\n query.fn = fn;\n query['~'] = 'Query' as CustomQueryTypes<\n TTable,\n TInput,\n TSchema,\n TReturn,\n TContext\n >;\n\n return query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n}\n\n// ----------------------------------------------------------------------------\n// defineQueries\n// ----------------------------------------------------------------------------\n\n/**\n * Converts query definitions created with {@link defineQuery} into callable\n * {@link Query} objects that can be invoked with arguments and a context.\n *\n * Query definitions can be nested for organization. The resulting query names\n * are dot-separated paths (e.g., `users.byId`).\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * issues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n * users: {\n * byId: defineQuery(({args}: {args: {id: string}}) =>\n * builder.user.where('id', args.id),\n * ),\n * },\n * });\n *\n * // Usage:\n * const request = queries.issues.byId({id: '123'});\n * const [data] = zero.useQuery(request);\n * ```\n *\n * @param defs - An object containing query definitions or nested objects of\n * query definitions.\n * @returns An object with the same structure where each query definition is\n * converted to a {@link CustomQuery}.\n */\nexport function defineQueries<\n // let QD infer freely so defaults aren't erased by a QueryDefinitions<any, any> constraint\n const QD,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n defs: QD & AssertQueryDefinitions<QD>,\n): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\nexport function defineQueries<\n const TBase,\n const TOverrides,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n>;\n\nexport function defineQueries<QD extends QueryDefinitions, S extends Schema>(\n defsOrBase: QD | QueryRegistry<QD, S>,\n overrides?: QueryDefinitions,\n): QueryRegistry<QD, S> {\n function processDefinitions(\n definitions: QueryDefinitions,\n path: string[],\n ): Record<string | symbol, unknown> {\n const result: Record<string | symbol, unknown> = {\n ['~']: 'QueryRegistry',\n };\n\n for (const [key, value] of Object.entries(definitions)) {\n path.push(key);\n const defaultName = path.join('.');\n\n if (isQueryDefinition(value)) {\n result[key] = createQuery(defaultName, value);\n } else {\n // Nested definitions\n result[key] = processDefinitions(value, path);\n }\n path.pop();\n }\n\n return result;\n }\n\n if (overrides !== undefined) {\n // Merge base and overrides\n\n let base: Record<string | symbol, unknown>;\n if (!isQueryRegistry(defsOrBase)) {\n base = processDefinitions(defsOrBase, []);\n } else {\n base = defsOrBase;\n }\n\n const processed = processDefinitions(overrides, []);\n\n const merged = deepMerge(base, processed, isQueryLeaf);\n merged['~'] = 'QueryRegistry';\n return merged as QueryRegistry<QD, S>;\n }\n\n return processDefinitions(defsOrBase as QD, []) as QueryRegistry<QD, S>;\n}\n\nconst isQueryLeaf = (value: unknown): boolean =>\n !isPlainObject(value) || isQuery(value);\n\nexport type AssertQueryDefinitions<QD> = QD extends QueryDefinitions\n ? unknown\n : never;\n\nexport type EnsureQueryDefinitions<QD> = QD extends QueryDefinitions\n ? QD\n : QD extends QueryRegistry<infer InnerQD, infer _S>\n ? InnerQD\n : never;\n\n/**\n * Creates a function that can be used to define queries with a specific schema.\n */\nexport function defineQueriesWithType<\n TSchema extends Schema,\n>(): TypedDefineQueries<TSchema> {\n return defineQueries;\n}\n\n/**\n * The return type of defineQueriesWithType. A function matching the\n * defineQueries overloads but with Schema pre-bound.\n */\ntype TypedDefineQueries<S extends Schema> = {\n // Single definitions\n <QD>(\n definitions: QD & AssertQueryDefinitions<QD>,\n ): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\n // Base and overrides\n <TBase, TOverrides>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n ): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n >;\n};\n\nconst separatorRe = /[.|]/;\n\n// ----------------------------------------------------------------------------\n// getQuery / mustGetQuery\n// ----------------------------------------------------------------------------\n\nexport function getQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> | undefined {\n const q = getValueAtPath(queries, name, separatorRe);\n return q as FromQueryTree<QD, S> | undefined;\n}\n\nexport function mustGetQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> {\n const query = getQuery(queries, name);\n if (query === undefined) {\n throw new Error(`Query not found: ${name}`);\n }\n return query;\n}\n"],"mappings":";;;;;;AAgFA,SAAgB,QACd,OAEqD;CACrD,OACE,OAAO,UAAU,cACjB,OAAQ,MAAgC,cAAc,YACtD,OAAQ,MAAyB,OAAO;AAE5C;;;;;;;;AAqEA,IAAa,qBAQX,OAQA,YAEA,WAAW,QAAQ,MAAM,MAAM,GAAG;CAAC,KAAK;CAAS,MAAM,MAAM;AAAI,CAAC,IAAI;AAMxE,SAAgB,gBAAgB,KAAuC;CACrE,OACE,OAAO,QAAQ,YACf,QAAQ,QACP,MAAqC,SAAS;AAEnD;AAgGA,SAAgB,kBAAkB,GAAqC;CACrE,OACE,OAAO,MAAM,YACb,MAAM,QACL,EAAwB,SAAS;AAEtC;AAqGA,SAAgB,YASd,oBAGA,SAC6D;CAE7D,IAAI;CACJ,IAAI;CAOJ,IAAI,eAAe,oBAAoB;EAErC,YAAY;EACZ,gBAAgB,KAAK,OAAO;CAC9B,OAAO;EAEL,YAAY,KAAA;EACZ,gBAAgB;CAClB;CAmBA,OAAO;EAVL,MAAM;EACN,aAAa;EACb,KAAK;CAQA;AACT;AAyCA,SAAgB,sBAAsB;CACpC,OAAO;AACT;AAkCA,SAAgB,YAQd,MACA,YACkE;CAClE,MAAM,EAAC,cAAa;CAEpB,MAAM,MAKF,YAAW;EACb,MAAM,gBAAgB,YAClB,cAAc,MAAM,QAAQ,MAAM,WAAW,OAAO,IACnD,QAAQ;EAEb,OAAO,iBACL,WAAW,GAAG;GACZ,MAAM;GACN,KAAK,QAAQ;EACf,CAAC,CACH,EAAE,YACA,MAGA,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,CACjD;CACF;CAEA,MAAM,SACJ,UACuE;EACvE;EACA,KAAK;EAQL,SAAS;CAQX;CAEA,MAAM,YAAY;CAClB,MAAM,KAAK;CACX,MAAM,OAAO;CAQb,OAAO;AAQT;AA8DA,SAAgB,cACd,YACA,WACsB;CACtB,SAAS,mBACP,aACA,MACkC;EAClC,MAAM,SAA2C,GAC9C,MAAM,gBACT;EAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,WAAW,GAAG;GACtD,KAAK,KAAK,GAAG;GACb,MAAM,cAAc,KAAK,KAAK,GAAG;GAEjC,IAAI,kBAAkB,KAAK,GACzB,OAAO,OAAO,YAAY,aAAa,KAAK;QAG5C,OAAO,OAAO,mBAAmB,OAAO,IAAI;GAE9C,KAAK,IAAI;EACX;EAEA,OAAO;CACT;CAEA,IAAI,cAAc,KAAA,GAAW;EAG3B,IAAI;EACJ,IAAI,CAAC,gBAAgB,UAAU,GAC7B,OAAO,mBAAmB,YAAY,CAAC,CAAC;OAExC,OAAO;EAGT,MAAM,YAAY,mBAAmB,WAAW,CAAC,CAAC;EAElD,MAAM,SAAS,UAAU,MAAM,WAAW,WAAW;EACrD,OAAO,OAAO;EACd,OAAO;CACT;CAEA,OAAO,mBAAmB,YAAkB,CAAC,CAAC;AAChD;AAEA,IAAM,eAAe,UACnB,CAAC,cAAc,KAAK,KAAK,QAAQ,KAAK;;;;AAexC,SAAgB,wBAEiB;CAC/B,OAAO;AACT;AA4BA,IAAM,cAAc;AAMpB,SAAgB,SACd,SACA,MACkC;CAElC,OADU,eAAe,SAAS,MAAM,WACjC;AACT;AAEA,SAAgB,aACd,SACA,MACsB;CACtB,MAAM,QAAQ,SAAS,SAAS,IAAI;CACpC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,oBAAoB,MAAM;CAE5C,OAAO;AACT"}
1
+ {"version":3,"file":"query-registry.js","names":[],"sources":["../../../../../zql/src/query/query-registry.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\nimport {\n deepMerge,\n isPlainObject,\n type DeepMerge,\n} from '../../../shared/src/deep-merge.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {getValueAtPath} from '../../../shared/src/object-traversal.ts';\nimport type {\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n IsUnknown,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport type {PullRow, Query} from './query.ts';\nimport {validateInput} from './validate-input.ts';\n\n// ----------------------------------------------------------------------------\n// CustomQuery and QueryRequest types\n// ----------------------------------------------------------------------------\n\nexport type CustomQueryTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'Query' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * CustomQuery is returned from defineQueries. It is a callable that captures\n * args and can be turned into a Query via {@link QueryRequest}.\n */\nexport type CustomQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined = TInput,\n TSchema extends Schema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext = DefaultContext,\n> = {\n readonly 'queryName': string;\n readonly 'fn': QueryExecutionFunction<TTable, TInput, TReturn, TContext>;\n readonly '~': CustomQueryTypes<TTable, TInput, TSchema, TReturn, TContext>;\n} & CustomQueryCallable<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n\ntype CustomQueryCallable<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = [TInput] extends [undefined]\n ? () => QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n : undefined extends TInput\n ? {\n (): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n (\n args?: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n }\n : {\n (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n };\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyCustomQuery = CustomQuery<string, any, any, Schema, any, any>;\n\nexport function isQuery<S extends Schema>(\n value: unknown,\n // oxlint-disable-next-line no-explicit-any\n): value is CustomQuery<string, any, any, S, any, any> {\n return (\n typeof value === 'function' &&\n typeof (value as {queryName?: unknown}).queryName === 'string' &&\n typeof (value as {fn?: unknown}).fn === 'function'\n );\n}\n\nexport type QueryRequestTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'QueryRequest' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\nexport type QueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = {\n readonly 'query': CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n readonly 'args': TInput;\n readonly '~': QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n};\n\n/**\n * A shared type that can be a query request or a query builder.\n *\n * If it is a query request, it will be converted to a {@link Query} using the context.\n * Otherwise, it will be returned as is.\n */\nexport type QueryOrQueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> =\n | QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Query<TTable, TSchema, TReturn>;\n\n/**\n * Converts a query request to a {@link Query} using the context,\n * or returns the query as is.\n *\n * @param query - The query request or query builder to convert\n * @param context - The context to use to convert the query request\n */\nexport const addContextToQuery = <\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n context: TContext,\n): Query<TTable, TSchema, TReturn> =>\n 'query' in query ? query.query.fn({ctx: context, args: query.args}) : query;\n\n// ----------------------------------------------------------------------------\n// QueryRegistry types\n// ----------------------------------------------------------------------------\n\nexport function isQueryRegistry(obj: unknown): obj is AnyQueryRegistry {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as unknown as {['~']: string})?.['~'] === 'QueryRegistry'\n );\n}\n\nexport type QueryRegistryTypes<TSchema extends Schema> = 'QueryRegistry' & {\n readonly $schema: TSchema;\n};\n\nexport type QueryRegistry<\n QD extends QueryDefinitions,\n S extends Schema,\n> = ToQueryTree<QD, S> & {\n ['~']: QueryRegistryTypes<S>;\n};\n\nexport type AnyQueryRegistry = {\n ['~']: QueryRegistryTypes<Schema>;\n [key: string]: unknown;\n};\n\ntype ToQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? // pull types from the phantom property\n CustomQuery<\n QD[K]['~']['$tableName'],\n QD[K]['~']['$input'],\n QD[K]['~']['$output'],\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? ToQueryTree<QD[K], S>\n : never;\n};\n\nexport type FromQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? CustomQuery<\n QD[K]['~']['$tableName'],\n // intentionally left as generic to avoid variance issues\n ReadonlyJSONValue | undefined,\n ReadonlyJSONValue | undefined,\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? FromQueryTree<QD[K], S>\n : never;\n}[keyof QD];\n\nexport type QueryDefinitions = {\n readonly [key: string]: AnyQueryDefinition | QueryDefinitions;\n};\n\n// ----------------------------------------------------------------------------\n// defineQuery\n// ----------------------------------------------------------------------------\n\nexport type QueryDefinitionTypes<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput,\n TReturn,\n TContext,\n> = 'QueryDefinition' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * A query definition is the return type of `defineQuery()`.\n */\nexport type QueryDefinition<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext = DefaultContext,\n> = {\n readonly 'fn': QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>;\n readonly 'validator': StandardSchemaV1<TInput, TOutput> | undefined;\n readonly '~': QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >;\n};\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryDefinition = QueryDefinition<any, any, any, any, any>;\n\nexport function isQueryDefinition(f: unknown): f is AnyQueryDefinition {\n return (\n typeof f === 'object' &&\n f !== null &&\n (f as {['~']?: unknown})['~'] === 'QueryDefinition'\n );\n}\n\nexport type QueryDefinitionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (options: {args: TInput; ctx: TContext}) => Query<TTable, Schema, TReturn>;\n\nexport type QueryExecutionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (\n options: QueryExecutionOptions<TInput, TContext>,\n) => Query<TTable, Schema, TReturn>;\n\ntype QueryExecutionOptions<\n TInput extends ReadonlyJSONValue | undefined,\n TContext,\n> = undefined extends TInput\n ? IsUnknown<TContext> extends true\n ? {args?: TInput | undefined; ctx?: TContext | undefined}\n : {args?: TInput | undefined; ctx: TContext}\n : IsUnknown<TContext> extends true\n ? {args: TInput; ctx?: TContext | undefined}\n : {args: TInput; ctx: TContext};\n\n/**\n * Defines a query to be used with {@link defineQueries}.\n *\n * The query function receives an object with `args` (the query arguments) and\n * `ctx` (the context). It should return a {@link Query} built using a builder\n * created from {@link createBuilder}.\n *\n * Note: A query defined with `defineQuery` must be passed to\n * {@link defineQueries} to be usable. The query name is derived from its\n * position in the `defineQueries` object.\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * // Simple query with no arguments\n * allIssues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n *\n * // Query with typed arguments\n * issueById: defineQuery(({args}: {args: {id: string}}) =>\n * builder.issue.where('id', args.id).one(),\n * ),\n *\n * // Query with validation using a Standard Schema validator (e.g., Zod)\n * issuesByStatus: defineQuery(\n * z.object({status: z.enum(['open', 'closed'])}),\n * ({args}) => builder.issue.where('status', args.status),\n * ),\n *\n * // Query using context\n * myIssues: defineQuery(({ctx}: {ctx: {userID: string}}) =>\n * builder.issue.where('creatorID', ctx.userID),\n * ),\n * });\n * ```\n *\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} that can be passed to {@link defineQueries}.\n *\n * @overload\n * @param validator - A Standard Schema validator for the arguments.\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} with validated arguments.\n */\n// Overload for no validator parameter with default inference for untyped functions\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n queryFn: QueryDefinitionFunction<TTable, TInput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TInput, TReturn, TContext>;\n\n// Overload for validator parameter - Input and Output can be different\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n\n// Implementation\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validatorOrQueryFn:\n | StandardSchemaV1<TInput, TOutput>\n | QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n queryFn?: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext> {\n // Handle different parameter patterns\n let validator: StandardSchemaV1<TInput, TOutput> | undefined;\n let actualQueryFn: QueryDefinitionFunction<\n TTable,\n TOutput,\n TReturn,\n TContext\n >;\n\n if ('~standard' in validatorOrQueryFn) {\n // defineQuery(validator, queryFn) - with validator\n validator = validatorOrQueryFn;\n actualQueryFn = must(queryFn);\n } else {\n // defineQuery(queryFn) - no validator\n validator = undefined;\n actualQueryFn = validatorOrQueryFn;\n }\n\n const queryDefinition: QueryDefinition<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n > = {\n 'fn': actualQueryFn,\n 'validator': validator,\n '~': 'QueryDefinition' as unknown as QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >,\n };\n return queryDefinition;\n}\n\n/**\n * Returns a typed version of {@link defineQuery} with the schema and context\n * types pre-specified. This enables better type inference when defining\n * queries.\n *\n * @example\n * ```ts\n * const zql = createBuilder(schema);\n *\n * // With both Schema and Context types\n * const defineAppQuery = defineQueryWithType<AppSchema, AppContext>();\n * const myQuery = defineAppQuery(({ctx}) =>\n * zql.issue.where('userID', ctx.userID),\n * );\n *\n * // With just Context type (Schema inferred)\n * const defineAppQuery = defineQueryWithType<AppContext>();\n * ```\n *\n * @typeParam S - The Zero schema type.\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with types\n * pre-bound.\n */\nexport function defineQueryWithType<\n S extends Schema,\n C = unknown,\n>(): TypedDefineQuery<S, C>;\n\n/**\n * Returns a typed version of {@link defineQuery} with the context type\n * pre-specified.\n *\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with the context\n * type pre-bound.\n */\nexport function defineQueryWithType<C>(): TypedDefineQuery<Schema, C>;\n\nexport function defineQueryWithType() {\n return defineQuery;\n}\n\n/**\n * The return type of defineQueryWithType. A function matching the\n * defineQuery overloads but with Schema and Context pre-bound.\n */\ntype TypedDefineQuery<TSchema extends Schema, TContext> = {\n // Without validator\n <\n TArgs extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n queryFn: QueryDefinitionFunction<TTable, TArgs, TReturn, TContext>,\n ): QueryDefinition<TTable, TArgs, TArgs, TReturn, TContext>;\n\n // With validator\n <\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n ): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n};\n\n// ----------------------------------------------------------------------------\n// createQuery\n// ----------------------------------------------------------------------------\n\nexport function createQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n name: string,\n definition: QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>,\n): CustomQuery<TTable, TInput, TOutput, TSchema, TReturn, TContext> {\n const {validator} = definition;\n\n const fn: QueryExecutionFunction<\n TTable,\n TInput,\n TReturn,\n TContext\n > = options => {\n const validatedArgs = validator\n ? validateInput(name, options.args, validator, 'query')\n : (options.args as unknown as TOutput);\n\n return asQueryInternals(\n definition.fn({\n args: validatedArgs,\n ctx: options.ctx as TContext,\n }),\n ).nameAndArgs(\n name,\n // TODO(arv): Get rid of the array?\n // Send original input args to server (not transformed output)\n options.args === undefined ? [] : [options.args],\n );\n };\n\n const query = (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext> => ({\n args,\n '~': 'QueryRequest' as QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n 'query': query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n });\n\n query.queryName = name;\n query.fn = fn;\n query['~'] = 'Query' as CustomQueryTypes<\n TTable,\n TInput,\n TSchema,\n TReturn,\n TContext\n >;\n\n return query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n}\n\n// ----------------------------------------------------------------------------\n// defineQueries\n// ----------------------------------------------------------------------------\n\n/**\n * Converts query definitions created with {@link defineQuery} into callable\n * {@link Query} objects that can be invoked with arguments and a context.\n *\n * Query definitions can be nested for organization. The resulting query names\n * are dot-separated paths (e.g., `users.byId`).\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * issues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n * users: {\n * byId: defineQuery(({args}: {args: {id: string}}) =>\n * builder.user.where('id', args.id),\n * ),\n * },\n * });\n *\n * // Usage:\n * const request = queries.issues.byId({id: '123'});\n * const [data] = zero.useQuery(request);\n * ```\n *\n * @param defs - An object containing query definitions or nested objects of\n * query definitions.\n * @returns An object with the same structure where each query definition is\n * converted to a {@link CustomQuery}.\n */\nexport function defineQueries<\n // let QD infer freely so defaults aren't erased by a QueryDefinitions<any, any> constraint\n const QD,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n defs: QD & AssertQueryDefinitions<QD>,\n): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\nexport function defineQueries<\n const TBase,\n const TOverrides,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n>;\n\nexport function defineQueries<QD extends QueryDefinitions, S extends Schema>(\n defsOrBase: QD | QueryRegistry<QD, S>,\n overrides?: QueryDefinitions,\n): QueryRegistry<QD, S> {\n function processDefinitions(\n definitions: QueryDefinitions,\n path: string[],\n ): Record<string | symbol, unknown> {\n const result: Record<string | symbol, unknown> = {\n ['~']: 'QueryRegistry',\n };\n\n for (const [key, value] of Object.entries(definitions)) {\n path.push(key);\n const defaultName = path.join('.');\n\n if (isQueryDefinition(value)) {\n result[key] = createQuery(defaultName, value);\n } else {\n // Nested definitions\n result[key] = processDefinitions(value, path);\n }\n path.pop();\n }\n\n return result;\n }\n\n if (overrides !== undefined) {\n // Merge base and overrides\n\n let base: Record<string | symbol, unknown>;\n if (!isQueryRegistry(defsOrBase)) {\n base = processDefinitions(defsOrBase, []);\n } else {\n base = defsOrBase;\n }\n\n const processed = processDefinitions(overrides, []);\n\n const merged = deepMerge(base, processed, isQueryLeaf);\n merged['~'] = 'QueryRegistry';\n return merged as QueryRegistry<QD, S>;\n }\n\n return processDefinitions(defsOrBase as QD, []) as QueryRegistry<QD, S>;\n}\n\nconst isQueryLeaf = (value: unknown): boolean =>\n !isPlainObject(value) || isQuery(value);\n\nexport type AssertQueryDefinitions<QD> = QD extends QueryDefinitions\n ? unknown\n : never;\n\nexport type EnsureQueryDefinitions<QD> = QD extends QueryDefinitions\n ? QD\n : QD extends QueryRegistry<infer InnerQD, infer _S>\n ? InnerQD\n : never;\n\n/**\n * Creates a function that can be used to define queries with a specific schema.\n */\nexport function defineQueriesWithType<\n TSchema extends Schema,\n>(): TypedDefineQueries<TSchema> {\n return defineQueries;\n}\n\n/**\n * The return type of defineQueriesWithType. A function matching the\n * defineQueries overloads but with Schema pre-bound.\n */\ntype TypedDefineQueries<S extends Schema> = {\n // Single definitions\n <QD>(\n definitions: QD & AssertQueryDefinitions<QD>,\n ): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\n // Base and overrides\n <TBase, TOverrides>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n ): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n >;\n};\n\nconst separatorRe = /[.|]/;\n\n// ----------------------------------------------------------------------------\n// getQuery / mustGetQuery\n// ----------------------------------------------------------------------------\n\nexport function getQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> | undefined {\n const q = getValueAtPath(queries, name, separatorRe);\n return q as FromQueryTree<QD, S> | undefined;\n}\n\nexport function mustGetQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> {\n const query = getQuery(queries, name);\n if (query === undefined) {\n throw new Error(`Query not found: ${name}`);\n }\n return query;\n}\n"],"mappings":";;;;;;AAgFA,SAAgB,QACd,OAEqD;CACrD,OACE,OAAO,UAAU,cACjB,OAAQ,MAAgC,cAAc,YACtD,OAAQ,MAAyB,OAAO;AAE5C;;;;;;;;AAqEA,IAAa,qBAQX,OAQA,YAEA,WAAW,QAAQ,MAAM,MAAM,GAAG;CAAC,KAAK;CAAS,MAAM,MAAM;AAAI,CAAC,IAAI;AAMxE,SAAgB,gBAAgB,KAAuC;CACrE,OACE,OAAO,QAAQ,YACf,QAAQ,QACP,MAAqC,SAAS;AAEnD;AAgGA,SAAgB,kBAAkB,GAAqC;CACrE,OACE,OAAO,MAAM,YACb,MAAM,QACL,EAAwB,SAAS;AAEtC;AAqGA,SAAgB,YASd,oBAGA,SAC6D;CAE7D,IAAI;CACJ,IAAI;CAOJ,IAAI,eAAe,oBAAoB;EAErC,YAAY;EACZ,gBAAgB,KAAK,OAAO;CAC9B,OAAO;EAEL,YAAY,KAAA;EACZ,gBAAgB;CAClB;CAmBA,OAAO;EAVL,MAAM;EACN,aAAa;EACb,KAAK;CAQA;AACT;AAyCA,SAAgB,sBAAsB;CACpC,OAAO;AACT;AAkCA,SAAgB,YAQd,MACA,YACkE;CAClE,MAAM,EAAC,cAAa;CAEpB,MAAM,MAKF,YAAW;EACb,MAAM,gBAAgB,YAClB,cAAc,MAAM,QAAQ,MAAM,WAAW,OAAO,IACnD,QAAQ;EAEb,OAAO,iBACL,WAAW,GAAG;GACZ,MAAM;GACN,KAAK,QAAQ;EACf,CAAC,CACH,CAAC,CAAC,YACA,MAGA,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,CACjD;CACF;CAEA,MAAM,SACJ,UACuE;EACvE;EACA,KAAK;EAQL,SAAS;CAQX;CAEA,MAAM,YAAY;CAClB,MAAM,KAAK;CACX,MAAM,OAAO;CAQb,OAAO;AAQT;AA8DA,SAAgB,cACd,YACA,WACsB;CACtB,SAAS,mBACP,aACA,MACkC;EAClC,MAAM,SAA2C,GAC9C,MAAM,gBACT;EAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,WAAW,GAAG;GACtD,KAAK,KAAK,GAAG;GACb,MAAM,cAAc,KAAK,KAAK,GAAG;GAEjC,IAAI,kBAAkB,KAAK,GACzB,OAAO,OAAO,YAAY,aAAa,KAAK;QAG5C,OAAO,OAAO,mBAAmB,OAAO,IAAI;GAE9C,KAAK,IAAI;EACX;EAEA,OAAO;CACT;CAEA,IAAI,cAAc,KAAA,GAAW;EAG3B,IAAI;EACJ,IAAI,CAAC,gBAAgB,UAAU,GAC7B,OAAO,mBAAmB,YAAY,CAAC,CAAC;OAExC,OAAO;EAGT,MAAM,YAAY,mBAAmB,WAAW,CAAC,CAAC;EAElD,MAAM,SAAS,UAAU,MAAM,WAAW,WAAW;EACrD,OAAO,OAAO;EACd,OAAO;CACT;CAEA,OAAO,mBAAmB,YAAkB,CAAC,CAAC;AAChD;AAEA,IAAM,eAAe,UACnB,CAAC,cAAc,KAAK,KAAK,QAAQ,KAAK;;;;AAexC,SAAgB,wBAEiB;CAC/B,OAAO;AACT;AA4BA,IAAM,cAAc;AAMpB,SAAgB,SACd,SACA,MACkC;CAElC,OADU,eAAe,SAAS,MAAM,WACjC;AACT;AAEA,SAAgB,aACd,SACA,MACsB;CACtB,MAAM,QAAQ,SAAS,SAAS,IAAI;CACpC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,oBAAoB,MAAM;CAE5C,OAAO;AACT"}
@@ -70,7 +70,7 @@ var Transitions = class {
70
70
  };
71
71
  const bucket = byValue.get(value);
72
72
  if (bucket === void 0) byValue.set(value, entry);
73
- else if (!(bucket instanceof Set)) byValue.set(value, new Set([bucket, entry]));
73
+ else if (!(bucket instanceof Set)) byValue.set(value, /* @__PURE__ */ new Set([bucket, entry]));
74
74
  else {
75
75
  if (bucket.size >= 64) return;
76
76
  bucket.add(entry);