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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (577) hide show
  1. package/out/analyze-query/src/bin-analyze.js +1 -1
  2. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  3. package/out/replicache/src/btree/read.d.ts +12 -1
  4. package/out/replicache/src/btree/read.d.ts.map +1 -1
  5. package/out/replicache/src/btree/read.js +24 -12
  6. package/out/replicache/src/btree/read.js.map +1 -1
  7. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  8. package/out/replicache/src/dag/gc.js +2 -1
  9. package/out/replicache/src/dag/gc.js.map +1 -1
  10. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +12 -0
  11. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +1 -0
  12. package/out/replicache/src/dag/invalid-ref-count-error.js +19 -0
  13. package/out/replicache/src/dag/invalid-ref-count-error.js.map +1 -0
  14. package/out/replicache/src/dag/store-impl.d.ts +12 -2
  15. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  16. package/out/replicache/src/dag/store-impl.js +22 -8
  17. package/out/replicache/src/dag/store-impl.js.map +1 -1
  18. package/out/replicache/src/db/rebase.d.ts +14 -2
  19. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  20. package/out/replicache/src/db/rebase.js +27 -5
  21. package/out/replicache/src/db/rebase.js.map +1 -1
  22. package/out/replicache/src/db/write.js.map +1 -1
  23. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  24. package/out/replicache/src/kv/expo-sqlite/store.js +28 -5
  25. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  26. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +15 -5
  27. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
  28. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
  29. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  30. package/out/replicache/src/kv/idb-store.d.ts +9 -0
  31. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  32. package/out/replicache/src/kv/idb-store.js +14 -2
  33. package/out/replicache/src/kv/idb-store.js.map +1 -1
  34. package/out/replicache/src/kv/mem-store.d.ts +1 -0
  35. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  36. package/out/replicache/src/kv/mem-store.js +3 -0
  37. package/out/replicache/src/kv/mem-store.js.map +1 -1
  38. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  39. package/out/replicache/src/kv/op-sqlite/store.js +1 -1
  40. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  41. package/out/replicache/src/kv/sqlite-store.d.ts +13 -1
  42. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  43. package/out/replicache/src/kv/sqlite-store.js +49 -4
  44. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  45. package/out/replicache/src/kv/store.d.ts +6 -0
  46. package/out/replicache/src/kv/store.d.ts.map +1 -1
  47. package/out/replicache/src/persist/collect-idb-databases.d.ts +10 -5
  48. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  49. package/out/replicache/src/persist/collect-idb-databases.js +16 -9
  50. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  51. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  52. package/out/replicache/src/persist/persist.js +12 -5
  53. package/out/replicache/src/persist/persist.js.map +1 -1
  54. package/out/replicache/src/persist/refresh.js +6 -2
  55. package/out/replicache/src/persist/refresh.js.map +1 -1
  56. package/out/replicache/src/replicache-impl.d.ts +14 -3
  57. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  58. package/out/replicache/src/replicache-impl.js +118 -11
  59. package/out/replicache/src/replicache-impl.js.map +1 -1
  60. package/out/replicache/src/replicache-options.d.ts +9 -0
  61. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  62. package/out/replicache/src/transactions.d.ts.map +1 -1
  63. package/out/replicache/src/transactions.js +1 -1
  64. package/out/replicache/src/transactions.js.map +1 -1
  65. package/out/shared/src/error.d.ts +11 -0
  66. package/out/shared/src/error.d.ts.map +1 -1
  67. package/out/shared/src/error.js +35 -1
  68. package/out/shared/src/error.js.map +1 -1
  69. package/out/shared/src/iterables.d.ts +2 -0
  70. package/out/shared/src/iterables.d.ts.map +1 -1
  71. package/out/shared/src/iterables.js +18 -1
  72. package/out/shared/src/iterables.js.map +1 -1
  73. package/out/shared/src/map.d.ts +7 -2
  74. package/out/shared/src/map.d.ts.map +1 -1
  75. package/out/shared/src/map.js.map +1 -1
  76. package/out/shared/src/ring-buffer.d.ts +8 -0
  77. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  78. package/out/shared/src/ring-buffer.js +22 -1
  79. package/out/shared/src/ring-buffer.js.map +1 -1
  80. package/out/zero/package.js +3 -4
  81. package/out/zero/package.js.map +1 -1
  82. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  83. package/out/zero-cache/src/config/normalize.js +25 -1
  84. package/out/zero-cache/src/config/normalize.js.map +1 -1
  85. package/out/zero-cache/src/config/zero-config.d.ts +48 -2
  86. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  87. package/out/zero-cache/src/config/zero-config.js +171 -29
  88. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  89. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  90. package/out/zero-cache/src/server/change-streamer.js +25 -9
  91. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  92. package/out/zero-cache/src/server/inspector-delegate.d.ts +18 -2
  93. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  94. package/out/zero-cache/src/server/inspector-delegate.js +20 -7
  95. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  96. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  97. package/out/zero-cache/src/server/main.js +8 -1
  98. package/out/zero-cache/src/server/main.js.map +1 -1
  99. package/out/zero-cache/src/server/mutator.js +2 -0
  100. package/out/zero-cache/src/server/mutator.js.map +1 -1
  101. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  102. package/out/zero-cache/src/server/reaper.js +2 -0
  103. package/out/zero-cache/src/server/reaper.js.map +1 -1
  104. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  105. package/out/zero-cache/src/server/replicator.js +8 -2
  106. package/out/zero-cache/src/server/replicator.js.map +1 -1
  107. package/out/zero-cache/src/server/runner/run-worker.js +1 -1
  108. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  109. package/out/zero-cache/src/server/runner/zero-dispatcher.js +3 -0
  110. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  111. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  112. package/out/zero-cache/src/server/syncer.js +2 -0
  113. package/out/zero-cache/src/server/syncer.js.map +1 -1
  114. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  115. package/out/zero-cache/src/services/analyze.js +3 -2
  116. package/out/zero-cache/src/services/analyze.js.map +1 -1
  117. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  118. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +14 -1
  119. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  120. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  121. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +15 -3
  122. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  123. package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
  124. package/out/zero-cache/src/services/change-source/common/replica-schema.js +2 -39
  125. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  126. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts +156 -0
  127. package/out/zero-cache/src/services/change-source/pg/backfill-resume.d.ts.map +1 -0
  128. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js +15 -0
  129. package/out/zero-cache/src/services/change-source/pg/backfill-resume.js.map +1 -0
  130. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts +25 -0
  131. package/out/zero-cache/src/services/change-source/pg/change-source-init.d.ts.map +1 -0
  132. package/out/zero-cache/src/services/change-source/pg/change-source-init.js +202 -0
  133. package/out/zero-cache/src/services/change-source/pg/change-source-init.js.map +1 -0
  134. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +14 -16
  135. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  136. package/out/zero-cache/src/services/change-source/pg/change-source.js +64 -143
  137. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  138. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +28 -2
  139. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  140. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +44 -21
  141. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  142. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts +16 -0
  143. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.d.ts.map +1 -0
  144. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js +113 -0
  145. package/out/zero-cache/src/services/change-source/pg/replication-slot-cleanup-monitor.js.map +1 -0
  146. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +21 -15
  147. package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
  148. package/out/zero-cache/src/services/change-source/pg/replication-slots.js +86 -23
  149. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  150. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
  151. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +68 -8
  152. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
  153. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  154. package/out/zero-cache/src/services/change-source/pg/schema/init.js +32 -1
  155. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  156. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts +10 -0
  157. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.d.ts.map +1 -0
  158. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js +6 -0
  159. package/out/zero-cache/src/services/change-source/pg/schema/replica-stage-enum.js.map +1 -0
  160. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +50 -27
  161. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  162. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +100 -34
  163. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  164. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +58 -7
  166. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  167. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +8 -2
  168. package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/change-streamer/broadcast.js +24 -4
  170. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  171. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -4
  172. package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -1
  173. package/out/zero-cache/src/services/change-streamer/change-log-codec.js +28 -8
  174. package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -1
  175. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +5 -2
  176. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +21 -14
  178. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  179. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +6 -0
  180. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  181. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +97 -63
  182. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  183. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +12 -8
  184. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  185. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  186. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +3 -3
  187. package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
  188. package/out/zero-cache/src/services/change-streamer/forwarder.js +36 -5
  189. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  190. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +1 -1
  191. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/schema/tables.js +4 -4
  193. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  194. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +3 -1
  195. package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
  196. package/out/zero-cache/src/services/change-streamer/snapshot.js +54 -20
  197. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  198. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +6 -1
  199. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -1
  200. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +27 -9
  201. package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -1
  202. package/out/zero-cache/src/services/change-streamer/storer.d.ts +2 -2
  203. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  204. package/out/zero-cache/src/services/change-streamer/storer.js +8 -5
  205. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  206. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +4 -1
  207. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  208. package/out/zero-cache/src/services/change-streamer/subscriber.js +42 -0
  209. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  210. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +17 -1
  211. package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -1
  212. package/out/zero-cache/src/services/change-streamer/upstream-acker.js +19 -3
  213. package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -1
  214. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.d.ts.map +1 -1
  215. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js +1 -0
  216. package/out/zero-cache/src/services/change-streamer/vfs-watermark-poller.js.map +1 -1
  217. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  218. package/out/zero-cache/src/services/life-cycle.js +3 -1
  219. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  220. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  221. package/out/zero-cache/src/services/litestream/commands.js +8 -3
  222. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  223. package/out/zero-cache/src/services/litestream/config-v5.yml +15 -1
  224. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +131 -0
  225. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +1 -0
  226. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +70 -0
  227. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +1 -0
  228. package/out/zero-cache/src/services/litestream/litestream-controller.js +101 -0
  229. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +1 -0
  230. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +5 -0
  231. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  232. package/out/zero-cache/src/services/mutagen/mutagen.js +7 -1
  233. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  234. package/out/zero-cache/src/services/mutagen/pusher.js +2 -1
  235. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  236. package/out/zero-cache/src/services/profz.d.ts +7 -0
  237. package/out/zero-cache/src/services/profz.d.ts.map +1 -0
  238. package/out/zero-cache/src/services/profz.js +105 -0
  239. package/out/zero-cache/src/services/profz.js.map +1 -0
  240. package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
  241. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +5 -4
  242. package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -1
  243. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +20 -22
  244. package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
  245. package/out/zero-cache/src/services/replicator/change-processor.js +1 -0
  246. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  247. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
  248. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  249. package/out/zero-cache/src/services/replicator/incremental-sync.js +58 -17
  250. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  251. package/out/zero-cache/src/services/replicator/replication-status.d.ts +35 -1
  252. package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
  253. package/out/zero-cache/src/services/replicator/replication-status.js +96 -6
  254. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  255. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  256. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +6 -6
  257. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -1
  258. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +19 -14
  259. package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -1
  260. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +31 -6
  261. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  262. package/out/zero-cache/src/services/replicator/write-worker-client.js +5 -4
  263. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  264. package/out/zero-cache/src/services/replicator/write-worker.js +30 -5
  265. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  266. package/out/zero-cache/src/services/run-ast.d.ts +12 -0
  267. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  268. package/out/zero-cache/src/services/run-ast.js +26 -14
  269. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  270. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  271. package/out/zero-cache/src/services/runner.js +1 -1
  272. package/out/zero-cache/src/services/runner.js.map +1 -1
  273. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +1 -1
  274. package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
  275. package/out/zero-cache/src/services/view-syncer/client-handler.js +36 -31
  276. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  277. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +45 -0
  278. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  279. package/out/zero-cache/src/services/view-syncer/cvr.js +133 -1
  280. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  281. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +14 -1
  282. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  283. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +30 -4
  284. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  285. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +33 -0
  286. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +1 -0
  287. package/out/zero-cache/src/services/view-syncer/hydration-budget.js +62 -0
  288. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +1 -0
  289. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +51 -0
  290. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +1 -0
  291. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +78 -0
  292. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +1 -0
  293. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
  294. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  295. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  296. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  297. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
  298. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  299. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +33 -18
  300. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  301. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -1
  302. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  303. package/out/zero-cache/src/services/view-syncer/snapshotter.js +9 -3
  304. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  305. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
  306. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  307. package/out/zero-cache/src/services/view-syncer/view-syncer.js +507 -93
  308. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  309. package/out/zero-cache/src/types/processes.d.ts +32 -0
  310. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  311. package/out/zero-cache/src/types/processes.js +43 -4
  312. package/out/zero-cache/src/types/processes.js.map +1 -1
  313. package/out/zero-cache/src/types/profiler.d.ts +12 -0
  314. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  315. package/out/zero-cache/src/types/profiler.js +46 -1
  316. package/out/zero-cache/src/types/profiler.js.map +1 -1
  317. package/out/zero-cache/src/types/streams.d.ts +25 -9
  318. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  319. package/out/zero-cache/src/types/streams.js +118 -34
  320. package/out/zero-cache/src/types/streams.js.map +1 -1
  321. package/out/zero-cache/src/types/subscription.d.ts +4 -0
  322. package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
  323. package/out/zero-cache/src/types/subscription.js +71 -0
  324. package/out/zero-cache/src/types/subscription.js.map +1 -1
  325. package/out/zero-cache/src/types/ws.d.ts.map +1 -1
  326. package/out/zero-cache/src/types/ws.js +23 -8
  327. package/out/zero-cache/src/types/ws.js.map +1 -1
  328. package/out/zero-cache/src/workers/connection.js +2 -2
  329. package/out/zero-cache/src/workers/replicator.d.ts +1 -0
  330. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  331. package/out/zero-cache/src/workers/replicator.js +4 -2
  332. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  333. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  334. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +21 -16
  335. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  336. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  337. package/out/zero-cache/src/workers/syncer.js +10 -1
  338. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  339. package/out/zero-client/src/client/connection-manager.d.ts +20 -0
  340. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  341. package/out/zero-client/src/client/connection-manager.js +77 -13
  342. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  343. package/out/zero-client/src/client/connection-status-enum.d.ts +2 -0
  344. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  345. package/out/zero-client/src/client/connection-status-enum.js +3 -1
  346. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  347. package/out/zero-client/src/client/connection.d.ts +6 -0
  348. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  349. package/out/zero-client/src/client/connection.js +2 -1
  350. package/out/zero-client/src/client/connection.js.map +1 -1
  351. package/out/zero-client/src/client/context.d.ts +27 -2
  352. package/out/zero-client/src/client/context.d.ts.map +1 -1
  353. package/out/zero-client/src/client/context.js +112 -1
  354. package/out/zero-client/src/client/context.js.map +1 -1
  355. package/out/zero-client/src/client/custom.js +2 -2
  356. package/out/zero-client/src/client/custom.js.map +1 -1
  357. package/out/zero-client/src/client/error.js +1 -1
  358. package/out/zero-client/src/client/inspector/lazy-inspector.js +2 -2
  359. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  360. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  361. package/out/zero-client/src/client/ivm-branch.js +20 -3
  362. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  363. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  364. package/out/zero-client/src/client/mutator-proxy.js +2 -1
  365. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  366. package/out/zero-client/src/client/options.d.ts +3 -0
  367. package/out/zero-client/src/client/options.d.ts.map +1 -1
  368. package/out/zero-client/src/client/options.js.map +1 -1
  369. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  370. package/out/zero-client/src/client/query-manager.js +42 -6
  371. package/out/zero-client/src/client/query-manager.js.map +1 -1
  372. package/out/zero-client/src/client/version.js +1 -1
  373. package/out/zero-client/src/client/zero-rep.d.ts +1 -0
  374. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  375. package/out/zero-client/src/client/zero-rep.js +9 -6
  376. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  377. package/out/zero-client/src/client/zero.d.ts +18 -3
  378. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  379. package/out/zero-client/src/client/zero.js +122 -34
  380. package/out/zero-client/src/client/zero.js.map +1 -1
  381. package/out/zero-client/src/types/query-result.d.ts +2 -0
  382. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  383. package/out/zero-events/src/status.d.ts +26 -0
  384. package/out/zero-events/src/status.d.ts.map +1 -1
  385. package/out/zero-protocol/src/analyze-query-result.d.ts +5 -5
  386. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  387. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  388. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  389. package/out/zero-protocol/src/down.d.ts +4 -4
  390. package/out/zero-protocol/src/inspect-down.d.ts +6 -6
  391. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  392. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  393. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  394. package/out/zero-react/src/use-query.d.ts +5 -4
  395. package/out/zero-react/src/use-query.d.ts.map +1 -1
  396. package/out/zero-react/src/use-query.js +86 -9
  397. package/out/zero-react/src/use-query.js.map +1 -1
  398. package/out/zero-server/src/adapters/drizzle.d.ts +2 -1
  399. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  400. package/out/zero-server/src/adapters/drizzle.js +12 -7
  401. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  402. package/out/zero-server/src/adapters/kysely.d.ts +2 -1
  403. package/out/zero-server/src/adapters/kysely.d.ts.map +1 -1
  404. package/out/zero-server/src/adapters/kysely.js +8 -2
  405. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  406. package/out/zero-server/src/adapters/pg.d.ts +1 -0
  407. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  408. package/out/zero-server/src/adapters/pg.js +8 -2
  409. package/out/zero-server/src/adapters/pg.js.map +1 -1
  410. package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
  411. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  412. package/out/zero-server/src/adapters/postgresjs.js +7 -1
  413. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  414. package/out/zero-server/src/adapters/prisma.d.ts +3 -2
  415. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
  416. package/out/zero-server/src/adapters/prisma.js +8 -2
  417. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  418. package/out/zero-server/src/custom.d.ts +5 -1
  419. package/out/zero-server/src/custom.d.ts.map +1 -1
  420. package/out/zero-server/src/custom.js +6 -3
  421. package/out/zero-server/src/custom.js.map +1 -1
  422. package/out/zero-server/src/mod.d.ts +1 -1
  423. package/out/zero-server/src/mod.d.ts.map +1 -1
  424. package/out/zero-server/src/pg-query-executor.d.ts +2 -2
  425. package/out/zero-server/src/pg-query-executor.d.ts.map +1 -1
  426. package/out/zero-server/src/pg-query-executor.js +2 -2
  427. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  428. package/out/zero-server/src/schema.d.ts +2 -2
  429. package/out/zero-server/src/schema.d.ts.map +1 -1
  430. package/out/zero-server/src/schema.js +2 -2
  431. package/out/zero-server/src/schema.js.map +1 -1
  432. package/out/zero-server/src/zql-database.d.ts +21 -1
  433. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  434. package/out/zero-server/src/zql-database.js +33 -2
  435. package/out/zero-server/src/zql-database.js.map +1 -1
  436. package/out/zero-solid/src/solid-view.d.ts +17 -0
  437. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  438. package/out/zero-solid/src/solid-view.js +39 -1
  439. package/out/zero-solid/src/solid-view.js.map +1 -1
  440. package/out/zero-solid/src/use-query.js +5 -3
  441. package/out/zero-solid/src/use-query.js.map +1 -1
  442. package/out/zql/src/builder/builder.d.ts.map +1 -1
  443. package/out/zql/src/builder/builder.js +16 -10
  444. package/out/zql/src/builder/builder.js.map +1 -1
  445. package/out/zql/src/builder/debug-delegate.d.ts +6 -1
  446. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  447. package/out/zql/src/builder/debug-delegate.js +14 -2
  448. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  449. package/out/zql/src/ivm/array-view.d.ts +29 -0
  450. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  451. package/out/zql/src/ivm/array-view.js +63 -12
  452. package/out/zql/src/ivm/array-view.js.map +1 -1
  453. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  454. package/out/zql/src/ivm/cap.js +5 -3
  455. package/out/zql/src/ivm/cap.js.map +1 -1
  456. package/out/zql/src/ivm/data.d.ts.map +1 -1
  457. package/out/zql/src/ivm/data.js +8 -3
  458. package/out/zql/src/ivm/data.js.map +1 -1
  459. package/out/zql/src/ivm/deferred-input.d.ts +44 -0
  460. package/out/zql/src/ivm/deferred-input.d.ts.map +1 -0
  461. package/out/zql/src/ivm/deferred-input.js +89 -0
  462. package/out/zql/src/ivm/deferred-input.js.map +1 -0
  463. package/out/zql/src/ivm/exists.d.ts +1 -1
  464. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  465. package/out/zql/src/ivm/exists.js.map +1 -1
  466. package/out/zql/src/ivm/fan-in.d.ts +2 -2
  467. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  468. package/out/zql/src/ivm/fan-in.js +6 -5
  469. package/out/zql/src/ivm/fan-in.js.map +1 -1
  470. package/out/zql/src/ivm/fan-out.d.ts +2 -2
  471. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  472. package/out/zql/src/ivm/fan-out.js.map +1 -1
  473. package/out/zql/src/ivm/filter-operators.d.ts +7 -6
  474. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  475. package/out/zql/src/ivm/filter-operators.js +29 -12
  476. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  477. package/out/zql/src/ivm/filter.d.ts +2 -2
  478. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  479. package/out/zql/src/ivm/filter.js +7 -4
  480. package/out/zql/src/ivm/filter.js.map +1 -1
  481. package/out/zql/src/ivm/flipped-join.js +2 -2
  482. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  483. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  484. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  485. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +6 -4
  486. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  487. package/out/zql/src/ivm/memory-source.d.ts +15 -3
  488. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  489. package/out/zql/src/ivm/memory-source.js +57 -23
  490. package/out/zql/src/ivm/memory-source.js.map +1 -1
  491. package/out/zql/src/ivm/operator.d.ts +40 -0
  492. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  493. package/out/zql/src/ivm/operator.js.map +1 -1
  494. package/out/zql/src/ivm/take.d.ts.map +1 -1
  495. package/out/zql/src/ivm/take.js +3 -4
  496. package/out/zql/src/ivm/take.js.map +1 -1
  497. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  498. package/out/zql/src/ivm/union-fan-in.js +9 -7
  499. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  500. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  501. package/out/zql/src/ivm/view-apply-change.js +9 -4
  502. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  503. package/out/zql/src/ivm/view.d.ts +15 -0
  504. package/out/zql/src/ivm/view.d.ts.map +1 -1
  505. package/out/zql/src/mutate/custom.d.ts +24 -1
  506. package/out/zql/src/mutate/custom.d.ts.map +1 -1
  507. package/out/zql/src/mutate/custom.js.map +1 -1
  508. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  509. package/out/zql/src/mutate/mutator-registry.js +2 -2
  510. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  511. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  512. package/out/zql/src/planner/planner-builder.js +14 -4
  513. package/out/zql/src/planner/planner-builder.js.map +1 -1
  514. package/out/zql/src/planner/planner-connection.d.ts +13 -0
  515. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  516. package/out/zql/src/planner/planner-connection.js +42 -7
  517. package/out/zql/src/planner/planner-connection.js.map +1 -1
  518. package/out/zql/src/planner/planner-debug.d.ts +1 -1
  519. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  520. package/out/zql/src/planner/planner-debug.js.map +1 -1
  521. package/out/zql/src/planner/planner-fan-out.d.ts +1 -0
  522. package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
  523. package/out/zql/src/planner/planner-fan-out.js +3 -0
  524. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  525. package/out/zql/src/planner/planner-filter.d.ts +59 -0
  526. package/out/zql/src/planner/planner-filter.d.ts.map +1 -0
  527. package/out/zql/src/planner/planner-filter.js +116 -0
  528. package/out/zql/src/planner/planner-filter.js.map +1 -0
  529. package/out/zql/src/planner/planner-graph.d.ts +2 -0
  530. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  531. package/out/zql/src/planner/planner-graph.js +2 -0
  532. package/out/zql/src/planner/planner-graph.js.map +1 -1
  533. package/out/zql/src/planner/planner-join.d.ts +2 -0
  534. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  535. package/out/zql/src/planner/planner-join.js +7 -0
  536. package/out/zql/src/planner/planner-join.js.map +1 -1
  537. package/out/zql/src/planner/planner-node.d.ts +2 -1
  538. package/out/zql/src/planner/planner-node.d.ts.map +1 -1
  539. package/out/zql/src/planner/planner-node.js.map +1 -1
  540. package/out/zql/src/query/query-delegate-base.d.ts +9 -1
  541. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  542. package/out/zql/src/query/query-delegate-base.js +129 -33
  543. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  544. package/out/zql/src/query/query-delegate.d.ts +50 -1
  545. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  546. package/out/zql/src/query/query-impl.d.ts +13 -11
  547. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  548. package/out/zql/src/query/query-impl.js +383 -60
  549. package/out/zql/src/query/query-impl.js.map +1 -1
  550. package/out/zql/src/query/query-transitions.d.ts +171 -0
  551. package/out/zql/src/query/query-transitions.d.ts.map +1 -0
  552. package/out/zql/src/query/query-transitions.js +207 -0
  553. package/out/zql/src/query/query-transitions.js.map +1 -0
  554. package/out/zql/src/query/query.d.ts +11 -2
  555. package/out/zql/src/query/query.d.ts.map +1 -1
  556. package/out/zql/src/query/runnable-query-impl.d.ts +1 -0
  557. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  558. package/out/zql/src/query/runnable-query-impl.js +21 -1
  559. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  560. package/out/zql/src/query/typed-view.d.ts +1 -1
  561. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  562. package/out/zqlite/src/db.d.ts +9 -1
  563. package/out/zqlite/src/db.d.ts.map +1 -1
  564. package/out/zqlite/src/db.js +8 -2
  565. package/out/zqlite/src/db.js.map +1 -1
  566. package/out/zqlite/src/query-builder.d.ts +1 -1
  567. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  568. package/out/zqlite/src/query-builder.js +2 -1
  569. package/out/zqlite/src/query-builder.js.map +1 -1
  570. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  571. package/out/zqlite/src/sqlite-cost-model.js +2 -30
  572. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  573. package/out/zqlite/src/table-source.d.ts +1 -0
  574. package/out/zqlite/src/table-source.d.ts.map +1 -1
  575. package/out/zqlite/src/table-source.js +20 -8
  576. package/out/zqlite/src/table-source.js.map +1 -1
  577. package/package.json +3 -4
