@rocicorp/zero 1.3.0 → 1.4.0-canary.1

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 (332) hide show
  1. package/out/analyze-query/src/analyze-cli.d.ts +24 -0
  2. package/out/analyze-query/src/analyze-cli.d.ts.map +1 -0
  3. package/out/analyze-query/src/analyze-cli.js +289 -0
  4. package/out/analyze-query/src/analyze-cli.js.map +1 -0
  5. package/out/analyze-query/src/bin-analyze.js +6 -6
  6. package/out/analyze-query/src/bin-transform.js +2 -2
  7. package/out/ast-to-zql/src/bin.js +1 -1
  8. package/out/shared/src/logging.d.ts.map +1 -1
  9. package/out/shared/src/logging.js +1 -1
  10. package/out/shared/src/logging.js.map +1 -1
  11. package/out/shared/src/options.d.ts.map +1 -1
  12. package/out/shared/src/options.js +1 -1
  13. package/out/shared/src/options.js.map +1 -1
  14. package/out/z2s/src/compiler.d.ts.map +1 -1
  15. package/out/z2s/src/compiler.js +4 -1
  16. package/out/z2s/src/compiler.js.map +1 -1
  17. package/out/z2s/src/sql.d.ts.map +1 -1
  18. package/out/z2s/src/sql.js +1 -0
  19. package/out/z2s/src/sql.js.map +1 -1
  20. package/out/zero/package.js +95 -89
  21. package/out/zero/package.js.map +1 -1
  22. package/out/zero/src/analyze.d.ts +2 -0
  23. package/out/zero/src/analyze.d.ts.map +1 -0
  24. package/out/zero/src/analyze.js +2 -0
  25. package/out/zero/src/bindings.js +1 -1
  26. package/out/zero/src/zero-cache-dev.js +1 -1
  27. package/out/zero/src/zero-cache-dev.js.map +1 -1
  28. package/out/zero/src/zero-out.js +1 -1
  29. package/out/zero-cache/src/auth/auth.d.ts.map +1 -1
  30. package/out/zero-cache/src/auth/auth.js.map +1 -1
  31. package/out/zero-cache/src/auth/load-permissions.js +2 -2
  32. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  33. package/out/zero-cache/src/auth/write-authorizer.js +5 -14
  34. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  35. package/out/zero-cache/src/config/network.d.ts +1 -1
  36. package/out/zero-cache/src/config/network.d.ts.map +1 -1
  37. package/out/zero-cache/src/config/network.js +1 -1
  38. package/out/zero-cache/src/config/network.js.map +1 -1
  39. package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
  40. package/out/zero-cache/src/config/normalize.js.map +1 -1
  41. package/out/zero-cache/src/config/zero-config.d.ts +5 -0
  42. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  43. package/out/zero-cache/src/config/zero-config.js +16 -3
  44. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  45. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  46. package/out/zero-cache/src/db/lite-tables.js +3 -3
  47. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  48. package/out/zero-cache/src/db/transaction-pool.d.ts +43 -40
  49. package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
  50. package/out/zero-cache/src/db/transaction-pool.js +76 -56
  51. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  52. package/out/zero-cache/src/observability/events.d.ts.map +1 -1
  53. package/out/zero-cache/src/observability/events.js +1 -1
  54. package/out/zero-cache/src/observability/events.js.map +1 -1
  55. package/out/zero-cache/src/scripts/decommission.js +1 -1
  56. package/out/zero-cache/src/scripts/deploy-permissions.js +2 -2
  57. package/out/zero-cache/src/scripts/permissions.js +1 -1
  58. package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
  59. package/out/zero-cache/src/server/anonymous-otel-start.js +4 -4
  60. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  61. package/out/zero-cache/src/server/change-streamer.d.ts +1 -1
  62. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  63. package/out/zero-cache/src/server/change-streamer.js +27 -12
  64. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  65. package/out/zero-cache/src/server/logging.d.ts +1 -3
  66. package/out/zero-cache/src/server/logging.d.ts.map +1 -1
  67. package/out/zero-cache/src/server/logging.js +6 -3
  68. package/out/zero-cache/src/server/logging.js.map +1 -1
  69. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  70. package/out/zero-cache/src/server/main.js +26 -26
  71. package/out/zero-cache/src/server/main.js.map +1 -1
  72. package/out/zero-cache/src/server/mutator.js +4 -2
  73. package/out/zero-cache/src/server/mutator.js.map +1 -1
  74. package/out/zero-cache/src/server/otel-log-sink.d.ts.map +1 -1
  75. package/out/zero-cache/src/server/otel-log-sink.js +0 -2
  76. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  77. package/out/zero-cache/src/server/otel-start.d.ts +1 -1
  78. package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
  79. package/out/zero-cache/src/server/otel-start.js +7 -3
  80. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  81. package/out/zero-cache/src/server/reaper.js +6 -6
  82. package/out/zero-cache/src/server/reaper.js.map +1 -1
  83. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  84. package/out/zero-cache/src/server/replicator.js +5 -3
  85. package/out/zero-cache/src/server/replicator.js.map +1 -1
  86. package/out/zero-cache/src/server/runner/run-worker.js +2 -2
  87. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  88. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  89. package/out/zero-cache/src/server/syncer.js +13 -12
  90. package/out/zero-cache/src/server/syncer.js.map +1 -1
  91. package/out/zero-cache/src/server/worker-dispatcher.js +1 -1
  92. package/out/zero-cache/src/services/analyze.js +1 -1
  93. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
  94. package/out/zero-cache/src/services/change-source/common/replica-schema.js +1 -1
  95. package/out/zero-cache/src/services/change-source/custom/change-source.js +2 -2
  96. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -1
  97. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  98. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  99. package/out/zero-cache/src/services/change-source/pg/change-source.js +19 -23
  100. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  101. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +58 -3
  102. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  103. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +209 -52
  104. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  105. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +2 -2
  106. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +24 -15
  107. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  108. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +35 -58
  109. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  110. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  111. package/out/zero-cache/src/services/change-source/pg/schema/init.js +2 -2
  112. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  113. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +1 -2
  114. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  115. package/out/zero-cache/src/services/change-source/pg/schema/published.js +15 -18
  116. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  117. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +1 -1
  118. package/out/zero-cache/src/services/change-source/protocol/current/data.js +1 -1
  119. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +1 -1
  120. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +1 -1
  121. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  122. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +1 -1
  123. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  124. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +5 -1
  125. package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
  126. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +10 -7
  127. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  128. package/out/zero-cache/src/services/change-streamer/replica-monitor.js +2 -2
  129. package/out/zero-cache/src/services/change-streamer/storer.d.ts +19 -2
  130. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  131. package/out/zero-cache/src/services/change-streamer/storer.js +70 -6
  132. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  133. package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
  134. package/out/zero-cache/src/services/heapz.js +1 -1
  135. package/out/zero-cache/src/services/heapz.js.map +1 -1
  136. package/out/zero-cache/src/services/life-cycle.d.ts +2 -1
  137. package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
  138. package/out/zero-cache/src/services/life-cycle.js +10 -7
  139. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  140. package/out/zero-cache/src/services/litestream/commands.d.ts +15 -4
  141. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  142. package/out/zero-cache/src/services/litestream/commands.js +40 -34
  143. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  144. package/out/zero-cache/src/services/mutagen/mutagen.js +3 -3
  145. package/out/zero-cache/src/services/mutagen/pusher.d.ts +28 -28
  146. package/out/zero-cache/src/services/replicator/change-processor.js +2 -2
  147. package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
  148. package/out/zero-cache/src/services/replicator/schema/replication-state.js +1 -1
  149. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  150. package/out/zero-cache/src/services/replicator/write-worker.js +3 -3
  151. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  152. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  153. package/out/zero-cache/src/services/run-ast.js +3 -3
  154. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  155. package/out/zero-cache/src/services/statz.d.ts.map +1 -1
  156. package/out/zero-cache/src/services/statz.js +3 -3
  157. package/out/zero-cache/src/services/statz.js.map +1 -1
  158. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +1 -1
  159. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts +2 -2
  160. package/out/zero-cache/src/services/view-syncer/connection-context-manager.d.ts.map +1 -1
  161. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  162. package/out/zero-cache/src/services/view-syncer/cvr-purger.js +1 -1
  163. package/out/zero-cache/src/services/view-syncer/cvr-store.js +3 -3
  164. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  165. package/out/zero-cache/src/services/view-syncer/cvr.js +1 -1
  166. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  167. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +6 -16
  168. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  169. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +31 -39
  170. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  171. package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
  172. package/out/zero-cache/src/services/view-syncer/row-record-cache.js +4 -4
  173. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  174. package/out/zero-cache/src/services/view-syncer/snapshotter.js +2 -2
  175. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  176. package/out/zero-cache/src/services/view-syncer/view-syncer.js +6 -6
  177. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  178. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  179. package/out/zero-cache/src/types/profiler.js.map +1 -1
  180. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  181. package/out/zero-cache/src/types/row-key.js.map +1 -1
  182. package/out/zero-cache/src/types/streams.d.ts +1 -1
  183. package/out/zero-cache/src/types/streams.d.ts.map +1 -1
  184. package/out/zero-cache/src/types/streams.js.map +1 -1
  185. package/out/zero-cache/src/types/websocket-handoff.d.ts +1 -1
  186. package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
  187. package/out/zero-cache/src/types/websocket-handoff.js +1 -1
  188. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  189. package/out/zero-cache/src/workers/connection.d.ts +1 -1
  190. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  191. package/out/zero-cache/src/workers/connection.js.map +1 -1
  192. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  193. package/out/zero-cache/src/workers/syncer.d.ts +1 -1
  194. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  195. package/out/zero-cache/src/workers/syncer.js +3 -3
  196. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  197. package/out/zero-client/src/client/bindings.js +1 -1
  198. package/out/zero-client/src/client/crud-impl.d.ts.map +1 -1
  199. package/out/zero-client/src/client/crud-impl.js +4 -13
  200. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  201. package/out/zero-client/src/client/inspector/inspector.d.ts +24 -0
  202. package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
  203. package/out/zero-client/src/client/inspector/inspector.js +28 -0
  204. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  205. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +9 -0
  206. package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
  207. package/out/zero-client/src/client/inspector/lazy-inspector.js +28 -1
  208. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  209. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  210. package/out/zero-client/src/client/ivm-branch.js +4 -13
  211. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  212. package/out/zero-client/src/client/log-options.d.ts +1 -0
  213. package/out/zero-client/src/client/log-options.d.ts.map +1 -1
  214. package/out/zero-client/src/client/log-options.js +3 -2
  215. package/out/zero-client/src/client/log-options.js.map +1 -1
  216. package/out/zero-client/src/client/options.d.ts +13 -1
  217. package/out/zero-client/src/client/options.d.ts.map +1 -1
  218. package/out/zero-client/src/client/options.js.map +1 -1
  219. package/out/zero-client/src/client/version.js +1 -1
  220. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  221. package/out/zero-client/src/client/zero.js +2 -1
  222. package/out/zero-client/src/client/zero.js.map +1 -1
  223. package/out/zero-protocol/src/error.d.ts.map +1 -1
  224. package/out/zero-protocol/src/error.js +1 -1
  225. package/out/zero-protocol/src/error.js.map +1 -1
  226. package/out/zero-react/src/bindings.js +1 -1
  227. package/out/zero-solid/src/bindings.js +1 -1
  228. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  229. package/out/zero-solid/src/solid-view.js +14 -14
  230. package/out/zero-solid/src/solid-view.js.map +1 -1
  231. package/out/zql/src/builder/builder.d.ts.map +1 -1
  232. package/out/zql/src/builder/builder.js.map +1 -1
  233. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  234. package/out/zql/src/ivm/array-view.js +27 -2
  235. package/out/zql/src/ivm/array-view.js.map +1 -1
  236. package/out/zql/src/ivm/change-index-enum.d.ts +9 -0
  237. package/out/zql/src/ivm/change-index-enum.d.ts.map +1 -0
  238. package/out/zql/src/ivm/change-index.d.ts +5 -0
  239. package/out/zql/src/ivm/change-index.d.ts.map +1 -0
  240. package/out/zql/src/ivm/change-type-enum.d.ts +9 -0
  241. package/out/zql/src/ivm/change-type-enum.d.ts.map +1 -0
  242. package/out/zql/src/ivm/change-type.d.ts +5 -0
  243. package/out/zql/src/ivm/change-type.d.ts.map +1 -0
  244. package/out/zql/src/ivm/change.d.ts +20 -22
  245. package/out/zql/src/ivm/change.d.ts.map +1 -1
  246. package/out/zql/src/ivm/change.js +33 -0
  247. package/out/zql/src/ivm/change.js.map +1 -0
  248. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  249. package/out/zql/src/ivm/exists.js +27 -38
  250. package/out/zql/src/ivm/exists.js.map +1 -1
  251. package/out/zql/src/ivm/fan-in.d.ts +3 -2
  252. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  253. package/out/zql/src/ivm/fan-in.js.map +1 -1
  254. package/out/zql/src/ivm/fan-out.d.ts +1 -1
  255. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  256. package/out/zql/src/ivm/fan-out.js +1 -1
  257. package/out/zql/src/ivm/fan-out.js.map +1 -1
  258. package/out/zql/src/ivm/filter-operators.d.ts +3 -3
  259. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  260. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  261. package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
  262. package/out/zql/src/ivm/filter-push.js +7 -7
  263. package/out/zql/src/ivm/filter-push.js.map +1 -1
  264. package/out/zql/src/ivm/filter.d.ts +1 -1
  265. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  266. package/out/zql/src/ivm/filter.js.map +1 -1
  267. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  268. package/out/zql/src/ivm/flipped-join.js +49 -58
  269. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  270. package/out/zql/src/ivm/join-utils.d.ts +2 -6
  271. package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
  272. package/out/zql/src/ivm/join-utils.js +25 -25
  273. package/out/zql/src/ivm/join-utils.js.map +1 -1
  274. package/out/zql/src/ivm/join.d.ts.map +1 -1
  275. package/out/zql/src/ivm/join.js +32 -51
  276. package/out/zql/src/ivm/join.js.map +1 -1
  277. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  278. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  279. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +5 -10
  280. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  281. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  282. package/out/zql/src/ivm/memory-source.js +52 -60
  283. package/out/zql/src/ivm/memory-source.js.map +1 -1
  284. package/out/zql/src/ivm/operator.d.ts +1 -1
  285. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  286. package/out/zql/src/ivm/operator.js +2 -4
  287. package/out/zql/src/ivm/operator.js.map +1 -1
  288. package/out/zql/src/ivm/push-accumulated.d.ts +3 -2
  289. package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
  290. package/out/zql/src/ivm/push-accumulated.js +98 -122
  291. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  292. package/out/zql/src/ivm/skip-yields.d.ts +4 -0
  293. package/out/zql/src/ivm/skip-yields.d.ts.map +1 -0
  294. package/out/zql/src/ivm/skip-yields.js +33 -0
  295. package/out/zql/src/ivm/skip-yields.js.map +1 -0
  296. package/out/zql/src/ivm/skip.d.ts +1 -1
  297. package/out/zql/src/ivm/skip.d.ts.map +1 -1
  298. package/out/zql/src/ivm/skip.js +2 -2
  299. package/out/zql/src/ivm/skip.js.map +1 -1
  300. package/out/zql/src/ivm/source-change-index-enum.d.ts +7 -0
  301. package/out/zql/src/ivm/source-change-index-enum.d.ts.map +1 -0
  302. package/out/zql/src/ivm/source-change-index.d.ts +5 -0
  303. package/out/zql/src/ivm/source-change-index.d.ts.map +1 -0
  304. package/out/zql/src/ivm/source.d.ts +11 -13
  305. package/out/zql/src/ivm/source.d.ts.map +1 -1
  306. package/out/zql/src/ivm/source.js +26 -0
  307. package/out/zql/src/ivm/source.js.map +1 -0
  308. package/out/zql/src/ivm/take.d.ts.map +1 -1
  309. package/out/zql/src/ivm/take.js +27 -50
  310. package/out/zql/src/ivm/take.js.map +1 -1
  311. package/out/zql/src/ivm/union-fan-in.d.ts +2 -1
  312. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  313. package/out/zql/src/ivm/union-fan-in.js +3 -3
  314. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  315. package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
  316. package/out/zql/src/ivm/union-fan-out.js +1 -1
  317. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  318. package/out/zql/src/ivm/view-apply-change.js +1 -1
  319. package/out/zql/src/planner/planner-debug.d.ts +2 -2
  320. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  321. package/out/zql/src/planner/planner-debug.js.map +1 -1
  322. package/out/zql/src/planner/planner-graph.d.ts +1 -1
  323. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  324. package/out/zql/src/planner/planner-graph.js.map +1 -1
  325. package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -1
  326. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  327. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  328. package/out/zqlite/src/query-builder.js.map +1 -1
  329. package/out/zqlite/src/table-source.d.ts.map +1 -1
  330. package/out/zqlite/src/table-source.js +11 -11
  331. package/out/zqlite/src/table-source.js.map +1 -1
  332. package/package.json +99 -93
