@rocicorp/zero 0.26.0-canary.2 → 0.26.0-canary.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/README.md +1 -1
  2. package/out/replicache/src/persist/collect-idb-databases.d.ts +4 -4
  3. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  4. package/out/replicache/src/persist/collect-idb-databases.js +22 -19
  5. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  6. package/out/replicache/src/persist/refresh.d.ts.map +1 -1
  7. package/out/replicache/src/persist/refresh.js +0 -8
  8. package/out/replicache/src/persist/refresh.js.map +1 -1
  9. package/out/replicache/src/process-scheduler.d.ts +23 -0
  10. package/out/replicache/src/process-scheduler.d.ts.map +1 -1
  11. package/out/replicache/src/process-scheduler.js +50 -1
  12. package/out/replicache/src/process-scheduler.js.map +1 -1
  13. package/out/replicache/src/replicache-impl.d.ts +8 -0
  14. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  15. package/out/replicache/src/replicache-impl.js +11 -2
  16. package/out/replicache/src/replicache-impl.js.map +1 -1
  17. package/out/shared/src/falsy.d.ts +3 -0
  18. package/out/shared/src/falsy.d.ts.map +1 -0
  19. package/out/zero/package.json.js +1 -1
  20. package/out/zero/src/adapters/drizzle.js +1 -2
  21. package/out/zero/src/adapters/prisma.d.ts +2 -0
  22. package/out/zero/src/adapters/prisma.d.ts.map +1 -0
  23. package/out/zero/src/adapters/prisma.js +6 -0
  24. package/out/zero/src/adapters/prisma.js.map +1 -0
  25. package/out/zero/src/pg.js +4 -7
  26. package/out/zero/src/react.js +3 -1
  27. package/out/zero/src/react.js.map +1 -1
  28. package/out/zero/src/server.js +5 -8
  29. package/out/zero-cache/src/auth/load-permissions.d.ts +3 -2
  30. package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
  31. package/out/zero-cache/src/auth/load-permissions.js +14 -8
  32. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  33. package/out/zero-cache/src/auth/write-authorizer.d.ts +6 -0
  34. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  35. package/out/zero-cache/src/auth/write-authorizer.js +16 -3
  36. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  37. package/out/zero-cache/src/config/zero-config.d.ts +44 -8
  38. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  39. package/out/zero-cache/src/config/zero-config.js +53 -13
  40. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  41. package/out/zero-cache/src/custom/fetch.d.ts +3 -0
  42. package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
  43. package/out/zero-cache/src/custom/fetch.js +26 -0
  44. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  45. package/out/zero-cache/src/db/lite-tables.js +1 -1
  46. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  47. package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
  48. package/out/zero-cache/src/db/migration-lite.js +9 -3
  49. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  50. package/out/zero-cache/src/db/migration.d.ts.map +1 -1
  51. package/out/zero-cache/src/db/migration.js +9 -3
  52. package/out/zero-cache/src/db/migration.js.map +1 -1
  53. package/out/zero-cache/src/db/specs.d.ts +4 -3
  54. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  55. package/out/zero-cache/src/db/specs.js +4 -1
  56. package/out/zero-cache/src/db/specs.js.map +1 -1
  57. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  58. package/out/zero-cache/src/db/transaction-pool.js +9 -3
  59. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  60. package/out/zero-cache/src/server/inspector-delegate.d.ts +1 -1
  61. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  62. package/out/zero-cache/src/server/inspector-delegate.js +11 -30
  63. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  64. package/out/zero-cache/src/server/main.js +1 -1
  65. package/out/zero-cache/src/server/main.js.map +1 -1
  66. package/out/zero-cache/src/server/priority-op.d.ts +8 -0
  67. package/out/zero-cache/src/server/priority-op.d.ts.map +1 -0
  68. package/out/zero-cache/src/server/priority-op.js +29 -0
  69. package/out/zero-cache/src/server/priority-op.js.map +1 -0
  70. package/out/zero-cache/src/server/syncer.d.ts +0 -1
  71. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  72. package/out/zero-cache/src/server/syncer.js +3 -21
  73. package/out/zero-cache/src/server/syncer.js.map +1 -1
  74. package/out/zero-cache/src/services/analyze.js +1 -1
  75. package/out/zero-cache/src/services/analyze.js.map +1 -1
  76. package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
  77. package/out/zero-cache/src/services/change-source/custom/change-source.js +4 -3
  78. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  79. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  80. package/out/zero-cache/src/services/change-source/pg/change-source.js +68 -13
  81. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  82. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  83. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -2
  84. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  85. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.d.ts.map +1 -1
  86. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +7 -4
  87. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  88. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +125 -180
  89. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  90. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  91. package/out/zero-cache/src/services/change-source/pg/schema/init.js +18 -10
  92. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  93. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +36 -90
  94. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  95. package/out/zero-cache/src/services/change-source/pg/schema/published.js +51 -14
  96. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  97. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +31 -36
  98. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +24 -3
  100. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +2 -2
  102. package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/schema/validation.js +2 -4
  104. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  105. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +158 -53
  106. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  107. package/out/zero-cache/src/services/change-source/protocol/current/data.js +55 -10
  108. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  109. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +210 -72
  110. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-source/protocol/current.js +4 -2
  112. package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
  113. package/out/zero-cache/src/services/change-source/replica-schema.js +19 -10
  114. package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
  115. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +1 -1
  116. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  117. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +71 -25
  118. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  119. package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
  120. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  121. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +1 -0
  122. package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
  123. package/out/zero-cache/src/services/change-streamer/schema/tables.js +6 -5
  124. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  125. package/out/zero-cache/src/services/change-streamer/storer.js +1 -1
  126. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  127. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +2 -0
  128. package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
  129. package/out/zero-cache/src/services/change-streamer/subscriber.js +14 -1
  130. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  131. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  132. package/out/zero-cache/src/services/heapz.js +1 -0
  133. package/out/zero-cache/src/services/heapz.js.map +1 -1
  134. package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
  135. package/out/zero-cache/src/services/mutagen/error.js +4 -1
  136. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  137. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  138. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -0
  139. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  140. package/out/zero-cache/src/services/mutagen/pusher.d.ts +7 -4
  141. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  142. package/out/zero-cache/src/services/mutagen/pusher.js +80 -8
  143. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  144. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  145. package/out/zero-cache/src/services/replicator/change-processor.js +21 -29
  146. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  147. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +1 -2
  148. package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
  149. package/out/zero-cache/src/services/replicator/schema/change-log.js +2 -5
  150. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  151. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.d.ts +3 -3
  152. package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts.map +1 -0
  153. package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.js +3 -3
  154. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -0
  155. package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
  156. package/out/zero-cache/src/services/replicator/schema/replication-state.js +3 -1
  157. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  158. package/out/zero-cache/src/services/run-ast.js +1 -1
  159. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  160. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  161. package/out/zero-cache/src/services/statz.js +1 -0
  162. package/out/zero-cache/src/services/statz.js.map +1 -1
  163. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +1 -1
  164. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/cvr-store.js +59 -40
  166. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  167. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +0 -1
  168. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/cvr.js +23 -6
  170. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  171. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +13 -14
  172. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  173. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +44 -56
  174. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  175. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
  176. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  177. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +22 -11
  178. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  179. package/out/zero-cache/src/services/view-syncer/snapshotter.js +1 -1
  180. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  181. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +6 -3
  182. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  183. package/out/zero-cache/src/services/view-syncer/view-syncer.js +192 -217
  184. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  185. package/out/zero-cache/src/types/lexi-version.d.ts.map +1 -1
  186. package/out/zero-cache/src/types/lexi-version.js +4 -1
  187. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  188. package/out/zero-cache/src/types/lite.d.ts.map +1 -1
  189. package/out/zero-cache/src/types/lite.js +8 -2
  190. package/out/zero-cache/src/types/lite.js.map +1 -1
  191. package/out/zero-cache/src/types/shards.js +1 -1
  192. package/out/zero-cache/src/types/shards.js.map +1 -1
  193. package/out/zero-cache/src/types/sql.d.ts +5 -0
  194. package/out/zero-cache/src/types/sql.d.ts.map +1 -1
  195. package/out/zero-cache/src/types/sql.js +5 -1
  196. package/out/zero-cache/src/types/sql.js.map +1 -1
  197. package/out/zero-cache/src/types/subscription.js +1 -1
  198. package/out/zero-cache/src/types/subscription.js.map +1 -1
  199. package/out/zero-cache/src/workers/connect-params.d.ts +1 -0
  200. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  201. package/out/zero-cache/src/workers/connect-params.js +2 -1
  202. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  203. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  204. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +14 -6
  205. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  206. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  207. package/out/zero-cache/src/workers/syncer.js +17 -10
  208. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  209. package/out/zero-client/src/client/connection-manager.d.ts +8 -0
  210. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  211. package/out/zero-client/src/client/connection-manager.js +33 -0
  212. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  213. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  214. package/out/zero-client/src/client/connection.js +6 -3
  215. package/out/zero-client/src/client/connection.js.map +1 -1
  216. package/out/zero-client/src/client/error.js +1 -1
  217. package/out/zero-client/src/client/error.js.map +1 -1
  218. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  219. package/out/zero-client/src/client/mutator-proxy.js +15 -1
  220. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  221. package/out/zero-client/src/client/options.d.ts +10 -0
  222. package/out/zero-client/src/client/options.d.ts.map +1 -1
  223. package/out/zero-client/src/client/options.js.map +1 -1
  224. package/out/zero-client/src/client/query-manager.d.ts +4 -0
  225. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  226. package/out/zero-client/src/client/query-manager.js +7 -0
  227. package/out/zero-client/src/client/query-manager.js.map +1 -1
  228. package/out/zero-client/src/client/version.js +1 -1
  229. package/out/zero-client/src/client/zero.d.ts +3 -1
  230. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  231. package/out/zero-client/src/client/zero.js +52 -7
  232. package/out/zero-client/src/client/zero.js.map +1 -1
  233. package/out/zero-client/src/mod.d.ts +1 -0
  234. package/out/zero-client/src/mod.d.ts.map +1 -1
  235. package/out/zero-protocol/src/connect.d.ts +4 -0
  236. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  237. package/out/zero-protocol/src/connect.js +3 -1
  238. package/out/zero-protocol/src/connect.js.map +1 -1
  239. package/out/zero-protocol/src/protocol-version.d.ts +1 -1
  240. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  241. package/out/zero-protocol/src/protocol-version.js +1 -1
  242. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  243. package/out/zero-protocol/src/push.d.ts +11 -2
  244. package/out/zero-protocol/src/push.d.ts.map +1 -1
  245. package/out/zero-protocol/src/push.js +22 -6
  246. package/out/zero-protocol/src/push.js.map +1 -1
  247. package/out/zero-protocol/src/up.d.ts +2 -0
  248. package/out/zero-protocol/src/up.d.ts.map +1 -1
  249. package/out/zero-react/src/mod.d.ts +3 -1
  250. package/out/zero-react/src/mod.d.ts.map +1 -1
  251. package/out/zero-react/src/paging-reducer.d.ts +61 -0
  252. package/out/zero-react/src/paging-reducer.d.ts.map +1 -0
  253. package/out/zero-react/src/paging-reducer.js +77 -0
  254. package/out/zero-react/src/paging-reducer.js.map +1 -0
  255. package/out/zero-react/src/use-query.d.ts +11 -1
  256. package/out/zero-react/src/use-query.d.ts.map +1 -1
  257. package/out/zero-react/src/use-query.js +13 -11
  258. package/out/zero-react/src/use-query.js.map +1 -1
  259. package/out/zero-react/src/use-rows.d.ts +39 -0
  260. package/out/zero-react/src/use-rows.d.ts.map +1 -0
  261. package/out/zero-react/src/use-rows.js +130 -0
  262. package/out/zero-react/src/use-rows.js.map +1 -0
  263. package/out/zero-react/src/use-zero-virtualizer.d.ts +122 -0
  264. package/out/zero-react/src/use-zero-virtualizer.d.ts.map +1 -0
  265. package/out/zero-react/src/use-zero-virtualizer.js +342 -0
  266. package/out/zero-react/src/use-zero-virtualizer.js.map +1 -0
  267. package/out/zero-react/src/zero-provider.js +1 -1
  268. package/out/zero-react/src/zero-provider.js.map +1 -1
  269. package/out/zero-server/src/adapters/drizzle.d.ts +18 -18
  270. package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
  271. package/out/zero-server/src/adapters/drizzle.js +8 -22
  272. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  273. package/out/zero-server/src/adapters/pg.d.ts +19 -13
  274. package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
  275. package/out/zero-server/src/adapters/pg.js.map +1 -1
  276. package/out/zero-server/src/adapters/postgresjs.d.ts +19 -13
  277. package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
  278. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  279. package/out/zero-server/src/adapters/prisma.d.ts +66 -0
  280. package/out/zero-server/src/adapters/prisma.d.ts.map +1 -0
  281. package/out/zero-server/src/adapters/prisma.js +63 -0
  282. package/out/zero-server/src/adapters/prisma.js.map +1 -0
  283. package/out/zero-server/src/custom.js +1 -15
  284. package/out/zero-server/src/custom.js.map +1 -1
  285. package/out/zero-server/src/mod.d.ts +9 -8
  286. package/out/zero-server/src/mod.d.ts.map +1 -1
  287. package/out/zero-server/src/process-mutations.d.ts +2 -2
  288. package/out/zero-server/src/process-mutations.d.ts.map +1 -1
  289. package/out/zero-server/src/process-mutations.js +4 -8
  290. package/out/zero-server/src/process-mutations.js.map +1 -1
  291. package/out/zero-server/src/push-processor.js +1 -1
  292. package/out/zero-server/src/push-processor.js.map +1 -1
  293. package/out/zero-server/src/schema.d.ts.map +1 -1
  294. package/out/zero-server/src/schema.js +4 -1
  295. package/out/zero-server/src/schema.js.map +1 -1
  296. package/out/zero-server/src/zql-database.d.ts.map +1 -1
  297. package/out/zero-server/src/zql-database.js +17 -8
  298. package/out/zero-server/src/zql-database.js.map +1 -1
  299. package/out/zero-solid/src/mod.d.ts +1 -1
  300. package/out/zero-solid/src/mod.d.ts.map +1 -1
  301. package/out/zero-solid/src/use-query.d.ts +10 -1
  302. package/out/zero-solid/src/use-query.d.ts.map +1 -1
  303. package/out/zero-solid/src/use-query.js +21 -5
  304. package/out/zero-solid/src/use-query.js.map +1 -1
  305. package/out/zero-solid/src/use-zero.js +1 -1
  306. package/out/zero-solid/src/use-zero.js.map +1 -1
  307. package/out/zql/src/ivm/constraint.d.ts.map +1 -1
  308. package/out/zql/src/ivm/constraint.js +4 -1
  309. package/out/zql/src/ivm/constraint.js.map +1 -1
  310. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  311. package/out/zql/src/ivm/exists.js +4 -1
  312. package/out/zql/src/ivm/exists.js.map +1 -1
  313. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  314. package/out/zql/src/ivm/join-utils.js +8 -2
  315. package/out/zql/src/ivm/join-utils.js.map +1 -1
  316. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  317. package/out/zql/src/ivm/memory-source.js +12 -3
  318. package/out/zql/src/ivm/memory-source.js.map +1 -1
  319. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  320. package/out/zql/src/ivm/push-accumulated.js +25 -2
  321. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  322. package/out/zql/src/ivm/take.d.ts.map +1 -1
  323. package/out/zql/src/ivm/take.js +24 -6
  324. package/out/zql/src/ivm/take.js.map +1 -1
  325. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  326. package/out/zql/src/ivm/union-fan-in.js +12 -3
  327. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  328. package/out/zqlite/src/table-source.d.ts.map +1 -1
  329. package/out/zqlite/src/table-source.js +1 -2
  330. package/out/zqlite/src/table-source.js.map +1 -1
  331. package/package.json +6 -2
  332. package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +0 -1
  333. package/out/zero-cache/src/services/change-source/column-metadata.js.map +0 -1