@@ -1,7 +1,7 @@
1
1
  import type { Schema } from '../../zero-types/src/schema.ts';
2
2
  import type { ServerSchema } from '../../zero-types/src/server-schema.ts';
3
3
  import { type CRUDExecutor, type TransactionMutate } from '../../zql/src/mutate/crud.ts';
4
- import type { DBTransaction, MutateCRUD, ServerTransaction } from '../../zql/src/mutate/custom.ts';
4
+ import type { DBTransaction, MutateCRUD, Queryable, ServerTransaction } from '../../zql/src/mutate/custom.ts';
5
5
  import type { HumanReadable, Query, RunOptions } from '../../zql/src/query/query.ts';
6
6
  import type { ConditionalSchemaQuery } from '../../zql/src/query/schema-query.ts';
7
7
  export type CustomMutatorDefs<TDBTransaction> = {
@@ -36,6 +36,10 @@ export declare class TransactionImpl<TSchema extends Schema, TWrappedTransaction
36
36
  export declare class CRUDMutatorFactory<S extends Schema> {
37
37
  #private;
38
38
  constructor(schema: S);
39
+ /**
40
+ * Gets the cached serverSchema, or fetches and caches it on first call.
41
+ */
42
+ getOrFetchServerSchema(queryable: Queryable): Promise<ServerSchema>;
39
43
  /**
40
44
  * Creates a CRUDExecutor bound to the given transaction and serverSchema.
41
45
  * Uses the pre-created TableCRUD methods from construction time.
@@ -1 +1 @@
1
- {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/custom.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"custom.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/custom.ts"],"names":[],"mappings":"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"}
@@ -91,8 +91,11 @@ var CRUDMutatorFactory = class {
91
91
  /**
92
92
  * Gets the cached serverSchema, or fetches and caches it on first call.
93
93
  */
94
- async #getOrFetchServerSchema(dbTransaction) {
95
- if (!this.#serverSchema) this.#serverSchema = await getServerSchema(dbTransaction, this.#schema);
94
+ getOrFetchServerSchema(queryable) {
95
+ if (!this.#serverSchema) this.#serverSchema = getServerSchema(queryable, this.#schema).catch((e) => {
96
+ this.#serverSchema = void 0;
97
+ throw e;
98
+ });
96
99
  return this.#serverSchema;
97
100
  }
98
101
  /**
@@ -114,7 +117,7 @@ var CRUDMutatorFactory = class {
114
117
  * Fetches/caches serverSchema automatically.
115
118
  */
116
119
  async createTransaction(dbTransaction, clientID, mutationID) {
117
- const serverSchema = await this.#getOrFetchServerSchema(dbTransaction);
120
+ const serverSchema = await this.getOrFetchServerSchema(dbTransaction);
118
121
  const executor = this.createExecutor(dbTransaction, serverSchema);
119
122
  return new TransactionImpl(dbTransaction, clientID, mutationID, makeTransactionMutate(this.#schema, executor), this.#schema, serverSchema);
120
123
  }
@@ -1 +1 @@
1
- {"version":3,"file":"custom.js","names":["#dbTransaction","#schema","#serverSchema","#tableCRUDs","#getOrFetchServerSchema"],"sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {mapValues} from '../../shared/src/objects.ts';\nimport {recordProxy} from '../../shared/src/record-proxy.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport {\n type CRUDExecutor,\n type CRUDKind,\n makeCRUDMutate,\n makeTransactionMutate,\n type SchemaCRUD,\n type TableCRUD,\n type TransactionMutate,\n} from '../../zql/src/mutate/crud.ts';\nimport type {\n DBTransaction,\n MutateCRUD,\n ServerTransaction,\n} from '../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../zql/src/query/create-builder.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {ConditionalSchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\n/**\n * QueryDelegate implementation for server-side transactions.\n * Extends QueryDelegateBase to satisfy the QueryDelegate interface,\n * but overrides run() to execute against Postgres and throws on\n * preload()/materialize() which don't make sense server-side.\n */\nclass ServerTransactionQueryDelegate extends QueryDelegateBase {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #schema: Schema;\n readonly #serverSchema: ServerSchema;\n\n readonly defaultQueryComplete = true;\n\n constructor(\n dbTransaction: DBTransaction<unknown>,\n schema: Schema,\n serverSchema: ServerSchema,\n ) {\n super();\n this.#dbTransaction = dbTransaction;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n getSource(): never {\n throw new Error('not implemented');\n }\n\n override 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 const queryInternals = asQueryInternals(query);\n return this.#dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n\n override preload(): never {\n throw new Error('preload() is not supported in server transactions');\n }\n\n override materialize(): never {\n throw new Error('materialize() is not supported in server transactions');\n }\n}\n\nexport class TransactionImpl<\n TSchema extends Schema,\n TWrappedTransaction,\n> implements ServerTransaction<TSchema, TWrappedTransaction> {\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: TransactionMutate<TSchema>;\n /**\n * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<TSchema>;\n\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: TransactionMutate<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n\n const delegate = new ServerTransactionQueryDelegate(\n dbTransaction,\n schema,\n serverSchema,\n );\n this.query = createRunnableBuilder(delegate, schema);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\n/**\n * Factory for creating MutateCRUD instances efficiently.\n *\n * Pre-creates the SQL-generating TableCRUD methods once from the schema,\n * caches the serverSchema after first fetch, and only binds the transaction\n * at transaction time.\n *\n * Use this when you need to create many transactions and want to avoid\n * the overhead of re-creating CRUD methods for each one.\n */\nexport class CRUDMutatorFactory<S extends Schema> {\n readonly #schema: S;\n readonly #tableCRUDs: Record<string, TableCRUD<TableSchema>>;\n #serverSchema: ServerSchema | undefined;\n\n constructor(schema: S) {\n this.#schema = schema;\n // Pre-create TableCRUD methods for each table once\n this.#tableCRUDs = {};\n for (const tableSchema of Object.values(schema.tables)) {\n this.#tableCRUDs[tableSchema.name] = makeServerTableCRUD(tableSchema);\n }\n }\n\n /**\n * Gets the cached serverSchema, or fetches and caches it on first call.\n */\n async #getOrFetchServerSchema(\n dbTransaction: DBTransaction<unknown>,\n ): Promise<ServerSchema> {\n if (!this.#serverSchema) {\n this.#serverSchema = await getServerSchema(dbTransaction, this.#schema);\n }\n return this.#serverSchema;\n }\n\n /**\n * Creates a CRUDExecutor bound to the given transaction and serverSchema.\n * Uses the pre-created TableCRUD methods from construction time.\n */\n createExecutor(\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ): CRUDExecutor {\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: dbTransaction,\n [serverSchemaSymbol]: serverSchema,\n };\n const boundCRUDs = recordProxy(this.#tableCRUDs, tableCRUD =>\n mapValues(tableCRUD, method => method.bind(txHolder)),\n ) as unknown as SchemaCRUD<S>;\n\n return (table: string, kind: CRUDKind, args: unknown) => {\n const tableCRUD = boundCRUDs[table as keyof S['tables']];\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return (tableCRUD as any)[kind](args);\n };\n }\n\n /**\n * Creates a full ServerTransaction.\n * Fetches/caches serverSchema automatically.\n */\n async createTransaction<TWrappedTransaction>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n ): Promise<TransactionImpl<S, TWrappedTransaction>> {\n const serverSchema = await this.#getOrFetchServerSchema(dbTransaction);\n const executor = this.createExecutor(dbTransaction, serverSchema);\n const mutate = makeTransactionMutate(this.#schema, executor);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate,\n this.#schema,\n serverSchema,\n );\n }\n}\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n // Use the internal executor and shared function directly,\n // bypassing the validation in makeMutateCRUD/makeSchemaCRUD\n const executor = makeServerCRUDExecutor(schema, dbTransaction, serverSchema);\n const mutate = makeTransactionMutate(schema, executor);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate,\n schema,\n serverSchema,\n );\n}\n\n/**\n * @deprecated Use transactions instead.\n *\n * Returns a curried function for backwards compatibility.\n */\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => MutateCRUD<S, true> {\n return (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) =>\n makeCRUDMutate(\n schema,\n true,\n makeServerCRUDExecutor(schema, dbTransaction, serverSchema),\n );\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\n/**\n * Creates a CRUDExecutor for server-side SQL execution.\n *\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * the SQL-generating methods once up-front and then bind them to\n * the transaction as requested.\n */\nfunction makeServerCRUDExecutor<S extends Schema>(\n schema: S,\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n): CRUDExecutor {\n // Pre-create TableCRUD methods for each table (optimization for large schemas)\n const tableCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n tableCRUDs[tableSchema.name] = makeServerTableCRUD(tableSchema);\n }\n\n // Bind transaction context to the methods\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: dbTransaction,\n [serverSchemaSymbol]: serverSchema,\n };\n const boundCRUDs = recordProxy(tableCRUDs, tableCRUD =>\n mapValues(tableCRUD, method => method.bind(txHolder)),\n ) as unknown as SchemaCRUD<S>;\n\n // Return executor that dispatches to bound methods\n return (table: string, kind: CRUDKind, args: unknown) => {\n const tableCRUD = boundCRUDs[table as keyof S['tables']];\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return (tableCRUD as any)[kind](args);\n };\n}\n\n/**\n * Creates SQL-generating TableCRUD methods for a table.\n * Methods use `this` context to access transaction and server schema.\n */\nfunction makeServerTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO NOTHING`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const updatedEntries = nonPrimaryKeyEntries(value, schema);\n const conflictAction =\n updatedEntries.length === 0\n ? sql`DO NOTHING`\n : sql`DO UPDATE SET ${sql.join(\n updatedEntries.map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`;\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) ${conflictAction}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(\n nonPrimaryKeyEntries(value, schema).map(([name]) => name),\n schema,\n );\n if (targetedColumns.length === 0) {\n return;\n }\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction nonPrimaryKeyEntries(\n value: Record<string, unknown>,\n schema: TableSchema,\n) {\n return Object.entries(value).filter(\n ([name]) => !schema.primaryKey.includes(name),\n );\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"mappings":";;;;;;;;;;;;;;;;AA2DA,IAAM,iCAAN,cAA6C,kBAAkB;CAC7D;CACA;CACA;CAEA,uBAAgC;CAEhC,YACE,eACA,QACA,cACA;EACA,MAAM;EACN,KAAKA,iBAAiB;EACtB,KAAKC,UAAU;EACf,KAAKC,gBAAgB;CACvB;CAEA,YAAmB;EACjB,MAAM,IAAI,MAAM,iBAAiB;CACnC;CAEA,IAKE,OACA,UACiC;EACjC,MAAM,iBAAiB,iBAAiB,KAAK;EAC7C,OAAO,KAAKF,eAAe,SACzB,eAAe,KACf,eAAe,QACf,KAAKC,SACL,KAAKC,aACP;CACF;CAEA,UAA0B;EACxB,MAAM,IAAI,MAAM,mDAAmD;CACrE;CAEA,cAA8B;EAC5B,MAAM,IAAI,MAAM,uDAAuD;CACzE;AACF;AAEA,IAAa,kBAAb,MAG6D;CAC3D,WAAoB;CACpB,SAAkB;CAClB;CACA;CACA;CACA;;;;CAIA;CAEA;CACA;CAEA,YACE,eACA,UACA,YACA,QACA,QACA,cACA;EACA,KAAK,gBAAgB;EACrB,KAAK,WAAW;EAChB,KAAK,aAAa;EAClB,KAAK,SAAS;EACd,KAAKD,UAAU;EACf,KAAKC,gBAAgB;EAErB,MAAM,WAAW,IAAI,+BACnB,eACA,QACA,YACF;EACA,KAAK,QAAQ,sBAAsB,UAAU,MAAM;CACrD;CAEA,IACE,OACA,UACiC;EACjC,MAAM,iBAAiB,iBAAiB,KAAK;EAG7C,OAAO,KAAK,cAAc,SACxB,eAAe,KACf,eAAe,QACf,KAAKD,SACL,KAAKC,aACP;CACF;AACF;AAEA,IAAM,aAAa,OAAO;AAE1B,IAAM,qBAAqB,OAAO;;;;;;;;;;;AAiBlC,IAAa,qBAAb,MAAkD;CAChD;CACA;CACA;CAEA,YAAY,QAAW;EACrB,KAAKD,UAAU;EAEf,KAAKE,cAAc,CAAC;EACpB,KAAK,MAAM,eAAe,OAAO,OAAO,OAAO,MAAM,GACnD,KAAKA,YAAY,YAAY,QAAQ,oBAAoB,WAAW;CAExE;;;;CAKA,MAAMC,wBACJ,eACuB;EACvB,IAAI,CAAC,KAAKF,eACR,KAAKA,gBAAgB,MAAM,gBAAgB,eAAe,KAAKD,OAAO;EAExE,OAAO,KAAKC;CACd;;;;;CAMA,eACE,eACA,cACc;EACd,MAAM,WAAkC;IACrC,aAAa;IACb,qBAAqB;EACxB;EACA,MAAM,aAAa,YAAY,KAAKC,cAAa,cAC/C,UAAU,YAAW,WAAU,OAAO,KAAK,QAAQ,CAAC,CACtD;EAEA,QAAQ,OAAe,MAAgB,SAAkB;GAGvD,OAFkB,WAAW,OAEH,MAAM,IAAI;EACtC;CACF;;;;;CAMA,MAAM,kBACJ,eACA,UACA,YACkD;EAClD,MAAM,eAAe,MAAM,KAAKC,wBAAwB,aAAa;EACrE,MAAM,WAAW,KAAK,eAAe,eAAe,YAAY;EAEhE,OAAO,IAAI,gBACT,eACA,UACA,YAJa,sBAAsB,KAAKH,SAAS,QAKjD,GACA,KAAKA,SACL,YACF;CACF;AACF;;;;;;AA+BA,SAAgB,eACd,QAIuB;CACvB,QAAQ,eAAuC,iBAC7C,eACE,QACA,MACA,uBAAuB,QAAQ,eAAe,YAAY,CAC5D;AACJ;AAEA,SAAS,gBAAmD,OAAa;CACvE,MAAM,wBAAiD,CAAC;CACxD,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,KAAK,GAC3C,IAAI,QAAQ,KAAA,GACV,sBAAsB,OAAO;CAGjC,OAAO;AACT;;;;;;;;;AAUA,SAAS,uBACP,QACA,eACA,cACc;CAEd,MAAM,aAAqD,CAAC;CAC5D,KAAK,MAAM,eAAe,OAAO,OAAO,OAAO,MAAM,GACnD,WAAW,YAAY,QAAQ,oBAAoB,WAAW;CAIhE,MAAM,WAAkC;GACrC,aAAa;GACb,qBAAqB;CACxB;CACA,MAAM,aAAa,YAAY,aAAY,cACzC,UAAU,YAAW,WAAU,OAAO,KAAK,QAAQ,CAAC,CACtD;CAGA,QAAQ,OAAe,MAAgB,SAAkB;EAGvD,OAFkB,WAAW,OAEH,MAAM,IAAI;CACtC;AACF;;;;;AAMA,SAAS,oBAAoB,QAA6C;CACxE,OAAO;EACL,MAAM,OAAoC,OAAO;GAC/C,QAAQ,gBAAgB,KAAK;GAC7B,MAAM,oBAAoB,KAAK,oBAAoB,WAAW,MAAM;GAEpE,MAAM,kBAAkB,sBAAsB,OAAO,KAAK,KAAK,GAAG,MAAM;GACxE,MAAM,oBAAoB,sBACxB,OAAO,YACP,MACF;GAEA,MAAM,OAAO,wBACX,GAAG,eAAe,IAAI,MAAM,WAAW,MAAM,CAAC,EAAE,IAAI,IAAI,KACtD,gBAAgB,KAAK,GAAG,gBAAgB,IAAI,MAAM,UAAU,CAAC,GAC7D,GACF,EAAE,YAAY,IAAI,KAChB,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,KAAK,OAC/B,eAAe,GAAG,kBAAkB,cAAc,KAAK,MAAM,EAAE,CACjE,GACA,IACF,EAAE,iBAAiB,IAAI,KACrB,kBAAkB,KAAK,GAAG,gBAAgB,IAAI,MAAM,UAAU,CAAC,GAC/D,IACF,EAAE,aACJ;GAEA,MADW,KAAK,YACP,MAAM,KAAK,MAAM,KAAK,MAAM;EACvC;EACA,MAAM,OAAoC,OAAO;GAC/C,QAAQ,gBAAgB,KAAK;GAC7B,MAAM,oBAAoB,KAAK,oBAAoB,WAAW,MAAM;GACpE,MAAM,kBAAkB,sBAAsB,OAAO,KAAK,KAAK,GAAG,MAAM;GACxE,MAAM,oBAAoB,sBACxB,OAAO,YACP,MACF;GACA,MAAM,iBAAiB,qBAAqB,OAAO,MAAM;GACzD,MAAM,iBACJ,eAAe,WAAW,IACtB,GAAG,eACH,GAAG,iBAAiB,IAAI,KACtB,eAAe,KACZ,CAAC,KAAK,SACL,GAAG,GAAG,IAAI,MACR,OAAO,QAAQ,KAAK,cAAc,GACpC,EAAE,KAAK,eAAe,KAAK,kBAAkB,cAAc,KAAK,MAAM,EAAE,GAC5E,GACA,IACF;GACN,MAAM,OAAO,wBACX,GAAG,eAAe,IAAI,MAAM,WAAW,MAAM,CAAC,EAAE,IAAI,IAAI,KACtD,gBAAgB,KAAK,GAAG,gBAAgB,IAAI,MAAM,UAAU,CAAC,GAC7D,GACF,EAAE,YAAY,IAAI,KAChB,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,KAAK,SAC/B,eAAe,KAAK,kBAAkB,cAAc,KAAK,MAAM,EAAE,CACnE,GACA,IACF,EAAE,iBAAiB,IAAI,KACrB,kBAAkB,KAAK,GAAG,gBAAgB,IAAI,MAAM,UAAU,CAAC,GAC/D,IACF,EAAE,IAAI,gBACR;GAEA,MADW,KAAK,YACP,MAAM,KAAK,MAAM,KAAK,MAAM;EACvC;EACA,MAAM,OAAoC,OAAO;GAC/C,QAAQ,gBAAgB,KAAK;GAC7B,MAAM,oBAAoB,KAAK,oBAAoB,WAAW,MAAM;GACpE,MAAM,kBAAkB,sBACtB,qBAAqB,OAAO,MAAM,EAAE,KAAK,CAAC,UAAU,IAAI,GACxD,MACF;GACA,IAAI,gBAAgB,WAAW,GAC7B;GAEF,MAAM,OAAO,wBACX,GAAG,UAAU,IAAI,MAAM,WAAW,MAAM,CAAC,EAAE,OAAO,IAAI,KACpD,gBAAgB,KACb,CAAC,UAAU,gBACV,GAAG,GAAG,IAAI,MAAM,UAAU,EAAE,KAAK,eAAe,MAAM,WAAW,kBAAkB,WAAW,GAClG,GACA,IACF,EAAE,SAAS,iBAAiB,QAAQ,mBAAmB,KAAK,GAC9D;GAEA,MADW,KAAK,YACP,MAAM,KAAK,MAAM,KAAK,MAAM;EACvC;EACA,MAAM,OAAoC,OAAO;GAC/C,QAAQ,gBAAgB,KAAK;GAC7B,MAAM,oBAAoB,KAAK,oBAAoB,WAAW,MAAM;GACpE,MAAM,OAAO,wBACX,GAAG,eAAe,IAAI,MACpB,WAAW,MAAM,CACnB,EAAE,SAAS,iBAAiB,QAAQ,mBAAmB,KAAK,GAC9D;GAEA,MADW,KAAK,YACP,MAAM,KAAK,MAAM,KAAK,MAAM;EACvC;CACF;AACF;AAEA,SAAS,qBACP,OACA,QACA;CACA,OAAO,OAAO,QAAQ,KAAK,EAAE,QAC1B,CAAC,UAAU,CAAC,OAAO,WAAW,SAAS,IAAI,CAC9C;AACF;AAEA,SAAS,WAAW,GAAoD;CACtE,OAAO,EAAE,cAAc,EAAE;AAC3B;AAEA,SAAS,iBACP,QACA,mBACA,KACA;CACA,MAAM,aAAa,sBAAsB,OAAO,YAAY,MAAM;CAClE,OAAO,GAAG,GAAG,IAAI,KACf,WAAW,KACR,CAAC,UAAU,gBACV,GAAG,GAAG,IAAI,MAAM,UAAU,EAAE,KAAK,SAAS,IAAI,WAAW,kBAAkB,WAAW,GAC1F,GACA,OACF;AACF;AAEA,SAAS,sBACP,eACA,QAC0C;CAC1C,OAAO,cAAc,KACnB,SAAQ,CAAC,MAAM,cAAc,MAAM,MAAM,CAAC,CAC5C;AACF;AAEA,SAAS,cAAc,cAAsB,QAA6B;CACxE,MAAM,MAAM,OAAO,QAAQ;CAC3B,OACE,KACA,UAAU,aAAa,kDAAkD,OAAO,MAClF;CACA,OAAO,IAAI,cAAc;AAC3B;AAEA,SAAS,SAAS,OAAgB,oBAAwC;CACxE,OAAO,oBAAoB,oBAAoB,OAAO,OAAO,IAAI;AACnE;AAEA,SAAS,eACP,OACA,oBACA;CACA,OAAO,oBAAoB,oBAAoB,OAAO,OAAO,KAAK;AACpE"}
1
+ {"version":3,"file":"custom.js","names":["#dbTransaction","#schema","#serverSchema","#tableCRUDs"],"sources":["../../../../zero-server/src/custom.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {mapValues} from '../../shared/src/objects.ts';\nimport {recordProxy} from '../../shared/src/record-proxy.ts';\nimport {\n formatPgInternalConvert,\n sql,\n sqlConvertColumnArg,\n} from '../../z2s/src/sql.ts';\nimport type {TableSchema} from '../../zero-schema/src/table-schema.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n ServerColumnSchema,\n ServerSchema,\n ServerTableSchema,\n} from '../../zero-types/src/server-schema.ts';\nimport {\n type CRUDExecutor,\n type CRUDKind,\n makeCRUDMutate,\n makeTransactionMutate,\n type SchemaCRUD,\n type TableCRUD,\n type TransactionMutate,\n} from '../../zql/src/mutate/crud.ts';\nimport type {\n DBTransaction,\n MutateCRUD,\n Queryable,\n ServerTransaction,\n} from '../../zql/src/mutate/custom.ts';\nimport {createRunnableBuilder} from '../../zql/src/query/create-builder.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport type {ConditionalSchemaQuery} from '../../zql/src/query/schema-query.ts';\nimport {getServerSchema} from './schema.ts';\n\nexport type CustomMutatorDefs<TDBTransaction> = {\n [namespaceOrKey: string]:\n | CustomMutatorImpl<TDBTransaction>\n | CustomMutatorDefs<TDBTransaction>;\n};\n\nexport type CustomMutatorImpl<\n TDBTransaction,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n Context = unknown,\n> = (tx: TDBTransaction, args: TArgs, ctx: Context) => Promise<void>;\n\n/**\n * QueryDelegate implementation for server-side transactions.\n * Extends QueryDelegateBase to satisfy the QueryDelegate interface,\n * but overrides run() to execute against Postgres and throws on\n * preload()/materialize() which don't make sense server-side.\n */\nclass ServerTransactionQueryDelegate extends QueryDelegateBase {\n readonly #dbTransaction: DBTransaction<unknown>;\n readonly #schema: Schema;\n readonly #serverSchema: ServerSchema;\n\n readonly defaultQueryComplete = true;\n\n constructor(\n dbTransaction: DBTransaction<unknown>,\n schema: Schema,\n serverSchema: ServerSchema,\n ) {\n super();\n this.#dbTransaction = dbTransaction;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n }\n\n getSource(): never {\n throw new Error('not implemented');\n }\n\n override 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 const queryInternals = asQueryInternals(query);\n return this.#dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n\n override preload(): never {\n throw new Error('preload() is not supported in server transactions');\n }\n\n override materialize(): never {\n throw new Error('materialize() is not supported in server transactions');\n }\n}\n\nexport class TransactionImpl<\n TSchema extends Schema,\n TWrappedTransaction,\n> implements ServerTransaction<TSchema, TWrappedTransaction> {\n readonly location = 'server';\n readonly reason = 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n readonly clientID: string;\n readonly mutationID: number;\n readonly mutate: TransactionMutate<TSchema>;\n /**\n * @deprecated Use {@linkcode createBuilder} with `tx.run(zql.table.where(...))` instead.\n */\n readonly query: ConditionalSchemaQuery<TSchema>;\n\n readonly #schema: TSchema;\n readonly #serverSchema: ServerSchema;\n\n constructor(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n mutate: TransactionMutate<TSchema>,\n schema: TSchema,\n serverSchema: ServerSchema,\n ) {\n this.dbTransaction = dbTransaction;\n this.clientID = clientID;\n this.mutationID = mutationID;\n this.mutate = mutate;\n this.#schema = schema;\n this.#serverSchema = serverSchema;\n\n const delegate = new ServerTransactionQueryDelegate(\n dbTransaction,\n schema,\n serverSchema,\n );\n this.query = createRunnableBuilder(delegate, schema);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const queryInternals = asQueryInternals(query);\n\n // Execute the query using the database-specific executor\n return this.dbTransaction.runQuery<TReturn>(\n queryInternals.ast,\n queryInternals.format,\n this.#schema,\n this.#serverSchema,\n );\n }\n}\n\nconst dbTxSymbol = Symbol();\n\nconst serverSchemaSymbol = Symbol();\n\ntype WithHiddenTxAndSchema = {\n [dbTxSymbol]: DBTransaction<unknown>;\n [serverSchemaSymbol]: ServerSchema;\n};\n\n/**\n * Factory for creating MutateCRUD instances efficiently.\n *\n * Pre-creates the SQL-generating TableCRUD methods once from the schema,\n * caches the serverSchema after first fetch, and only binds the transaction\n * at transaction time.\n *\n * Use this when you need to create many transactions and want to avoid\n * the overhead of re-creating CRUD methods for each one.\n */\nexport class CRUDMutatorFactory<S extends Schema> {\n readonly #schema: S;\n readonly #tableCRUDs: Record<string, TableCRUD<TableSchema>>;\n // The in-flight or resolved fetch is cached (not just the result) so that\n // concurrent cold callers share a single catalog query.\n #serverSchema: Promise<ServerSchema> | undefined;\n\n constructor(schema: S) {\n this.#schema = schema;\n // Pre-create TableCRUD methods for each table once\n this.#tableCRUDs = {};\n for (const tableSchema of Object.values(schema.tables)) {\n this.#tableCRUDs[tableSchema.name] = makeServerTableCRUD(tableSchema);\n }\n }\n\n /**\n * Gets the cached serverSchema, or fetches and caches it on first call.\n */\n getOrFetchServerSchema(queryable: Queryable): Promise<ServerSchema> {\n if (!this.#serverSchema) {\n this.#serverSchema = getServerSchema(queryable, this.#schema).catch(e => {\n // Don't poison the cache with a transient failure.\n this.#serverSchema = undefined;\n throw e;\n });\n }\n return this.#serverSchema;\n }\n\n /**\n * Creates a CRUDExecutor bound to the given transaction and serverSchema.\n * Uses the pre-created TableCRUD methods from construction time.\n */\n createExecutor(\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n ): CRUDExecutor {\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: dbTransaction,\n [serverSchemaSymbol]: serverSchema,\n };\n const boundCRUDs = recordProxy(this.#tableCRUDs, tableCRUD =>\n mapValues(tableCRUD, method => method.bind(txHolder)),\n ) as unknown as SchemaCRUD<S>;\n\n return (table: string, kind: CRUDKind, args: unknown) => {\n const tableCRUD = boundCRUDs[table as keyof S['tables']];\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return (tableCRUD as any)[kind](args);\n };\n }\n\n /**\n * Creates a full ServerTransaction.\n * Fetches/caches serverSchema automatically.\n */\n async createTransaction<TWrappedTransaction>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n ): Promise<TransactionImpl<S, TWrappedTransaction>> {\n const serverSchema = await this.getOrFetchServerSchema(dbTransaction);\n const executor = this.createExecutor(dbTransaction, serverSchema);\n const mutate = makeTransactionMutate(this.#schema, executor);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate,\n this.#schema,\n serverSchema,\n );\n }\n}\n\nexport async function makeServerTransaction<\n TSchema extends Schema,\n TWrappedTransaction,\n>(\n dbTransaction: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n schema: TSchema,\n) {\n const serverSchema = await getServerSchema(dbTransaction, schema);\n // Use the internal executor and shared function directly,\n // bypassing the validation in makeMutateCRUD/makeSchemaCRUD\n const executor = makeServerCRUDExecutor(schema, dbTransaction, serverSchema);\n const mutate = makeTransactionMutate(schema, executor);\n return new TransactionImpl(\n dbTransaction,\n clientID,\n mutationID,\n mutate,\n schema,\n serverSchema,\n );\n}\n\n/**\n * @deprecated Use transactions instead.\n *\n * Returns a curried function for backwards compatibility.\n */\nexport function makeSchemaCRUD<S extends Schema>(\n schema: S,\n): (\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n) => MutateCRUD<S, true> {\n return (dbTransaction: DBTransaction<unknown>, serverSchema: ServerSchema) =>\n makeCRUDMutate(\n schema,\n true,\n makeServerCRUDExecutor(schema, dbTransaction, serverSchema),\n );\n}\n\nfunction removeUndefined<T extends Record<string, unknown>>(value: T): T {\n const valueWithoutUndefined: Record<string, unknown> = {};\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n valueWithoutUndefined[key] = val;\n }\n }\n return valueWithoutUndefined as T;\n}\n\n/**\n * Creates a CRUDExecutor for server-side SQL execution.\n *\n * For users with very large schemas it is expensive to re-create\n * all the CRUD mutators for each transaction. Instead, we create\n * the SQL-generating methods once up-front and then bind them to\n * the transaction as requested.\n */\nfunction makeServerCRUDExecutor<S extends Schema>(\n schema: S,\n dbTransaction: DBTransaction<unknown>,\n serverSchema: ServerSchema,\n): CRUDExecutor {\n // Pre-create TableCRUD methods for each table (optimization for large schemas)\n const tableCRUDs: Record<string, TableCRUD<TableSchema>> = {};\n for (const tableSchema of Object.values(schema.tables)) {\n tableCRUDs[tableSchema.name] = makeServerTableCRUD(tableSchema);\n }\n\n // Bind transaction context to the methods\n const txHolder: WithHiddenTxAndSchema = {\n [dbTxSymbol]: dbTransaction,\n [serverSchemaSymbol]: serverSchema,\n };\n const boundCRUDs = recordProxy(tableCRUDs, tableCRUD =>\n mapValues(tableCRUD, method => method.bind(txHolder)),\n ) as unknown as SchemaCRUD<S>;\n\n // Return executor that dispatches to bound methods\n return (table: string, kind: CRUDKind, args: unknown) => {\n const tableCRUD = boundCRUDs[table as keyof S['tables']];\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return (tableCRUD as any)[kind](args);\n };\n}\n\n/**\n * Creates SQL-generating TableCRUD methods for a table.\n * Methods use `this` context to access transaction and server schema.\n */\nfunction makeServerTableCRUD(schema: TableSchema): TableCRUD<TableSchema> {\n return {\n async insert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, v]) =>\n sqlInsertValue(v, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) DO NOTHING`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async upsert(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(Object.keys(value), schema);\n const primaryKeyColumns = origAndServerNamesFor(\n schema.primaryKey,\n schema,\n );\n const updatedEntries = nonPrimaryKeyEntries(value, schema);\n const conflictAction =\n updatedEntries.length === 0\n ? sql`DO NOTHING`\n : sql`DO UPDATE SET ${sql.join(\n updatedEntries.map(\n ([col, val]) =>\n sql`${sql.ident(\n schema.columns[col].serverName ?? col,\n )} = ${sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)])}`,\n ),\n ', ',\n )}`;\n const stmt = formatPgInternalConvert(\n sql`INSERT INTO ${sql.ident(serverName(schema))} (${sql.join(\n targetedColumns.map(([, serverName]) => sql.ident(serverName)),\n ',',\n )}) VALUES (${sql.join(\n Object.entries(value).map(([col, val]) =>\n sqlInsertValue(val, serverTableSchema[serverNameFor(col, schema)]),\n ),\n ', ',\n )}) ON CONFLICT (${sql.join(\n primaryKeyColumns.map(([, serverName]) => sql.ident(serverName)),\n ', ',\n )}) ${conflictAction}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async update(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const targetedColumns = origAndServerNamesFor(\n nonPrimaryKeyEntries(value, schema).map(([name]) => name),\n schema,\n );\n if (targetedColumns.length === 0) {\n return;\n }\n const stmt = formatPgInternalConvert(\n sql`UPDATE ${sql.ident(serverName(schema))} SET ${sql.join(\n targetedColumns.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlInsertValue(value[origName], serverTableSchema[serverName])}`,\n ),\n ', ',\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n async delete(this: WithHiddenTxAndSchema, value) {\n value = removeUndefined(value);\n const serverTableSchema = this[serverSchemaSymbol][serverName(schema)];\n const stmt = formatPgInternalConvert(\n sql`DELETE FROM ${sql.ident(\n serverName(schema),\n )} WHERE ${primaryKeyClause(schema, serverTableSchema, value)}`,\n );\n const tx = this[dbTxSymbol];\n await tx.query(stmt.text, stmt.values);\n },\n };\n}\n\nfunction nonPrimaryKeyEntries(\n value: Record<string, unknown>,\n schema: TableSchema,\n) {\n return Object.entries(value).filter(\n ([name]) => !schema.primaryKey.includes(name),\n );\n}\n\nfunction serverName(x: {name: string; serverName?: string | undefined}) {\n return x.serverName ?? x.name;\n}\n\nfunction primaryKeyClause(\n schema: TableSchema,\n serverTableSchema: ServerTableSchema,\n row: Record<string, unknown>,\n) {\n const primaryKey = origAndServerNamesFor(schema.primaryKey, schema);\n return sql`${sql.join(\n primaryKey.map(\n ([origName, serverName]) =>\n sql`${sql.ident(serverName)} = ${sqlValue(row[origName], serverTableSchema[serverName])}`,\n ),\n ' AND ',\n )}`;\n}\n\nfunction origAndServerNamesFor(\n originalNames: readonly string[],\n schema: TableSchema,\n): [origName: string, serverName: string][] {\n return originalNames.map(\n name => [name, serverNameFor(name, schema)] as const,\n );\n}\n\nfunction serverNameFor(originalName: string, schema: TableSchema): string {\n const col = schema.columns[originalName];\n assert(\n col,\n `Column ${originalName} was not found in the Zero schema for the table ${schema.name}`,\n );\n return col.serverName ?? originalName;\n}\n\nfunction sqlValue(value: unknown, serverColumnSchema: ServerColumnSchema) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, true);\n}\n\nfunction sqlInsertValue(\n value: unknown,\n serverColumnSchema: ServerColumnSchema,\n) {\n return sqlConvertColumnArg(serverColumnSchema, value, false, false);\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ export { ApplicationError, isApplicationError, type ApplicationErrorOptions, } f
2
2
  export type { MutateResponse } from '../../zero-protocol/src/mutate-server.ts';
3
3
  export type { QueryResponse } from '../../zero-protocol/src/query-server.ts';
4
4
  export type { ServerColumnSchema, ServerSchema, ServerTableSchema, } from '../../zero-types/src/server-schema.ts';
5
- export type { AnyTransaction, ClientTransaction, DBConnection, DBTransaction, Location, MutateCRUD, Row, ServerTransaction, Transaction, TransactionBase, TransactionReason, } from '../../zql/src/mutate/custom.ts';
5
+ export type { AnyTransaction, ClientTransaction, DBConnection, DBTransaction, Location, MutateCRUD, Queryable, Row, ServerTransaction, Transaction, TransactionBase, TransactionReason, } from '../../zql/src/mutate/custom.ts';
6
6
  export { CRUDMutatorFactory, makeSchemaCRUD, type CustomMutatorDefs, } from './custom.ts';
7
7
  export { executePostgresQuery } from './pg-query-executor.ts';
8
8
  export { getMutation, handleMutateRequest, handleMutationRequest, OutOfOrderMutation, type Database, type ExtractTransactionType, type MutateRequestHandler, type Params, type Parsed, type TransactFn, type TransactFnCallback, type TransactionProviderHooks, type TransactionProviderInput, } from './process-mutations.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,8CAA8C,CAAC;AACtD,YAAY,EAAC,cAAc,EAAC,MAAM,0CAA0C,CAAC;AAC7E,YAAY,EAAC,aAAa,EAAC,MAAM,yCAAyC,CAAC;AAC3E,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACV,GAAG,EACH,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,uBAAuB,GAC7B,MAAM,8CAA8C,CAAC;AACtD,YAAY,EAAC,cAAc,EAAC,MAAM,0CAA0C,CAAC;AAC7E,YAAY,EAAC,aAAa,EAAC,MAAM,yCAAyC,CAAC;AAC3E,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,GAClB,MAAM,uCAAuC,CAAC;AAC/C,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,UAAU,EACV,SAAS,EACT,GAAG,EACH,iBAAiB,EACjB,WAAW,EACX,eAAe,EACf,iBAAiB,GAClB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,KAAK,iBAAiB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,oBAAoB,EAAC,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,QAAQ,EACb,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EACzB,KAAK,MAAM,EACX,KAAK,MAAM,EACX,KAAK,UAAU,EACf,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAC,aAAa,EAAC,MAAM,qBAAqB,CAAC;AAClD,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC5B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC"}
@@ -2,10 +2,10 @@ import type { AST } from '../../zero-protocol/src/ast.ts';
2
2
  import type { Format } from '../../zero-types/src/format.ts';
3
3
  import type { Schema } from '../../zero-types/src/schema.ts';
4
4
  import type { ServerSchema } from '../../zero-types/src/server-schema.ts';
5
- import type { DBTransaction } from '../../zql/src/mutate/custom.ts';
5
+ import type { Queryable } from '../../zql/src/mutate/custom.ts';
6
6
  import type { HumanReadable } from '../../zql/src/query/query.ts';
7
7
  /**
8
8
  * Executes a query AST against a PostgreSQL database.
9
9
  */
10
- export declare function executePostgresQuery<TReturn>(dbTransaction: DBTransaction<unknown>, ast: AST, format: Format, schema: Schema, serverSchema: ServerSchema): Promise<HumanReadable<TReturn>>;
10
+ export declare function executePostgresQuery<TReturn>(queryable: Queryable, ast: AST, format: Format, schema: Schema, serverSchema: ServerSchema): Promise<HumanReadable<TReturn>>;
11
11
  //# sourceMappingURL=pg-query-executor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pg-query-executor.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/pg-query-executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAEhE;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAChD,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,EACrC,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAmBjC"}
1
+ {"version":3,"file":"pg-query-executor.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/pg-query-executor.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,gCAAgC,CAAC;AACxD,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gCAAgC,CAAC;AAC9D,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAEhE;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAChD,SAAS,EAAE,SAAS,EACpB,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAmBjC"}
@@ -4,9 +4,9 @@ import { compile, extractZqlResult } from "../../z2s/src/compiler.js";
4
4
  /**
5
5
  * Executes a query AST against a PostgreSQL database.
6
6
  */
7
- async function executePostgresQuery(dbTransaction, ast, format, schema, serverSchema) {
7
+ async function executePostgresQuery(queryable, ast, format, schema, serverSchema) {
8
8
  const sqlQuery = formatPgInternalConvert(compile(serverSchema, schema, ast, format));
9
- const pgIterableResult = await dbTransaction.query(sqlQuery.text, sqlQuery.values);
9
+ const pgIterableResult = await queryable.query(sqlQuery.text, sqlQuery.values);
10
10
  const pgArrayResult = Array.isArray(pgIterableResult) ? pgIterableResult : [...pgIterableResult];
11
11
  if (pgArrayResult.length === 0 && format.singular) return;
12
12
  return extractZqlResult(pgArrayResult);
@@ -1 +1 @@
1
- {"version":3,"file":"pg-query-executor.js","names":[],"sources":["../../../../zero-server/src/pg-query-executor.ts"],"sourcesContent":["import {compile, extractZqlResult} from '../../z2s/src/compiler.ts';\nimport {formatPgInternalConvert} from '../../z2s/src/sql.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport type {Format} from '../../zero-types/src/format.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../zero-types/src/server-schema.ts';\nimport type {DBTransaction} from '../../zql/src/mutate/custom.ts';\nimport type {HumanReadable} from '../../zql/src/query/query.ts';\n\n/**\n * Executes a query AST against a PostgreSQL database.\n */\nexport async function executePostgresQuery<TReturn>(\n dbTransaction: DBTransaction<unknown>,\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n): Promise<HumanReadable<TReturn>> {\n const sqlQuery = formatPgInternalConvert(\n compile(serverSchema, schema, ast, format),\n );\n\n const pgIterableResult = await dbTransaction.query(\n sqlQuery.text,\n sqlQuery.values,\n );\n\n const pgArrayResult = Array.isArray(pgIterableResult)\n ? pgIterableResult\n : [...pgIterableResult];\n\n if (pgArrayResult.length === 0 && format.singular) {\n return undefined as unknown as HumanReadable<TReturn>;\n }\n\n return extractZqlResult(pgArrayResult) as HumanReadable<TReturn>;\n}\n"],"mappings":";;;;;;AAYA,eAAsB,qBACpB,eACA,KACA,QACA,QACA,cACiC;CACjC,MAAM,WAAW,wBACf,QAAQ,cAAc,QAAQ,KAAK,MAAM,CAC3C;CAEA,MAAM,mBAAmB,MAAM,cAAc,MAC3C,SAAS,MACT,SAAS,MACX;CAEA,MAAM,gBAAgB,MAAM,QAAQ,gBAAgB,IAChD,mBACA,CAAC,GAAG,gBAAgB;CAExB,IAAI,cAAc,WAAW,KAAK,OAAO,UACvC;CAGF,OAAO,iBAAiB,aAAa;AACvC"}
1
+ {"version":3,"file":"pg-query-executor.js","names":[],"sources":["../../../../zero-server/src/pg-query-executor.ts"],"sourcesContent":["import {compile, extractZqlResult} from '../../z2s/src/compiler.ts';\nimport {formatPgInternalConvert} from '../../z2s/src/sql.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport type {Format} from '../../zero-types/src/format.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../zero-types/src/server-schema.ts';\nimport type {Queryable} from '../../zql/src/mutate/custom.ts';\nimport type {HumanReadable} from '../../zql/src/query/query.ts';\n\n/**\n * Executes a query AST against a PostgreSQL database.\n */\nexport async function executePostgresQuery<TReturn>(\n queryable: Queryable,\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n): Promise<HumanReadable<TReturn>> {\n const sqlQuery = formatPgInternalConvert(\n compile(serverSchema, schema, ast, format),\n );\n\n const pgIterableResult = await queryable.query(\n sqlQuery.text,\n sqlQuery.values,\n );\n\n const pgArrayResult = Array.isArray(pgIterableResult)\n ? pgIterableResult\n : [...pgIterableResult];\n\n if (pgArrayResult.length === 0 && format.singular) {\n return undefined as unknown as HumanReadable<TReturn>;\n }\n\n return extractZqlResult(pgArrayResult) as HumanReadable<TReturn>;\n}\n"],"mappings":";;;;;;AAYA,eAAsB,qBACpB,WACA,KACA,QACA,QACA,cACiC;CACjC,MAAM,WAAW,wBACf,QAAQ,cAAc,QAAQ,KAAK,MAAM,CAC3C;CAEA,MAAM,mBAAmB,MAAM,UAAU,MACvC,SAAS,MACT,SAAS,MACX;CAEA,MAAM,gBAAgB,MAAM,QAAQ,gBAAgB,IAChD,mBACA,CAAC,GAAG,gBAAgB;CAExB,IAAI,cAAc,WAAW,KAAK,OAAO,UACvC;CAGF,OAAO,iBAAiB,aAAa;AACvC"}
@@ -1,7 +1,7 @@
1
1
  import type { Schema } from '../../zero-types/src/schema.ts';
2
2
  import type { ServerSchema } from '../../zero-types/src/server-schema.ts';
3
- import type { DBTransaction } from '../../zql/src/mutate/custom.ts';
4
- export declare function getServerSchema<S extends Schema>(dbTransaction: DBTransaction<unknown>, schema: S): Promise<ServerSchema>;
3
+ import type { Queryable } from '../../zql/src/mutate/custom.ts';
4
+ export declare function getServerSchema<S extends Schema>(queryable: Queryable, schema: S): Promise<ServerSchema>;
5
5
  /**
6
6
  * The query behind {@linkcode getServerSchema}, exported so that it can be
7
7
  * diffed against the `information_schema` query it replaced.
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/schema.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,gCAAgC,CAAC;AAkBlE,wBAAsB,eAAe,CAAC,CAAC,SAAS,MAAM,EACpD,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,EACrC,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,YAAY,CAAC,CAgFvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GACvD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAC,CAiFnC;AAwCD,MAAM,MAAM,0BAA0B,GAClC;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,GACD;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,0BAA0B,EAAE,CAkD9B"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/schema.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uCAAuC,CAAC;AACxE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,gCAAgC,CAAC;AAkB9D,wBAAsB,eAAe,CAAC,CAAC,SAAS,MAAM,EACpD,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,CAAC,GACR,OAAO,CAAC,YAAY,CAAC,CAgFvB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,gBAAgB,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GACvD;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,EAAE,CAAA;CAAC,CAiFnC;AAwCD,MAAM,MAAM,0BAA0B,GAClC;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,GACD;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GACD;IACE,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEN,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,0BAA0B,EAAE,CAkD9B"}
@@ -3,7 +3,7 @@ import { must } from "../../shared/src/must.js";
3
3
  import { dataTypeToZqlValueType } from "../../zero-cache/src/types/pg-data-type.js";
4
4
  import { formatPg, sql } from "../../z2s/src/sql.js";
5
5
  //#region ../zero-server/src/schema.ts
6
- async function getServerSchema(dbTransaction, schema) {
6
+ async function getServerSchema(queryable, schema) {
7
7
  const schemaTablePairs = Object.values(schema.tables).map(({ name, serverName }) => {
8
8
  let schemaTablePair = ["public", serverName ?? name];
9
9
  if (serverName) {
@@ -14,7 +14,7 @@ async function getServerSchema(dbTransaction, schema) {
14
14
  });
15
15
  if (schemaTablePairs.length === 0) return {};
16
16
  const { text, values } = serverSchemaQuery(schemaTablePairs);
17
- const results = await dbTransaction.query(text, values);
17
+ const results = await queryable.query(text, values);
18
18
  const serverSchema = {};
19
19
  for (const row of results) {
20
20
  const tableName = row.schema === "public" ? row.table : `${row.schema}.${row.table}`;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","names":[],"sources":["../../../../zero-server/src/schema.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport type {Enum} from '../../shared/src/enum.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {formatPg, sql} from '../../z2s/src/sql.ts';\nimport * as PostgresTypeClass from '../../zero-cache/src/db/postgres-type-class-enum.ts';\nimport {dataTypeToZqlValueType} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../zero-types/src/server-schema.ts';\nimport type {DBTransaction} from '../../zql/src/mutate/custom.ts';\n\ntype PostgresTypeClass = Enum<typeof PostgresTypeClass>;\n\ntype ServerSchemaRow = {\n schema: string;\n table: string;\n column: string;\n dataType: string;\n length: string | null;\n precision: string | null;\n scale: string | null;\n typtype: PostgresTypeClass;\n typename: string;\n elemTyptype: PostgresTypeClass | null;\n elemTypname: string | null;\n};\n\nexport async function getServerSchema<S extends Schema>(\n dbTransaction: DBTransaction<unknown>,\n schema: S,\n): Promise<ServerSchema> {\n const schemaTablePairs: [string, string][] = Object.values(schema.tables).map(\n ({name, serverName}) => {\n let schemaTablePair: [string, string] = ['public', serverName ?? name];\n if (serverName) {\n const firstPeriod = serverName.indexOf('.');\n if (firstPeriod > -1) {\n schemaTablePair = [\n serverName.substring(0, firstPeriod),\n serverName.substring(firstPeriod + 1, serverName.length),\n ];\n }\n }\n return schemaTablePair;\n },\n );\n\n if (schemaTablePairs.length === 0) {\n return {}; // No pairs to query for\n }\n\n const {text, values} = serverSchemaQuery(schemaTablePairs);\n const results: Iterable<ServerSchemaRow> = (await dbTransaction.query(\n text,\n values,\n )) as Iterable<ServerSchemaRow>;\n\n const serverSchema: ServerSchema = {};\n\n for (const row of results) {\n const tableName =\n row.schema === 'public' ? row.table : `${row.schema}.${row.table}`;\n let tableSchema = serverSchema[tableName];\n if (!tableSchema) {\n tableSchema = {};\n serverSchema[tableName] = tableSchema;\n }\n const isArray = row.elemTyptype !== null;\n const isEnum = (row.elemTyptype ?? row.typtype) === PostgresTypeClass.Enum;\n let type = row.dataType.toLowerCase();\n if (isArray) {\n type = must(\n row.elemTypname,\n `Array column \"${row.column}\" in table \"${tableName}\" is missing element type name`,\n );\n } else if (isEnum) {\n type = row.typename;\n } else if (\n type === 'user-defined' &&\n dataTypeToZqlValueType(row.typename, false, false) !== undefined\n ) {\n type = row.typename;\n }\n if (\n (type === 'bpchar' ||\n type === 'character' ||\n type === 'character varying' ||\n type === 'varchar') &&\n row.length\n ) {\n type = `${type}(${row.length})`;\n }\n if (\n (type === 'numeric' || type === 'decimal') &&\n row.precision !== null &&\n row.scale !== null\n ) {\n type = `${type}(${row.precision}, ${row.scale})`;\n }\n tableSchema[row.column] = {\n type,\n isEnum,\n isArray,\n };\n }\n\n const errors = checkSchemasAreCompatible(schema, serverSchema);\n assert(errors.length === 0, () => makeSchemaIncompatibleErrorMessage(errors));\n\n return serverSchema;\n}\n\n/**\n * The query behind {@linkcode getServerSchema}, exported so that it can be\n * diffed against the `information_schema` query it replaced.\n */\nexport function serverSchemaQuery(\n schemaTablePairs: readonly (readonly [string, string])[],\n): {text: string; values: unknown[]} {\n // Cast all inputs to text and all outputs to text to avoid\n // any conversions customer's DBTransaction impl has on other types.\n const inClause = sql.join(\n schemaTablePairs.map(\n ([schema, table]) => sql`(${schema}::text, ${table}::text)`,\n ),\n ',',\n );\n // Read pg_catalog directly instead of information_schema.columns. The view\n // derives every column it returns through the information_schema._pg_*\n // functions and a per column privilege check, which is several times slower\n // than the query below. Server processes run this on the first transaction\n // they serve, so serverless deployments pay for it on every cold start.\n //\n // The expressions below reproduce the parts of the view's definition that we\n // select, down to the int4 wire types of length, precision and scale: the\n // _pg_char_max_length / _pg_numeric_precision / _pg_numeric_scale arithmetic,\n // the single level domain unwrap that data_type and udt_name perform (`ut`),\n // and the view's own relkind, attnum and privilege filters. pg_type is joined\n // by OID rather than by udt_name, which additionally avoids duplicate rows\n // when two schemas declare a type with the same name. The types those\n // functions special case are named through regtype, which the parser resolves\n // while planning.\n const query = sql`\n SELECT\n n.nspname::text AS schema,\n cl.relname::text AS table,\n a.attname::text AS column,\n CASE\n WHEN ut.typelem <> 0 AND ut.typlen = -1 THEN 'ARRAY'\n WHEN nut.nspname = 'pg_catalog' THEN pg_catalog.format_type(ut.oid, NULL)\n ELSE 'USER-DEFINED'\n END::text AS \"dataType\",\n CASE\n WHEN tm.typmod = -1 THEN NULL\n WHEN ut.oid IN ('pg_catalog.bpchar'::regtype, 'pg_catalog.varchar'::regtype) THEN tm.typmod - 4\n WHEN ut.oid IN ('pg_catalog.bit'::regtype, 'pg_catalog.varbit'::regtype) THEN tm.typmod\n END AS length,\n CASE ut.oid\n WHEN 'pg_catalog.int2'::regtype THEN 16\n WHEN 'pg_catalog.int4'::regtype THEN 32\n WHEN 'pg_catalog.int8'::regtype THEN 64\n WHEN 'pg_catalog.float4'::regtype THEN 24\n WHEN 'pg_catalog.float8'::regtype THEN 53\n WHEN 'pg_catalog.numeric'::regtype THEN CASE WHEN tm.typmod = -1 THEN NULL ELSE ((tm.typmod - 4) >> 16) & 65535 END\n END AS precision,\n CASE\n WHEN ut.oid IN ('pg_catalog.int2'::regtype, 'pg_catalog.int4'::regtype, 'pg_catalog.int8'::regtype) THEN 0\n WHEN ut.oid = 'pg_catalog.numeric'::regtype AND tm.typmod <> -1 THEN (tm.typmod - 4) & 65535\n END AS scale,\n ut.typtype::text AS typtype,\n ut.typname::text AS typename,\n CASE WHEN ut.typelem <> 0 THEN et.typtype::text ELSE NULL END AS \"elemTyptype\",\n CASE WHEN ut.typelem <> 0 THEN et.typname::text ELSE NULL END AS \"elemTypname\"\n FROM\n pg_catalog.pg_attribute a\n JOIN\n pg_catalog.pg_class cl ON cl.oid = a.attrelid\n JOIN\n pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN\n pg_catalog.pg_type t ON t.oid = a.atttypid\n JOIN\n pg_catalog.pg_type ut ON ut.oid = CASE WHEN t.typtype = 'd' THEN t.typbasetype ELSE t.oid END\n JOIN\n pg_catalog.pg_namespace nut ON nut.oid = ut.typnamespace\n LEFT JOIN\n pg_catalog.pg_type et ON et.oid = ut.typelem\n CROSS JOIN LATERAL\n (SELECT CASE WHEN t.typtype = 'd' THEN t.typtypmod ELSE a.atttypmod END AS typmod) tm\n WHERE\n a.attnum > 0\n AND NOT a.attisdropped\n AND cl.relkind IN ('r', 'v', 'f', 'p')\n AND NOT pg_catalog.pg_is_other_temp_schema(n.oid)\n AND (pg_catalog.pg_has_role(cl.relowner, 'USAGE')\n OR pg_catalog.has_column_privilege(cl.oid, a.attnum, 'SELECT, INSERT, UPDATE, REFERENCES'))\n AND (n.nspname, cl.relname) IN (${inClause})\n `;\n return formatPg(query);\n}\n\nfunction makeSchemaIncompatibleErrorMessage(\n errors: SchemaIncompatibilityError[],\n) {\n if (errors.length === 0) {\n return 'No schema incompatibilities found.';\n }\n\n const messages: string[] = [];\n\n for (const error of errors) {\n switch (error.type) {\n case 'missingTable':\n messages.push(\n `Table \"${error.table}\" is defined in your zero schema but does not exist in the database.`,\n );\n break;\n case 'missingColumn':\n messages.push(\n `Column \"${error.column}\" in table \"${error.table}\" is defined in your zero schema but does not exist in the database.`,\n );\n break;\n case 'typeError':\n messages.push(\n `Type mismatch for column \"${error.column}\" in table \"${error.table}\": ${error.requiredType === undefined ? `${error.pgType} is currently unsupported in Zero. Please file a bug at https://bugs.rocicorp.dev/` : `${error.pgType} should be mapped to ${error.requiredType} in Zero not ${error.declaredType}.`}`,\n );\n break;\n }\n }\n\n return [\n 'Schema incompatibility detected between your zero schema definition and the database:',\n '',\n ...messages.map(msg => ` - ${msg}`),\n '',\n 'Please update your schema definition to match the database or migrate your database to match the schema.',\n ].join('\\n');\n}\n\nexport type SchemaIncompatibilityError =\n | {\n type: 'typeError';\n table: string;\n column: string;\n pgType: string;\n declaredType: string;\n requiredType: string | undefined;\n }\n | {\n type: 'missingColumn';\n table: string;\n column: string;\n }\n | {\n type: 'missingTable';\n table: string;\n };\n\nexport function checkSchemasAreCompatible(\n schema: Schema,\n serverSchema: ServerSchema,\n): SchemaIncompatibilityError[] {\n const errors: SchemaIncompatibilityError[] = [];\n // Check that all tables in schema exist in serverSchema\n for (const table of Object.values(schema.tables)) {\n const serverTableName = table.serverName ?? table.name;\n\n if (!serverSchema[serverTableName]) {\n errors.push({\n type: 'missingTable',\n table: serverTableName,\n });\n continue;\n }\n\n // Check that all columns in the table exist in serverSchema\n for (const [columnName, column] of Object.entries(table.columns)) {\n const serverColumnName = column.serverName ?? columnName;\n\n if (!serverSchema[serverTableName][serverColumnName]) {\n errors.push({\n type: 'missingColumn',\n table: serverTableName,\n column: serverColumnName,\n });\n continue;\n }\n\n // Check type compatibility\n const serverColumn = serverSchema[serverTableName][serverColumnName];\n const declaredType = column.type;\n const pgType = serverColumn.type;\n const requiredType = dataTypeToZqlValueType(\n pgType,\n serverColumn.isEnum,\n serverColumn.isArray,\n );\n if (requiredType !== declaredType) {\n errors.push({\n type: 'typeError',\n table: serverTableName,\n column: serverColumnName,\n pgType,\n declaredType,\n requiredType,\n });\n }\n }\n }\n\n return errors;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"schema.js","names":[],"sources":["../../../../zero-server/src/schema.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport type {Enum} from '../../shared/src/enum.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {formatPg, sql} from '../../z2s/src/sql.ts';\nimport * as PostgresTypeClass from '../../zero-cache/src/db/postgres-type-class-enum.ts';\nimport {dataTypeToZqlValueType} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {ServerSchema} from '../../zero-types/src/server-schema.ts';\nimport type {Queryable} from '../../zql/src/mutate/custom.ts';\n\ntype PostgresTypeClass = Enum<typeof PostgresTypeClass>;\n\ntype ServerSchemaRow = {\n schema: string;\n table: string;\n column: string;\n dataType: string;\n length: string | null;\n precision: string | null;\n scale: string | null;\n typtype: PostgresTypeClass;\n typename: string;\n elemTyptype: PostgresTypeClass | null;\n elemTypname: string | null;\n};\n\nexport async function getServerSchema<S extends Schema>(\n queryable: Queryable,\n schema: S,\n): Promise<ServerSchema> {\n const schemaTablePairs: [string, string][] = Object.values(schema.tables).map(\n ({name, serverName}) => {\n let schemaTablePair: [string, string] = ['public', serverName ?? name];\n if (serverName) {\n const firstPeriod = serverName.indexOf('.');\n if (firstPeriod > -1) {\n schemaTablePair = [\n serverName.substring(0, firstPeriod),\n serverName.substring(firstPeriod + 1, serverName.length),\n ];\n }\n }\n return schemaTablePair;\n },\n );\n\n if (schemaTablePairs.length === 0) {\n return {}; // No pairs to query for\n }\n\n const {text, values} = serverSchemaQuery(schemaTablePairs);\n const results: Iterable<ServerSchemaRow> = (await queryable.query(\n text,\n values,\n )) as Iterable<ServerSchemaRow>;\n\n const serverSchema: ServerSchema = {};\n\n for (const row of results) {\n const tableName =\n row.schema === 'public' ? row.table : `${row.schema}.${row.table}`;\n let tableSchema = serverSchema[tableName];\n if (!tableSchema) {\n tableSchema = {};\n serverSchema[tableName] = tableSchema;\n }\n const isArray = row.elemTyptype !== null;\n const isEnum = (row.elemTyptype ?? row.typtype) === PostgresTypeClass.Enum;\n let type = row.dataType.toLowerCase();\n if (isArray) {\n type = must(\n row.elemTypname,\n `Array column \"${row.column}\" in table \"${tableName}\" is missing element type name`,\n );\n } else if (isEnum) {\n type = row.typename;\n } else if (\n type === 'user-defined' &&\n dataTypeToZqlValueType(row.typename, false, false) !== undefined\n ) {\n type = row.typename;\n }\n if (\n (type === 'bpchar' ||\n type === 'character' ||\n type === 'character varying' ||\n type === 'varchar') &&\n row.length\n ) {\n type = `${type}(${row.length})`;\n }\n if (\n (type === 'numeric' || type === 'decimal') &&\n row.precision !== null &&\n row.scale !== null\n ) {\n type = `${type}(${row.precision}, ${row.scale})`;\n }\n tableSchema[row.column] = {\n type,\n isEnum,\n isArray,\n };\n }\n\n const errors = checkSchemasAreCompatible(schema, serverSchema);\n assert(errors.length === 0, () => makeSchemaIncompatibleErrorMessage(errors));\n\n return serverSchema;\n}\n\n/**\n * The query behind {@linkcode getServerSchema}, exported so that it can be\n * diffed against the `information_schema` query it replaced.\n */\nexport function serverSchemaQuery(\n schemaTablePairs: readonly (readonly [string, string])[],\n): {text: string; values: unknown[]} {\n // Cast all inputs to text and all outputs to text to avoid\n // any conversions customer's DBTransaction impl has on other types.\n const inClause = sql.join(\n schemaTablePairs.map(\n ([schema, table]) => sql`(${schema}::text, ${table}::text)`,\n ),\n ',',\n );\n // Read pg_catalog directly instead of information_schema.columns. The view\n // derives every column it returns through the information_schema._pg_*\n // functions and a per column privilege check, which is several times slower\n // than the query below. Server processes run this on the first transaction\n // they serve, so serverless deployments pay for it on every cold start.\n //\n // The expressions below reproduce the parts of the view's definition that we\n // select, down to the int4 wire types of length, precision and scale: the\n // _pg_char_max_length / _pg_numeric_precision / _pg_numeric_scale arithmetic,\n // the single level domain unwrap that data_type and udt_name perform (`ut`),\n // and the view's own relkind, attnum and privilege filters. pg_type is joined\n // by OID rather than by udt_name, which additionally avoids duplicate rows\n // when two schemas declare a type with the same name. The types those\n // functions special case are named through regtype, which the parser resolves\n // while planning.\n const query = sql`\n SELECT\n n.nspname::text AS schema,\n cl.relname::text AS table,\n a.attname::text AS column,\n CASE\n WHEN ut.typelem <> 0 AND ut.typlen = -1 THEN 'ARRAY'\n WHEN nut.nspname = 'pg_catalog' THEN pg_catalog.format_type(ut.oid, NULL)\n ELSE 'USER-DEFINED'\n END::text AS \"dataType\",\n CASE\n WHEN tm.typmod = -1 THEN NULL\n WHEN ut.oid IN ('pg_catalog.bpchar'::regtype, 'pg_catalog.varchar'::regtype) THEN tm.typmod - 4\n WHEN ut.oid IN ('pg_catalog.bit'::regtype, 'pg_catalog.varbit'::regtype) THEN tm.typmod\n END AS length,\n CASE ut.oid\n WHEN 'pg_catalog.int2'::regtype THEN 16\n WHEN 'pg_catalog.int4'::regtype THEN 32\n WHEN 'pg_catalog.int8'::regtype THEN 64\n WHEN 'pg_catalog.float4'::regtype THEN 24\n WHEN 'pg_catalog.float8'::regtype THEN 53\n WHEN 'pg_catalog.numeric'::regtype THEN CASE WHEN tm.typmod = -1 THEN NULL ELSE ((tm.typmod - 4) >> 16) & 65535 END\n END AS precision,\n CASE\n WHEN ut.oid IN ('pg_catalog.int2'::regtype, 'pg_catalog.int4'::regtype, 'pg_catalog.int8'::regtype) THEN 0\n WHEN ut.oid = 'pg_catalog.numeric'::regtype AND tm.typmod <> -1 THEN (tm.typmod - 4) & 65535\n END AS scale,\n ut.typtype::text AS typtype,\n ut.typname::text AS typename,\n CASE WHEN ut.typelem <> 0 THEN et.typtype::text ELSE NULL END AS \"elemTyptype\",\n CASE WHEN ut.typelem <> 0 THEN et.typname::text ELSE NULL END AS \"elemTypname\"\n FROM\n pg_catalog.pg_attribute a\n JOIN\n pg_catalog.pg_class cl ON cl.oid = a.attrelid\n JOIN\n pg_catalog.pg_namespace n ON n.oid = cl.relnamespace\n JOIN\n pg_catalog.pg_type t ON t.oid = a.atttypid\n JOIN\n pg_catalog.pg_type ut ON ut.oid = CASE WHEN t.typtype = 'd' THEN t.typbasetype ELSE t.oid END\n JOIN\n pg_catalog.pg_namespace nut ON nut.oid = ut.typnamespace\n LEFT JOIN\n pg_catalog.pg_type et ON et.oid = ut.typelem\n CROSS JOIN LATERAL\n (SELECT CASE WHEN t.typtype = 'd' THEN t.typtypmod ELSE a.atttypmod END AS typmod) tm\n WHERE\n a.attnum > 0\n AND NOT a.attisdropped\n AND cl.relkind IN ('r', 'v', 'f', 'p')\n AND NOT pg_catalog.pg_is_other_temp_schema(n.oid)\n AND (pg_catalog.pg_has_role(cl.relowner, 'USAGE')\n OR pg_catalog.has_column_privilege(cl.oid, a.attnum, 'SELECT, INSERT, UPDATE, REFERENCES'))\n AND (n.nspname, cl.relname) IN (${inClause})\n `;\n return formatPg(query);\n}\n\nfunction makeSchemaIncompatibleErrorMessage(\n errors: SchemaIncompatibilityError[],\n) {\n if (errors.length === 0) {\n return 'No schema incompatibilities found.';\n }\n\n const messages: string[] = [];\n\n for (const error of errors) {\n switch (error.type) {\n case 'missingTable':\n messages.push(\n `Table \"${error.table}\" is defined in your zero schema but does not exist in the database.`,\n );\n break;\n case 'missingColumn':\n messages.push(\n `Column \"${error.column}\" in table \"${error.table}\" is defined in your zero schema but does not exist in the database.`,\n );\n break;\n case 'typeError':\n messages.push(\n `Type mismatch for column \"${error.column}\" in table \"${error.table}\": ${error.requiredType === undefined ? `${error.pgType} is currently unsupported in Zero. Please file a bug at https://bugs.rocicorp.dev/` : `${error.pgType} should be mapped to ${error.requiredType} in Zero not ${error.declaredType}.`}`,\n );\n break;\n }\n }\n\n return [\n 'Schema incompatibility detected between your zero schema definition and the database:',\n '',\n ...messages.map(msg => ` - ${msg}`),\n '',\n 'Please update your schema definition to match the database or migrate your database to match the schema.',\n ].join('\\n');\n}\n\nexport type SchemaIncompatibilityError =\n | {\n type: 'typeError';\n table: string;\n column: string;\n pgType: string;\n declaredType: string;\n requiredType: string | undefined;\n }\n | {\n type: 'missingColumn';\n table: string;\n column: string;\n }\n | {\n type: 'missingTable';\n table: string;\n };\n\nexport function checkSchemasAreCompatible(\n schema: Schema,\n serverSchema: ServerSchema,\n): SchemaIncompatibilityError[] {\n const errors: SchemaIncompatibilityError[] = [];\n // Check that all tables in schema exist in serverSchema\n for (const table of Object.values(schema.tables)) {\n const serverTableName = table.serverName ?? table.name;\n\n if (!serverSchema[serverTableName]) {\n errors.push({\n type: 'missingTable',\n table: serverTableName,\n });\n continue;\n }\n\n // Check that all columns in the table exist in serverSchema\n for (const [columnName, column] of Object.entries(table.columns)) {\n const serverColumnName = column.serverName ?? columnName;\n\n if (!serverSchema[serverTableName][serverColumnName]) {\n errors.push({\n type: 'missingColumn',\n table: serverTableName,\n column: serverColumnName,\n });\n continue;\n }\n\n // Check type compatibility\n const serverColumn = serverSchema[serverTableName][serverColumnName];\n const declaredType = column.type;\n const pgType = serverColumn.type;\n const requiredType = dataTypeToZqlValueType(\n pgType,\n serverColumn.isEnum,\n serverColumn.isArray,\n );\n if (requiredType !== declaredType) {\n errors.push({\n type: 'typeError',\n table: serverTableName,\n column: serverColumnName,\n pgType,\n declaredType,\n requiredType,\n });\n }\n }\n }\n\n return errors;\n}\n"],"mappings":"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"}
@@ -16,6 +16,26 @@ export declare class ZQLDatabase<TSchema extends Schema, TWrappedTransaction> im
16
16
  readonly connection: DBConnection<TWrappedTransaction>;
17
17
  constructor(connection: DBConnection<TWrappedTransaction>, schema: TSchema);
18
18
  transaction<R>(callback: (tx: TransactionImpl<TSchema, TWrappedTransaction>, transactionHooks: TransactionProviderHooks) => MaybePromise<R>, transactionInput?: TransactionProviderInput): Promise<R>;
19
- run<TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TTable, TSchema, TReturn>, options?: RunOptions): Promise<HumanReadable<TReturn>>;
19
+ /**
20
+ * Runs a single read query.
21
+ *
22
+ * When the {@linkcode DBConnection} implements `query`, the compiled SQL is
23
+ * issued as a bare statement with no `BEGIN`/`COMMIT` around it (plus a
24
+ * one-time server schema lookup the first time this instance touches the
25
+ * database). Postgres then releases the statement's locks the moment it
26
+ * finishes instead of waiting for a `COMMIT` round-trip, which matters in
27
+ * serverless environments where the process can be frozen or reclaimed
28
+ * between the query resolving and the `COMMIT` being sent, leaving the
29
+ * transaction and its locks open indefinitely.
30
+ *
31
+ * Because no transaction is opened, any per-transaction setup the adapter
32
+ * performs inside `transaction` does not apply to these reads. If the
33
+ * connection does not implement `query`, the read is wrapped in a
34
+ * transaction as before.
35
+ *
36
+ * If you need multiple reads to observe a consistent snapshot, use
37
+ * {@linkcode transaction} and call `tx.run(...)` for each query instead.
38
+ */
39
+ run<TTable extends keyof TSchema['tables'] & string, TReturn>(query: Query<TTable, TSchema, TReturn>, _options?: RunOptions): Promise<HumanReadable<TReturn>>;
20
40
  }
21
41
  //# sourceMappingURL=zql-database.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"zql-database.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/zql-database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAG5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EAAC,YAAY,EAAgB,MAAM,gCAAgC,CAAC;AAChF,OAAO,KAAK,EACV,aAAa,EACb,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAqB,KAAK,eAAe,EAAC,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EACV,QAAQ,EACR,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;GAMG;AACH,qBAAa,WAAW,CACtB,OAAO,SAAS,MAAM,EACtB,mBAAmB,CACnB,YAAW,QAAQ,CAAC,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;;IAClE,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAGvD,YAAY,UAAU,EAAE,YAAY,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,OAAO,EAGzE;IAED,WAAW,CAAC,CAAC,EACX,QAAQ,EAAE,CACR,EAAE,EAAE,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,EACjD,gBAAgB,EAAE,wBAAwB,KACvC,YAAY,CAAC,CAAC,CAAC,EACpB,gBAAgB,CAAC,EAAE,wBAAwB,GAC1C,OAAO,CAAC,CAAC,CAAC,CAoEZ;IAUD,GAAG,CAAC,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,EAC1D,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EACtC,OAAO,CAAC,EAAE,UAAU,GACnB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAEjC;CACF"}
1
+ {"version":3,"file":"zql-database.d.ts","sourceRoot":"","sources":["../../../../zero-server/src/zql-database.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,2BAA2B,CAAC;AAG5D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,gCAAgC,CAAC;AAExC,OAAO,KAAK,EACV,aAAa,EACb,KAAK,EACL,UAAU,EACX,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAqB,KAAK,eAAe,EAAC,MAAM,aAAa,CAAC;AAErE,OAAO,KAAK,EACV,QAAQ,EACR,wBAAwB,EACxB,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAEhC;;;;;;GAMG;AACH,qBAAa,WAAW,CACtB,OAAO,SAAS,MAAM,EACtB,mBAAmB,CACnB,YAAW,QAAQ,CAAC,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;;IAClE,QAAQ,CAAC,UAAU,EAAE,YAAY,CAAC,mBAAmB,CAAC,CAAC;IAIvD,YAAY,UAAU,EAAE,YAAY,CAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,OAAO,EAIzE;IAED,WAAW,CAAC,CAAC,EACX,QAAQ,EAAE,CACR,EAAE,EAAE,eAAe,CAAC,OAAO,EAAE,mBAAmB,CAAC,EACjD,gBAAgB,EAAE,wBAAwB,KACvC,YAAY,CAAC,CAAC,CAAC,EACpB,gBAAgB,CAAC,EAAE,wBAAwB,GAC1C,OAAO,CAAC,CAAC,CAAC,CAoEZ;IAUD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,GAAG,CAAC,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE,OAAO,EAC1D,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,EACtC,QAAQ,CAAC,EAAE,UAAU,GACpB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAOjC;CAkBF"}
@@ -1,5 +1,7 @@
1
+ import { asQueryInternals } from "../../zql/src/query/query-internals.js";
1
2
  import { formatPg, sql } from "../../z2s/src/sql.js";
2
3
  import { CRUDMutatorFactory } from "./custom.js";
4
+ import { executePostgresQuery } from "./pg-query-executor.js";
3
5
  //#region ../zero-server/src/zql-database.ts
4
6
  /**
5
7
  * Implements a Database for use with PushProcessor that is backed by Postgres.
@@ -11,9 +13,11 @@ import { CRUDMutatorFactory } from "./custom.js";
11
13
  var ZQLDatabase = class {
12
14
  connection;
13
15
  #crudFactory;
16
+ #schema;
14
17
  constructor(connection, schema) {
15
18
  this.connection = connection;
16
19
  this.#crudFactory = new CRUDMutatorFactory(schema);
20
+ this.#schema = schema;
17
21
  }
18
22
  transaction(callback, transactionInput) {
19
23
  const { upstreamSchema = "", clientGroupID = "", clientID = "", mutationID = 0 } = transactionInput ?? {};
@@ -55,8 +59,35 @@ var ZQLDatabase = class {
55
59
  #makeServerTransaction(dbTx, clientID, mutationID) {
56
60
  return this.#crudFactory.createTransaction(dbTx, clientID, mutationID);
57
61
  }
58
- run(query, options) {
59
- return this.transaction((tx) => tx.run(query, options));
62
+ /**
63
+ * Runs a single read query.
64
+ *
65
+ * When the {@linkcode DBConnection} implements `query`, the compiled SQL is
66
+ * issued as a bare statement with no `BEGIN`/`COMMIT` around it (plus a
67
+ * one-time server schema lookup the first time this instance touches the
68
+ * database). Postgres then releases the statement's locks the moment it
69
+ * finishes instead of waiting for a `COMMIT` round-trip, which matters in
70
+ * serverless environments where the process can be frozen or reclaimed
71
+ * between the query resolving and the `COMMIT` being sent, leaving the
72
+ * transaction and its locks open indefinitely.
73
+ *
74
+ * Because no transaction is opened, any per-transaction setup the adapter
75
+ * performs inside `transaction` does not apply to these reads. If the
76
+ * connection does not implement `query`, the read is wrapped in a
77
+ * transaction as before.
78
+ *
79
+ * If you need multiple reads to observe a consistent snapshot, use
80
+ * {@linkcode transaction} and call `tx.run(...)` for each query instead.
81
+ */
82
+ run(query, _options) {
83
+ const { connection } = this;
84
+ if (connection.query) return this.#runOn(connection, query);
85
+ return connection.transaction((dbTx) => this.#runOn(dbTx, query));
86
+ }
87
+ async #runOn(target, query) {
88
+ const { ast, format } = asQueryInternals(query);
89
+ const serverSchema = await this.#crudFactory.getOrFetchServerSchema(target);
90
+ return target.runQuery ? target.runQuery(ast, format, this.#schema, serverSchema) : executePostgresQuery(target, ast, format, this.#schema, serverSchema);
60
91
  }
61
92
  };
62
93
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"zql-database.js","names":["#crudFactory","#makeServerTransaction"],"sources":["../../../../zero-server/src/zql-database.ts"],"sourcesContent":["import type {MaybePromise} from '../../shared/src/types.ts';\nimport {formatPg, sql} from '../../z2s/src/sql.ts';\nimport type {CleanupResultsArg} from '../../zero-protocol/src/mutation.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {DBConnection, DBTransaction} from '../../zql/src/mutate/custom.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport {CRUDMutatorFactory, type TransactionImpl} from './custom.ts';\nimport type {\n Database,\n TransactionProviderHooks,\n TransactionProviderInput,\n} from './process-mutations.ts';\n\n/**\n * Implements a Database for use with PushProcessor that is backed by Postgres.\n *\n * This implementation also implements the same ZQL interfaces for reading and\n * writing data that the Zero client does, so that mutator functions can be\n * shared across client and server.\n */\nexport class ZQLDatabase<\n TSchema extends Schema,\n TWrappedTransaction,\n> implements Database<TransactionImpl<TSchema, TWrappedTransaction>> {\n readonly connection: DBConnection<TWrappedTransaction>;\n readonly #crudFactory: CRUDMutatorFactory<TSchema>;\n\n constructor(connection: DBConnection<TWrappedTransaction>, schema: TSchema) {\n this.connection = connection;\n this.#crudFactory = new CRUDMutatorFactory(schema);\n }\n\n transaction<R>(\n callback: (\n tx: TransactionImpl<TSchema, TWrappedTransaction>,\n transactionHooks: TransactionProviderHooks,\n ) => MaybePromise<R>,\n transactionInput?: TransactionProviderInput,\n ): Promise<R> {\n // Icky hack. This is just here to have user not have to do this.\n // These interfaces need to be factored better.\n const {\n upstreamSchema = '',\n clientGroupID = '',\n clientID = '',\n mutationID = 0,\n } = transactionInput ?? {};\n return this.connection.transaction(async dbTx => {\n const zeroTx = await this.#makeServerTransaction(\n dbTx,\n clientID,\n mutationID,\n );\n\n return callback(zeroTx, {\n async updateClientMutationID() {\n const formatted = formatPg(\n sql`INSERT INTO ${sql.ident(upstreamSchema)}.clients \n as current (\"clientGroupID\", \"clientID\", \"lastMutationID\")\n VALUES (${clientGroupID}, ${clientID}, ${1})\n ON CONFLICT (\"clientGroupID\", \"clientID\")\n DO UPDATE SET \"lastMutationID\" = current.\"lastMutationID\" + 1\n RETURNING \"lastMutationID\"`,\n );\n\n const [{lastMutationID}] = (await dbTx.query(\n formatted.text,\n formatted.values,\n )) as {lastMutationID: bigint}[];\n\n return {lastMutationID};\n },\n\n async writeMutationResult(result) {\n const formatted = formatPg(\n sql`INSERT INTO ${sql.ident(upstreamSchema)}.mutations\n (\"clientGroupID\", \"clientID\", \"mutationID\", \"result\")\n VALUES (${clientGroupID}, ${result.id.clientID}, ${result.id.id}, ${JSON.stringify(\n result.result,\n )}::text::json)`,\n );\n await dbTx.query(formatted.text, formatted.values);\n },\n\n async deleteMutationResults(args: CleanupResultsArg) {\n if ('type' in args && args.type === 'bulk') {\n // Bulk deletion: delete all mutations for multiple clients\n const formatted = formatPg(\n sql`DELETE FROM ${sql.ident(upstreamSchema)}.\"mutations\"\n WHERE \"clientGroupID\" = ${args.clientGroupID}\n AND \"clientID\" = ANY(${args.clientIDs})`,\n );\n await dbTx.query(formatted.text, formatted.values);\n } else {\n // Single client (explicit 'single' or legacy without type): delete up to mutation ID\n const formatted = formatPg(\n sql`DELETE FROM ${sql.ident(upstreamSchema)}.\"mutations\"\n WHERE \"clientGroupID\" = ${args.clientGroupID}\n AND \"clientID\" = ${args.clientID}\n AND \"mutationID\" <= ${args.upToMutationID}`,\n );\n await dbTx.query(formatted.text, formatted.values);\n }\n },\n });\n });\n }\n\n #makeServerTransaction(\n dbTx: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n ) {\n return this.#crudFactory.createTransaction(dbTx, clientID, mutationID);\n }\n\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n return this.transaction(tx => tx.run(query, options));\n }\n}\n"],"mappings":";;;;;;;;;;AAwBA,IAAa,cAAb,MAGqE;CACnE;CACA;CAEA,YAAY,YAA+C,QAAiB;EAC1E,KAAK,aAAa;EAClB,KAAKA,eAAe,IAAI,mBAAmB,MAAM;CACnD;CAEA,YACE,UAIA,kBACY;EAGZ,MAAM,EACJ,iBAAiB,IACjB,gBAAgB,IAChB,WAAW,IACX,aAAa,MACX,oBAAoB,CAAC;EACzB,OAAO,KAAK,WAAW,YAAY,OAAM,SAAQ;GAO/C,OAAO,SAAS,MANK,KAAKC,uBACxB,MACA,UACA,UACF,GAEwB;IACtB,MAAM,yBAAyB;KAC7B,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;;kCAEtB,cAAc,IAAI,SAAS,IAAI,EAAE;;;+CAIzD;KAEA,MAAM,CAAC,EAAC,oBAAoB,MAAM,KAAK,MACrC,UAAU,MACV,UAAU,MACZ;KAEA,OAAO,EAAC,eAAc;IACxB;IAEA,MAAM,oBAAoB,QAAQ;KAChC,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;;0BAE9B,cAAc,IAAI,OAAO,GAAG,SAAS,IAAI,OAAO,GAAG,GAAG,IAAI,KAAK,UACvE,OAAO,MACT,EAAE,cACR;KACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;IACnD;IAEA,MAAM,sBAAsB,MAAyB;KACnD,IAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ;MAE1C,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;4CACd,KAAK,cAAc;2CACpB,KAAK,UAAU,EAC9C;MACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;KACnD,OAAO;MAEL,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;4CACd,KAAK,cAAc;uCACxB,KAAK,SAAS;0CACX,KAAK,gBACnC;MACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;KACnD;IACF;GACF,CAAC;EACH,CAAC;CACH;CAEA,uBACE,MACA,UACA,YACA;EACA,OAAO,KAAKD,aAAa,kBAAkB,MAAM,UAAU,UAAU;CACvE;CAEA,IACE,OACA,SACiC;EACjC,OAAO,KAAK,aAAY,OAAM,GAAG,IAAI,OAAO,OAAO,CAAC;CACtD;AACF"}
1
+ {"version":3,"file":"zql-database.js","names":["#crudFactory","#schema","#makeServerTransaction","#runOn"],"sources":["../../../../zero-server/src/zql-database.ts"],"sourcesContent":["import type {MaybePromise} from '../../shared/src/types.ts';\nimport {formatPg, sql} from '../../z2s/src/sql.ts';\nimport type {CleanupResultsArg} from '../../zero-protocol/src/mutation.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport type {\n DBConnection,\n DBTransaction,\n Queryable,\n} from '../../zql/src/mutate/custom.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {\n HumanReadable,\n Query,\n RunOptions,\n} from '../../zql/src/query/query.ts';\nimport {CRUDMutatorFactory, type TransactionImpl} from './custom.ts';\nimport {executePostgresQuery} from './pg-query-executor.ts';\nimport type {\n Database,\n TransactionProviderHooks,\n TransactionProviderInput,\n} from './process-mutations.ts';\n\n/**\n * Implements a Database for use with PushProcessor that is backed by Postgres.\n *\n * This implementation also implements the same ZQL interfaces for reading and\n * writing data that the Zero client does, so that mutator functions can be\n * shared across client and server.\n */\nexport class ZQLDatabase<\n TSchema extends Schema,\n TWrappedTransaction,\n> implements Database<TransactionImpl<TSchema, TWrappedTransaction>> {\n readonly connection: DBConnection<TWrappedTransaction>;\n readonly #crudFactory: CRUDMutatorFactory<TSchema>;\n readonly #schema: TSchema;\n\n constructor(connection: DBConnection<TWrappedTransaction>, schema: TSchema) {\n this.connection = connection;\n this.#crudFactory = new CRUDMutatorFactory(schema);\n this.#schema = schema;\n }\n\n transaction<R>(\n callback: (\n tx: TransactionImpl<TSchema, TWrappedTransaction>,\n transactionHooks: TransactionProviderHooks,\n ) => MaybePromise<R>,\n transactionInput?: TransactionProviderInput,\n ): Promise<R> {\n // Icky hack. This is just here to have user not have to do this.\n // These interfaces need to be factored better.\n const {\n upstreamSchema = '',\n clientGroupID = '',\n clientID = '',\n mutationID = 0,\n } = transactionInput ?? {};\n return this.connection.transaction(async dbTx => {\n const zeroTx = await this.#makeServerTransaction(\n dbTx,\n clientID,\n mutationID,\n );\n\n return callback(zeroTx, {\n async updateClientMutationID() {\n const formatted = formatPg(\n sql`INSERT INTO ${sql.ident(upstreamSchema)}.clients \n as current (\"clientGroupID\", \"clientID\", \"lastMutationID\")\n VALUES (${clientGroupID}, ${clientID}, ${1})\n ON CONFLICT (\"clientGroupID\", \"clientID\")\n DO UPDATE SET \"lastMutationID\" = current.\"lastMutationID\" + 1\n RETURNING \"lastMutationID\"`,\n );\n\n const [{lastMutationID}] = (await dbTx.query(\n formatted.text,\n formatted.values,\n )) as {lastMutationID: bigint}[];\n\n return {lastMutationID};\n },\n\n async writeMutationResult(result) {\n const formatted = formatPg(\n sql`INSERT INTO ${sql.ident(upstreamSchema)}.mutations\n (\"clientGroupID\", \"clientID\", \"mutationID\", \"result\")\n VALUES (${clientGroupID}, ${result.id.clientID}, ${result.id.id}, ${JSON.stringify(\n result.result,\n )}::text::json)`,\n );\n await dbTx.query(formatted.text, formatted.values);\n },\n\n async deleteMutationResults(args: CleanupResultsArg) {\n if ('type' in args && args.type === 'bulk') {\n // Bulk deletion: delete all mutations for multiple clients\n const formatted = formatPg(\n sql`DELETE FROM ${sql.ident(upstreamSchema)}.\"mutations\"\n WHERE \"clientGroupID\" = ${args.clientGroupID}\n AND \"clientID\" = ANY(${args.clientIDs})`,\n );\n await dbTx.query(formatted.text, formatted.values);\n } else {\n // Single client (explicit 'single' or legacy without type): delete up to mutation ID\n const formatted = formatPg(\n sql`DELETE FROM ${sql.ident(upstreamSchema)}.\"mutations\"\n WHERE \"clientGroupID\" = ${args.clientGroupID}\n AND \"clientID\" = ${args.clientID}\n AND \"mutationID\" <= ${args.upToMutationID}`,\n );\n await dbTx.query(formatted.text, formatted.values);\n }\n },\n });\n });\n }\n\n #makeServerTransaction(\n dbTx: DBTransaction<TWrappedTransaction>,\n clientID: string,\n mutationID: number,\n ) {\n return this.#crudFactory.createTransaction(dbTx, clientID, mutationID);\n }\n\n /**\n * Runs a single read query.\n *\n * When the {@linkcode DBConnection} implements `query`, the compiled SQL is\n * issued as a bare statement with no `BEGIN`/`COMMIT` around it (plus a\n * one-time server schema lookup the first time this instance touches the\n * database). Postgres then releases the statement's locks the moment it\n * finishes instead of waiting for a `COMMIT` round-trip, which matters in\n * serverless environments where the process can be frozen or reclaimed\n * between the query resolving and the `COMMIT` being sent, leaving the\n * transaction and its locks open indefinitely.\n *\n * Because no transaction is opened, any per-transaction setup the adapter\n * performs inside `transaction` does not apply to these reads. If the\n * connection does not implement `query`, the read is wrapped in a\n * transaction as before.\n *\n * If you need multiple reads to observe a consistent snapshot, use\n * {@linkcode transaction} and call `tx.run(...)` for each query instead.\n */\n run<TTable extends keyof TSchema['tables'] & string, TReturn>(\n query: Query<TTable, TSchema, TReturn>,\n _options?: RunOptions,\n ): Promise<HumanReadable<TReturn>> {\n const {connection} = this;\n if (connection.query) {\n // TS narrows `connection.query`, not `connection` itself.\n return this.#runOn(connection as ReadTarget<TWrappedTransaction>, query);\n }\n return connection.transaction(dbTx => this.#runOn(dbTx, query));\n }\n\n async #runOn<TTable extends keyof TSchema['tables'] & string, TReturn>(\n target: ReadTarget<TWrappedTransaction>,\n query: Query<TTable, TSchema, TReturn>,\n ): Promise<HumanReadable<TReturn>> {\n const {ast, format} = asQueryInternals(query);\n const serverSchema = await this.#crudFactory.getOrFetchServerSchema(target);\n return target.runQuery\n ? target.runQuery<TReturn>(ast, format, this.#schema, serverSchema)\n : executePostgresQuery<TReturn>(\n target,\n ast,\n format,\n this.#schema,\n serverSchema,\n );\n }\n}\n\n/**\n * Something a read can be executed against: a `DBTransaction`, or a\n * `DBConnection` that implements `query`.\n */\ntype ReadTarget<TWrappedTransaction> = Queryable & {\n runQuery?: DBTransaction<TWrappedTransaction>['runQuery'] | undefined;\n};\n"],"mappings":";;;;;;;;;;;;AA8BA,IAAa,cAAb,MAGqE;CACnE;CACA;CACA;CAEA,YAAY,YAA+C,QAAiB;EAC1E,KAAK,aAAa;EAClB,KAAKA,eAAe,IAAI,mBAAmB,MAAM;EACjD,KAAKC,UAAU;CACjB;CAEA,YACE,UAIA,kBACY;EAGZ,MAAM,EACJ,iBAAiB,IACjB,gBAAgB,IAChB,WAAW,IACX,aAAa,MACX,oBAAoB,CAAC;EACzB,OAAO,KAAK,WAAW,YAAY,OAAM,SAAQ;GAO/C,OAAO,SAAS,MANK,KAAKC,uBACxB,MACA,UACA,UACF,GAEwB;IACtB,MAAM,yBAAyB;KAC7B,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;;kCAEtB,cAAc,IAAI,SAAS,IAAI,EAAE;;;+CAIzD;KAEA,MAAM,CAAC,EAAC,oBAAoB,MAAM,KAAK,MACrC,UAAU,MACV,UAAU,MACZ;KAEA,OAAO,EAAC,eAAc;IACxB;IAEA,MAAM,oBAAoB,QAAQ;KAChC,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;;0BAE9B,cAAc,IAAI,OAAO,GAAG,SAAS,IAAI,OAAO,GAAG,GAAG,IAAI,KAAK,UACvE,OAAO,MACT,EAAE,cACR;KACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;IACnD;IAEA,MAAM,sBAAsB,MAAyB;KACnD,IAAI,UAAU,QAAQ,KAAK,SAAS,QAAQ;MAE1C,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;4CACd,KAAK,cAAc;2CACpB,KAAK,UAAU,EAC9C;MACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;KACnD,OAAO;MAEL,MAAM,YAAY,SAChB,GAAG,eAAe,IAAI,MAAM,cAAc,EAAE;4CACd,KAAK,cAAc;uCACxB,KAAK,SAAS;0CACX,KAAK,gBACnC;MACA,MAAM,KAAK,MAAM,UAAU,MAAM,UAAU,MAAM;KACnD;IACF;GACF,CAAC;EACH,CAAC;CACH;CAEA,uBACE,MACA,UACA,YACA;EACA,OAAO,KAAKF,aAAa,kBAAkB,MAAM,UAAU,UAAU;CACvE;;;;;;;;;;;;;;;;;;;;;CAsBA,IACE,OACA,UACiC;EACjC,MAAM,EAAC,eAAc;EACrB,IAAI,WAAW,OAEb,OAAO,KAAKG,OAAO,YAA+C,KAAK;EAEzE,OAAO,WAAW,aAAY,SAAQ,KAAKA,OAAO,MAAM,KAAK,CAAC;CAChE;CAEA,MAAMA,OACJ,QACA,OACiC;EACjC,MAAM,EAAC,KAAK,WAAU,iBAAiB,KAAK;EAC5C,MAAM,eAAe,MAAM,KAAKH,aAAa,uBAAuB,MAAM;EAC1E,OAAO,OAAO,WACV,OAAO,SAAkB,KAAK,QAAQ,KAAKC,SAAS,YAAY,IAChE,qBACE,QACA,KACA,QACA,KAAKA,SACL,YACF;CACN;AACF"}
@@ -3,6 +3,7 @@ import { type Change, type Entry, type ErroredQuery, type Format, type Input, ty
3
3
  export type State = [Entry, QueryResultDetails];
4
4
  export declare const COMPLETE: QueryResultDetails;
5
5
  export declare const UNKNOWN: QueryResultDetails;
6
+ export declare const CACHED: QueryResultDetails;
6
7
  /**
7
8
  * SolidView bridges Zero's incremental view updates with Solid's reactive
8
9
  * store.
@@ -49,6 +50,22 @@ export declare class SolidView implements Output {
49
50
  #private;
50
51
  constructor(input: Input, onTransactionCommit: (cb: () => void) => void, format: Format, onDestroy: () => void, queryComplete: true | ErroredQuery | Promise<true>, updateTTL: (ttl: TTL) => void, setState: SetStoreFunction<State>, retry: () => void);
51
52
  destroy(): void;
53
+ /**
54
+ * The store holds the server-confirmed result of this query from a
55
+ * previous connection. Never downgrades 'complete'/'error'; freshness stays
56
+ * a promise only the connection can keep, so nothing that waits on
57
+ * 'complete' resolves here.
58
+ */
59
+ markCached(): void;
60
+ /** The got key was deleted (eviction) before this connection confirmed it. */
61
+ unmarkCached(): void;
62
+ /**
63
+ * Called before a deferred pipeline hydrates this view over several tasks
64
+ * (see `ViewFactory`). Rows already only reach the store at commit; this
65
+ * makes result type transitions wait for that commit too, including when
66
+ * the hydration produced no rows.
67
+ */
68
+ holdData(): void;
52
69
  push(change: Change): readonly never[];
53
70
  updateTTL(ttl: TTL): void;
54
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"solid-view.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/solid-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAUzE,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,kBAAkB,EACvB,KAAK,MAAM,EAEX,KAAK,GAAG,EACT,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAEhD,eAAO,MAAM,QAAQ,EAAE,kBAAsD,CAAC;AAC9E,eAAO,MAAM,OAAO,EAAE,kBAAqD,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,SAAU,YAAW,MAAM;;IAoBtC,YACE,KAAK,EAAE,KAAK,EACZ,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,EAC7C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,IAAI,EACrB,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,EAC7B,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,EAAE,MAAM,IAAI,EAiDlB;IAgBD,OAAO,IAAI,IAAI,CAEd;IAwBD,IAAI,CAAC,MAAM,EAAE,MAAM,oBAgBlB;IAyCD,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAExB;CACF;AAsDD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,CAAC,EAAE,MAAM,IAAI,IAGhB,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAC/C,OAAO,SAAS,MAAM,EACtB,OAAO,UAEC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAChC,KAAK,UACJ,MAAM,aACH,MAAM,IAAI,uBACA,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,iBAC9B,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,aACvC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,eAiBhC"}
1
+ {"version":3,"file":"solid-view.d.ts","sourceRoot":"","sources":["../../../../zero-solid/src/solid-view.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAC,MAAM,gBAAgB,CAAC;AAUzE,OAAO,EAEL,KAAK,MAAM,EACX,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,MAAM,EACX,KAAK,KAAK,EAEV,KAAK,kBAAkB,EACvB,KAAK,MAAM,EAEX,KAAK,GAAG,EACT,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,KAAK,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAC;AAEhD,eAAO,MAAM,QAAQ,EAAE,kBAAsD,CAAC;AAC9E,eAAO,MAAM,OAAO,EAAE,kBAAqD,CAAC;AAC5E,eAAO,MAAM,MAAM,EAAE,kBAAoD,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,qBAAa,SAAU,YAAW,MAAM;;IAyBtC,YACE,KAAK,EAAE,KAAK,EACZ,mBAAmB,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,EAC7C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,IAAI,EACrB,aAAa,EAAE,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,EAClD,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,EAC7B,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,EAAE,MAAM,IAAI,EAmDlB;IAgBD,OAAO,IAAI,IAAI,CAEd;IAED;;;;;OAKG;IACH,UAAU,IAAI,IAAI,CAIjB;IAED,8EAA8E;IAC9E,YAAY,IAAI,IAAI,CAInB;IAED;;;;;OAKG;IACH,QAAQ,IAAI,IAAI,CAEf;IA+CD,IAAI,CAAC,MAAM,EAAE,MAAM,oBAgBlB;IAyCD,SAAS,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI,CAExB;CACF;AAsDD,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC,EACjC,KAAK,CAAC,EAAE,MAAM,IAAI,IAGhB,MAAM,SAAS,MAAM,OAAO,CAAC,QAAQ,CAAC,GAAG,MAAM,EAC/C,OAAO,SAAS,MAAM,EACtB,OAAO,UAEC,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAChC,KAAK,UACJ,MAAM,aACH,MAAM,IAAI,uBACA,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,iBAC9B,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,aACvC,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,eAiBhC"}
@@ -7,6 +7,7 @@ import { produce, reconcile } from "solid-js/store";
7
7
  //#region ../zero-solid/src/solid-view.ts
8
8
  var COMPLETE = Object.freeze({ type: "complete" });
9
9
  var UNKNOWN = Object.freeze({ type: "unknown" });
10
+ var CACHED = Object.freeze({ type: "cached" });
10
11
  /**
11
12
  * SolidView bridges Zero's incremental view updates with Solid's reactive
12
13
  * store.
@@ -57,6 +58,8 @@ var SolidView = class {
57
58
  #setState;
58
59
  #builderRoot;
59
60
  #pendingChanges = [];
61
+ #pendingResultType;
62
+ #held = false;
60
63
  #updateTTL;
61
64
  constructor(input, onTransactionCommit, format, onDestroy, queryComplete, updateTTL, setState, retry) {
62
65
  this.#input = input;
@@ -77,7 +80,7 @@ var SolidView = class {
77
80
  if (queryComplete !== true && !("error" in queryComplete)) queryComplete.then(() => {
78
81
  this.#setState((prev) => [prev[0], COMPLETE]);
79
82
  }).catch((error) => {
80
- this.#setState((prev) => [prev[0], this.#makeError(error)]);
83
+ this.#transitionResultType((prev) => [prev[0], this.#makeError(error)]);
81
84
  });
82
85
  }
83
86
  #makeError(error) {
@@ -96,7 +99,37 @@ var SolidView = class {
96
99
  destroy() {
97
100
  this.#onDestroy();
98
101
  }
102
+ /**
103
+ * The store holds the server-confirmed result of this query from a
104
+ * previous connection. Never downgrades 'complete'/'error'; freshness stays
105
+ * a promise only the connection can keep, so nothing that waits on
106
+ * 'complete' resolves here.
107
+ */
108
+ markCached() {
109
+ this.#transitionResultType((prev) => prev[1].type === "unknown" ? [prev[0], CACHED] : prev);
110
+ }
111
+ /** The got key was deleted (eviction) before this connection confirmed it. */
112
+ unmarkCached() {
113
+ this.#transitionResultType((prev) => prev[1].type === "cached" ? [prev[0], UNKNOWN] : prev);
114
+ }
115
+ /**
116
+ * Called before a deferred pipeline hydrates this view over several tasks
117
+ * (see `ViewFactory`). Rows already only reach the store at commit; this
118
+ * makes result type transitions wait for that commit too, including when
119
+ * the hydration produced no rows.
120
+ */
121
+ holdData() {
122
+ this.#held = true;
123
+ }
124
+ #transitionResultType(transition) {
125
+ if (this.#held || this.#hasUncommittedChanges()) this.#pendingResultType = transition;
126
+ else this.#setState(transition);
127
+ }
128
+ #hasUncommittedChanges() {
129
+ return this.#builderRoot !== void 0 && !isEmptyRoot(this.#builderRoot) || this.#pendingChanges.length > 0;
130
+ }
99
131
  #onTransactionCommit = () => {
132
+ this.#held = false;
100
133
  const builderRoot = this.#builderRoot;
101
134
  if (builderRoot) {
102
135
  if (!isEmptyRoot(builderRoot)) {
@@ -108,6 +141,11 @@ var SolidView = class {
108
141
  } finally {
109
142
  this.#pendingChanges = [];
110
143
  }
144
+ const pendingResultType = this.#pendingResultType;
145
+ if (pendingResultType) {
146
+ this.#pendingResultType = void 0;
147
+ this.#setState(pendingResultType);
148
+ }
111
149
  };
112
150
  push(change) {
113
151
  if (this.#builderRoot) this.#applyChangeToRoot(materializeRelationships(change), this.#builderRoot);