@@ -1,6 +1,7 @@
1
1
  import { assert, unreachable } from "../../../shared/src/asserts.js";
2
2
  import { must } from "../../../shared/src/must.js";
3
3
  import { emptyArray } from "../../../shared/src/sentinels.js";
4
+ import { makeAddChange, makeChildChange, makeEditChange, makeRemoveChange } from "./change.js";
4
5
  //#region ../zql/src/ivm/push-accumulated.ts
5
6
  /**
6
7
  * # pushAccumulatedChanges
@@ -75,11 +76,11 @@ function* pushAccumulatedChanges(accumulatedPushes, output, pusher, fanOutChange
75
76
  if (accumulatedPushes.length === 0) return;
76
77
  const candidatesToPush = /* @__PURE__ */ new Map();
77
78
  for (const change of accumulatedPushes) {
78
- if (fanOutChangeType === "child" && change.type !== "child") assert(candidatesToPush.has(change.type) === false, () => `Fan-in:child expected at most one ${change.type} when fan-out is of type child`);
79
- const existing = candidatesToPush.get(change.type);
79
+ if (fanOutChangeType === 3 && change[0] !== 3) assert(candidatesToPush.has(change[0]) === false, () => `Fan-in:child expected at most one ${change[0]} when fan-out is of type child`);
80
+ const existing = candidatesToPush.get(change[0]);
80
81
  let mergedChange = change;
81
82
  if (existing) mergedChange = mergeRelationships(existing, change);
82
- candidatesToPush.set(change.type, mergedChange);
83
+ candidatesToPush.set(change[0], mergedChange);
83
84
  }
84
85
  accumulatedPushes.length = 0;
85
86
  const types = [...candidatesToPush.keys()];