@@ -0,0 +1,342 @@
1
+ import { useVirtualizer, defaultKeyExtractor } from "@tanstack/react-virtual";
2
+ import { useReducer, useMemo, useState, useEffect, useLayoutEffect } from "react";
3
+ import { assert } from "../../shared/src/asserts.js";
4
+ import { pagingReducer } from "./paging-reducer.js";
5
+ import { useRows } from "./use-rows.js";
6
+ const MIN_PAGE_SIZE = 100;
7
+ const NUM_ROWS_FOR_LOADING_SKELETON = 1;
8
+ const TOP_ANCHOR = Object.freeze({
9
+ index: 0,
10
+ kind: "forward",
11
+ startRow: void 0
12
+ });
13
+ const createPermalinkAnchor = (id) => ({
14
+ id,
15
+ index: NUM_ROWS_FOR_LOADING_SKELETON,
16
+ kind: "permalink"
17
+ });
18
+ function useZeroVirtualizer({
19
+ // Tanstack Virtual params
20
+ estimateSize,
21
+ overscan = 5,
22
+ // Virtualizer defaults to 1.
23
+ getScrollElement,
24
+ getItemKey = defaultKeyExtractor,
25
+ // Zero specific params
26
+ listContextParams,
27
+ permalinkID,
28
+ getPageQuery,
29
+ getSingleQuery,
30
+ options,
31
+ toStartRow,
32
+ getRowKey,
33
+ // Permalink state persistence
34
+ permalinkState,
35
+ onPermalinkStateChange,
36
+ ...restVirtualizerOptions
37
+ }) {
38
+ const [
39
+ {
40
+ estimatedTotal,
41
+ hasReachedStart,
42
+ hasReachedEnd,
43
+ queryAnchor,
44
+ pagingPhase,
45
+ pendingScrollAdjustment
46
+ },
47
+ dispatch
48
+ ] = useReducer(
49
+ pagingReducer,
50
+ void 0,
51
+ () => {
52
+ const anchor2 = permalinkState ? permalinkState.anchor : permalinkID ? createPermalinkAnchor(permalinkID) : TOP_ANCHOR;
53
+ return {
54
+ estimatedTotal: permalinkState?.estimatedTotal ?? NUM_ROWS_FOR_LOADING_SKELETON,
55
+ hasReachedStart: permalinkState?.hasReachedStart ?? false,
56
+ hasReachedEnd: permalinkState?.hasReachedEnd ?? false,
57
+ queryAnchor: {
58
+ anchor: anchor2,
59
+ listContextParams
60
+ },
61
+ pagingPhase: "idle",
62
+ pendingScrollAdjustment: 0
63
+ };
64
+ }
65
+ );
66
+ const isListContextCurrent = queryAnchor.listContextParams === listContextParams;
67
+ const anchor = useMemo(() => {
68
+ if (isListContextCurrent) {
69
+ return queryAnchor.anchor;
70
+ }
71
+ return permalinkID ? createPermalinkAnchor(permalinkID) : TOP_ANCHOR;
72
+ }, [isListContextCurrent, queryAnchor.anchor, permalinkID]);
73
+ const [pageSize, setPageSize] = useState(MIN_PAGE_SIZE);
74
+ const {
75
+ rowAt,
76
+ rowsLength,
77
+ complete,
78
+ rowsEmpty,
79
+ atStart,
80
+ atEnd,
81
+ firstRowIndex,
82
+ permalinkNotFound
83
+ } = useRows({
84
+ pageSize,
85
+ anchor,
86
+ options,
87
+ getPageQuery,
88
+ getSingleQuery,
89
+ toStartRow
90
+ });
91
+ const newEstimatedTotal = firstRowIndex + rowsLength;
92
+ const virtualizer = useVirtualizer(
93
+ {
94
+ ...restVirtualizerOptions,
95
+ count: Math.max(estimatedTotal, newEstimatedTotal) + (!atEnd ? NUM_ROWS_FOR_LOADING_SKELETON : 0),
96
+ estimateSize,
97
+ overscan,
98
+ getScrollElement,
99
+ getItemKey: getRowKey ? (index) => {
100
+ const row = rowAt(index);
101
+ return row ? getRowKey(row) : getItemKey(index);
102
+ } : getItemKey,
103
+ initialOffset: () => {
104
+ if (permalinkState?.scrollTop !== void 0) {
105
+ return permalinkState.scrollTop;
106
+ }
107
+ if (anchor.kind === "permalink") {
108
+ return anchor.index * estimateSize(0);
109
+ }
110
+ return 0;
111
+ },
112
+ horizontal: false
113
+ }
114
+ );
115
+ useEffect(() => {
116
+ const newPageSize = virtualizer.scrollRect ? Math.max(
117
+ MIN_PAGE_SIZE,
118
+ makeEven(
119
+ Math.ceil(
120
+ virtualizer.scrollRect?.height / // TODO: Support dynamic item sizes
121
+ estimateSize(0)
122
+ ) * 3
123
+ )
124
+ ) : MIN_PAGE_SIZE;
125
+ if (newPageSize > pageSize) {
126
+ setPageSize(newPageSize);
127
+ }
128
+ }, [pageSize, virtualizer.scrollRect]);
129
+ useEffect(() => {
130
+ if (!isListContextCurrent || !onPermalinkStateChange) {
131
+ return;
132
+ }
133
+ const timeoutId = setTimeout(() => {
134
+ onPermalinkStateChange({
135
+ anchor,
136
+ scrollTop: virtualizer.scrollOffset ?? 0,
137
+ estimatedTotal,
138
+ hasReachedStart,
139
+ hasReachedEnd
140
+ });
141
+ }, 100);
142
+ return () => clearTimeout(timeoutId);
143
+ }, [
144
+ anchor,
145
+ virtualizer.scrollOffset,
146
+ estimatedTotal,
147
+ hasReachedStart,
148
+ hasReachedEnd,
149
+ isListContextCurrent,
150
+ onPermalinkStateChange
151
+ ]);
152
+ useEffect(() => {
153
+ if (atStart) {
154
+ dispatch({ type: "REACHED_START" });
155
+ }
156
+ }, [atStart]);
157
+ useEffect(() => {
158
+ if (atEnd) {
159
+ dispatch({ type: "REACHED_END" });
160
+ }
161
+ }, [atEnd]);
162
+ useEffect(() => {
163
+ if (complete && newEstimatedTotal > estimatedTotal) {
164
+ dispatch({ type: "UPDATE_ESTIMATED_TOTAL", newTotal: newEstimatedTotal });
165
+ }
166
+ }, [estimatedTotal, complete, newEstimatedTotal]);
167
+ useLayoutEffect(() => {
168
+ if (pendingScrollAdjustment !== 0) {
169
+ virtualizer.scrollToOffset(
170
+ (virtualizer.scrollOffset ?? 0) + pendingScrollAdjustment * // TODO: Support dynamic item sizes
171
+ estimateSize(0)
172
+ );
173
+ dispatch({ type: "SCROLL_ADJUSTED" });
174
+ }
175
+ }, [pendingScrollAdjustment, virtualizer]);
176
+ useEffect(() => {
177
+ if (rowsEmpty || !isListContextCurrent) {
178
+ return;
179
+ }
180
+ if (pagingPhase === "skipping" && pendingScrollAdjustment === 0) {
181
+ dispatch({ type: "PAGING_COMPLETE" });
182
+ return;
183
+ }
184
+ if (pendingScrollAdjustment !== 0) {
185
+ return;
186
+ }
187
+ if (firstRowIndex < 0) {
188
+ const placeholderRows = !atStart ? NUM_ROWS_FOR_LOADING_SKELETON : 0;
189
+ const offset = -firstRowIndex + placeholderRows;
190
+ const newAnchor = {
191
+ ...anchor,
192
+ index: anchor.index + offset
193
+ };
194
+ dispatch({ type: "SHIFT_ANCHOR_DOWN", offset, newAnchor });
195
+ return;
196
+ }
197
+ if (atStart && firstRowIndex > 0) {
198
+ dispatch({ type: "RESET_TO_TOP", offset: -firstRowIndex });
199
+ return;
200
+ }
201
+ }, [
202
+ firstRowIndex,
203
+ anchor,
204
+ atStart,
205
+ pendingScrollAdjustment,
206
+ pagingPhase,
207
+ rowsEmpty,
208
+ isListContextCurrent
209
+ // virtualizer - omitted to avoid infinite render loops from scroll events
210
+ ]);
211
+ useLayoutEffect(() => {
212
+ if (!isListContextCurrent) {
213
+ if (permalinkState) {
214
+ virtualizer.scrollToOffset(permalinkState.scrollTop);
215
+ dispatch({
216
+ type: "RESET_STATE",
217
+ estimatedTotal: permalinkState.estimatedTotal,
218
+ hasReachedStart: permalinkState.hasReachedStart,
219
+ hasReachedEnd: permalinkState.hasReachedEnd,
220
+ anchor: permalinkState.anchor,
221
+ listContextParams
222
+ });
223
+ } else if (permalinkID) {
224
+ virtualizer.scrollToOffset(
225
+ NUM_ROWS_FOR_LOADING_SKELETON * // TODO: Support dynamic item sizes
226
+ estimateSize(0)
227
+ );
228
+ dispatch({
229
+ type: "RESET_STATE",
230
+ estimatedTotal: NUM_ROWS_FOR_LOADING_SKELETON,
231
+ hasReachedStart: false,
232
+ hasReachedEnd: false,
233
+ anchor: createPermalinkAnchor(permalinkID),
234
+ listContextParams
235
+ });
236
+ } else {
237
+ virtualizer.scrollToOffset(0);
238
+ dispatch({
239
+ type: "RESET_STATE",
240
+ estimatedTotal: 0,
241
+ hasReachedStart: true,
242
+ hasReachedEnd: false,
243
+ anchor: TOP_ANCHOR,
244
+ listContextParams
245
+ });
246
+ }
247
+ }
248
+ }, [
249
+ isListContextCurrent,
250
+ permalinkState,
251
+ permalinkID,
252
+ virtualizer,
253
+ listContextParams
254
+ ]);
255
+ const total = hasReachedStart && hasReachedEnd ? estimatedTotal : void 0;
256
+ const virtualItems = virtualizer.getVirtualItems();
257
+ useEffect(() => {
258
+ if (!isListContextCurrent || virtualItems.length === 0 || !complete || pagingPhase !== "idle" || pendingScrollAdjustment !== 0) {
259
+ return;
260
+ }
261
+ if (atStart) {
262
+ if (firstRowIndex !== 0) {
263
+ dispatch({ type: "UPDATE_ANCHOR", anchor: TOP_ANCHOR });
264
+ return;
265
+ }
266
+ }
267
+ const updateAnchorForEdge = (targetIndex, type, indexOffset) => {
268
+ const index = toBoundIndex(targetIndex, firstRowIndex, rowsLength);
269
+ const startRow = rowAt(index);
270
+ assert(startRow !== void 0 || type === "forward");
271
+ dispatch({
272
+ type: "UPDATE_ANCHOR",
273
+ anchor: {
274
+ index: index + indexOffset,
275
+ kind: type,
276
+ startRow
277
+ }
278
+ });
279
+ };
280
+ const firstItem = virtualItems[0];
281
+ const lastItem = virtualItems[virtualItems.length - 1];
282
+ const nearPageEdgeThreshold = getNearPageEdgeThreshold(pageSize);
283
+ const distanceFromStart = firstItem.index - firstRowIndex;
284
+ const distanceFromEnd = firstRowIndex + rowsLength - lastItem.index;
285
+ if (!atStart && distanceFromStart <= nearPageEdgeThreshold) {
286
+ updateAnchorForEdge(
287
+ lastItem.index + 2 * nearPageEdgeThreshold,
288
+ "backward",
289
+ 0
290
+ );
291
+ return;
292
+ }
293
+ if (!atEnd && distanceFromEnd <= nearPageEdgeThreshold) {
294
+ updateAnchorForEdge(
295
+ firstItem.index - 2 * nearPageEdgeThreshold,
296
+ "forward",
297
+ 1
298
+ );
299
+ return;
300
+ }
301
+ }, [
302
+ isListContextCurrent,
303
+ virtualItems,
304
+ pagingPhase,
305
+ pendingScrollAdjustment,
306
+ complete,
307
+ pageSize,
308
+ firstRowIndex,
309
+ rowsLength,
310
+ atStart,
311
+ atEnd,
312
+ rowAt
313
+ ]);
314
+ return {
315
+ virtualizer,
316
+ rowAt,
317
+ complete,
318
+ rowsEmpty,
319
+ permalinkNotFound,
320
+ estimatedTotal,
321
+ total
322
+ };
323
+ }
324
+ function toBoundIndex(targetIndex, firstRowIndex, rowsLength) {
325
+ if (rowsLength === 0) {
326
+ return firstRowIndex;
327
+ }
328
+ return Math.max(
329
+ firstRowIndex,
330
+ Math.min(firstRowIndex + rowsLength - 1, targetIndex)
331
+ );
332
+ }
333
+ function getNearPageEdgeThreshold(pageSize) {
334
+ return Math.ceil(pageSize / 10);
335
+ }
336
+ function makeEven(n) {
337
+ return n % 2 === 0 ? n : n + 1;
338
+ }
339
+ export {
340
+ useZeroVirtualizer
341
+ };
342
+ //# sourceMappingURL=use-zero-virtualizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-zero-virtualizer.js","sources":["../../../../zero-react/src/use-zero-virtualizer.ts"],"sourcesContent":["import {\n defaultKeyExtractor,\n useVirtualizer,\n type Virtualizer,\n} from '@tanstack/react-virtual';\nimport {\n useEffect,\n useLayoutEffect,\n useMemo,\n useReducer,\n useState,\n type Key,\n} from 'react';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {pagingReducer, type PagingState} from './paging-reducer.ts';\nimport type {UseQueryOptions} from './use-query.tsx';\nimport {\n useRows,\n type Anchor,\n type GetPageQuery,\n type GetSingleQuery,\n} from './use-rows.ts';\n\n// Make sure this is even since we half it for permalink loading\nconst MIN_PAGE_SIZE = 100;\n\nconst NUM_ROWS_FOR_LOADING_SKELETON = 1;\n\n/**\n * State object that captures the virtualizer's scroll position and pagination state.\n * Used for persisting and restoring the virtualizer state across navigation or page reloads.\n *\n * @typeParam TStartRow - The type of the start row data used for pagination anchoring\n */\nexport type PermalinkHistoryState<TStartRow> = Readonly<{\n /** The anchor point for pagination (includes position, direction, and start row data) */\n anchor: Anchor<TStartRow>;\n /** The scroll position in pixels from the top of the scrollable container */\n scrollTop: number;\n /** The estimated total number of rows in the list */\n estimatedTotal: number;\n /** Whether the virtualizer has reached the start of the list */\n hasReachedStart: boolean;\n /** Whether the virtualizer has reached the end of the list */\n hasReachedEnd: boolean;\n}>;\n\nconst TOP_ANCHOR = Object.freeze({\n index: 0,\n kind: 'forward',\n startRow: undefined,\n}) satisfies Anchor<unknown>;\n\ntype TanstackUseVirtualizerOptions<\n TScrollElement extends Element,\n TItemElement extends Element,\n> = Parameters<typeof useVirtualizer<TScrollElement, TItemElement>>[0];\n\n/**\n * Options for configuring the Zero virtualizer.\n * Extends Tanstack Virtual's options with Zero-specific pagination and state management.\n *\n * @typeParam TScrollElement - The type of the scrollable container element\n * @typeParam TItemElement - The type of the individual item elements\n * @typeParam TListContextParams - The type of parameters that define the list's query context\n * @typeParam TRow - The type of row data returned from queries\n * @typeParam TStartRow - The type of data needed to anchor pagination (typically a subset of TRow)\n */\nexport type UseZeroVirtualizerOptions<\n TScrollElement extends Element,\n TItemElement extends Element,\n TListContextParams,\n TRow,\n TStartRow,\n> = Omit<\n TanstackUseVirtualizerOptions<TScrollElement, TItemElement>,\n // count is managed by useZeroVirtualizer\n | 'count'\n // initialOffset is managed by useZeroVirtualizer\n | 'initialOffset'\n // Only support vertical lists for now\n | 'horizontal'\n> & {\n /** Parameters that define the list's query context (filters, sort order, etc.) */\n listContextParams: TListContextParams;\n\n /** Optional ID to highlight/scroll to a specific row (permalink functionality) */\n permalinkID?: string | null | undefined;\n\n /** Function that returns a query for fetching a page of rows */\n getPageQuery: GetPageQuery<TRow, TStartRow>;\n /** Function that returns a query for fetching a single row by ID */\n getSingleQuery: GetSingleQuery<TRow>;\n /** Optional query options */\n options?: UseQueryOptions | undefined;\n /** Function to extract the start row data from a full row (for pagination anchoring) */\n toStartRow: (row: TRow) => TStartRow;\n\n /**\n * Function to extract a unique key from a row, used for stable item identification.\n * If provided, this will override {@linkcode TanstackUseVirtualizerOptions.getItemKey}\n */\n getRowKey?: ((row: TRow) => Key) | undefined;\n\n /**\n * Optional current permalink state for restoring virtualizer position.\n * If provided along with `onPermalinkStateChange`, enables state persistence.\n * If not provided, virtualizer operates in uncontrolled mode.\n */\n permalinkState?: PermalinkHistoryState<TStartRow> | null | undefined;\n /**\n * Optional callback invoked when the virtualizer state changes.\n * Use this to persist state (e.g., to browser history, local storage, etc.).\n * Called with the new state approximately 100ms after scroll/pagination changes.\n */\n onPermalinkStateChange?: (state: PermalinkHistoryState<TStartRow>) => void;\n};\n\nconst createPermalinkAnchor = (id: string) =>\n ({\n id,\n index: NUM_ROWS_FOR_LOADING_SKELETON,\n kind: 'permalink',\n }) as const;\n\n/**\n * Result object returned by the useZeroVirtualizer hook.\n *\n * @typeParam TScrollElement - The type of the scrollable container element\n * @typeParam TItemElement - The type of the individual item elements\n * @typeParam TRow - The type of row data returned from queries\n */\nexport type ZeroVirtualizerResult<\n TScrollElement extends Element,\n TItemElement extends Element,\n TRow,\n> = {\n /** The Tanstack Virtual virtualizer instance for rendering virtual items */\n virtualizer: Virtualizer<TScrollElement, TItemElement>;\n /** Function to get the row data at a specific index, or undefined if not loaded */\n rowAt: (index: number) => TRow | undefined;\n /** Whether all initially requested data has finished loading */\n complete: boolean;\n /** Whether the list is empty (no rows exist matching the query) */\n rowsEmpty: boolean;\n /** Whether the specified permalinkID was not found in the query results */\n permalinkNotFound: boolean;\n /** Estimated total number of rows (may be inexact until both ends are reached) */\n estimatedTotal: number;\n /** Exact total number of rows, or undefined if not yet known (requires reaching both ends) */\n total: number | undefined;\n};\n\n/**\n * Hook that creates a virtualized list with bidirectional pagination and state persistence.\n *\n * This hook combines Tanstack Virtual's efficient virtualization with Zero's reactive queries\n * to create infinitely scrolling lists that load data on demand. It supports:\n * - Bidirectional scrolling (load more items at top or bottom)\n * - Permalink functionality (jump to and highlight specific items)\n * - State persistence (restore scroll position across navigation)\n * - Dynamic page sizing based on viewport\n *\n * @typeParam TScrollElement - The type of the scrollable container element\n * @typeParam TItemElement - The type of the individual item elements\n * @typeParam TListContextParams - The type of parameters that define the list's query context\n * @typeParam TRow - The type of row data returned from queries\n * @typeParam TStartRow - The type of data needed to anchor pagination\n *\n * @param options - Configuration options including query functions, sizing, and state management\n * @returns An object containing the virtualizer instance, row accessor, and state flags\n *\n * @example\n * ```tsx\n * const {virtualizer, rowAt, complete} = useZeroVirtualizer({\n * estimateSize: () => 50,\n * getScrollElement: () => scrollRef.current,\n * listContextParams: {projectId: 'abc'},\n * getPageQuery: (limit, start, dir) => z.query.issues.where(...).limit(limit),\n * getSingleQuery: (id) => z.query.issues.where('id', id),\n * toStartRow: (row) => ({id: row.id, created: row.created}),\n * });\n * ```\n */\nexport function useZeroVirtualizer<\n TScrollElement extends Element,\n TItemElement extends Element,\n TListContextParams,\n TRow,\n TStartRow,\n>({\n // Tanstack Virtual params\n estimateSize,\n overscan = 5, // Virtualizer defaults to 1.\n getScrollElement,\n getItemKey = defaultKeyExtractor,\n\n // Zero specific params\n listContextParams,\n permalinkID,\n getPageQuery,\n getSingleQuery,\n options,\n toStartRow,\n getRowKey,\n\n // Permalink state persistence\n permalinkState,\n onPermalinkStateChange,\n\n ...restVirtualizerOptions\n}: UseZeroVirtualizerOptions<\n TScrollElement,\n TItemElement,\n TListContextParams,\n TRow,\n TStartRow\n>): ZeroVirtualizerResult<TScrollElement, TItemElement, TRow> {\n // Initialize paging state from permalinkState directly to avoid Strict Mode double-mount rows\n const [\n {\n estimatedTotal,\n hasReachedStart,\n hasReachedEnd,\n queryAnchor,\n pagingPhase,\n pendingScrollAdjustment,\n },\n dispatch,\n ] = useReducer(\n pagingReducer<TListContextParams, TStartRow>,\n undefined,\n (): PagingState<TListContextParams, TStartRow> => {\n const anchor = permalinkState\n ? permalinkState.anchor\n : permalinkID\n ? createPermalinkAnchor(permalinkID)\n : TOP_ANCHOR;\n return {\n estimatedTotal:\n permalinkState?.estimatedTotal ?? NUM_ROWS_FOR_LOADING_SKELETON,\n hasReachedStart: permalinkState?.hasReachedStart ?? false,\n hasReachedEnd: permalinkState?.hasReachedEnd ?? false,\n queryAnchor: {\n anchor,\n listContextParams,\n },\n pagingPhase: 'idle',\n pendingScrollAdjustment: 0,\n };\n },\n );\n\n const isListContextCurrent =\n queryAnchor.listContextParams === listContextParams;\n\n const anchor = useMemo(() => {\n if (isListContextCurrent) {\n return queryAnchor.anchor;\n }\n return permalinkID ? createPermalinkAnchor(permalinkID) : TOP_ANCHOR;\n }, [isListContextCurrent, queryAnchor.anchor, permalinkID]);\n\n const [pageSize, setPageSize] = useState(MIN_PAGE_SIZE);\n\n const {\n rowAt,\n rowsLength,\n complete,\n rowsEmpty,\n atStart,\n atEnd,\n firstRowIndex,\n permalinkNotFound,\n } = useRows({\n pageSize,\n anchor,\n options,\n getPageQuery,\n getSingleQuery,\n toStartRow,\n });\n\n const newEstimatedTotal = firstRowIndex + rowsLength;\n\n const virtualizer: Virtualizer<TScrollElement, TItemElement> = useVirtualizer(\n {\n ...restVirtualizerOptions,\n count:\n Math.max(estimatedTotal, newEstimatedTotal) +\n (!atEnd ? NUM_ROWS_FOR_LOADING_SKELETON : 0),\n estimateSize,\n overscan,\n getScrollElement,\n getItemKey: getRowKey\n ? (index: number) => {\n const row = rowAt(index);\n return row ? getRowKey(row) : getItemKey(index);\n }\n : getItemKey,\n initialOffset: () => {\n if (permalinkState?.scrollTop !== undefined) {\n return permalinkState.scrollTop;\n }\n if (anchor.kind === 'permalink') {\n // TODO: Support dynamic item sizes\n return anchor.index * estimateSize(0);\n }\n return 0;\n },\n horizontal: false,\n },\n );\n\n useEffect(() => {\n // Make sure page size is enough to fill the scroll element at least\n // 3 times. Don't shrink page size.\n const newPageSize = virtualizer.scrollRect\n ? Math.max(\n MIN_PAGE_SIZE,\n makeEven(\n Math.ceil(\n virtualizer.scrollRect?.height /\n // TODO: Support dynamic item sizes\n estimateSize(0),\n ) * 3,\n ),\n )\n : MIN_PAGE_SIZE;\n if (newPageSize > pageSize) {\n setPageSize(newPageSize);\n }\n }, [pageSize, virtualizer.scrollRect]);\n\n useEffect(() => {\n if (!isListContextCurrent || !onPermalinkStateChange) {\n return;\n }\n const timeoutId = setTimeout(() => {\n onPermalinkStateChange({\n anchor,\n scrollTop: virtualizer.scrollOffset ?? 0,\n estimatedTotal,\n hasReachedStart,\n hasReachedEnd,\n });\n }, 100);\n\n return () => clearTimeout(timeoutId);\n }, [\n anchor,\n virtualizer.scrollOffset,\n estimatedTotal,\n hasReachedStart,\n hasReachedEnd,\n isListContextCurrent,\n onPermalinkStateChange,\n ]);\n\n useEffect(() => {\n if (atStart) {\n dispatch({type: 'REACHED_START'});\n }\n }, [atStart]);\n\n useEffect(() => {\n if (atEnd) {\n dispatch({type: 'REACHED_END'});\n }\n }, [atEnd]);\n\n useEffect(() => {\n if (complete && newEstimatedTotal > estimatedTotal) {\n dispatch({type: 'UPDATE_ESTIMATED_TOTAL', newTotal: newEstimatedTotal});\n }\n }, [estimatedTotal, complete, newEstimatedTotal]);\n\n // Apply scroll adjustments synchronously with layout to prevent visual jumps\n useLayoutEffect(() => {\n if (pendingScrollAdjustment !== 0) {\n virtualizer.scrollToOffset(\n (virtualizer.scrollOffset ?? 0) +\n pendingScrollAdjustment *\n // TODO: Support dynamic item sizes\n estimateSize(0),\n );\n\n dispatch({type: 'SCROLL_ADJUSTED'});\n }\n }, [pendingScrollAdjustment, virtualizer]);\n\n useEffect(() => {\n if (rowsEmpty || !isListContextCurrent) {\n return;\n }\n\n if (pagingPhase === 'skipping' && pendingScrollAdjustment === 0) {\n dispatch({type: 'PAGING_COMPLETE'});\n return;\n }\n\n // Skip if there's a pending scroll adjustment - let useLayoutEffect handle it\n if (pendingScrollAdjustment !== 0) {\n return;\n }\n\n // First row is before start of list - need to shift down\n if (firstRowIndex < 0) {\n const placeholderRows = !atStart ? NUM_ROWS_FOR_LOADING_SKELETON : 0;\n const offset = -firstRowIndex + placeholderRows;\n const newAnchor = {\n ...anchor,\n index: anchor.index + offset,\n };\n dispatch({type: 'SHIFT_ANCHOR_DOWN', offset, newAnchor});\n return;\n }\n\n if (atStart && firstRowIndex > 0) {\n dispatch({type: 'RESET_TO_TOP', offset: -firstRowIndex});\n return;\n }\n }, [\n firstRowIndex,\n anchor,\n atStart,\n pendingScrollAdjustment,\n pagingPhase,\n rowsEmpty,\n isListContextCurrent,\n // virtualizer - omitted to avoid infinite render loops from scroll events\n ]);\n\n // Use layoutEffect to restore scroll position synchronously to avoid visual jumps\n useLayoutEffect(() => {\n if (!isListContextCurrent) {\n if (permalinkState) {\n virtualizer.scrollToOffset(permalinkState.scrollTop);\n dispatch({\n type: 'RESET_STATE',\n estimatedTotal: permalinkState.estimatedTotal,\n hasReachedStart: permalinkState.hasReachedStart,\n hasReachedEnd: permalinkState.hasReachedEnd,\n anchor: permalinkState.anchor,\n listContextParams,\n });\n } else if (permalinkID) {\n virtualizer.scrollToOffset(\n NUM_ROWS_FOR_LOADING_SKELETON *\n // TODO: Support dynamic item sizes\n estimateSize(0),\n );\n dispatch({\n type: 'RESET_STATE',\n estimatedTotal: NUM_ROWS_FOR_LOADING_SKELETON,\n hasReachedStart: false,\n hasReachedEnd: false,\n anchor: createPermalinkAnchor(permalinkID),\n listContextParams,\n });\n } else {\n virtualizer.scrollToOffset(0);\n dispatch({\n type: 'RESET_STATE',\n estimatedTotal: 0,\n hasReachedStart: true,\n hasReachedEnd: false,\n anchor: TOP_ANCHOR,\n listContextParams,\n });\n }\n }\n }, [\n isListContextCurrent,\n permalinkState,\n permalinkID,\n virtualizer,\n listContextParams,\n ]);\n\n const total = hasReachedStart && hasReachedEnd ? estimatedTotal : undefined;\n\n const virtualItems = virtualizer.getVirtualItems();\n\n useEffect(() => {\n if (\n !isListContextCurrent ||\n virtualItems.length === 0 ||\n !complete ||\n pagingPhase !== 'idle' ||\n pendingScrollAdjustment !== 0\n ) {\n return;\n }\n\n if (atStart) {\n if (firstRowIndex !== 0) {\n dispatch({type: 'UPDATE_ANCHOR', anchor: TOP_ANCHOR});\n return;\n }\n }\n\n const updateAnchorForEdge = (\n targetIndex: number,\n type: 'forward' | 'backward',\n indexOffset: number,\n ) => {\n const index = toBoundIndex(targetIndex, firstRowIndex, rowsLength);\n const startRow = rowAt(index);\n assert(startRow !== undefined || type === 'forward');\n dispatch({\n type: 'UPDATE_ANCHOR',\n anchor: {\n index: index + indexOffset,\n kind: type,\n startRow,\n } as Anchor<TStartRow>,\n });\n };\n\n const firstItem = virtualItems[0];\n const lastItem = virtualItems[virtualItems.length - 1];\n const nearPageEdgeThreshold = getNearPageEdgeThreshold(pageSize);\n\n const distanceFromStart = firstItem.index - firstRowIndex;\n const distanceFromEnd = firstRowIndex + rowsLength - lastItem.index;\n\n if (!atStart && distanceFromStart <= nearPageEdgeThreshold) {\n updateAnchorForEdge(\n lastItem.index + 2 * nearPageEdgeThreshold,\n 'backward',\n 0,\n );\n return;\n }\n\n if (!atEnd && distanceFromEnd <= nearPageEdgeThreshold) {\n updateAnchorForEdge(\n firstItem.index - 2 * nearPageEdgeThreshold,\n 'forward',\n 1,\n );\n return;\n }\n }, [\n isListContextCurrent,\n virtualItems,\n pagingPhase,\n pendingScrollAdjustment,\n complete,\n pageSize,\n firstRowIndex,\n rowsLength,\n atStart,\n atEnd,\n rowAt,\n ]);\n\n return {\n virtualizer,\n rowAt,\n complete,\n rowsEmpty,\n permalinkNotFound,\n estimatedTotal,\n total,\n };\n}\n\n/**\n * Clamps an index to be within the valid range of rows.\n * @param targetIndex - The desired index to clamp\n * @param firstRowIndex - The first valid row index\n * @param rowsLength - The number of rows available\n * @returns The clamped index within [firstRowIndex, firstRowIndex + rowsLength - 1]\n */\nfunction toBoundIndex(\n targetIndex: number,\n firstRowIndex: number,\n rowsLength: number,\n): number {\n if (rowsLength === 0) {\n return firstRowIndex;\n }\n return Math.max(\n firstRowIndex,\n Math.min(firstRowIndex + rowsLength - 1, targetIndex),\n );\n}\n\nfunction getNearPageEdgeThreshold(pageSize: number) {\n return Math.ceil(pageSize / 10);\n}\n\nfunction makeEven(n: number) {\n return n % 2 === 0 ? n : n + 1;\n}\n"],"names":["anchor"],"mappings":"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"}
@@ -57,7 +57,7 @@ function ZeroProvider({ children, init, ...props }) {
57
57
  };