@@ -94,19 +95,19 @@ function* pushAccumulatedChanges(accumulatedPushes, output, pusher, fanOutChange
94
95
  * - Many child changes because other operators may preserve the child change
95
96
  */
96
97
  switch (fanOutChangeType) {
97
- case "remove":
98
- assert(types.length === 1 && types[0] === "remove", "Fan-in:remove expected all removes");
99
- yield* output.push(addEmptyRelationships(must(candidatesToPush.get("remove"))), pusher);
98
+ case 1:
99
+ assert(types.length === 1 && types[0] === 1, "Fan-in:remove expected all removes");
100
+ yield* output.push(addEmptyRelationships(must(candidatesToPush.get(1))), pusher);
100
101
  return;
101
- case "add":
102
- assert(types.length === 1 && types[0] === "add", "Fan-in:add expected all adds");
103
- yield* output.push(addEmptyRelationships(must(candidatesToPush.get("add"))), pusher);
102
+ case 0:
103
+ assert(types.length === 1 && types[0] === 0, "Fan-in:add expected all adds");
104
+ yield* output.push(addEmptyRelationships(must(candidatesToPush.get(0))), pusher);
104
105
  return;
105
- case "edit": {
106
- assert(types.every((type) => type === "add" || type === "remove" || type === "edit"), "Fan-in:edit expected all adds, removes, or edits");
107
- const addChange = candidatesToPush.get("add");
108
- const removeChange = candidatesToPush.get("remove");
109
- let editChange = candidatesToPush.get("edit");
106
+ case 2: {
107
+ assert(types.every((type) => type === 0 || type === 1 || type === 2), "Fan-in:edit expected all adds, removes, or edits");
108
+ const addChange = candidatesToPush.get(0);
109
+ const removeChange = candidatesToPush.get(1);
110
+ let editChange = candidatesToPush.get(2);
110
111
  if (editChange) {
111
112
  if (addChange) editChange = mergeRelationships(editChange, addChange);
112
113
  if (removeChange) editChange = mergeRelationships(editChange, removeChange);
@@ -114,26 +115,22 @@ function* pushAccumulatedChanges(accumulatedPushes, output, pusher, fanOutChange
114
115
  return;
115
116
  }
116
117
  if (addChange && removeChange) {
117
- yield* output.push(addEmptyRelationships({
118
- type: "edit",
119
- node: addChange.node,
120
- oldNode: removeChange.node
121
- }), pusher);
118
+ yield* output.push(addEmptyRelationships(makeEditChange(addChange[1], removeChange[1])), pusher);
122
119
  return;
123
120
  }
124
121
  yield* output.push(addEmptyRelationships(must(addChange ?? removeChange)), pusher);
125
122
  return;
126
123
  }
127
- case "child": {
128
- assert(types.every((type) => type === "add" || type === "remove" || type === "child"), "Fan-in:child expected all adds, removes, or children");
124
+ case 3: {
125
+ assert(types.every((type) => type === 0 || type === 1 || type === 3), "Fan-in:child expected all adds, removes, or children");
129
126
  assert(types.length <= 2, "Fan-in:child expected at most 2 types on a child change from fan-out");
130
- const childChange = candidatesToPush.get("child");
127
+ const childChange = candidatesToPush.get(3);
131
128
  if (childChange) {
132
129
  yield* output.push(childChange, pusher);
133
130
  return;
134
131
  }
135
- const addChange = candidatesToPush.get("add");
136
- const removeChange = candidatesToPush.get("remove");
132
+ const addChange = candidatesToPush.get(0);
133
+ const removeChange = candidatesToPush.get(1);
137
134
  assert(addChange === void 0 || removeChange === void 0, "Fan-in:child expected either add or remove, not both");
138
135
  yield* output.push(addEmptyRelationships(must(addChange ?? removeChange)), pusher);
139
136
  return;
@@ -145,120 +142,99 @@ function* pushAccumulatedChanges(accumulatedPushes, output, pusher, fanOutChange
145
142
  * Puts relationships from `right` into `left` if they don't already exist in `left`.
146
143
  */
147
144
  function mergeRelationships(left, right) {
148
- if (left.type === right.type) switch (left.type) {
149
- case "add": return {
150
- type: "add",
151
- node: {
152
- row: left.node.row,
153
- relationships: {
154
- ...right.node.relationships,
155
- ...left.node.relationships
156
- }
145
+ if (left[0] === right[0]) switch (left[0]) {
146
+ case 0: return makeAddChange({
147
+ row: left[1].row,
148
+ relationships: {
149
+ ...right[1].relationships,
150
+ ...left[1].relationships
157
151
  }
158
- };
159
- case "remove": return {
160
- type: "remove",
161
- node: {
162
- row: left.node.row,
163
- relationships: {
164
- ...right.node.relationships,
165
- ...left.node.relationships
166
- }
152
+ });
153
+ case 1: return makeRemoveChange({
154
+ row: left[1].row,
155
+ relationships: {
156
+ ...right[1].relationships,
157
+ ...left[1].relationships
167
158
  }
168
- };
169
- case "edit":
170
- assert(right.type === "edit", () => `mergeRelationships: when left.type is edit and types match, right.type must be edit, got ${right.type}`);
171
- return {
172
- type: "edit",
173
- node: {
174
- row: left.node.row,
175
- relationships: {
176
- ...right.node.relationships,
177
- ...left.node.relationships
178
- }
179
- },
180
- oldNode: {
181
- row: left.oldNode.row,
182
- relationships: {
183
- ...right.oldNode.relationships,
184
- ...left.oldNode.relationships
185
- }
159
+ });
160
+ case 2:
161
+ assert(right[0] === 2, () => `mergeRelationships: when left.type is edit and types match, right.type must be edit, got ${right[0]}`);
162
+ return makeEditChange({
163
+ row: left[1].row,
164
+ relationships: {
165
+ ...right[1].relationships,
166
+ ...left[1].relationships
186
167
  }
187
- };
188
- case "child":
189
- assert(right.type === "child", () => `mergeRelationships: when left.type is child and types match, right.type must be child, got ${right.type}`);
190
- return {
191
- type: "child",
192
- node: {
193
- row: left.node.row,
194
- relationships: {
195
- ...right.node.relationships,
196
- ...left.node.relationships
197
- }
198
- },
199
- child: left.child
200
- };
201
- }
202
- assert(left.type === "edit", () => `mergeRelationships: when types differ, left.type must be edit, got left.type=${left.type}, right.type=${right.type}`);
203
- switch (right.type) {
204
- case "add": return {
205
- type: "edit",
206
- node: {
207
- ...left.node,
168
+ }, {
169
+ row: left[2].row,
208
170
  relationships: {
209
- ...right.node.relationships,
210
- ...left.node.relationships
171
+ ...right[2].relationships,
172
+ ...left[2].relationships
211
173
  }
212
- },
213
- oldNode: left.oldNode
214
- };
215
- case "remove": return {
216
- type: "edit",
217
- node: left.node,
218
- oldNode: {
219
- ...left.oldNode,
174
+ });
175
+ case 3:
176
+ assert(right[0] === 3, () => `mergeRelationships: when left.type is child and types match, right.type must be child, got ${right[0]}`);
177
+ return makeChildChange({
178
+ row: left[1].row,
220
179
  relationships: {
221
- ...right.node.relationships,
222
- ...left.oldNode.relationships
180
+ ...right[1].relationships,
181
+ ...left[1].relationships
223
182
  }
183
+ }, left[2]);
184
+ }
185
+ assert(left[0] === 2, () => `mergeRelationships: when types differ, left.type must be edit, got left.type=${left[0]}, right.type=${right[0]}`);
186
+ switch (right[0]) {
187
+ case 0: return makeEditChange({
188
+ ...left[1],
189
+ relationships: {
190
+ ...right[1].relationships,
191
+ ...left[1].relationships
224
192
  }
225
- };
193
+ }, left[2]);
194
+ case 1: return makeEditChange(left[1], {
195
+ ...left[2],
196
+ relationships: {
197
+ ...right[1].relationships,
198
+ ...left[2].relationships
199
+ }
200
+ });
226
201
  }
227
202
  unreachable();
228
203
  }
229
204
  function makeAddEmptyRelationships(schema) {
230
205
  return (change) => {
231
206
  if (Object.keys(schema.relationships).length === 0) return change;
232
- switch (change.type) {
233
- case "add":
234
- case "remove": {
235
- const ret = {
236
- ...change,
237
- node: {
238
- ...change.node,
239
- relationships: { ...change.node.relationships }
240
- }
241
- };
242
- mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));
243
- return ret;
207
+ switch (change[0]) {
208
+ case 0: {
209
+ const relationships = { ...change[1].relationships };
210
+ mergeEmpty(relationships, Object.keys(schema.relationships));
211
+ return makeAddChange({
212
+ row: change[1].row,
213
+ relationships
214
+ });
215
+ }
216
+ case 1: {
217
+ const relationships = { ...change[1].relationships };
218
+ mergeEmpty(relationships, Object.keys(schema.relationships));
219
+ return makeRemoveChange({
220
+ row: change[1].row,
221
+ relationships
222
+ });
244
223
  }
245
- case "edit": {
246
- const ret = {
247
- ...change,
248
- node: {
249
- ...change.node,
250
- relationships: { ...change.node.relationships }
251
- },
252
- oldNode: {
253
- ...change.oldNode,
254
- relationships: { ...change.oldNode.relationships }
255
- }
256
- };
257
- mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));
258
- mergeEmpty(ret.oldNode.relationships, Object.keys(schema.relationships));
259
- return ret;
224
+ case 2: {
225
+ const nodeRelationships = { ...change[1].relationships };
226
+ const oldNodeRelationships = { ...change[2].relationships };
227
+ mergeEmpty(nodeRelationships, Object.keys(schema.relationships));
228
+ mergeEmpty(oldNodeRelationships, Object.keys(schema.relationships));
229
+ return makeEditChange({
230
+ row: change[1].row,
231
+ relationships: nodeRelationships
232
+ }, {
233
+ row: change[2].row,
234
+ relationships: oldNodeRelationships
235
+ });
260
236
  }
261
- case "child": return change;
237
+ case 3: return change;
262
238
  }
263
239
  };
264
240
  }
@@ -1 +1 @@
1
- {"version":3,"file":"push-accumulated.js","names":[],"sources":["../../../../../zql/src/ivm/push-accumulated.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Change} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {InputBase, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * # pushAccumulatedChanges\n *\n * Pushes the changes that were accumulated by\n * [fan-out, fan-in] or [ufo, ufi] sub-graphs.\n *\n * This function is called at the end of the sub-graph.\n *\n * The sub-graphs represents `OR`s.\n *\n * Changes that can enter the subgraphs:\n * 1. child (due to exist joins being above the sub-graph)\n * 2. add\n * 3. remove\n * 4. edit\n *\n * # Changes that can exit into `pushAccumulatedChanges`:\n *\n * ## Child\n * If a `child` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `child` change\n * - stop the `child` change (e.g., filter)\n * - convert it to an `add` or `remove` (e.g., exists filter)\n *\n * ## Add\n * If an `add` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `add` change\n * - hide the change (e.g., filter)\n *\n * ## Remove\n * If a `remove` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `remove` change\n * - hide the change (e.g., filter)\n *\n * ## Edit\n * If an `edit` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `edit` change\n * - convert it to an `add` (e.g., filter where old didn't match but new does)\n * - convert it to a `remove` (e.g., filter where old matched but new doesn't)\n *\n * This results in some invariants:\n * - an add coming in will only create adds coming out\n * - a remove coming in will only create removes coming out\n * - an edit coming in can create adds, removes, and edits coming out\n * - a child coming in can create adds, removes, and children coming out\n *\n * # Return of `pushAccumulatedChanges`\n *\n * This function will only push a single change.\n * Given the above invariants, how is this possible?\n *\n * An add that becomes many `adds` results in a single add\n * as the `add` is the same row across all adds. Branches do not change the row.\n *\n * A remove that becomes many `removes` results in a single remove\n * for the same reason.\n *\n * If a child enters and exits, it takes precedence over all other changes.\n * If a child enters and is converted only to add and remove it exits as an edit.\n * If a child enters and is converted to only add or only remove, it exits as that change.\n *\n * If an edit enters and is converted to add and remove it exits as an edit.\n * If an edit enters and is converted to only add or only remove, it exits as that change.\n * If an edit enters and exits as edits only, it exits as a single edit.\n */\nexport function* pushAccumulatedChanges(\n accumulatedPushes: Change[],\n output: Output,\n pusher: InputBase,\n fanOutChangeType: Change['type'],\n mergeRelationships: (existing: Change, incoming: Change) => Change,\n addEmptyRelationships: (change: Change) => Change,\n): Stream<'yield'> {\n if (accumulatedPushes.length === 0) {\n // It is possible for no forks to pass along the push.\n // E.g., if no filters match in any fork.\n return;\n }\n\n // collapse down to a single change per type\n const candidatesToPush = new Map<Change['type'], Change>();\n for (const change of accumulatedPushes) {\n if (fanOutChangeType === 'child' && change.type !== 'child') {\n assert(\n candidatesToPush.has(change.type) === false,\n () =>\n `Fan-in:child expected at most one ${change.type} when fan-out is of type child`,\n );\n }\n\n const existing = candidatesToPush.get(change.type);\n let mergedChange = change;\n if (existing) {\n // merge in relationships\n mergedChange = mergeRelationships(existing, change);\n }\n candidatesToPush.set(change.type, mergedChange);\n }\n\n accumulatedPushes.length = 0;\n\n const types = [...candidatesToPush.keys()];\n /**\n * Based on the received `fanOutChangeType` only certain output types are valid.\n *\n * - remove must result in all removes\n * - add must result in all adds\n * - edit must result in add or removes or edits\n * - child must result in a single add or single remove or many child changes\n * - Single add or remove because the relationship will be unique to one exist check within the fan-out,fan-in sub-graph\n * - Many child changes because other operators may preserve the child change\n */\n switch (fanOutChangeType) {\n case 'remove':\n assert(\n types.length === 1 && types[0] === 'remove',\n 'Fan-in:remove expected all removes',\n );\n yield* output.push(\n addEmptyRelationships(must(candidatesToPush.get('remove'))),\n pusher,\n );\n return;\n case 'add':\n assert(\n types.length === 1 && types[0] === 'add',\n 'Fan-in:add expected all adds',\n );\n yield* output.push(\n addEmptyRelationships(must(candidatesToPush.get('add'))),\n pusher,\n );\n return;\n case 'edit': {\n assert(\n types.every(\n type => type === 'add' || type === 'remove' || type === 'edit',\n ),\n 'Fan-in:edit expected all adds, removes, or edits',\n );\n const addChange = candidatesToPush.get('add');\n const removeChange = candidatesToPush.get('remove');\n let editChange = candidatesToPush.get('edit');\n\n // If an `edit` is present, it supersedes `add` and `remove`\n // as it semantically represents both.\n if (editChange) {\n if (addChange) {\n editChange = mergeRelationships(editChange, addChange);\n }\n if (removeChange) {\n editChange = mergeRelationships(editChange, removeChange);\n }\n yield* output.push(addEmptyRelationships(editChange), pusher);\n return;\n }\n\n // If `edit` didn't make it through but both `add` and `remove` did,\n // convert back to an edit.\n //\n // When can this happen?\n //\n // EDIT old: a=1, new: a=2\n // |\n // FanOut\n // / \\\n // a=1 a=2\n // | |\n // remove add\n // \\ /\n // FanIn\n //\n // The left filter converts the edit into a remove.\n // The right filter converts the edit into an add.\n if (addChange && removeChange) {\n yield* output.push(\n addEmptyRelationships({\n type: 'edit',\n node: addChange.node,\n oldNode: removeChange.node,\n } as const),\n pusher,\n );\n return;\n }\n\n yield* output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n case 'child': {\n assert(\n types.every(\n type =>\n type === 'add' || // exists can change child to add or remove\n type === 'remove' || // exists can change child to add or remove\n type === 'child', // other operators may preserve the child change\n ),\n 'Fan-in:child expected all adds, removes, or children',\n );\n assert(\n types.length <= 2,\n 'Fan-in:child expected at most 2 types on a child change from fan-out',\n );\n\n // If any branch preserved the original child change, that takes precedence over all other changes.\n const childChange = candidatesToPush.get('child');\n if (childChange) {\n yield* output.push(childChange, pusher);\n return;\n }\n\n const addChange = candidatesToPush.get('add');\n const removeChange = candidatesToPush.get('remove');\n\n assert(\n addChange === undefined || removeChange === undefined,\n 'Fan-in:child expected either add or remove, not both',\n );\n\n yield* output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n default:\n fanOutChangeType satisfies never;\n }\n}\n\n/**\n * Puts relationships from `right` into `left` if they don't already exist in `left`.\n */\nexport function mergeRelationships(left: Change, right: Change): Change {\n // change types will always match\n // unless we have an edit on the left\n // then the right could be edit, add, or remove\n if (left.type === right.type) {\n switch (left.type) {\n case 'add': {\n return {\n type: 'add',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n };\n }\n case 'remove': {\n return {\n type: 'remove',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n };\n }\n case 'edit': {\n assert(\n right.type === 'edit',\n () =>\n `mergeRelationships: when left.type is edit and types match, right.type must be edit, got ${right.type}`,\n );\n // merge edits into a single edit\n return {\n type: 'edit',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n oldNode: {\n row: left.oldNode.row,\n relationships: {\n ...right.oldNode.relationships,\n ...left.oldNode.relationships,\n },\n },\n };\n }\n case 'child': {\n // Multiple branches may preserve the same child change, each adding\n // different relationships. Merge the relationships, keeping the child\n // (which should be identical across branches).\n assert(\n right.type === 'child',\n () =>\n `mergeRelationships: when left.type is child and types match, right.type must be child, got ${right.type}`,\n );\n return {\n type: 'child',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n child: left.child,\n };\n }\n }\n }\n\n // left is always an edit here\n assert(\n left.type === 'edit',\n () =>\n `mergeRelationships: when types differ, left.type must be edit, got left.type=${left.type}, right.type=${right.type}`,\n );\n switch (right.type) {\n case 'add': {\n return {\n type: 'edit',\n node: {\n ...left.node,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n oldNode: left.oldNode,\n };\n }\n case 'remove': {\n return {\n type: 'edit',\n node: left.node,\n oldNode: {\n ...left.oldNode,\n relationships: {\n ...right.node.relationships,\n ...left.oldNode.relationships,\n },\n },\n };\n }\n }\n\n unreachable();\n}\n\nexport function makeAddEmptyRelationships(\n schema: SourceSchema,\n): (change: Change) => Change {\n return (change: Change): Change => {\n if (Object.keys(schema.relationships).length === 0) {\n return change;\n }\n\n switch (change.type) {\n case 'add':\n case 'remove': {\n const ret = {\n ...change,\n node: {\n ...change.node,\n relationships: {\n ...change.node.relationships,\n },\n },\n };\n\n mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));\n\n return ret;\n }\n case 'edit': {\n const ret = {\n ...change,\n node: {\n ...change.node,\n relationships: {\n ...change.node.relationships,\n },\n },\n oldNode: {\n ...change.oldNode,\n relationships: {\n ...change.oldNode.relationships,\n },\n },\n };\n\n mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));\n mergeEmpty(\n ret.oldNode.relationships,\n Object.keys(schema.relationships),\n );\n\n return ret;\n }\n case 'child':\n return change; // children only have relationships along the path to the change\n }\n };\n}\n\n/**\n * For each relationship in `schema` that does not exist\n * in `relationships`, add it with an empty stream.\n *\n * This modifies the `relationships` object in place.\n */\nexport function mergeEmpty(\n relationships: Record<string, () => Stream<Node | 'yield'>>,\n relationshipNames: string[],\n) {\n for (const relName of relationshipNames) {\n if (relationships[relName] === undefined) {\n relationships[relName] = () => emptyArray;\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"push-accumulated.js","names":[],"sources":["../../../../../zql/src/ivm/push-accumulated.ts"],"sourcesContent":["import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {\n makeAddChange,\n makeChildChange,\n makeEditChange,\n makeRemoveChange,\n type Change,\n} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {InputBase, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * # pushAccumulatedChanges\n *\n * Pushes the changes that were accumulated by\n * [fan-out, fan-in] or [ufo, ufi] sub-graphs.\n *\n * This function is called at the end of the sub-graph.\n *\n * The sub-graphs represents `OR`s.\n *\n * Changes that can enter the subgraphs:\n * 1. child (due to exist joins being above the sub-graph)\n * 2. add\n * 3. remove\n * 4. edit\n *\n * # Changes that can exit into `pushAccumulatedChanges`:\n *\n * ## Child\n * If a `child` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `child` change\n * - stop the `child` change (e.g., filter)\n * - convert it to an `add` or `remove` (e.g., exists filter)\n *\n * ## Add\n * If an `add` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `add` change\n * - hide the change (e.g., filter)\n *\n * ## Remove\n * If a `remove` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `remove` change\n * - hide the change (e.g., filter)\n *\n * ## Edit\n * If an `edit` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `edit` change\n * - convert it to an `add` (e.g., filter where old didn't match but new does)\n * - convert it to a `remove` (e.g., filter where old matched but new doesn't)\n *\n * This results in some invariants:\n * - an add coming in will only create adds coming out\n * - a remove coming in will only create removes coming out\n * - an edit coming in can create adds, removes, and edits coming out\n * - a child coming in can create adds, removes, and children coming out\n *\n * # Return of `pushAccumulatedChanges`\n *\n * This function will only push a single change.\n * Given the above invariants, how is this possible?\n *\n * An add that becomes many `adds` results in a single add\n * as the `add` is the same row across all adds. Branches do not change the row.\n *\n * A remove that becomes many `removes` results in a single remove\n * for the same reason.\n *\n * If a child enters and exits, it takes precedence over all other changes.\n * If a child enters and is converted only to add and remove it exits as an edit.\n * If a child enters and is converted to only add or only remove, it exits as that change.\n *\n * If an edit enters and is converted to add and remove it exits as an edit.\n * If an edit enters and is converted to only add or only remove, it exits as that change.\n * If an edit enters and exits as edits only, it exits as a single edit.\n */\nexport function* pushAccumulatedChanges(\n accumulatedPushes: Change[],\n output: Output,\n pusher: InputBase,\n fanOutChangeType: ChangeType,\n mergeRelationships: (existing: Change, incoming: Change) => Change,\n addEmptyRelationships: (change: Change) => Change,\n): Stream<'yield'> {\n if (accumulatedPushes.length === 0) {\n // It is possible for no forks to pass along the push.\n // E.g., if no filters match in any fork.\n return;\n }\n\n // collapse down to a single change per type\n const candidatesToPush = new Map<ChangeType, Change>();\n for (const change of accumulatedPushes) {\n if (\n fanOutChangeType === ChangeType.CHILD &&\n change[ChangeIndex.TYPE] !== ChangeType.CHILD\n ) {\n assert(\n candidatesToPush.has(change[ChangeIndex.TYPE]) === false,\n () =>\n `Fan-in:child expected at most one ${change[ChangeIndex.TYPE]} when fan-out is of type child`,\n );\n }\n\n const existing = candidatesToPush.get(change[ChangeIndex.TYPE]);\n let mergedChange = change;\n if (existing) {\n // merge in relationships\n mergedChange = mergeRelationships(existing, change);\n }\n candidatesToPush.set(change[ChangeIndex.TYPE], mergedChange);\n }\n\n accumulatedPushes.length = 0;\n\n const types = [...candidatesToPush.keys()];\n /**\n * Based on the received `fanOutChangeType` only certain output types are valid.\n *\n * - remove must result in all removes\n * - add must result in all adds\n * - edit must result in add or removes or edits\n * - child must result in a single add or single remove or many child changes\n * - Single add or remove because the relationship will be unique to one exist check within the fan-out,fan-in sub-graph\n * - Many child changes because other operators may preserve the child change\n */\n switch (fanOutChangeType) {\n case ChangeType.REMOVE:\n assert(\n types.length === 1 && types[0] === ChangeType.REMOVE,\n 'Fan-in:remove expected all removes',\n );\n yield* output.push(\n addEmptyRelationships(must(candidatesToPush.get(ChangeType.REMOVE))),\n pusher,\n );\n return;\n case ChangeType.ADD:\n assert(\n types.length === 1 && types[0] === ChangeType.ADD,\n 'Fan-in:add expected all adds',\n );\n yield* output.push(\n addEmptyRelationships(must(candidatesToPush.get(ChangeType.ADD))),\n pusher,\n );\n return;\n case ChangeType.EDIT: {\n assert(\n types.every(\n type =>\n type === ChangeType.ADD ||\n type === ChangeType.REMOVE ||\n type === ChangeType.EDIT,\n ),\n 'Fan-in:edit expected all adds, removes, or edits',\n );\n const addChange = candidatesToPush.get(ChangeType.ADD);\n const removeChange = candidatesToPush.get(ChangeType.REMOVE);\n let editChange = candidatesToPush.get(ChangeType.EDIT);\n\n // If an `edit` is present, it supersedes `add` and `remove`\n // as it semantically represents both.\n if (editChange) {\n if (addChange) {\n editChange = mergeRelationships(editChange, addChange);\n }\n if (removeChange) {\n editChange = mergeRelationships(editChange, removeChange);\n }\n yield* output.push(addEmptyRelationships(editChange), pusher);\n return;\n }\n\n // If `edit` didn't make it through but both `add` and `remove` did,\n // convert back to an edit.\n //\n // When can this happen?\n //\n // EDIT old: a=1, new: a=2\n // |\n // FanOut\n // / \\\n // a=1 a=2\n // | |\n // remove add\n // \\ /\n // FanIn\n //\n // The left filter converts the edit into a remove.\n // The right filter converts the edit into an add.\n if (addChange && removeChange) {\n yield* output.push(\n addEmptyRelationships(\n makeEditChange(\n addChange[ChangeIndex.NODE],\n removeChange[ChangeIndex.NODE],\n ),\n ),\n pusher,\n );\n return;\n }\n\n yield* output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n case ChangeType.CHILD: {\n assert(\n types.every(\n type =>\n type === ChangeType.ADD || // exists can change child to add or remove\n type === ChangeType.REMOVE || // exists can change child to add or remove\n type === ChangeType.CHILD, // other operators may preserve the child change\n ),\n 'Fan-in:child expected all adds, removes, or children',\n );\n assert(\n types.length <= 2,\n 'Fan-in:child expected at most 2 types on a child change from fan-out',\n );\n\n // If any branch preserved the original child change, that takes precedence over all other changes.\n const childChange = candidatesToPush.get(ChangeType.CHILD);\n if (childChange) {\n yield* output.push(childChange, pusher);\n return;\n }\n\n const addChange = candidatesToPush.get(ChangeType.ADD);\n const removeChange = candidatesToPush.get(ChangeType.REMOVE);\n\n assert(\n addChange === undefined || removeChange === undefined,\n 'Fan-in:child expected either add or remove, not both',\n );\n\n yield* output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n default:\n fanOutChangeType satisfies never;\n }\n}\n\n/**\n * Puts relationships from `right` into `left` if they don't already exist in `left`.\n */\nexport function mergeRelationships(left: Change, right: Change): Change {\n // change types will always match\n // unless we have an edit on the left\n // then the right could be edit, add, or remove\n if (left[ChangeIndex.TYPE] === right[ChangeIndex.TYPE]) {\n switch (left[ChangeIndex.TYPE]) {\n case ChangeType.ADD: {\n return makeAddChange({\n row: left[ChangeIndex.NODE].row,\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.NODE].relationships,\n },\n });\n }\n case ChangeType.REMOVE: {\n return makeRemoveChange({\n row: left[ChangeIndex.NODE].row,\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.NODE].relationships,\n },\n });\n }\n case ChangeType.EDIT: {\n assert(\n right[ChangeIndex.TYPE] === ChangeType.EDIT,\n () =>\n `mergeRelationships: when left.type is edit and types match, right.type must be edit, got ${right[ChangeIndex.TYPE]}`,\n );\n // merge edits into a single edit\n return makeEditChange(\n {\n row: left[ChangeIndex.NODE].row,\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.NODE].relationships,\n },\n },\n {\n row: left[ChangeIndex.OLD_NODE].row,\n relationships: {\n ...right[ChangeIndex.OLD_NODE].relationships,\n ...left[ChangeIndex.OLD_NODE].relationships,\n },\n },\n );\n }\n case ChangeType.CHILD: {\n // Multiple branches may preserve the same child change, each adding\n // different relationships. Merge the relationships, keeping the child\n // (which should be identical across branches).\n assert(\n right[ChangeIndex.TYPE] === ChangeType.CHILD,\n () =>\n `mergeRelationships: when left.type is child and types match, right.type must be child, got ${right[ChangeIndex.TYPE]}`,\n );\n return makeChildChange(\n {\n row: left[ChangeIndex.NODE].row,\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.NODE].relationships,\n },\n },\n left[ChangeIndex.CHILD_DATA],\n );\n }\n }\n }\n\n // left is always an edit here\n assert(\n left[ChangeIndex.TYPE] === ChangeType.EDIT,\n () =>\n `mergeRelationships: when types differ, left.type must be edit, got left.type=${left[ChangeIndex.TYPE]}, right.type=${right[ChangeIndex.TYPE]}`,\n );\n switch (right[ChangeIndex.TYPE]) {\n case ChangeType.ADD: {\n return makeEditChange(\n {\n ...left[ChangeIndex.NODE],\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.NODE].relationships,\n },\n },\n left[ChangeIndex.OLD_NODE],\n );\n }\n case ChangeType.REMOVE: {\n return makeEditChange(left[ChangeIndex.NODE], {\n ...left[ChangeIndex.OLD_NODE],\n relationships: {\n ...right[ChangeIndex.NODE].relationships,\n ...left[ChangeIndex.OLD_NODE].relationships,\n },\n });\n }\n }\n\n unreachable();\n}\n\nexport function makeAddEmptyRelationships(\n schema: SourceSchema,\n): (change: Change) => Change {\n return (change: Change): Change => {\n if (Object.keys(schema.relationships).length === 0) {\n return change;\n }\n\n switch (change[ChangeIndex.TYPE]) {\n case ChangeType.ADD: {\n const relationships = {...change[ChangeIndex.NODE].relationships};\n mergeEmpty(relationships, Object.keys(schema.relationships));\n return makeAddChange({\n row: change[ChangeIndex.NODE].row,\n relationships,\n });\n }\n case ChangeType.REMOVE: {\n const relationships = {...change[ChangeIndex.NODE].relationships};\n mergeEmpty(relationships, Object.keys(schema.relationships));\n return makeRemoveChange({\n row: change[ChangeIndex.NODE].row,\n relationships,\n });\n }\n case ChangeType.EDIT: {\n const nodeRelationships = {...change[ChangeIndex.NODE].relationships};\n const oldNodeRelationships = {\n ...change[ChangeIndex.OLD_NODE].relationships,\n };\n mergeEmpty(nodeRelationships, Object.keys(schema.relationships));\n mergeEmpty(oldNodeRelationships, Object.keys(schema.relationships));\n return makeEditChange(\n {row: change[ChangeIndex.NODE].row, relationships: nodeRelationships},\n {\n row: change[ChangeIndex.OLD_NODE].row,\n relationships: oldNodeRelationships,\n },\n );\n }\n case ChangeType.CHILD:\n return change; // children only have relationships along the path to the change\n }\n };\n}\n\n/**\n * For each relationship in `schema` that does not exist\n * in `relationships`, add it with an empty stream.\n *\n * This modifies the `relationships` object in place.\n */\nexport function mergeEmpty(\n relationships: Record<string, () => Stream<Node | 'yield'>>,\n relationshipNames: string[],\n) {\n for (const relName of relationshipNames) {\n if (relationships[relName] === undefined) {\n relationships[relName] = () => emptyArray;\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Node } from './data.ts';
2
+ import type { Stream } from './stream.ts';
3
+ export declare function skipYields(stream: Stream<Node | 'yield'>): Stream<Node>;
4
+ //# sourceMappingURL=skip-yields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skip-yields.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/skip-yields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AA0CxC,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAEvE"}
@@ -0,0 +1,33 @@
1
+ //#region ../zql/src/ivm/skip-yields.ts
2
+ var SkipYieldsStream = class {
3
+ #stream;
4
+ #it = void 0;
5
+ constructor(stream) {
6
+ this.#stream = stream;
7
+ }
8
+ [Symbol.iterator]() {
9
+ this.#it = this.#stream[Symbol.iterator]();
10
+ return this;
11
+ }
12
+ next() {
13
+ const it = this.#it;
14
+ for (;;) {
15
+ const r = it.next();
16
+ if (r.done || r.value !== "yield") return r;
17
+ }
18
+ }
19
+ return(value) {
20
+ this.#it?.return?.(value);
21
+ return {
22
+ done: true,
23
+ value: void 0
24
+ };
25
+ }
26
+ };
27
+ function skipYields(stream) {
28
+ return new SkipYieldsStream(stream);
29
+ }
30
+ //#endregion
31
+ export { skipYields };
32
+
33
+ //# sourceMappingURL=skip-yields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skip-yields.js","names":["#stream","#it"],"sources":["../../../../../zql/src/ivm/skip-yields.ts"],"sourcesContent":["import type {Node} from './data.ts';\nimport type {Stream} from './stream.ts';\n\n// Implemented as a custom IterableIterator rather than a generator function to\n// reduce allocations. A generator creates a new state-machine object each time\n// it is called. By returning `this` from [Symbol.iterator](), the same object\n// acts as both the Iterable and the Iterator, so iterating the stream incurs\n// only one allocation (the SkipYieldsStream instance itself) instead of two.\n// Additionally, the IteratorResult objects ({value, done}) from the inner\n// iterator are returned directly rather than being recreated, avoiding further\n// per-item allocations.\nclass SkipYieldsStream implements IterableIterator<Node> {\n readonly #stream: Stream<Node | 'yield'>;\n #it: Iterator<Node | 'yield'> | undefined = undefined;\n\n constructor(stream: Stream<Node | 'yield'>) {\n this.#stream = stream;\n }\n\n [Symbol.iterator](): IterableIterator<Node> {\n this.#it = this.#stream[Symbol.iterator]();\n return this;\n }\n\n next(): IteratorResult<Node> {\n // #it is always set before next() is called, as [Symbol.iterator]() must\n // be called first (e.g. by a for-of loop).\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const it = this.#it!;\n for (;;) {\n const r = it.next();\n if (r.done || r.value !== 'yield') {\n return r as IteratorResult<Node>;\n }\n }\n }\n\n return(value?: undefined): IteratorResult<Node> {\n this.#it?.return?.(value);\n return {done: true, value: undefined};\n }\n}\n\nexport function skipYields(stream: Stream<Node | 'yield'>): Stream<Node> {\n return new SkipYieldsStream(stream);\n}\n"],"mappings":";AAWA,IAAM,mBAAN,MAAyD;CACvD;CACA,MAA4C,KAAA;CAE5C,YAAY,QAAgC;AAC1C,QAAA,SAAe;;CAGjB,CAAC,OAAO,YAAoC;AAC1C,QAAA,KAAW,MAAA,OAAa,OAAO,WAAW;AAC1C,SAAO;;CAGT,OAA6B;EAI3B,MAAM,KAAK,MAAA;AACX,WAAS;GACP,MAAM,IAAI,GAAG,MAAM;AACnB,OAAI,EAAE,QAAQ,EAAE,UAAU,QACxB,QAAO;;;CAKb,OAAO,OAAyC;AAC9C,QAAA,IAAU,SAAS,MAAM;AACzB,SAAO;GAAC,MAAM;GAAM,OAAO,KAAA;GAAU;;;AAIzC,SAAgB,WAAW,QAA8C;AACvE,QAAO,IAAI,iBAAiB,OAAO"}
@@ -1,5 +1,5 @@
1
1
  import type { Row } from '../../../zero-protocol/src/data.ts';
2
- import type { Change } from './change.ts';
2
+ import { type Change } from './change.ts';
3
3
  import type { Node } from './data.ts';
4
4
  import { type FetchRequest, type Input, type Operator, type Output } from './operator.ts';
5
5
  import type { SourceSchema } from './schema.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"skip.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/skip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAY,MAAM,EAA4B,MAAM,aAAa,CAAC;AAC9E,OAAO,KAAK,EAAa,IAAI,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAOvB,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IAStC,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IAsBjD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,OAAO,IAAI,IAAI;IASd,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;CA+EvC"}
1
+ {"version":3,"file":"skip.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/skip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAG5D,OAAO,EAEL,KAAK,MAAM,EAGZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAa,IAAI,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EAEZ,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,KAAK,GAAG;IAClB,GAAG,EAAE,GAAG,CAAC;IACT,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF;;;GAGG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAOvB,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK;IAStC,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IAsBjD,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,OAAO,IAAI,IAAI;IASd,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;CA+EvC"}
@@ -54,11 +54,11 @@ var Skip = class {
54
54
  }
55
55
  *push(change) {
56
56
  const shouldBePresent = (row) => this.#shouldBePresent(row);
57
- if (change.type === "edit") {
57
+ if (change[0] === 2) {
58
58
  yield* maybeSplitAndPushEditChange(change, shouldBePresent, this.#output, this);
59
59
  return;
60
60
  }
61
- if (shouldBePresent(change.node.row)) yield* this.#output.push(change, this);
61
+ if (shouldBePresent(change[1].row)) yield* this.#output.push(change, this);
62
62
  }
63
63
  #getStart(req) {
64
64
  const boundStart = {
@@ -1 +1 @@
1
- {"version":3,"file":"skip.js","names":["#input","#bound","#comparator","#getStart","#shouldBePresent","#output"],"sources":["../../../../../zql/src/ivm/skip.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {AddChange, Change, ChildChange, RemoveChange} from './change.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output = throwOutput;\n\n constructor(input: Input, bound: Bound) {\n const {sort} = input.getSchema();\n assert(sort !== undefined, 'Skip requires sorted input');\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n input.setOutput(this);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const start = this.#getStart(req);\n if (start === 'empty') {\n return;\n }\n const nodes = this.#input.fetch({...req, start});\n if (!req.reverse) {\n yield* nodes;\n return;\n }\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!this.#shouldBePresent(node.row)) {\n return;\n }\n yield node;\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n #shouldBePresent(row: Row): boolean {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n }\n\n *push(change: Change): Stream<'yield'> {\n const shouldBePresent = (row: Row) => this.#shouldBePresent(row);\n if (change.type === 'edit') {\n yield* maybeSplitAndPushEditChange(\n change,\n shouldBePresent,\n this.#output,\n this,\n );\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n if (shouldBePresent(change.node.row)) {\n yield* this.#output.push(change, this);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined | 'empty' {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n if (req.reverse) {\n return undefined;\n }\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n if (!req.reverse) {\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n return req.start;\n }\n\n req.reverse satisfies true;\n\n // bound is after the start, but request is for reverse so results\n // must be empty\n if (cmp > 0) {\n return 'empty';\n }\n\n if (cmp === 0) {\n // if both are inclusive, the result can be the single row at bound\n // return it as start\n if (!this.#bound.exclusive && req.start.basis === 'at') {\n return boundStart;\n }\n // otherwise the results must be empty, one or both are exclusive\n // in opposite directions\n return 'empty';\n }\n\n // bound is before the start, return start\n return req.start;\n }\n}\n"],"mappings":";;;;;;;;AAyBA,IAAa,OAAb,MAAsC;CACpC;CACA;CACA;CAEA,UAAkB;CAElB,YAAY,OAAc,OAAc;EACtC,MAAM,EAAC,SAAQ,MAAM,WAAW;AAChC,SAAO,SAAS,KAAA,GAAW,6BAA6B;AACxD,QAAA,QAAc;AACd,QAAA,QAAc;AACd,QAAA,aAAmB,MAAM,WAAW,CAAC;AACrC,QAAM,UAAU,KAAK;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,MAAM,KAA2C;EAChD,MAAM,QAAQ,MAAA,SAAe,IAAI;AACjC,MAAI,UAAU,QACZ;EAEF,MAAM,QAAQ,MAAA,MAAY,MAAM;GAAC,GAAG;GAAK;GAAM,CAAC;AAChD,MAAI,CAAC,IAAI,SAAS;AAChB,UAAO;AACP;;AAEF,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,SAAS,SAAS;AACpB,UAAM;AACN;;AAEF,OAAI,CAAC,MAAA,gBAAsB,KAAK,IAAI,CAClC;AAEF,SAAM;;;CAIV,UAAU,QAAsB;AAC9B,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,iBAAiB,KAAmB;EAClC,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI;AAClD,SAAO,MAAM,KAAM,QAAQ,KAAK,CAAC,MAAA,MAAY;;CAG/C,CAAC,KAAK,QAAiC;EACrC,MAAM,mBAAmB,QAAa,MAAA,gBAAsB,IAAI;AAChE,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAO,4BACL,QACA,iBACA,MAAA,QACA,KACD;AACD;;AAKF,MAAI,gBAAgB,OAAO,KAAK,IAAI,CAClC,QAAO,MAAA,OAAa,KAAK,QAAQ,KAAK;;CAI1C,UAAU,KAAgD;EACxD,MAAM,aAAa;GACjB,KAAK,MAAA,MAAY;GACjB,OAAO,MAAA,MAAY,YAAY,UAAU;GAC1C;AAED,MAAI,CAAC,IAAI,OAAO;AACd,OAAI,IAAI,QACN;AAEF,UAAO;;EAGT,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI,MAAM,IAAI;AAE5D,MAAI,CAAC,IAAI,SAAS;AAIhB,OAAI,MAAM,EACR,QAAO;AAKT,OAAI,QAAQ,GAAG;AACb,QAAI,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,QAC/C,QAAO;KACL,KAAK,MAAA,MAAY;KACjB,OAAO;KACR;AAEH,WAAO;;AAGT,UAAO,IAAI;;AAGb,MAAI;AAIJ,MAAI,MAAM,EACR,QAAO;AAGT,MAAI,QAAQ,GAAG;AAGb,OAAI,CAAC,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,KAChD,QAAO;AAIT,UAAO;;AAIT,SAAO,IAAI"}
1
+ {"version":3,"file":"skip.js","names":["#input","#bound","#comparator","#getStart","#shouldBePresent","#output"],"sources":["../../../../../zql/src/ivm/skip.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {ChangeIndex} from './change-index.ts';\nimport {ChangeType} from './change-type.ts';\nimport {\n type AddChange,\n type Change,\n type ChildChange,\n type RemoveChange,\n} from './change.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output = throwOutput;\n\n constructor(input: Input, bound: Bound) {\n const {sort} = input.getSchema();\n assert(sort !== undefined, 'Skip requires sorted input');\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n input.setOutput(this);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node | 'yield'> {\n const start = this.#getStart(req);\n if (start === 'empty') {\n return;\n }\n const nodes = this.#input.fetch({...req, start});\n if (!req.reverse) {\n yield* nodes;\n return;\n }\n for (const node of nodes) {\n if (node === 'yield') {\n yield node;\n continue;\n }\n if (!this.#shouldBePresent(node.row)) {\n return;\n }\n yield node;\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n #shouldBePresent(row: Row): boolean {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n }\n\n *push(change: Change): Stream<'yield'> {\n const shouldBePresent = (row: Row) => this.#shouldBePresent(row);\n if (change[ChangeIndex.TYPE] === ChangeType.EDIT) {\n yield* maybeSplitAndPushEditChange(\n change,\n shouldBePresent,\n this.#output,\n this,\n );\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n if (shouldBePresent(change[ChangeIndex.NODE].row)) {\n yield* this.#output.push(change, this);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined | 'empty' {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n if (req.reverse) {\n return undefined;\n }\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n if (!req.reverse) {\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n return req.start;\n }\n\n req.reverse satisfies true;\n\n // bound is after the start, but request is for reverse so results\n // must be empty\n if (cmp > 0) {\n return 'empty';\n }\n\n if (cmp === 0) {\n // if both are inclusive, the result can be the single row at bound\n // return it as start\n if (!this.#bound.exclusive && req.start.basis === 'at') {\n return boundStart;\n }\n // otherwise the results must be empty, one or both are exclusive\n // in opposite directions\n return 'empty';\n }\n\n // bound is before the start, return start\n return req.start;\n }\n}\n"],"mappings":";;;;;;;;AAgCA,IAAa,OAAb,MAAsC;CACpC;CACA;CACA;CAEA,UAAkB;CAElB,YAAY,OAAc,OAAc;EACtC,MAAM,EAAC,SAAQ,MAAM,WAAW;AAChC,SAAO,SAAS,KAAA,GAAW,6BAA6B;AACxD,QAAA,QAAc;AACd,QAAA,QAAc;AACd,QAAA,aAAmB,MAAM,WAAW,CAAC;AACrC,QAAM,UAAU,KAAK;;CAGvB,YAA0B;AACxB,SAAO,MAAA,MAAY,WAAW;;CAGhC,CAAC,MAAM,KAA2C;EAChD,MAAM,QAAQ,MAAA,SAAe,IAAI;AACjC,MAAI,UAAU,QACZ;EAEF,MAAM,QAAQ,MAAA,MAAY,MAAM;GAAC,GAAG;GAAK;GAAM,CAAC;AAChD,MAAI,CAAC,IAAI,SAAS;AAChB,UAAO;AACP;;AAEF,OAAK,MAAM,QAAQ,OAAO;AACxB,OAAI,SAAS,SAAS;AACpB,UAAM;AACN;;AAEF,OAAI,CAAC,MAAA,gBAAsB,KAAK,IAAI,CAClC;AAEF,SAAM;;;CAIV,UAAU,QAAsB;AAC9B,QAAA,SAAe;;CAGjB,UAAgB;AACd,QAAA,MAAY,SAAS;;CAGvB,iBAAiB,KAAmB;EAClC,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI;AAClD,SAAO,MAAM,KAAM,QAAQ,KAAK,CAAC,MAAA,MAAY;;CAG/C,CAAC,KAAK,QAAiC;EACrC,MAAM,mBAAmB,QAAa,MAAA,gBAAsB,IAAI;AAChE,MAAI,OAAO,OAAsB,GAAiB;AAChD,UAAO,4BACL,QACA,iBACA,MAAA,QACA,KACD;AACD;;AAKF,MAAI,gBAAgB,OAAO,GAAkB,IAAI,CAC/C,QAAO,MAAA,OAAa,KAAK,QAAQ,KAAK;;CAI1C,UAAU,KAAgD;EACxD,MAAM,aAAa;GACjB,KAAK,MAAA,MAAY;GACjB,OAAO,MAAA,MAAY,YAAY,UAAU;GAC1C;AAED,MAAI,CAAC,IAAI,OAAO;AACd,OAAI,IAAI,QACN;AAEF,UAAO;;EAGT,MAAM,MAAM,MAAA,WAAiB,MAAA,MAAY,KAAK,IAAI,MAAM,IAAI;AAE5D,MAAI,CAAC,IAAI,SAAS;AAIhB,OAAI,MAAM,EACR,QAAO;AAKT,OAAI,QAAQ,GAAG;AACb,QAAI,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,QAC/C,QAAO;KACL,KAAK,MAAA,MAAY;KACjB,OAAO;KACR;AAEH,WAAO;;AAGT,UAAO,IAAI;;AAGb,MAAI;AAIJ,MAAI,MAAM,EACR,QAAO;AAGT,MAAI,QAAQ,GAAG;AAGb,OAAI,CAAC,MAAA,MAAY,aAAa,IAAI,MAAM,UAAU,KAChD,QAAO;AAIT,UAAO;;AAIT,SAAO,IAAI"}
@@ -0,0 +1,7 @@
1
+ export declare const TYPE = 0;
2
+ export declare const ROW = 1;
3
+ export declare const OLD_ROW = 2;
4
+ export type TYPE = typeof TYPE;
5
+ export type ROW = typeof ROW;
6
+ export type OLD_ROW = typeof OLD_ROW;
7
+ //# sourceMappingURL=source-change-index-enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-change-index-enum.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source-change-index-enum.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,IAAI,CAAC;AACtB,eAAO,MAAM,GAAG,IAAI,CAAC;AACrB,eAAO,MAAM,OAAO,IAAI,CAAC;AAEzB,MAAM,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC;AAC/B,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC;AAC7B,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { Enum } from '../../../shared/src/enum.ts';
2
+ import * as SourceChangeIndexEnum from './source-change-index-enum.ts';
3
+ export { SourceChangeIndexEnum as SourceChangeIndex };
4
+ export type SourceChangeIndex = Enum<typeof SourceChangeIndexEnum>;
5
+ //# sourceMappingURL=source-change-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-change-index.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source-change-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AAEvE,OAAO,EAAC,qBAAqB,IAAI,iBAAiB,EAAC,CAAC;AACpD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -2,22 +2,20 @@ import type { Condition, Ordering } from '../../../zero-protocol/src/ast.ts';
2
2
  import type { Row } from '../../../zero-protocol/src/data.ts';
3
3
  import type { TableSchema } from '../../../zero-types/src/schema.ts';
4
4
  import type { DebugDelegate } from '../builder/debug-delegate.ts';
5
+ import { ChangeType } from './change-type.ts';
5
6
  import type { Input } from './operator.ts';
6
7
  import type { Stream } from './stream.ts';
7
- export type SourceChangeAdd = {
8
- type: 'add';
9
- row: Row;
10
- };
11
- export type SourceChangeRemove = {
12
- type: 'remove';
13
- row: Row;
14
- };
15
- export type SourceChangeEdit = {
16
- type: 'edit';
17
- row: Row;
18
- oldRow: Row;
19
- };
8
+ export type SourceChangeAdd = [type: ChangeType.ADD, row: Row, extra: null];
9
+ export type SourceChangeRemove = [
10
+ type: ChangeType.REMOVE,
11
+ row: Row,
12
+ extra: null
13
+ ];
14
+ export type SourceChangeEdit = [type: ChangeType.EDIT, row: Row, oldRow: Row];
20
15
  export type SourceChange = SourceChangeAdd | SourceChangeRemove | SourceChangeEdit;
16
+ export declare function makeSourceChangeAdd(row: Row): SourceChangeAdd;
17
+ export declare function makeSourceChangeRemove(row: Row): SourceChangeRemove;
18
+ export declare function makeSourceChangeEdit(row: Row, oldRow: Row): SourceChangeEdit;
21
19
  /**
22
20
  * A source is an input that serves as the root data source of the pipeline.
23
21
  * Sources have multiple outputs. To add an output, call `connect()`, then
@@ -1 +1 @@
1
- {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,CAAC;AAErB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,WAAW,IAAI,WAAW,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,OAAO,CACL,IAAI,EAAE,QAAQ,GAAG,SAAS,EAC1B,OAAO,CAAC,EAAE,SAAS,EACnB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,aAAa,GACpB,WAAW,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5C;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC"}
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/source.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,SAAS,EAAE,QAAQ,EAAC,MAAM,mCAAmC,CAAC;AAC3E,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAC5C,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AAExC,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;AAC5E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,UAAU,CAAC,MAAM;IACvB,GAAG,EAAE,GAAG;IACR,KAAK,EAAE,IAAI;CACZ,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;AAE9E,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,GAAG,GAAG,eAAe,CAE7D;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,GAAG,GAAG,kBAAkB,CAEnE;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAG,gBAAgB,CAE5E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,MAAM;IACrB,IAAI,WAAW,IAAI,WAAW,CAAC;IAC/B;;;;;;;;;;;OAWG;IACH,OAAO,CACL,IAAI,EAAE,QAAQ,GAAG,SAAS,EAC1B,OAAO,CAAC,EAAE,SAAS,EACnB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAC3B,KAAK,CAAC,EAAE,aAAa,GACpB,WAAW,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAE5C;;;;;;;;;OASG;IACH,OAAO,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,WAAY,SAAQ,KAAK;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;CACvC"}
@@ -0,0 +1,26 @@
1
+ //#region ../zql/src/ivm/source.ts
2
+ function makeSourceChangeAdd(row) {
3
+ return [
4
+ 0,
5
+ row,
6
+ null
7
+ ];
8
+ }
9
+ function makeSourceChangeRemove(row) {
10
+ return [
11
+ 1,
12
+ row,
13
+ null
14
+ ];
15
+ }
16
+ function makeSourceChangeEdit(row, oldRow) {
17
+ return [
18
+ 2,
19
+ row,
20
+ oldRow
21
+ ];
22
+ }
23
+ //#endregion
24
+ export { makeSourceChangeAdd, makeSourceChangeEdit, makeSourceChangeRemove };
25
+
26
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","names":[],"sources":["../../../../../zql/src/ivm/source.ts"],"sourcesContent":["import type {Condition, Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {TableSchema} from '../../../zero-types/src/schema.ts';\nimport type {DebugDelegate} from '../builder/debug-delegate.ts';\nimport {ChangeType} from './change-type.ts';\nimport type {Input} from './operator.ts';\nimport type {Stream} from './stream.ts';\n\nexport type SourceChangeAdd = [type: ChangeType.ADD, row: Row, extra: null];\nexport type SourceChangeRemove = [\n type: ChangeType.REMOVE,\n row: Row,\n extra: null,\n];\nexport type SourceChangeEdit = [type: ChangeType.EDIT, row: Row, oldRow: Row];\n\nexport type SourceChange =\n | SourceChangeAdd\n | SourceChangeRemove\n | SourceChangeEdit;\n\nexport function makeSourceChangeAdd(row: Row): SourceChangeAdd {\n return [ChangeType.ADD, row, null];\n}\n\nexport function makeSourceChangeRemove(row: Row): SourceChangeRemove {\n return [ChangeType.REMOVE, row, null];\n}\n\nexport function makeSourceChangeEdit(row: Row, oldRow: Row): SourceChangeEdit {\n return [ChangeType.EDIT, row, oldRow];\n}\n\n/**\n * A source is an input that serves as the root data source of the pipeline.\n * Sources have multiple outputs. To add an output, call `connect()`, then\n * hook yourself up to the returned Connector, like:\n *\n * ```ts\n * class MyOperator implements Output {\n * constructor(input: Input) {\n * input.setOutput(this);\n * }\n *\n * push(change: Change): void {\n * // Handle change\n * }\n * }\n *\n * const connection = source.connect(ordering);\n * const myOperator = new MyOperator(connection);\n * ```\n */\nexport interface Source {\n get tableSchema(): TableSchema;\n /**\n * Creates an input that an operator can connect to. To free resources used\n * by connection, downstream operators call `destroy()` on the returned\n * input.\n *\n * @param sort The ordering of the rows. Source must return rows in this\n * order. Must include all primary keys of the table.\n * @param filters Filters to apply to the source.\n * @param splitEditKeys If an edit change modifies the values of any of the\n * keys in splitEditKeys, the source should split the edit change into\n * a remove of the old row followed by an add of the new row.\n */\n connect(\n sort: Ordering | undefined,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n debug?: DebugDelegate,\n ): SourceInput;\n\n /**\n * Pushes a change into the source and into all connected outputs.\n *\n * The returned stream can yield 'yield' to yield control to the caller\n * for purposes of responsiveness.\n *\n * Once the stream is exhausted, the change will have been pushed into all\n * connected inputs and committed to the source.\n */\n push(change: SourceChange): Stream<'yield'>;\n\n /**\n * Pushes a change into the source.\n *\n * Iterating the returned stream will push the change into one connected input\n * at a time, yielding `undefined` between each, and yielding `'yield'` to\n * yield control to the caller for purposes of responsiveness.\n *\n * Once the stream is exhausted, the change will have been pushed\n * into all connected inputs and committed to the source.\n */\n genPush(change: SourceChange): Stream<'yield' | undefined>;\n}\n\nexport interface SourceInput extends Input {\n readonly fullyAppliedFilters: boolean;\n}\n"],"mappings":";AAqBA,SAAgB,oBAAoB,KAA2B;AAC7D,QAAO;EAAC;EAAgB;EAAK;EAAK;;AAGpC,SAAgB,uBAAuB,KAA8B;AACnE,QAAO;EAAC;EAAmB;EAAK;EAAK;;AAGvC,SAAgB,qBAAqB,KAAU,QAA+B;AAC5E,QAAO;EAAC;EAAiB;EAAK;EAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"take.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/take.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAE1E,OAAO,EAAC,KAAK,MAAM,EAAqC,MAAM,aAAa,CAAC;AAC5E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAiBxC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAYjC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,YAAY;IAe7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IA0JhD,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;IA4dtC,OAAO,IAAI,IAAI;CAGhB;AAmBD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,OAAO,CAaT;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,GACzB,UAAU,CAUZ"}
1
+ {"version":3,"file":"take.d.ts","sourceRoot":"","sources":["../../../../../zql/src/ivm/take.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,2CAA2C,CAAC;AAI1E,OAAO,EAGL,KAAK,MAAM,EAEZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,IAAI,EAAC,MAAM,WAAW,CAAC;AACpE,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,KAAK,EACV,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAC,KAAK,MAAM,EAAC,MAAM,aAAa,CAAC;AAiBxC,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC;AAEtC;;;;;;;;;;GAUG;AACH,qBAAa,IAAK,YAAW,QAAQ;;gBAYjC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,YAAY,CAAC,EAAE,YAAY;IAe7B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAI/B,SAAS,IAAI,YAAY;IAIxB,KAAK,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;IA0JhD,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC;IA0ctC,OAAO,IAAI,IAAI;CAGhB;AAmBD,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,UAAU,GAAG,SAAS,EAClC,YAAY,EAAE,YAAY,GAAG,SAAS,GACrC,OAAO,CAaT;AAED,wBAAgB,0BAA0B,CACxC,YAAY,EAAE,YAAY,GACzB,UAAU,CAUZ"}