58
58
  }, [init, ...keysWithoutAuth]);
59
59
  useEffect(() => {
60
- if (!zero) return;
60
+ if (!zero || isExternalZero) return;
61
61
  const authChanged = auth !== prevAuthRef.current;
62
62
  if (authChanged) {
63
63
  prevAuthRef.current = auth;
@@ -1 +1 @@
1
- {"version":3,"file":"zero-provider.js","sources":["../../../../zero-react/src/zero-provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {stringCompare} from '../../shared/src/string-compare.ts';\nimport {\n Zero,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type Schema,\n type ZeroOptions,\n} from './zero.ts';\n\n// oxlint-disable-next-line no-explicit-any\nexport const ZeroContext = createContext<Zero<any, any, any> | undefined>(\n undefined,\n);\n\nexport function useZero<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>(): Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD, Context>;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport type ZeroProviderProps<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n> = (ZeroOptions<S, MD, Context> | {zero: Zero<S, MD, Context>}) & {\n init?: (zero: Zero<S, MD, Context>) => void;\n children: ReactNode;\n};\n\nconst NO_AUTH_SET = Symbol();\n\nexport function ZeroProvider<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>({children, init, ...props}: ZeroProviderProps<S, MD, Context>) {\n const isExternalZero = 'zero' in props;\n\n const [zero, setZero] = useState<Zero<S, MD, Context> | undefined>(\n isExternalZero ? props.zero : undefined,\n );\n\n const auth = 'auth' in props ? props.auth : NO_AUTH_SET;\n const prevAuthRef = useRef<typeof auth>(auth);\n\n const keysWithoutAuth = useMemo(\n () =>\n Object.entries(props)\n .filter(([key]) => key !== 'auth')\n .sort(([a], [b]) => stringCompare(a, b))\n .map(([_, value]) => value),\n [props],\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if (isExternalZero) {\n setZero(props.zero);\n return;\n }\n\n const z = new Zero(props);\n init?.(z);\n setZero(z);\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n // we intentionally don't include auth in the dependency array\n // to avoid closing zero when auth changes\n }, [init, ...keysWithoutAuth]);\n\n useEffect(() => {\n if (!zero) return;\n\n const authChanged = auth !== prevAuthRef.current;\n\n if (authChanged) {\n prevAuthRef.current = auth;\n void zero.connection.connect({\n auth: auth === NO_AUTH_SET ? undefined : auth,\n });\n }\n }, [auth, zero]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,cAAc;AAAA,EACzB;AACF;AAEO,SAAS,UAIU;AACxB,QAAM,OAAO,WAAW,WAAW;AACnC,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AACT;AAaO,SAAS,gBAIZ;AACF,SAAO,MAAM,QAAA;AACf;AAWA,MAAM,cAAc,OAAA;AAEb,SAAS,aAId,EAAC,UAAU,MAAM,GAAG,SAA2C;AAC/D,QAAM,iBAAiB,UAAU;AAEjC,QAAM,CAAC,MAAM,OAAO,IAAI;AAAA,IACtB,iBAAiB,MAAM,OAAO;AAAA,EAAA;AAGhC,QAAM,OAAO,UAAU,QAAQ,MAAM,OAAO;AAC5C,QAAM,cAAc,OAAoB,IAAI;AAE5C,QAAM,kBAAkB;AAAA,IACtB,MACE,OAAO,QAAQ,KAAK,EACjB,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,MAAM,EAChC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,EACtC,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM,KAAK;AAAA,IAC9B,CAAC,KAAK;AAAA,EAAA;AAQR,YAAU,MAAM;AACd,QAAI,gBAAgB;AAClB,cAAQ,MAAM,IAAI;AAClB;AAAA,IACF;AAEA,UAAM,IAAI,IAAI,KAAK,KAAK;AACxB,WAAO,CAAC;AACR,YAAQ,CAAC;AAET,WAAO,MAAM;AACX,WAAK,EAAE,MAAA;AACP,cAAQ,MAAS;AAAA,IACnB;AAAA,EAGF,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC;AAE7B,YAAU,MAAM;AACd,QAAI,CAAC,KAAM;AAEX,UAAM,cAAc,SAAS,YAAY;AAEzC,QAAI,aAAa;AACf,kBAAY,UAAU;AACtB,WAAK,KAAK,WAAW,QAAQ;AAAA,QAC3B,MAAM,SAAS,cAAc,SAAY;AAAA,MAAA,CAC1C;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,IAAI,CAAC;AAEf,SACE,QAAQ,oBAAC,YAAY,UAAZ,EAAqB,OAAO,MAAO,UAAS;AAEzD;"}
1
+ {"version":3,"file":"zero-provider.js","sources":["../../../../zero-react/src/zero-provider.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {stringCompare} from '../../shared/src/string-compare.ts';\nimport {\n Zero,\n type CustomMutatorDefs,\n type DefaultContext,\n type DefaultSchema,\n type Schema,\n type ZeroOptions,\n} from './zero.ts';\n\n// oxlint-disable-next-line no-explicit-any\nexport const ZeroContext = createContext<Zero<any, any, any> | undefined>(\n undefined,\n);\n\nexport function useZero<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>(): Zero<S, MD, Context> {\n const zero = useContext(ZeroContext);\n if (zero === undefined) {\n throw new Error('useZero must be used within a ZeroProvider');\n }\n return zero as Zero<S, MD, Context>;\n}\n\n/**\n * @deprecated Use {@linkcode useZero} instead, alongside default types defined with:\n *\n * ```ts\n * declare module '@rocicorp/zero' {\n * interface DefaultTypes {\n * schema: typeof schema;\n * context: Context;\n * }\n * }\n */\nexport function createUseZero<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>() {\n return () => useZero<S, MD, Context>();\n}\n\nexport type ZeroProviderProps<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n> = (ZeroOptions<S, MD, Context> | {zero: Zero<S, MD, Context>}) & {\n init?: (zero: Zero<S, MD, Context>) => void;\n children: ReactNode;\n};\n\nconst NO_AUTH_SET = Symbol();\n\nexport function ZeroProvider<\n S extends Schema = DefaultSchema,\n MD extends CustomMutatorDefs | undefined = undefined,\n Context = DefaultContext,\n>({children, init, ...props}: ZeroProviderProps<S, MD, Context>) {\n const isExternalZero = 'zero' in props;\n\n const [zero, setZero] = useState<Zero<S, MD, Context> | undefined>(\n isExternalZero ? props.zero : undefined,\n );\n\n const auth = 'auth' in props ? props.auth : NO_AUTH_SET;\n const prevAuthRef = useRef<typeof auth>(auth);\n\n const keysWithoutAuth = useMemo(\n () =>\n Object.entries(props)\n .filter(([key]) => key !== 'auth')\n .sort(([a], [b]) => stringCompare(a, b))\n .map(([_, value]) => value),\n [props],\n );\n\n // If Zero is not passed in, we construct it, but only client-side.\n // Zero doesn't really work SSR today so this is usually the right thing.\n // When we support Zero SSR this will either become a breaking change or\n // more likely server support will be opt-in with a new prop on this\n // component.\n useEffect(() => {\n if (isExternalZero) {\n setZero(props.zero);\n return;\n }\n\n const z = new Zero(props);\n init?.(z);\n setZero(z);\n\n return () => {\n void z.close();\n setZero(undefined);\n };\n // we intentionally don't include auth in the dependency array\n // to avoid closing zero when auth changes\n }, [init, ...keysWithoutAuth]);\n\n useEffect(() => {\n if (!zero || isExternalZero) return;\n\n const authChanged = auth !== prevAuthRef.current;\n\n if (authChanged) {\n prevAuthRef.current = auth;\n void zero.connection.connect({\n auth: auth === NO_AUTH_SET ? undefined : auth,\n });\n }\n }, [auth, zero]);\n\n return (\n zero && <ZeroContext.Provider value={zero}>{children}</ZeroContext.Provider>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBO,MAAM,cAAc;AAAA,EACzB;AACF;AAEO,SAAS,UAIU;AACxB,QAAM,OAAO,WAAW,WAAW;AACnC,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACA,SAAO;AACT;AAaO,SAAS,gBAIZ;AACF,SAAO,MAAM,QAAA;AACf;AAWA,MAAM,cAAc,OAAA;AAEb,SAAS,aAId,EAAC,UAAU,MAAM,GAAG,SAA2C;AAC/D,QAAM,iBAAiB,UAAU;AAEjC,QAAM,CAAC,MAAM,OAAO,IAAI;AAAA,IACtB,iBAAiB,MAAM,OAAO;AAAA,EAAA;AAGhC,QAAM,OAAO,UAAU,QAAQ,MAAM,OAAO;AAC5C,QAAM,cAAc,OAAoB,IAAI;AAE5C,QAAM,kBAAkB;AAAA,IACtB,MACE,OAAO,QAAQ,KAAK,EACjB,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,MAAM,EAChC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,EACtC,IAAI,CAAC,CAAC,GAAG,KAAK,MAAM,KAAK;AAAA,IAC9B,CAAC,KAAK;AAAA,EAAA;AAQR,YAAU,MAAM;AACd,QAAI,gBAAgB;AAClB,cAAQ,MAAM,IAAI;AAClB;AAAA,IACF;AAEA,UAAM,IAAI,IAAI,KAAK,KAAK;AACxB,WAAO,CAAC;AACR,YAAQ,CAAC;AAET,WAAO,MAAM;AACX,WAAK,EAAE,MAAA;AACP,cAAQ,MAAS;AAAA,IACnB;AAAA,EAGF,GAAG,CAAC,MAAM,GAAG,eAAe,CAAC;AAE7B,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,eAAgB;AAE7B,UAAM,cAAc,SAAS,YAAY;AAEzC,QAAI,aAAa;AACf,kBAAY,UAAU;AACtB,WAAK,KAAK,WAAW,QAAQ;AAAA,QAC3B,MAAM,SAAS,cAAc,SAAY;AAAA,MAAA,CAC1C;AAAA,IACH;AAAA,EACF,GAAG,CAAC,MAAM,IAAI,CAAC;AAEf,SACE,QAAQ,oBAAC,YAAY,UAAZ,EAAqB,OAAO,MAAO,UAAS;AAEzD;"}
@@ -1,4 +1,3 @@
1
- import { type SQL } from 'drizzle-orm';
2
1
  import type { PgDatabase, PgQueryResultHKT, PgTransaction } from 'drizzle-orm/pg-core';
3
2
  import type { ExtractTablesWithRelations } from 'drizzle-orm/relations';
4
3
  import type { Schema } from '../../../zero-types/src/schema.ts';
@@ -17,10 +16,6 @@ export declare class DrizzleConnection<TDrizzle extends DrizzleDatabase, TTransa
17
16
  constructor(drizzle: TDrizzle);
18
17
  transaction<T>(fn: (tx: DBTransaction<TTransaction>) => Promise<T>): Promise<T>;
19
18
  }
20
- /**
21
- * Turn `$1, $2...` placeholders into a Drizzle SQL object with bound params.
22
- */
23
- export declare function fromDollarParams(text: string, params: unknown[]): SQL;
24
19
  export declare function toIterableRows(result: unknown): Iterable<Row>;
25
20
  /**
26
21
  * Wrap a `drizzle-orm` database for Zero ZQL.
@@ -35,24 +30,29 @@ export declare function toIterableRows(result: unknown): Iterable<Row>;
35
30
  * ```ts
36
31
  * import {Pool} from 'pg';
37
32
  * import {drizzle} from 'drizzle-orm/node-postgres';
38
- * import type {ServerTransaction} from '@rocicorp/zero';
33
+ * import {defineMutator, defineMutators} from '@rocicorp/zero';
34
+ * import {zeroDrizzle} from '@rocicorp/zero/server/adapters/drizzle';
35
+ * import {z} from 'zod/mini';
39
36
  *
40
37
  * const pool = new Pool({connectionString: process.env.ZERO_UPSTREAM_DB!});
41
38
  * const drizzleDb = drizzle(pool, {schema: drizzleSchema});
42
- *
43
39
  * const zql = zeroDrizzle(schema, drizzleDb);
44
40
  *
45
- * // Define the server mutator transaction type using the helper
46
- * type ServerTx = ServerTransaction<Schema, DrizzleTransaction<typeof drizzleDb>>;
47
- *
48
- * async function createUser(
49
- * tx: ServerTx,
50
- * {id, name}: {id: string; name: string},
51
- * ) {
52
- * await tx.dbTransaction.wrappedTransaction
53
- * .insert(drizzleSchema.user)
54
- * .values({id, name})
55
- * }
41
+ * export const serverMutators = defineMutators({
42
+ * user: {
43
+ * create: defineMutator(
44
+ * z.object({id: z.string(), name: z.string()}),
45
+ * async ({tx, args}) => {
46
+ * if (tx.location !== 'server') {
47
+ * throw new Error('Server-only mutator');
48
+ * }
49
+ * await tx.dbTransaction.wrappedTransaction
50
+ * .insert(drizzleSchema.user)
51
+ * .values({id: args.id, name: args.name, status: 'active'});
52
+ * },
53
+ * ),
54
+ * },
55
+ * });
56
56
  * ```
57
57
  */
58
58
  export declare function zeroDrizzle<TSchema extends Schema, TDrizzle extends DrizzleDatabase>(schema: TSchema, client: TDrizzle): ZQLDatabase<TSchema, DrizzleTransaction<TDrizzle>>;
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../../../../zero-server/src/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,GAAG,EAAC,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,uBAAuB,CAAC;AAGtE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAE9D,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,GAAG,EACJ,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAE/C,YAAY,EAAC,WAAW,EAAC,CAAC;AAE1B,MAAM,MAAM,eAAe,CACzB,YAAY,SAAS,gBAAgB,GAAG,gBAAgB,EACxD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAC5B,WAAW,SAAS,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,SAAS,UAAU,CACtE,gBAAgB,EAChB,MAAM,eAAe,CACtB,GACG,eAAe,GACf,WAAW,IACb,aAAa,CACf,gBAAgB,EAChB,OAAO,EACP,0BAA0B,CAAC,OAAO,CAAC,CACpC,CAAC;AAEF,qBAAa,iBAAiB,CAC5B,QAAQ,SAAS,eAAe,EAChC,YAAY,SACV,kBAAkB,CAAC,QAAQ,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAC7D,YAAW,YAAY,CAAC,YAAY,CAAC;;gBAIzB,OAAO,EAAE,QAAQ;IAI7B,WAAW,CAAC,CAAC,EACX,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,CAAC,CAAC;CASd;AAkCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,GAAG,CAiBrE;AAUD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAuB7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAAS,MAAM,EACtB,QAAQ,SAAS,eAAe,EAEhC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,QAAQ,GACf,WAAW,CAAC,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAKpD"}
1
+ {"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../../../../zero-server/src/adapters/drizzle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAC,0BAA0B,EAAC,MAAM,uBAAuB,CAAC;AAGtE,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAE9D,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,GAAG,EACJ,MAAM,mCAAmC,CAAC;AAG3C,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAE/C,YAAY,EAAC,WAAW,EAAC,CAAC;AAE1B,MAAM,MAAM,eAAe,CACzB,YAAY,SAAS,gBAAgB,GAAG,gBAAgB,EACxD,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC/D,UAAU,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;AAEtC;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,CAC5B,WAAW,SAAS,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,WAAW,SAAS,UAAU,CACtE,gBAAgB,EAChB,MAAM,eAAe,CACtB,GACG,eAAe,GACf,WAAW,IACb,aAAa,CACf,gBAAgB,EAChB,OAAO,EACP,0BAA0B,CAAC,OAAO,CAAC,CACpC,CAAC;AAEF,qBAAa,iBAAiB,CAC5B,QAAQ,SAAS,eAAe,EAChC,YAAY,SACV,kBAAkB,CAAC,QAAQ,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAC7D,YAAW,YAAY,CAAC,YAAY,CAAC;;gBAIzB,OAAO,EAAE,QAAQ;IAI7B,WAAW,CAAC,CAAC,EACX,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAClD,OAAO,CAAC,CAAC,CAAC;CASd;AA+CD,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAuB7D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,WAAW,CACzB,OAAO,SAAS,MAAM,EACtB,QAAQ,SAAS,eAAe,EAEhC,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,QAAQ,GACf,WAAW,CAAC,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAKpD"}
@@ -1,4 +1,3 @@
1
- import { sql } from "drizzle-orm";
2
1
  import { executePostgresQuery } from "../pg-query-executor.js";
3
2
  import { ZQLDatabase } from "../zql-database.js";
4
3
  class DrizzleConnection {
@@ -30,29 +29,17 @@ class DrizzleInternalTransaction {
30
29
  serverSchema
31
30
  );
32
31
  }
33
- async query(sql2, params) {
34
- const stmt = fromDollarParams(sql2, params);
35
- const result = await this.wrappedTransaction.execute(stmt);
32
+ async query(sql, params) {
33
+ const prepared = this.wrappedTransaction._.session.prepareQuery(
34
+ { sql, params },
35
+ void 0,
36
+ void 0,
37
+ false
38
+ );
39
+ const result = await prepared.execute();
36
40
  return toIterableRows(result);
37
41
  }
38
42
  }
39
- function fromDollarParams(text, params) {
40
- const re = /\$(\d+)/g;
41
- const s = sql.empty();
42
- let last = 0;
43
- let m;
44
- while ((m = re.exec(text)) !== null) {
45
- const idx = Number(m[1]) - 1;
46
- if (idx < 0 || idx >= params.length) {
47
- throw new Error(`Missing param for $${m[1]}`);
48
- }
49
- if (m.index > last) s.append(sql.raw(text.slice(last, m.index)));
50
- s.append(sql`${params[idx]}`);
51
- last = m.index + m[0].length;
52
- }
53
- if (last < text.length) s.append(sql.raw(text.slice(last)));
54
- return s;
55
- }
56
43
  function isIterable(value) {
57
44
  return (
58
45
  // oxlint-disable-next-line eqeqeq
@@ -91,7 +78,6 @@ function zeroDrizzle(schema, client) {
91
78
  }
92
79
  export {
93
80
  DrizzleConnection,
94
- fromDollarParams,
95
81
  toIterableRows,
96
82
  zeroDrizzle
97
83
  };
@@ -1 +1 @@
1
- {"version":3,"file":"drizzle.js","sources":["../../../../../zero-server/src/adapters/drizzle.ts"],"sourcesContent":["import {sql, type SQL} from 'drizzle-orm';\nimport type {\n PgDatabase,\n PgQueryResultHKT,\n PgTransaction,\n} from 'drizzle-orm/pg-core';\nimport type {ExtractTablesWithRelations} from 'drizzle-orm/relations';\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 {\n DBConnection,\n DBTransaction,\n Row,\n} from '../../../zql/src/mutate/custom.ts';\nimport type {HumanReadable} from '../../../zql/src/query/query.ts';\nimport {executePostgresQuery} from '../pg-query-executor.ts';\nimport {ZQLDatabase} from '../zql-database.ts';\n\nexport type {ZQLDatabase};\n\nexport type DrizzleDatabase<\n TQueryResult extends PgQueryResultHKT = PgQueryResultHKT,\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> = PgDatabase<TQueryResult, TSchema>;\n\n/**\n * Helper type for the wrapped transaction used by drizzle-orm.\n *\n * @remarks Use with `ServerTransaction` as `ServerTransaction<Schema, DrizzleTransaction<typeof drizzleDb>>`.\n */\nexport type DrizzleTransaction<\n TDbOrSchema extends DrizzleDatabase | Record<string, unknown>,\n TSchema extends Record<string, unknown> = TDbOrSchema extends PgDatabase<\n PgQueryResultHKT,\n infer TInferredSchema\n >\n ? TInferredSchema\n : TDbOrSchema,\n> = PgTransaction<\n PgQueryResultHKT,\n TSchema,\n ExtractTablesWithRelations<TSchema>\n>;\n\nexport class DrizzleConnection<\n TDrizzle extends DrizzleDatabase,\n TTransaction extends\n DrizzleTransaction<TDrizzle> = DrizzleTransaction<TDrizzle>,\n> implements DBConnection<TTransaction>\n{\n readonly #drizzle: TDrizzle;\n\n constructor(drizzle: TDrizzle) {\n this.#drizzle = drizzle;\n }\n\n transaction<T>(\n fn: (tx: DBTransaction<TTransaction>) => Promise<T>,\n ): Promise<T> {\n return this.#drizzle.transaction(drizzleTx =>\n fn(\n new DrizzleInternalTransaction(\n drizzleTx,\n ) as DBTransaction<TTransaction>,\n ),\n );\n }\n}\n\nclass DrizzleInternalTransaction<\n TTransaction extends DrizzleTransaction<DrizzleDatabase>,\n> implements DBTransaction<TTransaction>\n{\n readonly wrappedTransaction: TTransaction;\n\n constructor(drizzleTx: TTransaction) {\n this.wrappedTransaction = drizzleTx;\n }\n\n runQuery<TReturn>(\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n ): Promise<HumanReadable<TReturn>> {\n return executePostgresQuery<TReturn>(\n this,\n ast,\n format,\n schema,\n serverSchema,\n );\n }\n\n async query(sql: string, params: unknown[]): Promise<Iterable<Row>> {\n const stmt = fromDollarParams(sql, params);\n const result = await this.wrappedTransaction.execute(stmt);\n return toIterableRows(result);\n }\n}\n\n/**\n * Turn `$1, $2...` placeholders into a Drizzle SQL object with bound params.\n */\nexport function fromDollarParams(text: string, params: unknown[]): SQL {\n const re = /\\$(\\d+)/g;\n const s = sql.empty();\n let last = 0;\n let m: RegExpExecArray | null;\n\n while ((m = re.exec(text)) !== null) {\n const idx = Number(m[1]) - 1;\n if (idx < 0 || idx >= params.length) {\n throw new Error(`Missing param for $${m[1]}`);\n }\n if (m.index > last) s.append(sql.raw(text.slice(last, m.index)));\n s.append(sql`${params[idx]}`); // parameterized value\n last = m.index + m[0].length;\n }\n if (last < text.length) s.append(sql.raw(text.slice(last)));\n return s;\n}\n\nfunction isIterable(value: unknown): value is Iterable<unknown> {\n return (\n // oxlint-disable-next-line eqeqeq\n value != null &&\n typeof (value as Iterable<unknown>)[Symbol.iterator] === 'function'\n );\n}\n\nexport function toIterableRows(result: unknown): Iterable<Row> {\n if (result === null || result === undefined) {\n return [] as Row[];\n }\n if (Array.isArray(result)) {\n return result as Row[];\n }\n if (isIterable(result)) {\n return result as Iterable<Row>;\n }\n if (typeof result === 'object') {\n const rows = (result as {rows?: unknown}).rows;\n if (rows === null || rows === undefined) {\n return [] as Row[];\n }\n if (Array.isArray(rows)) {\n return rows as Row[];\n }\n if (isIterable(rows)) {\n return rows as Iterable<Row>;\n }\n }\n throw new TypeError('Drizzle query result is not iterable');\n}\n\n/**\n * Wrap a `drizzle-orm` database for Zero ZQL.\n *\n * Provides ZQL querying plus access to the underlying drizzle transaction.\n * Use {@link DrizzleTransaction} to type your server mutator transaction.\n *\n * @param schema - Zero schema.\n * @param client - Drizzle database.\n *\n * @example\n * ```ts\n * import {Pool} from 'pg';\n * import {drizzle} from 'drizzle-orm/node-postgres';\n * import type {ServerTransaction} from '@rocicorp/zero';\n *\n * const pool = new Pool({connectionString: process.env.ZERO_UPSTREAM_DB!});\n * const drizzleDb = drizzle(pool, {schema: drizzleSchema});\n *\n * const zql = zeroDrizzle(schema, drizzleDb);\n *\n * // Define the server mutator transaction type using the helper\n * type ServerTx = ServerTransaction<Schema, DrizzleTransaction<typeof drizzleDb>>;\n *\n * async function createUser(\n * tx: ServerTx,\n * {id, name}: {id: string; name: string},\n * ) {\n * await tx.dbTransaction.wrappedTransaction\n * .insert(drizzleSchema.user)\n * .values({id, name})\n * }\n * ```\n */\nexport function zeroDrizzle<\n TSchema extends Schema,\n TDrizzle extends DrizzleDatabase,\n>(\n schema: TSchema,\n client: TDrizzle,\n): ZQLDatabase<TSchema, DrizzleTransaction<TDrizzle>> {\n return new ZQLDatabase(\n new DrizzleConnection<TDrizzle, DrizzleTransaction<TDrizzle>>(client),\n schema,\n );\n}\n"],"names":["sql"],"mappings":";;;AA8CO,MAAM,kBAKb;AAAA,EACW;AAAA,EAET,YAAY,SAAmB;AAC7B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,YACE,IACY;AACZ,WAAO,KAAK,SAAS;AAAA,MAAY,CAAA,cAC/B;AAAA,QACE,IAAI;AAAA,UACF;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,MAAM,2BAGN;AAAA,EACW;AAAA,EAET,YAAY,WAAyB;AACnC,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,SACE,KACA,QACA,QACA,cACiC;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,MAAMA,MAAa,QAA2C;AAClE,UAAM,OAAO,iBAAiBA,MAAK,MAAM;AACzC,UAAM,SAAS,MAAM,KAAK,mBAAmB,QAAQ,IAAI;AACzD,WAAO,eAAe,MAAM;AAAA,EAC9B;AACF;AAKO,SAAS,iBAAiB,MAAc,QAAwB;AACrE,QAAM,KAAK;AACX,QAAM,IAAI,IAAI,MAAA;AACd,MAAI,OAAO;AACX,MAAI;AAEJ,UAAQ,IAAI,GAAG,KAAK,IAAI,OAAO,MAAM;AACnC,UAAM,MAAM,OAAO,EAAE,CAAC,CAAC,IAAI;AAC3B,QAAI,MAAM,KAAK,OAAO,OAAO,QAAQ;AACnC,YAAM,IAAI,MAAM,sBAAsB,EAAE,CAAC,CAAC,EAAE;AAAA,IAC9C;AACA,QAAI,EAAE,QAAQ,KAAM,GAAE,OAAO,IAAI,IAAI,KAAK,MAAM,MAAM,EAAE,KAAK,CAAC,CAAC;AAC/D,MAAE,OAAO,MAAM,OAAO,GAAG,CAAC,EAAE;AAC5B,WAAO,EAAE,QAAQ,EAAE,CAAC,EAAE;AAAA,EACxB;AACA,MAAI,OAAO,KAAK,OAAQ,GAAE,OAAO,IAAI,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AAC1D,SAAO;AACT;AAEA,SAAS,WAAW,OAA4C;AAC9D;AAAA;AAAA,IAEE,SAAS,QACT,OAAQ,MAA4B,OAAO,QAAQ,MAAM;AAAA;AAE7D;AAEO,SAAS,eAAe,QAAgC;AAC7D,MAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,WAAO,CAAA;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO;AAAA,EACT;AACA,MAAI,WAAW,MAAM,GAAG;AACtB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,OAAQ,OAA4B;AAC1C,QAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,aAAO,CAAA;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,IAAI,GAAG;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI,UAAU,sCAAsC;AAC5D;AAmCO,SAAS,YAId,QACA,QACoD;AACpD,SAAO,IAAI;AAAA,IACT,IAAI,kBAA0D,MAAM;AAAA,IACpE;AAAA,EAAA;AAEJ;"}
1
+ {"version":3,"file":"drizzle.js","sources":["../../../../../zero-server/src/adapters/drizzle.ts"],"sourcesContent":["import type {\n PgDatabase,\n PgQueryResultHKT,\n PgTransaction,\n} from 'drizzle-orm/pg-core';\nimport type {ExtractTablesWithRelations} from 'drizzle-orm/relations';\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 {\n DBConnection,\n DBTransaction,\n Row,\n} from '../../../zql/src/mutate/custom.ts';\nimport type {HumanReadable} from '../../../zql/src/query/query.ts';\nimport {executePostgresQuery} from '../pg-query-executor.ts';\nimport {ZQLDatabase} from '../zql-database.ts';\n\nexport type {ZQLDatabase};\n\nexport type DrizzleDatabase<\n TQueryResult extends PgQueryResultHKT = PgQueryResultHKT,\n TSchema extends Record<string, unknown> = Record<string, unknown>,\n> = PgDatabase<TQueryResult, TSchema>;\n\n/**\n * Helper type for the wrapped transaction used by drizzle-orm.\n *\n * @remarks Use with `ServerTransaction` as `ServerTransaction<Schema, DrizzleTransaction<typeof drizzleDb>>`.\n */\nexport type DrizzleTransaction<\n TDbOrSchema extends DrizzleDatabase | Record<string, unknown>,\n TSchema extends Record<string, unknown> = TDbOrSchema extends PgDatabase<\n PgQueryResultHKT,\n infer TInferredSchema\n >\n ? TInferredSchema\n : TDbOrSchema,\n> = PgTransaction<\n PgQueryResultHKT,\n TSchema,\n ExtractTablesWithRelations<TSchema>\n>;\n\nexport class DrizzleConnection<\n TDrizzle extends DrizzleDatabase,\n TTransaction extends\n DrizzleTransaction<TDrizzle> = DrizzleTransaction<TDrizzle>,\n> implements DBConnection<TTransaction>\n{\n readonly #drizzle: TDrizzle;\n\n constructor(drizzle: TDrizzle) {\n this.#drizzle = drizzle;\n }\n\n transaction<T>(\n fn: (tx: DBTransaction<TTransaction>) => Promise<T>,\n ): Promise<T> {\n return this.#drizzle.transaction(drizzleTx =>\n fn(\n new DrizzleInternalTransaction(\n drizzleTx,\n ) as DBTransaction<TTransaction>,\n ),\n );\n }\n}\n\nclass DrizzleInternalTransaction<\n TTransaction extends DrizzleTransaction<DrizzleDatabase>,\n> implements DBTransaction<TTransaction>\n{\n readonly wrappedTransaction: TTransaction;\n\n constructor(drizzleTx: TTransaction) {\n this.wrappedTransaction = drizzleTx;\n }\n\n runQuery<TReturn>(\n ast: AST,\n format: Format,\n schema: Schema,\n serverSchema: ServerSchema,\n ): Promise<HumanReadable<TReturn>> {\n return executePostgresQuery<TReturn>(\n this,\n ast,\n format,\n schema,\n serverSchema,\n );\n }\n\n async query(sql: string, params: unknown[]): Promise<Iterable<Row>> {\n const prepared = this.wrappedTransaction._.session.prepareQuery(\n {sql, params},\n undefined,\n undefined,\n false,\n );\n const result = await prepared.execute();\n return toIterableRows(result);\n }\n}\n\nfunction isIterable(value: unknown): value is Iterable<unknown> {\n return (\n // oxlint-disable-next-line eqeqeq\n value != null &&\n typeof (value as Iterable<unknown>)[Symbol.iterator] === 'function'\n );\n}\n\nexport function toIterableRows(result: unknown): Iterable<Row> {\n if (result === null || result === undefined) {\n return [] as Row[];\n }\n if (Array.isArray(result)) {\n return result as Row[];\n }\n if (isIterable(result)) {\n return result as Iterable<Row>;\n }\n if (typeof result === 'object') {\n const rows = (result as {rows?: unknown}).rows;\n if (rows === null || rows === undefined) {\n return [] as Row[];\n }\n if (Array.isArray(rows)) {\n return rows as Row[];\n }\n if (isIterable(rows)) {\n return rows as Iterable<Row>;\n }\n }\n throw new TypeError('Drizzle query result is not iterable');\n}\n\n/**\n * Wrap a `drizzle-orm` database for Zero ZQL.\n *\n * Provides ZQL querying plus access to the underlying drizzle transaction.\n * Use {@link DrizzleTransaction} to type your server mutator transaction.\n *\n * @param schema - Zero schema.\n * @param client - Drizzle database.\n *\n * @example\n * ```ts\n * import {Pool} from 'pg';\n * import {drizzle} from 'drizzle-orm/node-postgres';\n * import {defineMutator, defineMutators} from '@rocicorp/zero';\n * import {zeroDrizzle} from '@rocicorp/zero/server/adapters/drizzle';\n * import {z} from 'zod/mini';\n *\n * const pool = new Pool({connectionString: process.env.ZERO_UPSTREAM_DB!});\n * const drizzleDb = drizzle(pool, {schema: drizzleSchema});\n * const zql = zeroDrizzle(schema, drizzleDb);\n *\n * export const serverMutators = defineMutators({\n * user: {\n * create: defineMutator(\n * z.object({id: z.string(), name: z.string()}),\n * async ({tx, args}) => {\n * if (tx.location !== 'server') {\n * throw new Error('Server-only mutator');\n * }\n * await tx.dbTransaction.wrappedTransaction\n * .insert(drizzleSchema.user)\n * .values({id: args.id, name: args.name, status: 'active'});\n * },\n * ),\n * },\n * });\n * ```\n */\nexport function zeroDrizzle<\n TSchema extends Schema,\n TDrizzle extends DrizzleDatabase,\n>(\n schema: TSchema,\n client: TDrizzle,\n): ZQLDatabase<TSchema, DrizzleTransaction<TDrizzle>> {\n return new ZQLDatabase(\n new DrizzleConnection<TDrizzle, DrizzleTransaction<TDrizzle>>(client),\n schema,\n );\n}\n"],"names":[],"mappings":";;AA6CO,MAAM,kBAKb;AAAA,EACW;AAAA,EAET,YAAY,SAAmB;AAC7B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,YACE,IACY;AACZ,WAAO,KAAK,SAAS;AAAA,MAAY,CAAA,cAC/B;AAAA,QACE,IAAI;AAAA,UACF;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,MAAM,2BAGN;AAAA,EACW;AAAA,EAET,YAAY,WAAyB;AACnC,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,SACE,KACA,QACA,QACA,cACiC;AACjC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,MAAM,KAAa,QAA2C;AAClE,UAAM,WAAW,KAAK,mBAAmB,EAAE,QAAQ;AAAA,MACjD,EAAC,KAAK,OAAA;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAEF,UAAM,SAAS,MAAM,SAAS,QAAA;AAC9B,WAAO,eAAe,MAAM;AAAA,EAC9B;AACF;AAEA,SAAS,WAAW,OAA4C;AAC9D;AAAA;AAAA,IAEE,SAAS,QACT,OAAQ,MAA4B,OAAO,QAAQ,MAAM;AAAA;AAE7D;AAEO,SAAS,eAAe,QAAgC;AAC7D,MAAI,WAAW,QAAQ,WAAW,QAAW;AAC3C,WAAO,CAAA;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,WAAO;AAAA,EACT;AACA,MAAI,WAAW,MAAM,GAAG;AACtB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,OAAQ,OAA4B;AAC1C,QAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,aAAO,CAAA;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,IAAI,GAAG;AACpB,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI,UAAU,sCAAsC;AAC5D;AAwCO,SAAS,YAId,QACA,QACoD;AACpD,SAAO,IAAI;AAAA,IACT,IAAI,kBAA0D,MAAM;AAAA,IACpE;AAAA,EAAA;AAEJ;"}
@@ -37,23 +37,29 @@ export declare class NodePgTransactionInternal implements DBTransaction<NodePgTr
37
37
  * @example
38
38
  * ```ts
39
39
  * import {Pool} from 'pg';
40
+ * import {defineMutator, defineMutators} from '@rocicorp/zero';
41
+ * import {zeroNodePg} from '@rocicorp/zero/server/adapters/pg';
42
+ * import {z} from 'zod/mini';
40
43
  *
41
44
  * const pool = new Pool({connectionString: process.env.ZERO_UPSTREAM_DB!});
42
45
  * const zql = zeroNodePg(schema, pool);
43
46
  *
44
- * // Define the server mutator transaction type using the helper
45
- * type ServerTx = ServerTransaction<
46
- * Schema,
47
- * NodePgTransaction
48
- * >;
49
- *
50
- * async function createUser(
51
- * tx: ServerTx,
52
- * {id, name}: {id: string; name: string},
53
- * ) {
54
- * await tx.dbTransaction.wrappedTransaction
55
- * .query('SELECT * FROM "user" WHERE id = $1', [id]);
56
- * }
47
+ * export const serverMutators = defineMutators({
48
+ * user: {
49
+ * create: defineMutator(
50
+ * z.object({id: z.string(), name: z.string()}),
51
+ * async ({tx, args}) => {
52
+ * if (tx.location !== 'server') {
53
+ * throw new Error('Server-only mutator');
54
+ * }
55
+ * await tx.dbTransaction.wrappedTransaction.query(
56
+ * 'INSERT INTO "user" (id, name, status) VALUES ($1, $2, $3)',
57
+ * [args.id, args.name, 'active'],
58
+ * );
59
+ * },
60
+ * ),
61
+ * },
62
+ * });
57
63
  * ```
58
64
  */
59
65
  export declare function zeroNodePg<S extends Schema>(schema: S, pg: NodePgTransaction | string): ZQLDatabase<S, NodePgTransaction>;
@@ -1 +1 @@
1
- {"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../../../../zero-server/src/adapters/pg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAC,IAAI,EAAE,KAAK,UAAU,EAAC,MAAM,IAAI,CAAC;AACzC,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,mCAAmC,CAAC;AAC3D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,GAAG,EACJ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAE/C,YAAY,EAAC,WAAW,EAAC,CAAC;AAE1B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D,qBAAa,gBAAiB,YAAW,YAAY,CAAC,iBAAiB,CAAC;;gBAG1D,IAAI,EAAE,iBAAiB;IAI7B,WAAW,CAAC,IAAI,EACpB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC;CAqBjB;AAED,qBAAa,yBACX,YAAW,aAAa,CAAC,iBAAiB,CAAC;IAE3C,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;gBAEnC,MAAM,EAAE,iBAAiB;IAIrC,QAAQ,CAAC,OAAO,EACd,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAU5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAI5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,MAAM,EAAE,CAAC,EACT,EAAE,EAAE,iBAAiB,GAAG,MAAM,qCAM/B"}
1
+ {"version":3,"file":"pg.d.ts","sourceRoot":"","sources":["../../../../../zero-server/src/adapters/pg.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAC,IAAI,EAAE,KAAK,UAAU,EAAC,MAAM,IAAI,CAAC;AACzC,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,mCAAmC,CAAC;AAC3D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAC3E,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,GAAG,EACJ,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,iCAAiC,CAAC;AAEnE,OAAO,EAAC,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAE/C,YAAY,EAAC,WAAW,EAAC,CAAC;AAE1B;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3D,qBAAa,gBAAiB,YAAW,YAAY,CAAC,iBAAiB,CAAC;;gBAG1D,IAAI,EAAE,iBAAiB;IAI7B,WAAW,CAAC,IAAI,EACpB,EAAE,EAAE,CAAC,EAAE,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC;CAqBjB;AAED,qBAAa,yBACX,YAAW,aAAa,CAAC,iBAAiB,CAAC;IAE3C,QAAQ,CAAC,kBAAkB,EAAE,iBAAiB,CAAC;gBAEnC,MAAM,EAAE,iBAAiB;IAIrC,QAAQ,CAAC,OAAO,EACd,GAAG,EAAE,GAAG,EACR,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IAU5B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;CAI5D;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,EACzC,MAAM,EAAE,CAAC,EACT,EAAE,EAAE,iBAAiB,GAAG,MAAM,qCAM/B"}