@rocicorp/zero 1.10.0-canary.24 → 1.10.0-canary.25

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 (570) hide show
  1. package/out/analyze-query/src/bin-analyze.js +8 -9
  2. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  3. package/out/replicache/src/btree/node.d.ts.map +1 -1
  4. package/out/replicache/src/btree/node.js +6 -3
  5. package/out/replicache/src/btree/node.js.map +1 -1
  6. package/out/replicache/src/btree/read.d.ts +1 -12
  7. package/out/replicache/src/btree/read.d.ts.map +1 -1
  8. package/out/replicache/src/btree/read.js +12 -24
  9. package/out/replicache/src/btree/read.js.map +1 -1
  10. package/out/replicache/src/dag/gc.d.ts.map +1 -1
  11. package/out/replicache/src/dag/gc.js +11 -8
  12. package/out/replicache/src/dag/gc.js.map +1 -1
  13. package/out/replicache/src/dag/store-impl.d.ts +2 -12
  14. package/out/replicache/src/dag/store-impl.d.ts.map +1 -1
  15. package/out/replicache/src/dag/store-impl.js +8 -22
  16. package/out/replicache/src/dag/store-impl.js.map +1 -1
  17. package/out/replicache/src/db/rebase.d.ts +2 -14
  18. package/out/replicache/src/db/rebase.d.ts.map +1 -1
  19. package/out/replicache/src/db/rebase.js +5 -27
  20. package/out/replicache/src/db/rebase.js.map +1 -1
  21. package/out/replicache/src/db/write.js.map +1 -1
  22. package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
  23. package/out/replicache/src/kv/expo-sqlite/store.js +5 -28
  24. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  25. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +5 -15
  26. package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -1
  27. package/out/replicache/src/kv/idb-store-with-mem-fallback.js +25 -25
  28. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  29. package/out/replicache/src/kv/idb-store.d.ts +0 -9
  30. package/out/replicache/src/kv/idb-store.d.ts.map +1 -1
  31. package/out/replicache/src/kv/idb-store.js +2 -14
  32. package/out/replicache/src/kv/idb-store.js.map +1 -1
  33. package/out/replicache/src/kv/mem-store.d.ts +0 -1
  34. package/out/replicache/src/kv/mem-store.d.ts.map +1 -1
  35. package/out/replicache/src/kv/mem-store.js +0 -3
  36. package/out/replicache/src/kv/mem-store.js.map +1 -1
  37. package/out/replicache/src/kv/op-sqlite/store.d.ts.map +1 -1
  38. package/out/replicache/src/kv/op-sqlite/store.js +1 -1
  39. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  40. package/out/replicache/src/kv/sqlite-store.d.ts +1 -13
  41. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  42. package/out/replicache/src/kv/sqlite-store.js +6 -73
  43. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  44. package/out/replicache/src/kv/store.d.ts +0 -6
  45. package/out/replicache/src/kv/store.d.ts.map +1 -1
  46. package/out/replicache/src/persist/collect-idb-databases.d.ts +5 -10
  47. package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
  48. package/out/replicache/src/persist/collect-idb-databases.js +9 -16
  49. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  50. package/out/replicache/src/persist/persist.d.ts.map +1 -1
  51. package/out/replicache/src/persist/persist.js +6 -13
  52. package/out/replicache/src/persist/persist.js.map +1 -1
  53. package/out/replicache/src/persist/refresh.js +2 -6
  54. package/out/replicache/src/persist/refresh.js.map +1 -1
  55. package/out/replicache/src/replicache-impl.d.ts +3 -14
  56. package/out/replicache/src/replicache-impl.d.ts.map +1 -1
  57. package/out/replicache/src/replicache-impl.js +11 -118
  58. package/out/replicache/src/replicache-impl.js.map +1 -1
  59. package/out/replicache/src/replicache-options.d.ts +0 -9
  60. package/out/replicache/src/replicache-options.d.ts.map +1 -1
  61. package/out/replicache/src/transactions.d.ts.map +1 -1
  62. package/out/replicache/src/transactions.js +1 -1
  63. package/out/replicache/src/transactions.js.map +1 -1
  64. package/out/shared/src/arrays.d.ts +0 -5
  65. package/out/shared/src/arrays.d.ts.map +1 -1
  66. package/out/shared/src/arrays.js +24 -8
  67. package/out/shared/src/arrays.js.map +1 -1
  68. package/out/shared/src/base64.d.ts +19 -0
  69. package/out/shared/src/base64.d.ts.map +1 -0
  70. package/out/shared/src/base64.js +40 -0
  71. package/out/shared/src/base64.js.map +1 -0
  72. package/out/shared/src/error.d.ts +0 -11
  73. package/out/shared/src/error.d.ts.map +1 -1
  74. package/out/shared/src/error.js +1 -35
  75. package/out/shared/src/error.js.map +1 -1
  76. package/out/shared/src/hash.d.ts +0 -1
  77. package/out/shared/src/hash.d.ts.map +1 -1
  78. package/out/shared/src/hash.js +10 -87
  79. package/out/shared/src/hash.js.map +1 -1
  80. package/out/shared/src/iterables.d.ts +0 -2
  81. package/out/shared/src/iterables.d.ts.map +1 -1
  82. package/out/shared/src/iterables.js +1 -18
  83. package/out/shared/src/iterables.js.map +1 -1
  84. package/out/shared/src/json.d.ts.map +1 -1
  85. package/out/shared/src/json.js +2 -2
  86. package/out/shared/src/json.js.map +1 -1
  87. package/out/shared/src/map.d.ts +2 -24
  88. package/out/shared/src/map.d.ts.map +1 -1
  89. package/out/shared/src/map.js +4 -18
  90. package/out/shared/src/map.js.map +1 -1
  91. package/out/shared/src/packed-boolean-map.d.ts +7 -0
  92. package/out/shared/src/packed-boolean-map.d.ts.map +1 -0
  93. package/out/shared/src/packed-boolean-map.js +36 -0
  94. package/out/shared/src/packed-boolean-map.js.map +1 -0
  95. package/out/shared/src/ring-buffer.d.ts +0 -8
  96. package/out/shared/src/ring-buffer.d.ts.map +1 -1
  97. package/out/shared/src/ring-buffer.js +1 -22
  98. package/out/shared/src/ring-buffer.js.map +1 -1
  99. package/out/z2s/src/sql.d.ts.map +1 -1
  100. package/out/z2s/src/sql.js +2 -2
  101. package/out/z2s/src/sql.js.map +1 -1
  102. package/out/zero/package.js +3 -2
  103. package/out/zero/package.js.map +1 -1
  104. package/out/zero-cache/src/auth/read-authorizer.js +1 -1
  105. package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
  106. package/out/zero-cache/src/auth/write-authorizer.js +0 -1
  107. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  108. package/out/zero-cache/src/config/zero-config.d.ts +2 -42
  109. package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
  110. package/out/zero-cache/src/config/zero-config.js +28 -149
  111. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  112. package/out/zero-cache/src/custom-queries/transform-query.js +1 -1
  113. package/out/zero-cache/src/db/create.d.ts.map +1 -1
  114. package/out/zero-cache/src/db/create.js +1 -4
  115. package/out/zero-cache/src/db/create.js.map +1 -1
  116. package/out/zero-cache/src/db/lite-tables.d.ts +2 -10
  117. package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
  118. package/out/zero-cache/src/db/lite-tables.js +6 -10
  119. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  120. package/out/zero-cache/src/db/specs.d.ts +0 -41
  121. package/out/zero-cache/src/db/specs.d.ts.map +1 -1
  122. package/out/zero-cache/src/db/specs.js +3 -30
  123. package/out/zero-cache/src/db/specs.js.map +1 -1
  124. package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
  125. package/out/zero-cache/src/observability/metrics.js +7 -2
  126. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  127. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  128. package/out/zero-cache/src/server/change-streamer.js +4 -13
  129. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  130. package/out/zero-cache/src/server/inspector-delegate.d.ts +2 -18
  131. package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
  132. package/out/zero-cache/src/server/inspector-delegate.js +17 -25
  133. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  134. package/out/zero-cache/src/server/main.d.ts.map +1 -1
  135. package/out/zero-cache/src/server/main.js +1 -8
  136. package/out/zero-cache/src/server/main.js.map +1 -1
  137. package/out/zero-cache/src/server/mutator.js +0 -2
  138. package/out/zero-cache/src/server/mutator.js.map +1 -1
  139. package/out/zero-cache/src/server/reaper.d.ts.map +1 -1
  140. package/out/zero-cache/src/server/reaper.js +0 -2
  141. package/out/zero-cache/src/server/reaper.js.map +1 -1
  142. package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
  143. package/out/zero-cache/src/server/replicator.js +2 -8
  144. package/out/zero-cache/src/server/replicator.js.map +1 -1
  145. package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
  146. package/out/zero-cache/src/server/runner/zero-dispatcher.js +0 -3
  147. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  148. package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
  149. package/out/zero-cache/src/server/syncer.js +1 -5
  150. package/out/zero-cache/src/server/syncer.js.map +1 -1
  151. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  152. package/out/zero-cache/src/services/analyze.js +9 -11
  153. package/out/zero-cache/src/services/analyze.js.map +1 -1
  154. package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -1
  155. package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -14
  156. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  157. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -1
  158. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +3 -15
  159. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  160. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -11
  161. package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
  162. package/out/zero-cache/src/services/change-source/pg/change-source.js +2 -21
  163. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  164. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +0 -1
  165. package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
  166. package/out/zero-cache/src/services/change-source/pg/initial-sync.js +7 -8
  167. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  168. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +229 -1513
  169. package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
  170. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +2 -2
  171. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  172. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +1 -1
  173. package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
  174. package/out/zero-cache/src/services/change-source/pg/schema/init.js +6 -15
  175. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  176. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +20 -137
  177. package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
  178. package/out/zero-cache/src/services/change-source/pg/schema/published.js +13 -82
  179. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  180. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +21 -128
  181. package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
  182. package/out/zero-cache/src/services/change-source/pg/schema/shard.js +5 -5
  183. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  184. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +0 -2
  185. package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
  186. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +0 -3
  187. package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
  188. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +0 -3
  189. package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
  190. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +1 -3
  191. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  192. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +0 -1
  193. package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
  194. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  195. package/out/zero-cache/src/services/litestream/commands.js +3 -8
  196. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  197. package/out/zero-cache/src/services/litestream/config-v5.yml +1 -15
  198. package/out/zero-cache/src/services/mutagen/mutagen.d.ts +0 -5
  199. package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
  200. package/out/zero-cache/src/services/mutagen/mutagen.js +1 -7
  201. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  202. package/out/zero-cache/src/services/mutagen/pusher.d.ts +119 -119
  203. package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
  204. package/out/zero-cache/src/services/mutagen/pusher.js +6 -5
  205. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  206. package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
  207. package/out/zero-cache/src/services/replicator/change-processor.js +16 -16
  208. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  209. package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
  210. package/out/zero-cache/src/services/replicator/incremental-sync.js +0 -1
  211. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  212. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +2 -27
  213. package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -1
  214. package/out/zero-cache/src/services/replicator/write-worker-client.js +2 -3
  215. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  216. package/out/zero-cache/src/services/replicator/write-worker.js +5 -24
  217. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  218. package/out/zero-cache/src/services/run-ast.d.ts +0 -12
  219. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  220. package/out/zero-cache/src/services/run-ast.js +15 -27
  221. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  222. package/out/zero-cache/src/services/runner.d.ts.map +1 -1
  223. package/out/zero-cache/src/services/runner.js +1 -1
  224. package/out/zero-cache/src/services/runner.js.map +1 -1
  225. package/out/zero-cache/src/services/view-syncer/cvr.d.ts +0 -45
  226. package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
  227. package/out/zero-cache/src/services/view-syncer/cvr.js +1 -133
  228. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  229. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts +1 -14
  230. package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
  231. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +4 -30
  232. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  233. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +1 -1
  234. package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
  235. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +2 -2
  236. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  237. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +1 -2
  238. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  239. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +27 -48
  240. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  241. package/out/zero-cache/src/services/view-syncer/query-covering.d.ts.map +1 -1
  242. package/out/zero-cache/src/services/view-syncer/query-covering.js +6 -2
  243. package/out/zero-cache/src/services/view-syncer/query-covering.js.map +1 -1
  244. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +4 -42
  245. package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
  246. package/out/zero-cache/src/services/view-syncer/snapshotter.js +28 -117
  247. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  248. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +1 -11
  249. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  250. package/out/zero-cache/src/services/view-syncer/view-syncer.js +95 -466
  251. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  252. package/out/zero-cache/src/types/processes.d.ts +0 -32
  253. package/out/zero-cache/src/types/processes.d.ts.map +1 -1
  254. package/out/zero-cache/src/types/processes.js +4 -43
  255. package/out/zero-cache/src/types/processes.js.map +1 -1
  256. package/out/zero-cache/src/types/profiler.d.ts +0 -12
  257. package/out/zero-cache/src/types/profiler.d.ts.map +1 -1
  258. package/out/zero-cache/src/types/profiler.js +1 -46
  259. package/out/zero-cache/src/types/profiler.js.map +1 -1
  260. package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
  261. package/out/zero-cache/src/types/row-key.js +5 -5
  262. package/out/zero-cache/src/types/row-key.js.map +1 -1
  263. package/out/zero-cache/src/workers/connect-params.d.ts +17 -1
  264. package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
  265. package/out/zero-cache/src/workers/connect-params.js +21 -1
  266. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  267. package/out/zero-cache/src/workers/connection.d.ts +4 -4
  268. package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
  269. package/out/zero-cache/src/workers/connection.js +8 -8
  270. package/out/zero-cache/src/workers/connection.js.map +1 -1
  271. package/out/zero-cache/src/workers/replicator.d.ts +0 -1
  272. package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
  273. package/out/zero-cache/src/workers/replicator.js +2 -4
  274. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  275. package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
  276. package/out/zero-cache/src/workers/syncer-ws-message-handler.js +16 -21
  277. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  278. package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
  279. package/out/zero-cache/src/workers/syncer.js +1 -10
  280. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  281. package/out/zero-client/src/client/connection-manager.d.ts +0 -20
  282. package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
  283. package/out/zero-client/src/client/connection-manager.js +13 -77
  284. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  285. package/out/zero-client/src/client/connection-status-enum.d.ts +0 -2
  286. package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -1
  287. package/out/zero-client/src/client/connection-status-enum.js +1 -3
  288. package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
  289. package/out/zero-client/src/client/connection.d.ts +0 -6
  290. package/out/zero-client/src/client/connection.d.ts.map +1 -1
  291. package/out/zero-client/src/client/connection.js +1 -2
  292. package/out/zero-client/src/client/connection.js.map +1 -1
  293. package/out/zero-client/src/client/context.d.ts +2 -27
  294. package/out/zero-client/src/client/context.d.ts.map +1 -1
  295. package/out/zero-client/src/client/context.js +1 -112
  296. package/out/zero-client/src/client/context.js.map +1 -1
  297. package/out/zero-client/src/client/custom.js +2 -2
  298. package/out/zero-client/src/client/custom.js.map +1 -1
  299. package/out/zero-client/src/client/error.js +1 -1
  300. package/out/zero-client/src/client/inspector/lazy-inspector.js +2 -2
  301. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  302. package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
  303. package/out/zero-client/src/client/ivm-branch.js +3 -20
  304. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  305. package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
  306. package/out/zero-client/src/client/mutation-tracker.js +1 -1
  307. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  308. package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
  309. package/out/zero-client/src/client/mutator-proxy.js +1 -2
  310. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  311. package/out/zero-client/src/client/options.d.ts +0 -3
  312. package/out/zero-client/src/client/options.d.ts.map +1 -1
  313. package/out/zero-client/src/client/options.js.map +1 -1
  314. package/out/zero-client/src/client/query-manager.d.ts +0 -2
  315. package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
  316. package/out/zero-client/src/client/query-manager.js +14 -50
  317. package/out/zero-client/src/client/query-manager.js.map +1 -1
  318. package/out/zero-client/src/client/version.js +1 -1
  319. package/out/zero-client/src/client/zero-rep.d.ts +0 -1
  320. package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
  321. package/out/zero-client/src/client/zero-rep.js +6 -9
  322. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  323. package/out/zero-client/src/client/zero.d.ts +3 -18
  324. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  325. package/out/zero-client/src/client/zero.js +36 -123
  326. package/out/zero-client/src/client/zero.js.map +1 -1
  327. package/out/zero-client/src/types/query-result.d.ts +0 -2
  328. package/out/zero-client/src/types/query-result.d.ts.map +1 -1
  329. package/out/zero-protocol/src/analyze-query-result.d.ts +5 -5
  330. package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
  331. package/out/zero-protocol/src/analyze-query-result.js +1 -1
  332. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  333. package/out/zero-protocol/src/ast.d.ts +1 -64
  334. package/out/zero-protocol/src/ast.d.ts.map +1 -1
  335. package/out/zero-protocol/src/ast.js +54 -225
  336. package/out/zero-protocol/src/ast.js.map +1 -1
  337. package/out/zero-protocol/src/connect.d.ts +16 -0
  338. package/out/zero-protocol/src/connect.d.ts.map +1 -1
  339. package/out/zero-protocol/src/connect.js +27 -1
  340. package/out/zero-protocol/src/connect.js.map +1 -1
  341. package/out/zero-protocol/src/down.d.ts +2 -2
  342. package/out/zero-protocol/src/error.d.ts +1 -1
  343. package/out/zero-protocol/src/feature-flag-enum.d.ts +7 -0
  344. package/out/zero-protocol/src/feature-flag-enum.d.ts.map +1 -0
  345. package/out/zero-protocol/src/feature-flag-enum.js +7 -0
  346. package/out/zero-protocol/src/feature-flag-enum.js.map +1 -0
  347. package/out/zero-protocol/src/feature-flag.d.ts +5 -0
  348. package/out/zero-protocol/src/feature-flag.d.ts.map +1 -0
  349. package/out/zero-protocol/src/inspect-down.d.ts +6 -6
  350. package/out/zero-protocol/src/poke.d.ts +11 -4
  351. package/out/zero-protocol/src/poke.d.ts.map +1 -1
  352. package/out/zero-protocol/src/poke.js +3 -2
  353. package/out/zero-protocol/src/poke.js.map +1 -1
  354. package/out/zero-protocol/src/protocol-version.d.ts +30 -6
  355. package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
  356. package/out/zero-protocol/src/protocol-version.js +1 -1
  357. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  358. package/out/zero-protocol/src/query-hash.d.ts +2 -7
  359. package/out/zero-protocol/src/query-hash.d.ts.map +1 -1
  360. package/out/zero-protocol/src/query-hash.js +10 -10
  361. package/out/zero-protocol/src/query-hash.js.map +1 -1
  362. package/out/zero-react/src/use-query.d.ts +4 -5
  363. package/out/zero-react/src/use-query.d.ts.map +1 -1
  364. package/out/zero-react/src/use-query.js +9 -86
  365. package/out/zero-react/src/use-query.js.map +1 -1
  366. package/out/zero-solid/src/solid-view.d.ts +0 -17
  367. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  368. package/out/zero-solid/src/solid-view.js +1 -39
  369. package/out/zero-solid/src/solid-view.js.map +1 -1
  370. package/out/zero-solid/src/use-query.js +3 -5
  371. package/out/zero-solid/src/use-query.js.map +1 -1
  372. package/out/zql/src/builder/builder.d.ts +0 -19
  373. package/out/zql/src/builder/builder.d.ts.map +1 -1
  374. package/out/zql/src/builder/builder.js +11 -28
  375. package/out/zql/src/builder/builder.js.map +1 -1
  376. package/out/zql/src/builder/debug-delegate.d.ts +1 -6
  377. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  378. package/out/zql/src/builder/debug-delegate.js +2 -14
  379. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  380. package/out/zql/src/ivm/array-view.d.ts +0 -29
  381. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  382. package/out/zql/src/ivm/array-view.js +12 -63
  383. package/out/zql/src/ivm/array-view.js.map +1 -1
  384. package/out/zql/src/ivm/cap.d.ts.map +1 -1
  385. package/out/zql/src/ivm/cap.js +3 -5
  386. package/out/zql/src/ivm/cap.js.map +1 -1
  387. package/out/zql/src/ivm/data.d.ts.map +1 -1
  388. package/out/zql/src/ivm/data.js +3 -8
  389. package/out/zql/src/ivm/data.js.map +1 -1
  390. package/out/zql/src/ivm/exists.d.ts +1 -1
  391. package/out/zql/src/ivm/exists.d.ts.map +1 -1
  392. package/out/zql/src/ivm/exists.js.map +1 -1
  393. package/out/zql/src/ivm/fan-in.d.ts +2 -2
  394. package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
  395. package/out/zql/src/ivm/fan-in.js +5 -6
  396. package/out/zql/src/ivm/fan-in.js.map +1 -1
  397. package/out/zql/src/ivm/fan-out.d.ts +2 -2
  398. package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
  399. package/out/zql/src/ivm/fan-out.js.map +1 -1
  400. package/out/zql/src/ivm/filter-operators.d.ts +6 -7
  401. package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
  402. package/out/zql/src/ivm/filter-operators.js +12 -29
  403. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  404. package/out/zql/src/ivm/filter.d.ts +2 -2
  405. package/out/zql/src/ivm/filter.d.ts.map +1 -1
  406. package/out/zql/src/ivm/filter.js +4 -7
  407. package/out/zql/src/ivm/filter.js.map +1 -1
  408. package/out/zql/src/ivm/flipped-join.js +2 -2
  409. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  410. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
  411. package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
  412. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +4 -6
  413. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  414. package/out/zql/src/ivm/memory-source.d.ts +3 -15
  415. package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
  416. package/out/zql/src/ivm/memory-source.js +23 -57
  417. package/out/zql/src/ivm/memory-source.js.map +1 -1
  418. package/out/zql/src/ivm/operator.d.ts +0 -40
  419. package/out/zql/src/ivm/operator.d.ts.map +1 -1
  420. package/out/zql/src/ivm/operator.js.map +1 -1
  421. package/out/zql/src/ivm/take.d.ts.map +1 -1
  422. package/out/zql/src/ivm/take.js +4 -3
  423. package/out/zql/src/ivm/take.js.map +1 -1
  424. package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
  425. package/out/zql/src/ivm/union-fan-in.js +7 -9
  426. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  427. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  428. package/out/zql/src/ivm/view-apply-change.js +4 -9
  429. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  430. package/out/zql/src/ivm/view.d.ts +0 -15
  431. package/out/zql/src/ivm/view.d.ts.map +1 -1
  432. package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
  433. package/out/zql/src/mutate/mutator-registry.js +2 -2
  434. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  435. package/out/zql/src/planner/planner-builder.d.ts +3 -12
  436. package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
  437. package/out/zql/src/planner/planner-builder.js +20 -40
  438. package/out/zql/src/planner/planner-builder.js.map +1 -1
  439. package/out/zql/src/planner/planner-connection.d.ts +2 -28
  440. package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
  441. package/out/zql/src/planner/planner-connection.js +8 -108
  442. package/out/zql/src/planner/planner-connection.js.map +1 -1
  443. package/out/zql/src/planner/planner-debug.d.ts +1 -1
  444. package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
  445. package/out/zql/src/planner/planner-debug.js +8 -3
  446. package/out/zql/src/planner/planner-debug.js.map +1 -1
  447. package/out/zql/src/planner/planner-fan-out.d.ts +0 -1
  448. package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
  449. package/out/zql/src/planner/planner-fan-out.js +0 -3
  450. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  451. package/out/zql/src/planner/planner-graph.d.ts +0 -2
  452. package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
  453. package/out/zql/src/planner/planner-graph.js +0 -2
  454. package/out/zql/src/planner/planner-graph.js.map +1 -1
  455. package/out/zql/src/planner/planner-join.d.ts +0 -2
  456. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  457. package/out/zql/src/planner/planner-join.js +0 -7
  458. package/out/zql/src/planner/planner-join.js.map +1 -1
  459. package/out/zql/src/planner/planner-node.d.ts +1 -2
  460. package/out/zql/src/planner/planner-node.d.ts.map +1 -1
  461. package/out/zql/src/planner/planner-node.js.map +1 -1
  462. package/out/zql/src/planner/planner-source.d.ts +2 -2
  463. package/out/zql/src/planner/planner-source.d.ts.map +1 -1
  464. package/out/zql/src/planner/planner-source.js +2 -2
  465. package/out/zql/src/planner/planner-source.js.map +1 -1
  466. package/out/zql/src/query/query-delegate-base.d.ts +1 -9
  467. package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
  468. package/out/zql/src/query/query-delegate-base.js +36 -132
  469. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  470. package/out/zql/src/query/query-delegate.d.ts +1 -50
  471. package/out/zql/src/query/query-delegate.d.ts.map +1 -1
  472. package/out/zql/src/query/query-impl.d.ts +14 -25
  473. package/out/zql/src/query/query-impl.d.ts.map +1 -1
  474. package/out/zql/src/query/query-impl.js +94 -397
  475. package/out/zql/src/query/query-impl.js.map +1 -1
  476. package/out/zql/src/query/query-internals.d.ts +11 -21
  477. package/out/zql/src/query/query-internals.d.ts.map +1 -1
  478. package/out/zql/src/query/query-internals.js.map +1 -1
  479. package/out/zql/src/query/query.d.ts +2 -11
  480. package/out/zql/src/query/query.d.ts.map +1 -1
  481. package/out/zql/src/query/runnable-query-impl.d.ts +2 -3
  482. package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
  483. package/out/zql/src/query/runnable-query-impl.js +2 -15
  484. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  485. package/out/zql/src/query/typed-view.d.ts +1 -1
  486. package/out/zql/src/query/typed-view.d.ts.map +1 -1
  487. package/out/zqlite/src/db.d.ts +1 -9
  488. package/out/zqlite/src/db.d.ts.map +1 -1
  489. package/out/zqlite/src/db.js +2 -8
  490. package/out/zqlite/src/db.js.map +1 -1
  491. package/out/zqlite/src/query-builder.d.ts +1 -1
  492. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  493. package/out/zqlite/src/query-builder.js +2 -4
  494. package/out/zqlite/src/query-builder.js.map +1 -1
  495. package/out/zqlite/src/query-delegate.d.ts.map +1 -1
  496. package/out/zqlite/src/query-delegate.js +6 -5
  497. package/out/zqlite/src/query-delegate.js.map +1 -1
  498. package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
  499. package/out/zqlite/src/sqlite-cost-model.js +30 -2
  500. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  501. package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -1
  502. package/out/zqlite/src/sqlite-stat-fanout.js +5 -4
  503. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  504. package/out/zqlite/src/table-source.d.ts +3 -16
  505. package/out/zqlite/src/table-source.d.ts.map +1 -1
  506. package/out/zqlite/src/table-source.js +14 -33
  507. package/out/zqlite/src/table-source.js.map +1 -1
  508. package/package.json +3 -2
  509. package/out/replicache/src/dag/invalid-ref-count-error.d.ts +0 -12
  510. package/out/replicache/src/dag/invalid-ref-count-error.d.ts.map +0 -1
  511. package/out/replicache/src/dag/invalid-ref-count-error.js +0 -19
  512. package/out/replicache/src/dag/invalid-ref-count-error.js.map +0 -1
  513. package/out/shared/src/xxhash32.d.ts +0 -36
  514. package/out/shared/src/xxhash32.d.ts.map +0 -1
  515. package/out/shared/src/xxhash32.js +0 -51
  516. package/out/shared/src/xxhash32.js.map +0 -1
  517. package/out/zero-cache/src/db/index-predicate.d.ts +0 -4
  518. package/out/zero-cache/src/db/index-predicate.d.ts.map +0 -1
  519. package/out/zero-cache/src/db/index-predicate.js +0 -46
  520. package/out/zero-cache/src/db/index-predicate.js.map +0 -1
  521. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts +0 -19
  522. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +0 -1
  523. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js +0 -581
  524. package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +0 -1
  525. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js +0 -131
  526. package/out/zero-cache/src/services/litestream/litestream-checkpointer.js.map +0 -1
  527. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts +0 -70
  528. package/out/zero-cache/src/services/litestream/litestream-controller.d.ts.map +0 -1
  529. package/out/zero-cache/src/services/litestream/litestream-controller.js +0 -101
  530. package/out/zero-cache/src/services/litestream/litestream-controller.js.map +0 -1
  531. package/out/zero-cache/src/services/profz.d.ts +0 -7
  532. package/out/zero-cache/src/services/profz.d.ts.map +0 -1
  533. package/out/zero-cache/src/services/profz.js +0 -103
  534. package/out/zero-cache/src/services/profz.js.map +0 -1
  535. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts +0 -33
  536. package/out/zero-cache/src/services/view-syncer/hydration-budget.d.ts.map +0 -1
  537. package/out/zero-cache/src/services/view-syncer/hydration-budget.js +0 -62
  538. package/out/zero-cache/src/services/view-syncer/hydration-budget.js.map +0 -1
  539. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts +0 -51
  540. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.d.ts.map +0 -1
  541. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js +0 -78
  542. package/out/zero-cache/src/services/view-syncer/hydration-circuit-breaker.js.map +0 -1
  543. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts +0 -95
  544. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.d.ts.map +0 -1
  545. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js +0 -155
  546. package/out/zero-cache/src/services/view-syncer/snapshot-row-cache.js.map +0 -1
  547. package/out/zero-protocol/src/query-hash-visitor.d.ts +0 -81
  548. package/out/zero-protocol/src/query-hash-visitor.d.ts.map +0 -1
  549. package/out/zero-protocol/src/query-hash-visitor.js +0 -324
  550. package/out/zero-protocol/src/query-hash-visitor.js.map +0 -1
  551. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts +0 -43
  552. package/out/zql/src/builder/correlated-predicate-pushdown.d.ts.map +0 -1
  553. package/out/zql/src/builder/correlated-predicate-pushdown.js +0 -161
  554. package/out/zql/src/builder/correlated-predicate-pushdown.js.map +0 -1
  555. package/out/zql/src/ivm/connection-index.d.ts +0 -68
  556. package/out/zql/src/ivm/connection-index.d.ts.map +0 -1
  557. package/out/zql/src/ivm/connection-index.js +0 -149
  558. package/out/zql/src/ivm/connection-index.js.map +0 -1
  559. package/out/zql/src/ivm/deferred-input.d.ts +0 -44
  560. package/out/zql/src/ivm/deferred-input.d.ts.map +0 -1
  561. package/out/zql/src/ivm/deferred-input.js +0 -89
  562. package/out/zql/src/ivm/deferred-input.js.map +0 -1
  563. package/out/zql/src/planner/planner-filter.d.ts +0 -59
  564. package/out/zql/src/planner/planner-filter.d.ts.map +0 -1
  565. package/out/zql/src/planner/planner-filter.js +0 -116
  566. package/out/zql/src/planner/planner-filter.js.map +0 -1
  567. package/out/zql/src/query/query-transitions.d.ts +0 -171
  568. package/out/zql/src/query/query-transitions.d.ts.map +0 -1
  569. package/out/zql/src/query/query-transitions.js +0 -204
  570. package/out/zql/src/query/query-transitions.js.map +0 -1
@@ -1,5 +1,4 @@
1
1
  import { valita_exports } from "../../shared/src/valita.js";
2
- import { getOrInsertComputed } from "../../shared/src/map.js";
3
2
  import { must } from "../../shared/src/must.js";
4
3
  import "../../zero-protocol/src/ast.js";
5
4
  import { clientToServer } from "../../zero-schema/src/name-mapper.js";
@@ -79,7 +78,6 @@ var cfg = parseOptions({
79
78
  },
80
79
  app: appOptions,
81
80
  shard: shardOptions,
82
- enableCorrelatedPredicatePushdown: zeroOptions.enableCorrelatedPredicatePushdown,
83
81
  log: {
84
82
  ...logOptions,
85
83
  level: logLevel.default("error")
@@ -143,18 +141,19 @@ var { schema, permissions } = await loadSchemaAndPermissions(config.schema.path)
143
141
  var clientSchema = clientSchemaFrom(schema).clientSchema;
144
142
  var sources = /* @__PURE__ */ new Map();
145
143
  var clientToServerMapper = clientToServer(schema.tables);
146
- var debug = new Debug(config.outputVendedRows);
144
+ var debug = new Debug();
147
145
  var tableSpecs = computeZqlSpecs(lc, db, { includeBackfillingColumns: false });
148
146
  var AnalyzeQueryDelegate = class extends QueryDelegateBase {
149
147
  debug = debug;
150
148
  defaultQueryComplete = true;
151
- disableCorrelatedPredicatePushdown = !config.enableCorrelatedPredicatePushdown;
152
149
  getSource(serverTableName) {
153
- return getOrInsertComputed(sources, serverTableName, (serverTableName) => {
154
- const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);
155
- const { primaryKey } = tableSpec.tableSpec;
156
- return new TableSource(lc, config.log, db, serverTableName, tableSpec.zqlSpec, primaryKey);
157
- });
150
+ let source = sources.get(serverTableName);
151
+ if (source) return source;
152
+ const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);
153
+ const { primaryKey } = tableSpec.tableSpec;
154
+ source = new TableSource(lc, config.log, db, serverTableName, tableSpec.zqlSpec, primaryKey);
155
+ sources.set(serverTableName, source);
156
+ return source;
158
157
  }
159
158
  };
160
159
  var host = new AnalyzeQueryDelegate();
@@ -1 +1 @@
1
- {"version":3,"file":"bin-analyze.js","names":[],"sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport fs from 'node:fs';\nimport {styleText} from 'node:util';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {getOrInsertComputed} from '../../shared/src/map.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {runAst} from '../../zero-cache/src/services/run-ast.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport {type PullRow, type Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {explainQueries} from '../../zqlite/src/explain-queries.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: ['File path to the SQLite replica to test queries against.'],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n 'Query to be analyzed in the form of: table.where(...).related(...).etc. ',\n 'Only one of ast/query/hash should be provided.',\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n 'Hash of the query to be analyzed. This is used to look up the query in the database. ',\n 'Only one of ast/query/hash should be provided.',\n 'You should run this script from the directory containing your .env file to reduce the amount of',\n 'configuration required. The .env file should contain the connection URL to the CVR database.',\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n // Read from the same env var as zero-cache, so the analysis matches what\n // the server runs.\n enableCorrelatedPredicatePushdown:\n zeroOptions.enableCorrelatedPredicatePushdown,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\ncolorConsole.warn(\n 'DEPRECATED: `analyze-query` is deprecated. Please migrate to a project-specific analyze command built with `runAnalyzeCLI` from `@rocicorp/zero/analyze`.',\n);\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug(config.outputVendedRows);\nconst tableSpecs = computeZqlSpecs(lc, db, {includeBackfillingColumns: false});\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n readonly disableCorrelatedPredicatePushdown =\n !config.enableCorrelatedPredicatePushdown;\n\n getSource(serverTableName: string): Source | undefined {\n return getOrInsertComputed(sources, serverTableName, serverTableName => {\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n return new TableSource(\n lc,\n config.log,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n });\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n result = await runAst(\n lc,\n clientSchema,\n JSON.parse(config.ast),\n true,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(\n lc,\n clientSchema,\n ast,\n false,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n 'analyze-query-hash-cvr',\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(\n lc,\n clientSchema,\n ast,\n true,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(styleText(['blue', 'bold'], '=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(styleText('bold', table + ':'), rows);\n }\n}\n\ncolorConsole.log(styleText(['blue', 'bold'], '=== Query Stats: ===\\n'));\ncolorConsole.log(\n styleText('bold', 'total synced rows:'),\n result.syncedRowCount,\n);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(\n styleText(['blue', 'bold'], '=== JS Row Scan Values: ===\\n'),\n );\n for (const source of sources.values()) {\n colorConsole.log(\n styleText('bold', `${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(\n styleText(['blue', 'bold'], '\\n=== Rows Scanned (by SQLite): ===\\n'),\n);\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(styleText('bold', `${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n styleText('bold', 'total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(styleText(['blue', 'bold'], '\\n\\n=== Query Plans: ===\\n'));\nconst fallbackPlans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nconst capturedPlans = debug.getSQLitePlans();\nconst plans: Record<string, string[]> = {...fallbackPlans, ...capturedPlans};\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(styleText('bold', 'query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n styleText('bold', source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n styleText('bold', 'Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n styleText('bold', 'time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return styleText('green', duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return styleText('yellow', duration.toFixed(2) + 'ms');\n }\n return styleText('red', duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return styleText('green', n.toString());\n } else if (n < 10000) {\n return styleText('yellow', n.toString());\n }\n return styleText('red', n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return styleText('yellow', row);\n }\n return styleText('red', row);\n }\n return styleText('green', row);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin-analyze.js","names":[],"sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport fs from 'node:fs';\nimport {styleText} from 'node:util';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {runAst} from '../../zero-cache/src/services/run-ast.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport {type PullRow, type Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {explainQueries} from '../../zqlite/src/explain-queries.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: ['File path to the SQLite replica to test queries against.'],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n 'Query to be analyzed in the form of: table.where(...).related(...).etc. ',\n 'Only one of ast/query/hash should be provided.',\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n 'Hash of the query to be analyzed. This is used to look up the query in the database. ',\n 'Only one of ast/query/hash should be provided.',\n 'You should run this script from the directory containing your .env file to reduce the amount of',\n 'configuration required. The .env file should contain the connection URL to the CVR database.',\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\ncolorConsole.warn(\n 'DEPRECATED: `analyze-query` is deprecated. Please migrate to a project-specific analyze command built with `runAnalyzeCLI` from `@rocicorp/zero/analyze`.',\n);\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug();\nconst tableSpecs = computeZqlSpecs(lc, db, {includeBackfillingColumns: false});\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n\n getSource(serverTableName: string): Source | undefined {\n let source = sources.get(serverTableName);\n if (source) {\n return source;\n }\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n config.log,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n\n sources.set(serverTableName, source);\n return source;\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n result = await runAst(\n lc,\n clientSchema,\n JSON.parse(config.ast),\n true,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(\n lc,\n clientSchema,\n ast,\n false,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n 'analyze-query-hash-cvr',\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(\n lc,\n clientSchema,\n ast,\n true,\n {\n applyPermissions: config.applyPermissions,\n auth: config.authData\n ? {type: 'jwt' as const, raw: '', decoded: JSON.parse(config.authData)}\n : undefined,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n },\n async () => {},\n );\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(styleText(['blue', 'bold'], '=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(styleText('bold', table + ':'), rows);\n }\n}\n\ncolorConsole.log(styleText(['blue', 'bold'], '=== Query Stats: ===\\n'));\ncolorConsole.log(\n styleText('bold', 'total synced rows:'),\n result.syncedRowCount,\n);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(\n styleText(['blue', 'bold'], '=== JS Row Scan Values: ===\\n'),\n );\n for (const source of sources.values()) {\n colorConsole.log(\n styleText('bold', `${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(\n styleText(['blue', 'bold'], '\\n=== Rows Scanned (by SQLite): ===\\n'),\n);\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(styleText('bold', `${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n styleText('bold', 'total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(styleText(['blue', 'bold'], '\\n\\n=== Query Plans: ===\\n'));\nconst fallbackPlans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nconst capturedPlans = debug.getSQLitePlans();\nconst plans: Record<string, string[]> = {...fallbackPlans, ...capturedPlans};\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(styleText('bold', 'query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n styleText('bold', source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n styleText('bold', 'Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n styleText('bold', 'time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return styleText('green', duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return styleText('yellow', duration.toFixed(2) + 'ms');\n }\n return styleText('red', duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return styleText('green', n.toString());\n } else if (n < 10000) {\n return styleText('yellow', n.toString());\n }\n return styleText('red', n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return styleText('yellow', row);\n }\n return styleText('red', row);\n }\n return styleText('green', row);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/btree/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/btree/node.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,6 @@ import { assertJSONValue } from "../../../shared/src/json.js";
4
4
  import "../config.js";
5
5
  import { assertDeepFrozen, deepFreeze } from "../frozen-json.js";
6
6
  import { emptyHash, newRandomHash } from "../hash.js";
7
- import { getOrInsertComputed } from "../../../shared/src/map.js";
8
- import { newArray } from "../../../shared/src/arrays.js";
9
7
  import { binarySearch as binarySearch$1 } from "../../../shared/src/binary-search.js";
10
8
  import { joinIterables } from "../../../shared/src/iterables.js";
11
9
  import { compareUTF8 } from "compare-utf8";
@@ -213,7 +211,12 @@ var InternalNodeImpl = class InternalNodeImpl extends NodeImpl {
213
211
  let i = binarySearchFrom(key, this.entries, searchStart);
214
212
  if (i === this.entries.length) i--;
215
213
  searchStart = i;
216
- getOrInsertComputed(childGroups, i, newArray).push(entry);
214
+ let group = childGroups.get(i);
215
+ if (!group) {
216
+ group = [];
217
+ childGroups.set(i, group);
218
+ }
219
+ group.push(entry);
217
220
  }
218
221
  const newEntries = [...this.entries];
219
222
  const childrenToRebalance = [];
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","names":["#childNodeSize","#splice","#mergeAndPartition","#replaceChild"],"sources":["../../../../../replicache/src/btree/node.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport {newArray} from '../../../shared/src/arrays.ts';\nimport {\n assert,\n assertArray,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport {binarySearch as binarySearchWithFunc} from '../../../shared/src/binary-search.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {joinIterables} from '../../../shared/src/iterables.ts';\nimport {\n type JSONValue,\n type ReadonlyJSONValue,\n assertJSONValue,\n} from '../../../shared/src/json.ts';\nimport {getOrInsertComputed} from '../../../shared/src/map.ts';\nimport {skipBTreeNodeAsserts} from '../config.ts';\nimport type {IndexKey} from '../db/index.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.ts';\nimport {type Hash, emptyHash, newRandomHash} from '../hash.ts';\nimport type {BTreeRead} from './read.ts';\nimport type {BTreeWrite} from './write.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport type Entry<V> = readonly [key: string, value: V, sizeOfEntry: number];\n\nexport const NODE_LEVEL = 0;\nexport const NODE_ENTRIES = 1;\n\n/**\n * The type of B+Tree node chunk data\n */\ntype BaseNode<V> = FrozenTag<\n readonly [level: number, entries: ReadonlyArray<Entry<V>>]\n>;\nexport type InternalNode = BaseNode<Hash>;\n\nexport type DataNode = BaseNode<FrozenJSONValue>;\n\nexport function makeNodeChunkData<V>(\n level: number,\n entries: ReadonlyArray<Entry<V>>,\n formatVersion: FormatVersion,\n): BaseNode<V> {\n return deepFreeze([\n level,\n (formatVersion >= FormatVersion.V7\n ? entries\n : entries.map(e => e.slice(0, 2))) as readonly ReadonlyJSONValue[],\n ]) as BaseNode<V>;\n}\n\nexport type Node = DataNode | InternalNode;\n\n/**\n * Describes the changes that happened to Replicache after a\n * {@link WriteTransaction} was committed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type Diff = IndexDiff | NoIndexDiff;\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type IndexDiff = readonly DiffOperation<IndexKey>[];\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type NoIndexDiff = readonly DiffOperation<string>[];\n\n/**\n * InternalDiff uses string keys even for the secondary index maps.\n */\nexport type InternalDiff = readonly InternalDiffOperation[];\n\nexport type DiffOperationAdd<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'add';\n readonly key: Key;\n readonly newValue: Value;\n};\n\nexport type DiffOperationDel<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'del';\n readonly key: Key;\n readonly oldValue: Value;\n};\n\nexport type DiffOperationChange<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'change';\n readonly key: Key;\n readonly oldValue: Value;\n readonly newValue: Value;\n};\n\n/**\n * The individual parts describing the changes that happened to the Replicache\n * data. There are three different kinds of operations:\n * - `add`: A new entry was added.\n * - `del`: An entry was deleted.\n * - `change`: An entry was changed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type DiffOperation<Key> =\n | DiffOperationAdd<Key>\n | DiffOperationDel<Key>\n | DiffOperationChange<Key>;\n\n// Duplicated with DiffOperation to make the docs less confusing.\nexport type InternalDiffOperation<Key = string, Value = FrozenJSONValue> =\n | DiffOperationAdd<Key, Value>\n | DiffOperationDel<Key, Value>\n | DiffOperationChange<Key, Value>;\n\n/**\n * Finds the leaf where a key is (if present) or where it should go if not\n * present.\n */\nexport async function findLeaf(\n key: string,\n hash: Hash,\n source: BTreeRead,\n expectedRootHash: Hash,\n): Promise<DataNodeImpl> {\n const node = await source.getNode(hash);\n // The root changed. Try again\n if (expectedRootHash !== source.rootHash) {\n return findLeaf(key, source.rootHash, source, source.rootHash);\n }\n if (isDataNodeImpl(node)) {\n return node;\n }\n const {entries} = node;\n let i = binarySearch(key, entries);\n if (i === entries.length) {\n i--;\n }\n const entry = entries[i];\n return findLeaf(key, entry[1], source, expectedRootHash);\n}\n\ntype BinarySearchEntries = readonly Entry<unknown>[];\n\n/**\n * Does a binary search over entries\n *\n * If the key found then the return value is the index it was found at.\n *\n * If the key was *not* found then the return value is the index where it should\n * be inserted at\n */\nexport function binarySearch(\n key: string,\n entries: BinarySearchEntries,\n): number {\n return binarySearchFrom(key, entries, 0);\n}\n\n/**\n * Binary search starting from a given index.\n */\nfunction binarySearchFrom(\n key: string,\n entries: BinarySearchEntries,\n start: number,\n): number {\n const result = binarySearchWithFunc(entries.length - start, i =>\n compareUTF8(key, entries[start + i][0]),\n );\n return start + result;\n}\n\nexport function binarySearchFound(\n i: number,\n entries: BinarySearchEntries,\n key: string,\n): boolean {\n return i !== entries.length && entries[i][0] === key;\n}\n\nexport function parseBTreeNode(\n v: unknown,\n formatVersion: FormatVersion,\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): InternalNode | DataNode {\n if (skipBTreeNodeAsserts && formatVersion >= FormatVersion.V7) {\n return v as InternalNode | DataNode;\n }\n\n assertArray(v);\n assertDeepFrozen(v);\n // Be relaxed about what we accept.\n assert(v.length >= 2, 'Expected node array to have at least 2 elements');\n const [level, entries] = v;\n assertNumber(level);\n assertArray(entries);\n\n const f = level > 0 ? assertString : assertJSONValue;\n\n // For V7 we do not need to change the entries. Just assert that they are correct.\n if (formatVersion >= FormatVersion.V7) {\n for (const e of entries) {\n assertEntry(e, f);\n }\n return v as unknown as InternalNode | DataNode;\n }\n\n const newEntries = entries.map(e => convertNonV7Entry(e, f, getSizeOfEntry));\n return [level, newEntries] as unknown as InternalNode | DataNode;\n}\n\nfunction assertEntry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n): asserts entry is Entry<Hash | JSONValue> {\n assertArray(entry);\n // Be relaxed about what we accept.\n assert(entry.length >= 3, 'Expected entry array to have at least 3 elements');\n assertString(entry[0]);\n f(entry[1]);\n assertNumber(entry[2]);\n}\n\n/**\n * Converts an entry that was from a format version before V7 to the format\n * wanted by V7.\n */\nfunction convertNonV7Entry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): Entry<Hash | JSONValue> {\n assertArray(entry);\n assert(entry.length >= 2, 'Expected entry array to have at least 2 elements');\n assertString(entry[0]);\n f(entry[1]);\n const entrySize = getSizeOfEntry(entry[0], entry[1]);\n return [entry[0], entry[1], entrySize] as Entry<Hash | JSONValue>;\n}\n\nexport function isInternalNode(node: Node): node is InternalNode {\n return node[NODE_LEVEL] > 0;\n}\n\nabstract class NodeImpl<Value> {\n entries: Array<Entry<Value>>;\n hash: Hash;\n abstract readonly level: number;\n readonly isMutable: boolean;\n\n #childNodeSize = -1;\n\n constructor(entries: Array<Entry<Value>>, hash: Hash, isMutable: boolean) {\n this.entries = entries;\n this.hash = hash;\n this.isMutable = isMutable;\n }\n\n abstract set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value>>;\n\n abstract putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value>>;\n\n abstract del(\n key: string,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value> | DataNodeImpl>;\n\n maxKey(): string {\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return this.entries.at(-1)![0];\n }\n\n getChildNodeSize(tree: BTreeRead): number {\n if (this.#childNodeSize !== -1) {\n return this.#childNodeSize;\n }\n\n let sum = tree.chunkHeaderSize;\n for (const entry of this.entries) {\n sum += entry[2];\n }\n return (this.#childNodeSize = sum);\n }\n\n protected _updateNode(tree: BTreeWrite) {\n this.#childNodeSize = -1;\n tree.updateNode(\n this as NodeImpl<unknown> as DataNodeImpl | InternalNodeImpl,\n );\n }\n}\n\nexport function toChunkData<V>(\n node: NodeImpl<V>,\n formatVersion: FormatVersion,\n): BaseNode<V> {\n return makeNodeChunkData(node.level, node.entries, formatVersion);\n}\n\nexport class DataNodeImpl extends NodeImpl<FrozenJSONValue> {\n readonly level = 0;\n\n set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<DataNodeImpl> {\n let deleteCount: number;\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found, insert.\n deleteCount = 0;\n } else {\n deleteCount = 1;\n }\n\n return Promise.resolve(\n this.#splice(tree, i, deleteCount, [key, value, entrySize]),\n );\n }\n\n putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<DataNodeImpl> {\n if (entries.length === 0) {\n return Promise.resolve(this);\n }\n\n // Merge sorted entries with existing entries\n const merged: Entry<FrozenJSONValue>[] = [];\n let i = 0; // index in this.entries\n let j = 0; // index in entries\n\n while (i < this.entries.length && j < entries.length) {\n const existingEntry = this.entries[i];\n const newEntry = entries[j];\n const cmp = compareUTF8(existingEntry[0], newEntry[0]);\n\n if (cmp < 0) {\n merged.push(existingEntry);\n i++;\n } else if (cmp > 0) {\n merged.push(newEntry);\n j++;\n } else {\n // Same key, new entry wins (update)\n merged.push(newEntry);\n i++;\n j++;\n }\n }\n\n // Add remaining entries\n while (i < this.entries.length) {\n merged.push(this.entries[i]);\n i++;\n }\n while (j < entries.length) {\n merged.push(entries[j]);\n j++;\n }\n\n if (this.isMutable) {\n this.entries = merged;\n this._updateNode(tree);\n return Promise.resolve(this);\n }\n\n return Promise.resolve(tree.newDataNodeImpl(merged));\n }\n\n #splice(\n tree: BTreeWrite,\n start: number,\n deleteCount: number,\n ...items: Entry<FrozenJSONValue>[]\n ): DataNodeImpl {\n if (this.isMutable) {\n this.entries.splice(start, deleteCount, ...items);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(this.entries, start, deleteCount, ...items);\n return tree.newDataNodeImpl(entries);\n }\n\n del(key: string, tree: BTreeWrite): Promise<DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found. Return this without changes.\n return Promise.resolve(this);\n }\n\n // Found. Create new node or mutate existing one.\n return Promise.resolve(this.#splice(tree, i, 1));\n }\n\n async *keys(_tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n yield entry[0];\n }\n }\n\n async *entriesIter(\n _tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n yield entry;\n }\n }\n}\n\nfunction readonlySplice<T>(\n array: ReadonlyArray<T>,\n start: number,\n deleteCount: number,\n ...items: T[]\n): T[] {\n const arr = array.slice(0, start);\n for (let i = 0; i < items.length; i++) {\n arr.push(items[i]);\n }\n for (let i = start + deleteCount; i < array.length; i++) {\n arr.push(array[i]);\n }\n return arr;\n}\n\nexport class InternalNodeImpl extends NodeImpl<Hash> {\n readonly level: number;\n\n constructor(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n ) {\n super(entries, hash, isMutable);\n this.level = level;\n }\n\n async set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl> {\n let i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // We are going to insert into last (right most) leaf.\n i--;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n\n const childNode = await oldChildNode.set(key, value, entrySize, tree);\n\n const childNodeSize = childNode.getChildNodeSize(tree);\n if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n const newEntry = createNewInternalEntryForNode(\n childNode,\n tree.getEntrySize,\n );\n return this.#replaceChild(tree, i, newEntry);\n }\n\n async putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl> {\n if (entries.length === 0) {\n return this;\n }\n\n // Group entries by child index\n // Since entries are sorted, we can restrict the binary search range\n const childGroups: Map<number, Entry<FrozenJSONValue>[]> = new Map();\n\n let searchStart = 0;\n for (const entry of entries) {\n const key = entry[0];\n // Binary search from searchStart to end (entries are sorted)\n let i = binarySearchFrom(key, this.entries, searchStart);\n if (i === this.entries.length) {\n // Insert into last (right most) leaf.\n i--;\n }\n searchStart = i;\n\n getOrInsertComputed(childGroups, i, newArray).push(entry);\n }\n\n // Process each affected child\n const newEntries = [...this.entries];\n const childrenToRebalance: Array<{\n index: number;\n node: DataNodeImpl | InternalNodeImpl;\n }> = [];\n\n for (const [childIndex, childEntries] of childGroups) {\n const childHash = this.entries[childIndex][1];\n const oldChildNode = await tree.getNode(childHash);\n const childNode = await oldChildNode.putMany(childEntries, tree);\n\n const childNodeSize = childNode.getChildNodeSize(tree);\n if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {\n childrenToRebalance.push({index: childIndex, node: childNode});\n } else {\n const newEntry = createNewInternalEntryForNode(\n childNode,\n tree.getEntrySize,\n );\n newEntries[childIndex] = newEntry;\n }\n }\n\n // Handle rebalancing - merge adjacent children that need rebalancing\n // into contiguous groups and process each group as one unit.\n //\n // BUG FIX: Previously, each child was rebalanced independently R-to-L.\n // When adjacent children (e.g., indices 0 and 1) both needed rebalancing,\n // child[1] would merge with sibling[0] (the ORIGINAL), then child[0]\n // would merge with the rebalanced result at position 1, duplicating\n // child[0]'s data. The fix groups adjacent indices together.\n if (childrenToRebalance.length > 0) {\n childrenToRebalance.sort((a, b) => a.index - b.index);\n\n // Group adjacent indices into contiguous runs, each extended by one\n // sibling on either side for merge context.\n const groups: Array<{\n nodes: Map<number, DataNodeImpl | InternalNodeImpl>;\n minIndex: number;\n maxIndex: number;\n }> = [];\n\n for (const {index, node} of childrenToRebalance) {\n const lastGroup = groups.at(-1);\n // Adjacent to previous group? (within 1 index of the last group's max)\n if (lastGroup && index <= lastGroup.maxIndex + 1) {\n lastGroup.nodes.set(index, node);\n lastGroup.maxIndex = index;\n } else {\n groups.push({\n nodes: new Map([[index, node]]),\n minIndex: index,\n maxIndex: index,\n });\n }\n }\n\n // Process groups from right to left to maintain indices during splices.\n for (let g = groups.length - 1; g >= 0; g--) {\n const group = groups[g];\n\n // Extend range by one sibling on each side for merge context.\n const startIndex = Math.max(0, group.minIndex - 1);\n const endIndex = Math.min(newEntries.length - 1, group.maxIndex + 1);\n const removeCount = endIndex - startIndex + 1;\n\n // Collect all entries from the range: use the putMany result for\n // indices that were rebalanced, the current newEntries node otherwise.\n type IterableHashEntries = Iterable<Entry<Hash>>;\n const allValues: IterableHashEntries[] = [];\n for (let idx = startIndex; idx <= endIndex; idx++) {\n const rebalancedNode = group.nodes.get(idx);\n if (rebalancedNode) {\n allValues.push(rebalancedNode.entries as IterableHashEntries);\n } else {\n const hash = newEntries[idx][1];\n const existingNode = await tree.getNode(hash);\n allValues.push(existingNode.entries as IterableHashEntries);\n }\n }\n\n const level = this.level - 1;\n const merged = joinIterables(...allValues);\n const rebalanced = partition(\n merged,\n e => e[2],\n tree.minSize - tree.chunkHeaderSize,\n tree.maxSize - tree.chunkHeaderSize,\n entries => {\n const node = tree.newNodeImpl(entries, level);\n return createNewInternalEntryForNode(node, tree.getEntrySize);\n },\n );\n\n newEntries.splice(startIndex, removeCount, ...rebalanced);\n }\n }\n\n if (this.isMutable) {\n this.entries = newEntries;\n this._updateNode(tree);\n return this;\n }\n\n return tree.newInternalNodeImpl(newEntries, this.level);\n }\n\n /**\n * This merges the child node entries with previous or next sibling and then\n * partitions the merged entries.\n */\n async #mergeAndPartition(\n tree: BTreeWrite,\n i: number,\n childNode: DataNodeImpl | InternalNodeImpl,\n ): Promise<InternalNodeImpl> {\n const level = this.level - 1;\n const thisEntries = this.entries;\n\n type IterableHashEntries = Iterable<Entry<Hash>>;\n\n let values: IterableHashEntries;\n let startIndex: number;\n let removeCount: number;\n if (i > 0) {\n const hash = thisEntries[i - 1][1];\n const previousSibling = await tree.getNode(hash);\n values = joinIterables(\n previousSibling.entries as IterableHashEntries,\n childNode.entries as IterableHashEntries,\n );\n startIndex = i - 1;\n removeCount = 2;\n } else if (i < thisEntries.length - 1) {\n const hash = thisEntries[i + 1][1];\n const nextSibling = await tree.getNode(hash);\n values = joinIterables(\n childNode.entries as IterableHashEntries,\n nextSibling.entries as IterableHashEntries,\n );\n startIndex = i;\n removeCount = 2;\n } else {\n values = childNode.entries as IterableHashEntries;\n startIndex = i;\n removeCount = 1;\n }\n\n const newEntries = partition(\n values,\n value => value[2],\n tree.minSize - tree.chunkHeaderSize,\n tree.maxSize - tree.chunkHeaderSize,\n entries => {\n const node = tree.newNodeImpl(entries, level);\n return createNewInternalEntryForNode(node, tree.getEntrySize);\n },\n );\n\n if (this.isMutable) {\n this.entries.splice(startIndex, removeCount, ...newEntries);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(\n thisEntries,\n startIndex,\n removeCount,\n ...newEntries,\n );\n\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n #replaceChild(\n tree: BTreeWrite,\n index: number,\n newEntry: Entry<Hash>,\n ): InternalNodeImpl {\n if (this.isMutable) {\n this.entries.splice(index, 1, newEntry);\n this._updateNode(tree);\n return this;\n }\n const entries = readonlySplice(this.entries, index, 1, newEntry);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n async del(\n key: string,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // Key is larger than maxKey of rightmost entry so it is not present.\n return this;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n const oldHash = oldChildNode.hash;\n\n const childNode = await oldChildNode.del(key, tree);\n if (childNode.hash === oldHash) {\n // Not changed so not found.\n return this;\n }\n\n if (childNode.entries.length === 0) {\n // Subtree is now empty. Remove internal node.\n const entries = readonlySplice(this.entries, i, 1);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n if (i === 0 && this.entries.length === 1) {\n // There was only one node at this level and it was removed. We can return\n // the modified subtree.\n return childNode;\n }\n\n // The child node is still a good size.\n if (childNode.getChildNodeSize(tree) > tree.minSize) {\n // No merging needed.\n const entry = createNewInternalEntryForNode(childNode, tree.getEntrySize);\n return this.#replaceChild(tree, i, entry);\n }\n\n // Child node size is too small.\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n async *keys(tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.keys(tree);\n }\n }\n\n async *entriesIter(\n tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.entriesIter(tree);\n }\n }\n\n getChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<Array<InternalNodeImpl | DataNodeImpl>> {\n const ps: Promise<DataNodeImpl | InternalNodeImpl>[] = [];\n for (let i = start; i < length && i < this.entries.length; i++) {\n ps.push(tree.getNode(this.entries[i][1]));\n }\n return Promise.all(ps);\n }\n\n async getCompositeChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const {level} = this;\n\n if (length === 0) {\n return new InternalNodeImpl([], newRandomHash(), level - 1, true);\n }\n\n const output = await this.getChildren(start, start + length, tree);\n\n if (level > 1) {\n const entries: Entry<Hash>[] = [];\n for (const child of output as InternalNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new InternalNodeImpl(entries, newRandomHash(), level - 1, true);\n }\n\n assert(level === 1, 'Expected level to be 1');\n const entries: Entry<FrozenJSONValue>[] = [];\n for (const child of output as DataNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new DataNodeImpl(entries, newRandomHash(), true);\n }\n}\n\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl {\n if (level === 0) {\n return new DataNodeImpl(\n entries as Entry<FrozenJSONValue>[],\n hash,\n isMutable,\n );\n }\n return new InternalNodeImpl(entries as Entry<Hash>[], hash, level, isMutable);\n}\n\nexport function isDataNodeImpl(\n node: DataNodeImpl | InternalNodeImpl,\n): node is DataNodeImpl {\n return node.level === 0;\n}\n\nexport function partition<T, R>(\n values: Iterable<T>,\n // This is the size of each Entry\n getSizeOfEntry: (v: T) => number,\n min: number,\n max: number,\n create: (entries: T[]) => R,\n): R[] {\n const results: R[] = [];\n let sum = 0;\n let accum: T[] = [];\n // The most recently finalized partition, held back until we know it won't be\n // merged with trailing entries.\n let lastPartition: T[] | null = null;\n let lastSize = 0;\n\n function commitLast() {\n if (lastPartition !== null) {\n results.push(create(lastPartition));\n lastPartition = null;\n }\n }\n\n for (const value of values) {\n const size = getSizeOfEntry(value);\n if (size >= max) {\n if (accum.length > 0) {\n commitLast();\n lastPartition = accum;\n lastSize = sum;\n accum = [];\n sum = 0;\n }\n commitLast();\n lastPartition = [value];\n lastSize = size;\n } else if (sum + size >= min) {\n accum.push(value);\n commitLast();\n lastPartition = accum;\n lastSize = sum + size;\n accum = [];\n sum = 0;\n } else {\n sum += size;\n accum.push(value);\n }\n }\n\n if (sum > 0) {\n if (lastPartition !== null && sum + lastSize <= max) {\n lastPartition.push(...accum);\n commitLast();\n } else {\n commitLast();\n results.push(create(accum));\n }\n } else {\n commitLast();\n }\n\n return results;\n}\n\nexport const emptyDataNode = makeNodeChunkData<ReadonlyJSONValue>(\n 0,\n [],\n FormatVersion.Latest,\n);\nexport const emptyDataNodeImpl = new DataNodeImpl([], emptyHash, false);\n\nexport function createNewInternalEntryForNode(\n node: NodeImpl<unknown>,\n getSizeOfEntry: <K, V>(k: K, v: V) => number,\n): [string, Hash, number] {\n const key = node.maxKey();\n const value = node.hash;\n const size = getSizeOfEntry(key, value);\n return [key, value, size];\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"node.js","names":["#childNodeSize","#splice","#mergeAndPartition","#replaceChild"],"sources":["../../../../../replicache/src/btree/node.ts"],"sourcesContent":["import {compareUTF8} from 'compare-utf8';\nimport {\n assert,\n assertArray,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport {binarySearch as binarySearchWithFunc} from '../../../shared/src/binary-search.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {joinIterables} from '../../../shared/src/iterables.ts';\nimport {\n type JSONValue,\n type ReadonlyJSONValue,\n assertJSONValue,\n} from '../../../shared/src/json.ts';\nimport {skipBTreeNodeAsserts} from '../config.ts';\nimport type {IndexKey} from '../db/index.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.ts';\nimport {type Hash, emptyHash, newRandomHash} from '../hash.ts';\nimport type {BTreeRead} from './read.ts';\nimport type {BTreeWrite} from './write.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport type Entry<V> = readonly [key: string, value: V, sizeOfEntry: number];\n\nexport const NODE_LEVEL = 0;\nexport const NODE_ENTRIES = 1;\n\n/**\n * The type of B+Tree node chunk data\n */\ntype BaseNode<V> = FrozenTag<\n readonly [level: number, entries: ReadonlyArray<Entry<V>>]\n>;\nexport type InternalNode = BaseNode<Hash>;\n\nexport type DataNode = BaseNode<FrozenJSONValue>;\n\nexport function makeNodeChunkData<V>(\n level: number,\n entries: ReadonlyArray<Entry<V>>,\n formatVersion: FormatVersion,\n): BaseNode<V> {\n return deepFreeze([\n level,\n (formatVersion >= FormatVersion.V7\n ? entries\n : entries.map(e => e.slice(0, 2))) as readonly ReadonlyJSONValue[],\n ]) as BaseNode<V>;\n}\n\nexport type Node = DataNode | InternalNode;\n\n/**\n * Describes the changes that happened to Replicache after a\n * {@link WriteTransaction} was committed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type Diff = IndexDiff | NoIndexDiff;\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type IndexDiff = readonly DiffOperation<IndexKey>[];\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type NoIndexDiff = readonly DiffOperation<string>[];\n\n/**\n * InternalDiff uses string keys even for the secondary index maps.\n */\nexport type InternalDiff = readonly InternalDiffOperation[];\n\nexport type DiffOperationAdd<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'add';\n readonly key: Key;\n readonly newValue: Value;\n};\n\nexport type DiffOperationDel<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'del';\n readonly key: Key;\n readonly oldValue: Value;\n};\n\nexport type DiffOperationChange<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'change';\n readonly key: Key;\n readonly oldValue: Value;\n readonly newValue: Value;\n};\n\n/**\n * The individual parts describing the changes that happened to the Replicache\n * data. There are three different kinds of operations:\n * - `add`: A new entry was added.\n * - `del`: An entry was deleted.\n * - `change`: An entry was changed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type DiffOperation<Key> =\n | DiffOperationAdd<Key>\n | DiffOperationDel<Key>\n | DiffOperationChange<Key>;\n\n// Duplicated with DiffOperation to make the docs less confusing.\nexport type InternalDiffOperation<Key = string, Value = FrozenJSONValue> =\n | DiffOperationAdd<Key, Value>\n | DiffOperationDel<Key, Value>\n | DiffOperationChange<Key, Value>;\n\n/**\n * Finds the leaf where a key is (if present) or where it should go if not\n * present.\n */\nexport async function findLeaf(\n key: string,\n hash: Hash,\n source: BTreeRead,\n expectedRootHash: Hash,\n): Promise<DataNodeImpl> {\n const node = await source.getNode(hash);\n // The root changed. Try again\n if (expectedRootHash !== source.rootHash) {\n return findLeaf(key, source.rootHash, source, source.rootHash);\n }\n if (isDataNodeImpl(node)) {\n return node;\n }\n const {entries} = node;\n let i = binarySearch(key, entries);\n if (i === entries.length) {\n i--;\n }\n const entry = entries[i];\n return findLeaf(key, entry[1], source, expectedRootHash);\n}\n\ntype BinarySearchEntries = readonly Entry<unknown>[];\n\n/**\n * Does a binary search over entries\n *\n * If the key found then the return value is the index it was found at.\n *\n * If the key was *not* found then the return value is the index where it should\n * be inserted at\n */\nexport function binarySearch(\n key: string,\n entries: BinarySearchEntries,\n): number {\n return binarySearchFrom(key, entries, 0);\n}\n\n/**\n * Binary search starting from a given index.\n */\nfunction binarySearchFrom(\n key: string,\n entries: BinarySearchEntries,\n start: number,\n): number {\n const result = binarySearchWithFunc(entries.length - start, i =>\n compareUTF8(key, entries[start + i][0]),\n );\n return start + result;\n}\n\nexport function binarySearchFound(\n i: number,\n entries: BinarySearchEntries,\n key: string,\n): boolean {\n return i !== entries.length && entries[i][0] === key;\n}\n\nexport function parseBTreeNode(\n v: unknown,\n formatVersion: FormatVersion,\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): InternalNode | DataNode {\n if (skipBTreeNodeAsserts && formatVersion >= FormatVersion.V7) {\n return v as InternalNode | DataNode;\n }\n\n assertArray(v);\n assertDeepFrozen(v);\n // Be relaxed about what we accept.\n assert(v.length >= 2, 'Expected node array to have at least 2 elements');\n const [level, entries] = v;\n assertNumber(level);\n assertArray(entries);\n\n const f = level > 0 ? assertString : assertJSONValue;\n\n // For V7 we do not need to change the entries. Just assert that they are correct.\n if (formatVersion >= FormatVersion.V7) {\n for (const e of entries) {\n assertEntry(e, f);\n }\n return v as unknown as InternalNode | DataNode;\n }\n\n const newEntries = entries.map(e => convertNonV7Entry(e, f, getSizeOfEntry));\n return [level, newEntries] as unknown as InternalNode | DataNode;\n}\n\nfunction assertEntry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n): asserts entry is Entry<Hash | JSONValue> {\n assertArray(entry);\n // Be relaxed about what we accept.\n assert(entry.length >= 3, 'Expected entry array to have at least 3 elements');\n assertString(entry[0]);\n f(entry[1]);\n assertNumber(entry[2]);\n}\n\n/**\n * Converts an entry that was from a format version before V7 to the format\n * wanted by V7.\n */\nfunction convertNonV7Entry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): Entry<Hash | JSONValue> {\n assertArray(entry);\n assert(entry.length >= 2, 'Expected entry array to have at least 2 elements');\n assertString(entry[0]);\n f(entry[1]);\n const entrySize = getSizeOfEntry(entry[0], entry[1]);\n return [entry[0], entry[1], entrySize] as Entry<Hash | JSONValue>;\n}\n\nexport function isInternalNode(node: Node): node is InternalNode {\n return node[NODE_LEVEL] > 0;\n}\n\nabstract class NodeImpl<Value> {\n entries: Array<Entry<Value>>;\n hash: Hash;\n abstract readonly level: number;\n readonly isMutable: boolean;\n\n #childNodeSize = -1;\n\n constructor(entries: Array<Entry<Value>>, hash: Hash, isMutable: boolean) {\n this.entries = entries;\n this.hash = hash;\n this.isMutable = isMutable;\n }\n\n abstract set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value>>;\n\n abstract putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value>>;\n\n abstract del(\n key: string,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value> | DataNodeImpl>;\n\n maxKey(): string {\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return this.entries.at(-1)![0];\n }\n\n getChildNodeSize(tree: BTreeRead): number {\n if (this.#childNodeSize !== -1) {\n return this.#childNodeSize;\n }\n\n let sum = tree.chunkHeaderSize;\n for (const entry of this.entries) {\n sum += entry[2];\n }\n return (this.#childNodeSize = sum);\n }\n\n protected _updateNode(tree: BTreeWrite) {\n this.#childNodeSize = -1;\n tree.updateNode(\n this as NodeImpl<unknown> as DataNodeImpl | InternalNodeImpl,\n );\n }\n}\n\nexport function toChunkData<V>(\n node: NodeImpl<V>,\n formatVersion: FormatVersion,\n): BaseNode<V> {\n return makeNodeChunkData(node.level, node.entries, formatVersion);\n}\n\nexport class DataNodeImpl extends NodeImpl<FrozenJSONValue> {\n readonly level = 0;\n\n set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<DataNodeImpl> {\n let deleteCount: number;\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found, insert.\n deleteCount = 0;\n } else {\n deleteCount = 1;\n }\n\n return Promise.resolve(\n this.#splice(tree, i, deleteCount, [key, value, entrySize]),\n );\n }\n\n putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<DataNodeImpl> {\n if (entries.length === 0) {\n return Promise.resolve(this);\n }\n\n // Merge sorted entries with existing entries\n const merged: Entry<FrozenJSONValue>[] = [];\n let i = 0; // index in this.entries\n let j = 0; // index in entries\n\n while (i < this.entries.length && j < entries.length) {\n const existingEntry = this.entries[i];\n const newEntry = entries[j];\n const cmp = compareUTF8(existingEntry[0], newEntry[0]);\n\n if (cmp < 0) {\n merged.push(existingEntry);\n i++;\n } else if (cmp > 0) {\n merged.push(newEntry);\n j++;\n } else {\n // Same key, new entry wins (update)\n merged.push(newEntry);\n i++;\n j++;\n }\n }\n\n // Add remaining entries\n while (i < this.entries.length) {\n merged.push(this.entries[i]);\n i++;\n }\n while (j < entries.length) {\n merged.push(entries[j]);\n j++;\n }\n\n if (this.isMutable) {\n this.entries = merged;\n this._updateNode(tree);\n return Promise.resolve(this);\n }\n\n return Promise.resolve(tree.newDataNodeImpl(merged));\n }\n\n #splice(\n tree: BTreeWrite,\n start: number,\n deleteCount: number,\n ...items: Entry<FrozenJSONValue>[]\n ): DataNodeImpl {\n if (this.isMutable) {\n this.entries.splice(start, deleteCount, ...items);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(this.entries, start, deleteCount, ...items);\n return tree.newDataNodeImpl(entries);\n }\n\n del(key: string, tree: BTreeWrite): Promise<DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found. Return this without changes.\n return Promise.resolve(this);\n }\n\n // Found. Create new node or mutate existing one.\n return Promise.resolve(this.#splice(tree, i, 1));\n }\n\n async *keys(_tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n yield entry[0];\n }\n }\n\n async *entriesIter(\n _tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n yield entry;\n }\n }\n}\n\nfunction readonlySplice<T>(\n array: ReadonlyArray<T>,\n start: number,\n deleteCount: number,\n ...items: T[]\n): T[] {\n const arr = array.slice(0, start);\n for (let i = 0; i < items.length; i++) {\n arr.push(items[i]);\n }\n for (let i = start + deleteCount; i < array.length; i++) {\n arr.push(array[i]);\n }\n return arr;\n}\n\nexport class InternalNodeImpl extends NodeImpl<Hash> {\n readonly level: number;\n\n constructor(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n ) {\n super(entries, hash, isMutable);\n this.level = level;\n }\n\n async set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl> {\n let i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // We are going to insert into last (right most) leaf.\n i--;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n\n const childNode = await oldChildNode.set(key, value, entrySize, tree);\n\n const childNodeSize = childNode.getChildNodeSize(tree);\n if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n const newEntry = createNewInternalEntryForNode(\n childNode,\n tree.getEntrySize,\n );\n return this.#replaceChild(tree, i, newEntry);\n }\n\n async putMany(\n entries: ReadonlyArray<Entry<FrozenJSONValue>>,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl> {\n if (entries.length === 0) {\n return this;\n }\n\n // Group entries by child index\n // Since entries are sorted, we can restrict the binary search range\n const childGroups: Map<number, Entry<FrozenJSONValue>[]> = new Map();\n\n let searchStart = 0;\n for (const entry of entries) {\n const key = entry[0];\n // Binary search from searchStart to end (entries are sorted)\n let i = binarySearchFrom(key, this.entries, searchStart);\n if (i === this.entries.length) {\n // Insert into last (right most) leaf.\n i--;\n }\n searchStart = i;\n\n let group = childGroups.get(i);\n if (!group) {\n group = [];\n childGroups.set(i, group);\n }\n group.push(entry);\n }\n\n // Process each affected child\n const newEntries = [...this.entries];\n const childrenToRebalance: Array<{\n index: number;\n node: DataNodeImpl | InternalNodeImpl;\n }> = [];\n\n for (const [childIndex, childEntries] of childGroups) {\n const childHash = this.entries[childIndex][1];\n const oldChildNode = await tree.getNode(childHash);\n const childNode = await oldChildNode.putMany(childEntries, tree);\n\n const childNodeSize = childNode.getChildNodeSize(tree);\n if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {\n childrenToRebalance.push({index: childIndex, node: childNode});\n } else {\n const newEntry = createNewInternalEntryForNode(\n childNode,\n tree.getEntrySize,\n );\n newEntries[childIndex] = newEntry;\n }\n }\n\n // Handle rebalancing - merge adjacent children that need rebalancing\n // into contiguous groups and process each group as one unit.\n //\n // BUG FIX: Previously, each child was rebalanced independently R-to-L.\n // When adjacent children (e.g., indices 0 and 1) both needed rebalancing,\n // child[1] would merge with sibling[0] (the ORIGINAL), then child[0]\n // would merge with the rebalanced result at position 1, duplicating\n // child[0]'s data. The fix groups adjacent indices together.\n if (childrenToRebalance.length > 0) {\n childrenToRebalance.sort((a, b) => a.index - b.index);\n\n // Group adjacent indices into contiguous runs, each extended by one\n // sibling on either side for merge context.\n const groups: Array<{\n nodes: Map<number, DataNodeImpl | InternalNodeImpl>;\n minIndex: number;\n maxIndex: number;\n }> = [];\n\n for (const {index, node} of childrenToRebalance) {\n const lastGroup = groups.at(-1);\n // Adjacent to previous group? (within 1 index of the last group's max)\n if (lastGroup && index <= lastGroup.maxIndex + 1) {\n lastGroup.nodes.set(index, node);\n lastGroup.maxIndex = index;\n } else {\n groups.push({\n nodes: new Map([[index, node]]),\n minIndex: index,\n maxIndex: index,\n });\n }\n }\n\n // Process groups from right to left to maintain indices during splices.\n for (let g = groups.length - 1; g >= 0; g--) {\n const group = groups[g];\n\n // Extend range by one sibling on each side for merge context.\n const startIndex = Math.max(0, group.minIndex - 1);\n const endIndex = Math.min(newEntries.length - 1, group.maxIndex + 1);\n const removeCount = endIndex - startIndex + 1;\n\n // Collect all entries from the range: use the putMany result for\n // indices that were rebalanced, the current newEntries node otherwise.\n type IterableHashEntries = Iterable<Entry<Hash>>;\n const allValues: IterableHashEntries[] = [];\n for (let idx = startIndex; idx <= endIndex; idx++) {\n const rebalancedNode = group.nodes.get(idx);\n if (rebalancedNode) {\n allValues.push(rebalancedNode.entries as IterableHashEntries);\n } else {\n const hash = newEntries[idx][1];\n const existingNode = await tree.getNode(hash);\n allValues.push(existingNode.entries as IterableHashEntries);\n }\n }\n\n const level = this.level - 1;\n const merged = joinIterables(...allValues);\n const rebalanced = partition(\n merged,\n e => e[2],\n tree.minSize - tree.chunkHeaderSize,\n tree.maxSize - tree.chunkHeaderSize,\n entries => {\n const node = tree.newNodeImpl(entries, level);\n return createNewInternalEntryForNode(node, tree.getEntrySize);\n },\n );\n\n newEntries.splice(startIndex, removeCount, ...rebalanced);\n }\n }\n\n if (this.isMutable) {\n this.entries = newEntries;\n this._updateNode(tree);\n return this;\n }\n\n return tree.newInternalNodeImpl(newEntries, this.level);\n }\n\n /**\n * This merges the child node entries with previous or next sibling and then\n * partitions the merged entries.\n */\n async #mergeAndPartition(\n tree: BTreeWrite,\n i: number,\n childNode: DataNodeImpl | InternalNodeImpl,\n ): Promise<InternalNodeImpl> {\n const level = this.level - 1;\n const thisEntries = this.entries;\n\n type IterableHashEntries = Iterable<Entry<Hash>>;\n\n let values: IterableHashEntries;\n let startIndex: number;\n let removeCount: number;\n if (i > 0) {\n const hash = thisEntries[i - 1][1];\n const previousSibling = await tree.getNode(hash);\n values = joinIterables(\n previousSibling.entries as IterableHashEntries,\n childNode.entries as IterableHashEntries,\n );\n startIndex = i - 1;\n removeCount = 2;\n } else if (i < thisEntries.length - 1) {\n const hash = thisEntries[i + 1][1];\n const nextSibling = await tree.getNode(hash);\n values = joinIterables(\n childNode.entries as IterableHashEntries,\n nextSibling.entries as IterableHashEntries,\n );\n startIndex = i;\n removeCount = 2;\n } else {\n values = childNode.entries as IterableHashEntries;\n startIndex = i;\n removeCount = 1;\n }\n\n const newEntries = partition(\n values,\n value => value[2],\n tree.minSize - tree.chunkHeaderSize,\n tree.maxSize - tree.chunkHeaderSize,\n entries => {\n const node = tree.newNodeImpl(entries, level);\n return createNewInternalEntryForNode(node, tree.getEntrySize);\n },\n );\n\n if (this.isMutable) {\n this.entries.splice(startIndex, removeCount, ...newEntries);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(\n thisEntries,\n startIndex,\n removeCount,\n ...newEntries,\n );\n\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n #replaceChild(\n tree: BTreeWrite,\n index: number,\n newEntry: Entry<Hash>,\n ): InternalNodeImpl {\n if (this.isMutable) {\n this.entries.splice(index, 1, newEntry);\n this._updateNode(tree);\n return this;\n }\n const entries = readonlySplice(this.entries, index, 1, newEntry);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n async del(\n key: string,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // Key is larger than maxKey of rightmost entry so it is not present.\n return this;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n const oldHash = oldChildNode.hash;\n\n const childNode = await oldChildNode.del(key, tree);\n if (childNode.hash === oldHash) {\n // Not changed so not found.\n return this;\n }\n\n if (childNode.entries.length === 0) {\n // Subtree is now empty. Remove internal node.\n const entries = readonlySplice(this.entries, i, 1);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n if (i === 0 && this.entries.length === 1) {\n // There was only one node at this level and it was removed. We can return\n // the modified subtree.\n return childNode;\n }\n\n // The child node is still a good size.\n if (childNode.getChildNodeSize(tree) > tree.minSize) {\n // No merging needed.\n const entry = createNewInternalEntryForNode(childNode, tree.getEntrySize);\n return this.#replaceChild(tree, i, entry);\n }\n\n // Child node size is too small.\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n async *keys(tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.keys(tree);\n }\n }\n\n async *entriesIter(\n tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.entriesIter(tree);\n }\n }\n\n getChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<Array<InternalNodeImpl | DataNodeImpl>> {\n const ps: Promise<DataNodeImpl | InternalNodeImpl>[] = [];\n for (let i = start; i < length && i < this.entries.length; i++) {\n ps.push(tree.getNode(this.entries[i][1]));\n }\n return Promise.all(ps);\n }\n\n async getCompositeChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const {level} = this;\n\n if (length === 0) {\n return new InternalNodeImpl([], newRandomHash(), level - 1, true);\n }\n\n const output = await this.getChildren(start, start + length, tree);\n\n if (level > 1) {\n const entries: Entry<Hash>[] = [];\n for (const child of output as InternalNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new InternalNodeImpl(entries, newRandomHash(), level - 1, true);\n }\n\n assert(level === 1, 'Expected level to be 1');\n const entries: Entry<FrozenJSONValue>[] = [];\n for (const child of output as DataNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new DataNodeImpl(entries, newRandomHash(), true);\n }\n}\n\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl {\n if (level === 0) {\n return new DataNodeImpl(\n entries as Entry<FrozenJSONValue>[],\n hash,\n isMutable,\n );\n }\n return new InternalNodeImpl(entries as Entry<Hash>[], hash, level, isMutable);\n}\n\nexport function isDataNodeImpl(\n node: DataNodeImpl | InternalNodeImpl,\n): node is DataNodeImpl {\n return node.level === 0;\n}\n\nexport function partition<T, R>(\n values: Iterable<T>,\n // This is the size of each Entry\n getSizeOfEntry: (v: T) => number,\n min: number,\n max: number,\n create: (entries: T[]) => R,\n): R[] {\n const results: R[] = [];\n let sum = 0;\n let accum: T[] = [];\n // The most recently finalized partition, held back until we know it won't be\n // merged with trailing entries.\n let lastPartition: T[] | null = null;\n let lastSize = 0;\n\n function commitLast() {\n if (lastPartition !== null) {\n results.push(create(lastPartition));\n lastPartition = null;\n }\n }\n\n for (const value of values) {\n const size = getSizeOfEntry(value);\n if (size >= max) {\n if (accum.length > 0) {\n commitLast();\n lastPartition = accum;\n lastSize = sum;\n accum = [];\n sum = 0;\n }\n commitLast();\n lastPartition = [value];\n lastSize = size;\n } else if (sum + size >= min) {\n accum.push(value);\n commitLast();\n lastPartition = accum;\n lastSize = sum + size;\n accum = [];\n sum = 0;\n } else {\n sum += size;\n accum.push(value);\n }\n }\n\n if (sum > 0) {\n if (lastPartition !== null && sum + lastSize <= max) {\n lastPartition.push(...accum);\n commitLast();\n } else {\n commitLast();\n results.push(create(accum));\n }\n } else {\n commitLast();\n }\n\n return results;\n}\n\nexport const emptyDataNode = makeNodeChunkData<ReadonlyJSONValue>(\n 0,\n [],\n FormatVersion.Latest,\n);\nexport const emptyDataNodeImpl = new DataNodeImpl([], emptyHash, false);\n\nexport function createNewInternalEntryForNode(\n node: NodeImpl<unknown>,\n getSizeOfEntry: <K, V>(k: K, v: V) => number,\n): [string, Hash, number] {\n const key = node.maxKey();\n const value = node.hash;\n const size = getSizeOfEntry(key, value);\n return [key, value, size];\n}\n"],"mappings":"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"}
@@ -25,18 +25,7 @@ export declare class BTreeRead implements AsyncIterable<Entry<FrozenJSONValue>>
25
25
  get(key: string): Promise<FrozenJSONValue | undefined>;
26
26
  has(key: string): Promise<boolean>;
27
27
  isEmpty(): Promise<boolean>;
28
- /**
29
- * We don't do any encoding of the key in the map, so we have no way of
30
- * determining from an entry.key alone whether it is a regular key or an
31
- * encoded IndexKey in an index map. Without encoding regular map keys the
32
- * caller has to deal with encoding and decoding the keys for the index map.
33
- *
34
- * @param prefetch Read sibling nodes in parallel before traversing them so
35
- * stores can batch the reads. This can read nodes that the caller never
36
- * visits. Enable it only when the caller expects to consume most of the scan
37
- * or explicitly accepts that extra work.
38
- */
39
- scan(fromKey: string, prefetch: boolean): AsyncIterableIterator<Entry<FrozenJSONValue>>;
28
+ scan(fromKey: string): AsyncIterableIterator<Entry<FrozenJSONValue>>;
40
29
  keys(): AsyncIterableIterator<string>;
41
30
  entries(): AsyncIterableIterator<Entry<FrozenJSONValue>>;
42
31
  [Symbol.asyncIterator](): AsyncIterableIterator<Entry<FrozenJSONValue>>;
@@ -1 +1 @@
1
- {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/btree/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAC9D,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAU3B,MAAM,WAAW,CAAC;AASnB,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,qBAAa,SAAU,YAAW,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACrE,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CACzD;IAEZ,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC;IACjD,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC;IACpD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAG/B,OAAO,EAAE,IAAI,EACb,aAAa,EAAE,aAAa,EAC5B,IAAI,GAAE,IAAgB,EACtB,YAAY,GAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAuB,EAC3D,eAAe,SAAmB;IAS9B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,CAAC;IA0B7D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAStD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMlC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAUjC;;;;;;;;;;OAUG;IACH,IAAI,CACF,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,OAAO,GAChB,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAczC,IAAI,IAAI,qBAAqB,CAAC,MAAM,CAAC;IAKrC,OAAO,IAAI,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAK/D,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAIhE,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC,qBAAqB,CAAC;CAO3E;AAyMD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,KAAK,GAAG,KAAK,GAChB,OAAO,CAAC,YAAY,CAAC,CAmBvB"}
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/btree/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAC,YAAY,EAAE,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAC9D,OAAO,EACL,KAAK,KAAK,EACV,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAU3B,MAAM,WAAW,CAAC;AASnB,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC,qBAAa,SAAU,YAAW,aAAa,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IACrE,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,YAAY,GAAG,gBAAgB,CAAC,CACzD;IAEZ,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IAClC,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC;IACjD,QAAQ,EAAE,IAAI,CAAC;IACf,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC;IACpD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;gBAG/B,OAAO,EAAE,IAAI,EACb,aAAa,EAAE,aAAa,EAC5B,IAAI,GAAE,IAAgB,EACtB,YAAY,GAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,MAAuB,EAC3D,eAAe,SAAmB;IAS9B,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,YAAY,GAAG,gBAAgB,CAAC;IA0B7D,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAStD,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMlC,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAcjC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAwB7D,IAAI,IAAI,qBAAqB,CAAC,MAAM,CAAC;IAKrC,OAAO,IAAI,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAK/D,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;IAIhE,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,qBAAqB,CAAC,qBAAqB,CAAC;CAO3E;AA8KD,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,SAAS,EACd,EAAE,EAAE,KAAK,GAAG,KAAK,GAChB,OAAO,CAAC,YAAY,CAAC,CAmBvB"}
@@ -42,22 +42,12 @@ var BTreeRead = class {
42
42
  if (this.rootHash !== rootHash) return this.isEmpty();
43
43
  return node.entries.length === 0;
44
44
  }
45
- /**
46
- * We don't do any encoding of the key in the map, so we have no way of
47
- * determining from an entry.key alone whether it is a regular key or an
48
- * encoded IndexKey in an index map. Without encoding regular map keys the
49
- * caller has to deal with encoding and decoding the keys for the index map.
50
- *
51
- * @param prefetch Read sibling nodes in parallel before traversing them so
52
- * stores can batch the reads. This can read nodes that the caller never
53
- * visits. Enable it only when the caller expects to consume most of the scan
54
- * or explicitly accepts that extra work.
55
- */
56
- scan(fromKey, prefetch) {
45
+ scan(fromKey) {
57
46
  return scanForHash(this.rootHash, () => this.rootHash, this.rootHash, fromKey, async (hash) => {
58
- const { level, isMutable, entries } = await this.getNode(hash);
59
- return [level, isMutable ? entries.slice() : entries];
60
- }, prefetch);
47
+ const cached = await this.getNode(hash);
48
+ if (cached) return [cached.level, cached.isMutable ? cached.entries.slice() : cached.entries];
49
+ return parseBTreeNode((await this._dagRead.mustGetChunk(hash)).data, this._formatVersion, this.getEntrySize);
50
+ });
61
51
  }
62
52
  async *keys() {
63
53
  yield* (await this.getNode(this.rootHash)).keys(this);
@@ -136,22 +126,20 @@ function* diffEntries(lastEntries, currentEntries) {
136
126
  newValue: currentEntries[j][1]
137
127
  };
138
128
  }
139
- async function* scanForHash(expectedRootHash, getRootHash, hash, fromKey, readNode, prefetch) {
129
+ async function* scanForHash(expectedRootHash, getRootHash, hash, fromKey, readNode) {
140
130
  if (hash === emptyHash) return;
141
131
  const data = await readNode(hash);
142
132
  const entries = data[1];
143
133
  let i = 0;
144
134
  if (fromKey) i = binarySearch(fromKey, entries);
145
- if (data[0] > 0) {
146
- if (prefetch) await Promise.all(entries.slice(i).map((entry) => readNode(entry[1]).catch(() => void 0)));
147
- for (; i < entries.length; i++) {
148
- yield* scanForHash(expectedRootHash, getRootHash, entries[i][1], fromKey, readNode, prefetch);
149
- fromKey = "";
150
- }
151
- } else for (; i < entries.length; i++) {
135
+ if (data[0] > 0) for (; i < entries.length; i++) {
136
+ yield* scanForHash(expectedRootHash, getRootHash, entries[i][1], fromKey, readNode);
137
+ fromKey = "";
138
+ }
139
+ else for (; i < entries.length; i++) {
152
140
  const rootHash = getRootHash();
153
141
  if (expectedRootHash !== rootHash) {
154
- yield* scanForHash(rootHash, getRootHash, rootHash, entries[i][0], readNode, prefetch);
142
+ yield* scanForHash(rootHash, getRootHash, rootHash, entries[i][0], readNode);
155
143
  return;
156
144
  }
157
145
  yield entries[i];
@@ -1 +1 @@
1
- {"version":3,"file":"read.js","names":[],"sources":["../../../../../replicache/src/btree/read.ts"],"sourcesContent":["import type {Enum} from '../../../shared/src/enum.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {getSizeOfEntry} from '../../../shared/src/size-of-value.ts';\nimport type {Read} from '../dag/store.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {type Hash, emptyHash} from '../hash.ts';\nimport type {DataNodeImpl, InternalNodeImpl} from './node.ts';\nimport {\n type Entry,\n type InternalDiff,\n type InternalDiffOperation,\n NODE_ENTRIES,\n NODE_LEVEL,\n binarySearch,\n binarySearchFound,\n emptyDataNodeImpl,\n findLeaf,\n isDataNodeImpl,\n newNodeImpl,\n parseBTreeNode,\n} from './node.ts';\nimport {\n SPLICE_ADDED,\n SPLICE_AT,\n SPLICE_FROM,\n SPLICE_REMOVED,\n computeSplices,\n} from './splice.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * The size of the header of a node. (If we had compile time\n * constants we would have used that).\n *\n * There is a test ensuring this is correct.\n */\nexport const NODE_HEADER_SIZE = 11;\n\nexport class BTreeRead implements AsyncIterable<Entry<FrozenJSONValue>> {\n protected readonly _cache: Map<Hash, DataNodeImpl | InternalNodeImpl> =\n new Map();\n\n protected readonly _dagRead: Read;\n protected readonly _formatVersion: FormatVersion;\n rootHash: Hash;\n readonly getEntrySize: <K, V>(k: K, v: V) => number;\n readonly chunkHeaderSize: number;\n\n constructor(\n dagRead: Read,\n formatVersion: FormatVersion,\n root: Hash = emptyHash,\n getEntrySize: <K, V>(k: K, v: V) => number = getSizeOfEntry,\n chunkHeaderSize = NODE_HEADER_SIZE,\n ) {\n this._dagRead = dagRead;\n this._formatVersion = formatVersion;\n this.rootHash = root;\n this.getEntrySize = getEntrySize;\n this.chunkHeaderSize = chunkHeaderSize;\n }\n\n async getNode(hash: Hash): Promise<DataNodeImpl | InternalNodeImpl> {\n if (hash === emptyHash) {\n return emptyDataNodeImpl;\n }\n\n const cached = this._cache.get(hash);\n if (cached) {\n return cached;\n }\n\n const chunk = await this._dagRead.mustGetChunk(hash);\n const data = parseBTreeNode(\n chunk.data,\n this._formatVersion,\n this.getEntrySize,\n );\n const impl = newNodeImpl(\n data[NODE_ENTRIES] as Entry<FrozenJSONValue>[],\n hash,\n data[NODE_LEVEL],\n false,\n );\n this._cache.set(hash, impl);\n return impl;\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n if (!binarySearchFound(index, leaf.entries, key)) {\n return undefined;\n }\n return leaf.entries[index][1];\n }\n\n async has(key: string): Promise<boolean> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n return binarySearchFound(index, leaf.entries, key);\n }\n\n async isEmpty(): Promise<boolean> {\n const {rootHash} = this;\n const node = await this.getNode(this.rootHash);\n // The root hash has changed, so the tree has been modified.\n if (this.rootHash !== rootHash) {\n return this.isEmpty();\n }\n return node.entries.length === 0;\n }\n\n /**\n * We don't do any encoding of the key in the map, so we have no way of\n * determining from an entry.key alone whether it is a regular key or an\n * encoded IndexKey in an index map. Without encoding regular map keys the\n * caller has to deal with encoding and decoding the keys for the index map.\n *\n * @param prefetch Read sibling nodes in parallel before traversing them so\n * stores can batch the reads. This can read nodes that the caller never\n * visits. Enable it only when the caller expects to consume most of the scan\n * or explicitly accepts that extra work.\n */\n scan(\n fromKey: string,\n prefetch: boolean,\n ): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return scanForHash(\n this.rootHash,\n () => this.rootHash,\n this.rootHash,\n fromKey,\n async hash => {\n const {level, isMutable, entries} = await this.getNode(hash);\n return [level, isMutable ? entries.slice() : entries];\n },\n prefetch,\n );\n }\n\n async *keys(): AsyncIterableIterator<string> {\n const node = await this.getNode(this.rootHash);\n yield* node.keys(this);\n }\n\n async *entries(): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n const node = await this.getNode(this.rootHash);\n yield* node.entriesIter(this);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return this.entries();\n }\n\n async *diff(last: BTreeRead): AsyncIterableIterator<InternalDiffOperation> {\n const [currentNode, lastNode] = await Promise.all([\n this.getNode(this.rootHash),\n last.getNode(last.rootHash),\n ]);\n yield* diffNodes(lastNode, currentNode, last, this);\n }\n}\n\nasync function* diffNodes(\n last: InternalNodeImpl | DataNodeImpl,\n current: InternalNodeImpl | DataNodeImpl,\n lastTree: BTreeRead,\n currentTree: BTreeRead,\n): AsyncIterableIterator<InternalDiffOperation> {\n if (last.level > current.level) {\n // merge all of last's children into a new node\n // We know last is an internal node because level > 0.\n const lastChild = (await (last as InternalNodeImpl).getCompositeChildren(\n 0,\n last.entries.length,\n lastTree,\n )) as InternalNodeImpl;\n yield* diffNodes(lastChild, current, lastTree, currentTree);\n return;\n }\n\n if (current.level > last.level) {\n // We know current is an internal node because level > 0.\n const currentChild = (await (\n current as InternalNodeImpl\n ).getCompositeChildren(\n 0,\n current.entries.length,\n currentTree,\n )) as InternalNodeImpl;\n yield* diffNodes(last, currentChild, lastTree, currentTree);\n return;\n }\n\n if (isDataNodeImpl(last) && isDataNodeImpl(current)) {\n yield* diffEntries(\n (last as DataNodeImpl).entries,\n (current as DataNodeImpl).entries,\n );\n return;\n }\n\n // Now we have two internal nodes with the same level. We compute the diff as\n // splices for the internal node entries. We then flatten these and call diff\n // recursively.\n const initialSplices = computeSplices(\n (last as InternalNodeImpl).entries,\n (current as InternalNodeImpl).entries,\n );\n for (const splice of initialSplices) {\n const [lastChild, currentChild] = await Promise.all([\n (last as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_AT],\n splice[SPLICE_REMOVED],\n lastTree,\n ),\n (current as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_FROM],\n splice[SPLICE_ADDED],\n currentTree,\n ),\n ]);\n yield* diffNodes(lastChild, currentChild, lastTree, currentTree);\n }\n}\n\nfunction* diffEntries(\n lastEntries: readonly Entry<FrozenJSONValue>[],\n currentEntries: readonly Entry<FrozenJSONValue>[],\n): IterableIterator<InternalDiffOperation> {\n const lastLength = lastEntries.length;\n const currentLength = currentEntries.length;\n let i = 0;\n let j = 0;\n while (i < lastLength && j < currentLength) {\n const lastKey = lastEntries[i][0];\n const currentKey = currentEntries[j][0];\n if (lastKey === currentKey) {\n if (!deepEqual(lastEntries[i][1], currentEntries[j][1])) {\n yield {\n op: 'change',\n key: lastKey,\n oldValue: lastEntries[i][1],\n newValue: currentEntries[j][1],\n };\n }\n i++;\n j++;\n } else if (lastKey < currentKey) {\n yield {\n op: 'del',\n key: lastKey,\n oldValue: lastEntries[i][1],\n };\n i++;\n } else {\n yield {\n op: 'add',\n key: currentKey,\n newValue: currentEntries[j][1],\n };\n j++;\n }\n }\n for (; i < lastLength; i++) {\n yield {\n op: 'del',\n key: lastEntries[i][0],\n oldValue: lastEntries[i][1],\n };\n }\n for (; j < currentLength; j++) {\n yield {\n op: 'add',\n key: currentEntries[j][0],\n newValue: currentEntries[j][1],\n };\n }\n}\n\n// Redefine the type here to allow the optional size in the tuple.\ntype ReadNodeResult = readonly [\n level: number,\n data: readonly Entry<FrozenJSONValue>[] | readonly Entry<Hash>[],\n];\n\ntype ReadNode = (hash: Hash) => Promise<ReadNodeResult>;\n\nasync function* scanForHash(\n expectedRootHash: Hash,\n getRootHash: () => Hash,\n hash: Hash,\n fromKey: string,\n readNode: ReadNode,\n prefetch: boolean,\n): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n if (hash === emptyHash) {\n return;\n }\n\n const data = await readNode(hash);\n const entries = data[NODE_ENTRIES];\n let i = 0;\n if (fromKey) {\n i = binarySearch(fromKey, entries);\n }\n if (data[NODE_LEVEL] > 0) {\n if (prefetch) {\n // Preload children in parallel so the backing store can coalesce their\n // reads. This can waste work when a caller stops before visiting every\n // child, so callers must explicitly opt in when they expect to consume\n // the full scan. Zero currently accepts that tradeoff: startup scans the\n // entire cached entity range into IVM memory before becoming ready (see\n // `ZeroRep.init` in packages/zero-client/src/client/zero-rep.ts), and\n // client views are intended to remain small. If views commonly outgrow\n // the 100 MB `LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT`, reconsider the\n // preload window, although batching may still be a useful general\n // optimization. Longer term, the Replicache/IVM boundary should also be\n // revisited because materializing entities into `MemorySource`\n // duplicates B-tree storage.\n //\n // The serial scan below preserves traversal order and remains the\n // authoritative read, so speculative failures are ignored here.\n await Promise.all(\n entries\n .slice(i)\n .map(entry =>\n readNode((entry as Entry<Hash>)[1]).catch(() => undefined),\n ),\n );\n }\n for (; i < entries.length; i++) {\n yield* scanForHash(\n expectedRootHash,\n getRootHash,\n (entries[i] as Entry<Hash>)[1],\n fromKey,\n readNode,\n prefetch,\n );\n fromKey = '';\n }\n } else {\n for (; i < entries.length; i++) {\n const rootHash = getRootHash();\n // If rootHash changed then we start a new iterator from the key.\n if (expectedRootHash !== rootHash) {\n yield* scanForHash(\n rootHash,\n getRootHash,\n rootHash,\n entries[i][0],\n readNode,\n prefetch,\n );\n return;\n }\n yield entries[i] as Entry<FrozenJSONValue>;\n }\n }\n}\n\nexport async function allEntriesAsDiff(\n map: BTreeRead,\n op: 'add' | 'del',\n): Promise<InternalDiff> {\n const diff: InternalDiffOperation[] = [];\n const make: (entry: Entry<FrozenJSONValue>) => InternalDiffOperation =\n op === 'add'\n ? entry => ({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n })\n : entry => ({\n op: 'del',\n key: entry[0],\n oldValue: entry[1],\n });\n\n for await (const entry of map.entries()) {\n diff.push(make(entry));\n }\n return diff;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"read.js","names":[],"sources":["../../../../../replicache/src/btree/read.ts"],"sourcesContent":["import type {Enum} from '../../../shared/src/enum.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {getSizeOfEntry} from '../../../shared/src/size-of-value.ts';\nimport type {Read} from '../dag/store.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {type Hash, emptyHash} from '../hash.ts';\nimport type {DataNodeImpl, InternalNodeImpl} from './node.ts';\nimport {\n type Entry,\n type InternalDiff,\n type InternalDiffOperation,\n NODE_ENTRIES,\n NODE_LEVEL,\n binarySearch,\n binarySearchFound,\n emptyDataNodeImpl,\n findLeaf,\n isDataNodeImpl,\n newNodeImpl,\n parseBTreeNode,\n} from './node.ts';\nimport {\n SPLICE_ADDED,\n SPLICE_AT,\n SPLICE_FROM,\n SPLICE_REMOVED,\n computeSplices,\n} from './splice.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * The size of the header of a node. (If we had compile time\n * constants we would have used that).\n *\n * There is a test ensuring this is correct.\n */\nexport const NODE_HEADER_SIZE = 11;\n\nexport class BTreeRead implements AsyncIterable<Entry<FrozenJSONValue>> {\n protected readonly _cache: Map<Hash, DataNodeImpl | InternalNodeImpl> =\n new Map();\n\n protected readonly _dagRead: Read;\n protected readonly _formatVersion: FormatVersion;\n rootHash: Hash;\n readonly getEntrySize: <K, V>(k: K, v: V) => number;\n readonly chunkHeaderSize: number;\n\n constructor(\n dagRead: Read,\n formatVersion: FormatVersion,\n root: Hash = emptyHash,\n getEntrySize: <K, V>(k: K, v: V) => number = getSizeOfEntry,\n chunkHeaderSize = NODE_HEADER_SIZE,\n ) {\n this._dagRead = dagRead;\n this._formatVersion = formatVersion;\n this.rootHash = root;\n this.getEntrySize = getEntrySize;\n this.chunkHeaderSize = chunkHeaderSize;\n }\n\n async getNode(hash: Hash): Promise<DataNodeImpl | InternalNodeImpl> {\n if (hash === emptyHash) {\n return emptyDataNodeImpl;\n }\n\n const cached = this._cache.get(hash);\n if (cached) {\n return cached;\n }\n\n const chunk = await this._dagRead.mustGetChunk(hash);\n const data = parseBTreeNode(\n chunk.data,\n this._formatVersion,\n this.getEntrySize,\n );\n const impl = newNodeImpl(\n data[NODE_ENTRIES] as Entry<FrozenJSONValue>[],\n hash,\n data[NODE_LEVEL],\n false,\n );\n this._cache.set(hash, impl);\n return impl;\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n if (!binarySearchFound(index, leaf.entries, key)) {\n return undefined;\n }\n return leaf.entries[index][1];\n }\n\n async has(key: string): Promise<boolean> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n return binarySearchFound(index, leaf.entries, key);\n }\n\n async isEmpty(): Promise<boolean> {\n const {rootHash} = this;\n const node = await this.getNode(this.rootHash);\n // The root hash has changed, so the tree has been modified.\n if (this.rootHash !== rootHash) {\n return this.isEmpty();\n }\n return node.entries.length === 0;\n }\n\n // We don't do any encoding of the key in the map, so we have no way of\n // determining from an entry.key alone whether it is a regular key or an\n // encoded IndexKey in an index map. Without encoding regular map keys the\n // caller has to deal with encoding and decoding the keys for the index map.\n scan(fromKey: string): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return scanForHash(\n this.rootHash,\n () => this.rootHash,\n this.rootHash,\n fromKey,\n async hash => {\n const cached = await this.getNode(hash);\n if (cached) {\n return [\n cached.level,\n cached.isMutable ? cached.entries.slice() : cached.entries,\n ];\n }\n const chunk = await this._dagRead.mustGetChunk(hash);\n return parseBTreeNode(\n chunk.data,\n this._formatVersion,\n this.getEntrySize,\n );\n },\n );\n }\n\n async *keys(): AsyncIterableIterator<string> {\n const node = await this.getNode(this.rootHash);\n yield* node.keys(this);\n }\n\n async *entries(): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n const node = await this.getNode(this.rootHash);\n yield* node.entriesIter(this);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return this.entries();\n }\n\n async *diff(last: BTreeRead): AsyncIterableIterator<InternalDiffOperation> {\n const [currentNode, lastNode] = await Promise.all([\n this.getNode(this.rootHash),\n last.getNode(last.rootHash),\n ]);\n yield* diffNodes(lastNode, currentNode, last, this);\n }\n}\n\nasync function* diffNodes(\n last: InternalNodeImpl | DataNodeImpl,\n current: InternalNodeImpl | DataNodeImpl,\n lastTree: BTreeRead,\n currentTree: BTreeRead,\n): AsyncIterableIterator<InternalDiffOperation> {\n if (last.level > current.level) {\n // merge all of last's children into a new node\n // We know last is an internal node because level > 0.\n const lastChild = (await (last as InternalNodeImpl).getCompositeChildren(\n 0,\n last.entries.length,\n lastTree,\n )) as InternalNodeImpl;\n yield* diffNodes(lastChild, current, lastTree, currentTree);\n return;\n }\n\n if (current.level > last.level) {\n // We know current is an internal node because level > 0.\n const currentChild = (await (\n current as InternalNodeImpl\n ).getCompositeChildren(\n 0,\n current.entries.length,\n currentTree,\n )) as InternalNodeImpl;\n yield* diffNodes(last, currentChild, lastTree, currentTree);\n return;\n }\n\n if (isDataNodeImpl(last) && isDataNodeImpl(current)) {\n yield* diffEntries(\n (last as DataNodeImpl).entries,\n (current as DataNodeImpl).entries,\n );\n return;\n }\n\n // Now we have two internal nodes with the same level. We compute the diff as\n // splices for the internal node entries. We then flatten these and call diff\n // recursively.\n const initialSplices = computeSplices(\n (last as InternalNodeImpl).entries,\n (current as InternalNodeImpl).entries,\n );\n for (const splice of initialSplices) {\n const [lastChild, currentChild] = await Promise.all([\n (last as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_AT],\n splice[SPLICE_REMOVED],\n lastTree,\n ),\n (current as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_FROM],\n splice[SPLICE_ADDED],\n currentTree,\n ),\n ]);\n yield* diffNodes(lastChild, currentChild, lastTree, currentTree);\n }\n}\n\nfunction* diffEntries(\n lastEntries: readonly Entry<FrozenJSONValue>[],\n currentEntries: readonly Entry<FrozenJSONValue>[],\n): IterableIterator<InternalDiffOperation> {\n const lastLength = lastEntries.length;\n const currentLength = currentEntries.length;\n let i = 0;\n let j = 0;\n while (i < lastLength && j < currentLength) {\n const lastKey = lastEntries[i][0];\n const currentKey = currentEntries[j][0];\n if (lastKey === currentKey) {\n if (!deepEqual(lastEntries[i][1], currentEntries[j][1])) {\n yield {\n op: 'change',\n key: lastKey,\n oldValue: lastEntries[i][1],\n newValue: currentEntries[j][1],\n };\n }\n i++;\n j++;\n } else if (lastKey < currentKey) {\n yield {\n op: 'del',\n key: lastKey,\n oldValue: lastEntries[i][1],\n };\n i++;\n } else {\n yield {\n op: 'add',\n key: currentKey,\n newValue: currentEntries[j][1],\n };\n j++;\n }\n }\n for (; i < lastLength; i++) {\n yield {\n op: 'del',\n key: lastEntries[i][0],\n oldValue: lastEntries[i][1],\n };\n }\n for (; j < currentLength; j++) {\n yield {\n op: 'add',\n key: currentEntries[j][0],\n newValue: currentEntries[j][1],\n };\n }\n}\n\n// Redefine the type here to allow the optional size in the tuple.\ntype ReadNodeResult = readonly [\n level: number,\n data: readonly Entry<FrozenJSONValue>[] | readonly Entry<Hash>[],\n];\n\ntype ReadNode = (hash: Hash) => Promise<ReadNodeResult>;\n\nasync function* scanForHash(\n expectedRootHash: Hash,\n getRootHash: () => Hash,\n hash: Hash,\n fromKey: string,\n readNode: ReadNode,\n): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n if (hash === emptyHash) {\n return;\n }\n\n const data = await readNode(hash);\n const entries = data[NODE_ENTRIES];\n let i = 0;\n if (fromKey) {\n i = binarySearch(fromKey, entries);\n }\n if (data[NODE_LEVEL] > 0) {\n for (; i < entries.length; i++) {\n yield* scanForHash(\n expectedRootHash,\n getRootHash,\n (entries[i] as Entry<Hash>)[1],\n fromKey,\n readNode,\n );\n fromKey = '';\n }\n } else {\n for (; i < entries.length; i++) {\n const rootHash = getRootHash();\n // If rootHash changed then we start a new iterator from the key.\n if (expectedRootHash !== rootHash) {\n yield* scanForHash(\n rootHash,\n getRootHash,\n rootHash,\n entries[i][0],\n readNode,\n );\n return;\n }\n yield entries[i] as Entry<FrozenJSONValue>;\n }\n }\n}\n\nexport async function allEntriesAsDiff(\n map: BTreeRead,\n op: 'add' | 'del',\n): Promise<InternalDiff> {\n const diff: InternalDiffOperation[] = [];\n const make: (entry: Entry<FrozenJSONValue>) => InternalDiffOperation =\n op === 'add'\n ? entry => ({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n })\n : entry => ({\n op: 'del',\n key: entry[0],\n oldValue: entry[1],\n });\n\n for await (const entry of map.entries()) {\n diff.push(make(entry));\n }\n return diff;\n}\n"],"mappings":";;;;;AAwCA,IAAa,YAAb,MAAwE;CACtE,yBACE,IAAI,IAAI;CAEV;CACA;CACA;CACA;CACA;CAEA,YACE,SACA,eACA,OAAa,WACb,eAA6C,gBAC7C,kBAAA,IACA;EACA,KAAK,WAAW;EAChB,KAAK,iBAAiB;EACtB,KAAK,WAAW;EAChB,KAAK,eAAe;EACpB,KAAK,kBAAkB;CACzB;CAEA,MAAM,QAAQ,MAAsD;EAClE,IAAI,SAAS,WACX,OAAO;EAGT,MAAM,SAAS,KAAK,OAAO,IAAI,IAAI;EACnC,IAAI,QACF,OAAO;EAIT,MAAM,OAAO,gBACX,MAFkB,KAAK,SAAS,aAAa,IAAI,GAE3C,MACN,KAAK,gBACL,KAAK,YACP;EACA,MAAM,OAAO,YACX,KAAA,IACA,MACA,KAAA,IACA,KACF;EACA,KAAK,OAAO,IAAI,MAAM,IAAI;EAC1B,OAAO;CACT;CAEA,MAAM,IAAI,KAAmD;EAC3D,MAAM,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU,MAAM,KAAK,QAAQ;EACnE,MAAM,QAAQ,aAAa,KAAK,KAAK,OAAO;EAC5C,IAAI,CAAC,kBAAkB,OAAO,KAAK,SAAS,GAAG,GAC7C;EAEF,OAAO,KAAK,QAAQ,OAAO;CAC7B;CAEA,MAAM,IAAI,KAA+B;EACvC,MAAM,OAAO,MAAM,SAAS,KAAK,KAAK,UAAU,MAAM,KAAK,QAAQ;EAEnE,OAAO,kBADO,aAAa,KAAK,KAAK,OACZ,GAAO,KAAK,SAAS,GAAG;CACnD;CAEA,MAAM,UAA4B;EAChC,MAAM,EAAC,aAAY;EACnB,MAAM,OAAO,MAAM,KAAK,QAAQ,KAAK,QAAQ;EAE7C,IAAI,KAAK,aAAa,UACpB,OAAO,KAAK,QAAQ;EAEtB,OAAO,KAAK,QAAQ,WAAW;CACjC;CAMA,KAAK,SAAgE;EACnE,OAAO,YACL,KAAK,gBACC,KAAK,UACX,KAAK,UACL,SACA,OAAM,SAAQ;GACZ,MAAM,SAAS,MAAM,KAAK,QAAQ,IAAI;GACtC,IAAI,QACF,OAAO,CACL,OAAO,OACP,OAAO,YAAY,OAAO,QAAQ,MAAM,IAAI,OAAO,OACrD;GAGF,OAAO,gBACL,MAFkB,KAAK,SAAS,aAAa,IAAI,GAE3C,MACN,KAAK,gBACL,KAAK,YACP;EACF,CACF;CACF;CAEA,OAAO,OAAsC;EAE3C,QAAO,MADY,KAAK,QAAQ,KAAK,QAAQ,GACjC,KAAK,IAAI;CACvB;CAEA,OAAO,UAAyD;EAE9D,QAAO,MADY,KAAK,QAAQ,KAAK,QAAQ,GACjC,YAAY,IAAI;CAC9B;CAEA,CAAC,OAAO,iBAAgE;EACtE,OAAO,KAAK,QAAQ;CACtB;CAEA,OAAO,KAAK,MAA+D;EACzE,MAAM,CAAC,aAAa,YAAY,MAAM,QAAQ,IAAI,CAChD,KAAK,QAAQ,KAAK,QAAQ,GAC1B,KAAK,QAAQ,KAAK,QAAQ,CAC5B,CAAC;EACD,OAAO,UAAU,UAAU,aAAa,MAAM,IAAI;CACpD;AACF;AAEA,gBAAgB,UACd,MACA,SACA,UACA,aAC8C;CAC9C,IAAI,KAAK,QAAQ,QAAQ,OAAO;EAQ9B,OAAO,UAAU,MALS,KAA0B,qBAClD,GACA,KAAK,QAAQ,QACb,QACF,GAC4B,SAAS,UAAU,WAAW;EAC1D;CACF;CAEA,IAAI,QAAQ,QAAQ,KAAK,OAAO;EAS9B,OAAO,UAAU,MAAM,MANrB,QACA,qBACA,GACA,QAAQ,QAAQ,QAChB,WACF,GACqC,UAAU,WAAW;EAC1D;CACF;CAEA,IAAI,eAAe,IAAI,KAAK,eAAe,OAAO,GAAG;EACnD,OAAO,YACJ,KAAsB,SACtB,QAAyB,OAC5B;EACA;CACF;CAKA,MAAM,iBAAiB,eACpB,KAA0B,SAC1B,QAA6B,OAChC;CACA,KAAK,MAAM,UAAU,gBAAgB;EACnC,MAAM,CAAC,WAAW,gBAAgB,MAAM,QAAQ,IAAI,CACjD,KAA0B,qBACzB,OAAA,IACA,OAAA,IACA,QACF,GACC,QAA6B,qBAC5B,OAAA,IACA,OAAA,IACA,WACF,CACF,CAAC;EACD,OAAO,UAAU,WAAW,cAAc,UAAU,WAAW;CACjE;AACF;AAEA,UAAU,YACR,aACA,gBACyC;CACzC,MAAM,aAAa,YAAY;CAC/B,MAAM,gBAAgB,eAAe;CACrC,IAAI,IAAI;CACR,IAAI,IAAI;CACR,OAAO,IAAI,cAAc,IAAI,eAAe;EAC1C,MAAM,UAAU,YAAY,GAAG;EAC/B,MAAM,aAAa,eAAe,GAAG;EACrC,IAAI,YAAY,YAAY;GAC1B,IAAI,CAAC,UAAU,YAAY,GAAG,IAAI,eAAe,GAAG,EAAE,GACpD,MAAM;IACJ,IAAI;IACJ,KAAK;IACL,UAAU,YAAY,GAAG;IACzB,UAAU,eAAe,GAAG;GAC9B;GAEF;GACA;EACF,OAAO,IAAI,UAAU,YAAY;GAC/B,MAAM;IACJ,IAAI;IACJ,KAAK;IACL,UAAU,YAAY,GAAG;GAC3B;GACA;EACF,OAAO;GACL,MAAM;IACJ,IAAI;IACJ,KAAK;IACL,UAAU,eAAe,GAAG;GAC9B;GACA;EACF;CACF;CACA,OAAO,IAAI,YAAY,KACrB,MAAM;EACJ,IAAI;EACJ,KAAK,YAAY,GAAG;EACpB,UAAU,YAAY,GAAG;CAC3B;CAEF,OAAO,IAAI,eAAe,KACxB,MAAM;EACJ,IAAI;EACJ,KAAK,eAAe,GAAG;EACvB,UAAU,eAAe,GAAG;CAC9B;AAEJ;AAUA,gBAAgB,YACd,kBACA,aACA,MACA,SACA,UAC+C;CAC/C,IAAI,SAAS,WACX;CAGF,MAAM,OAAO,MAAM,SAAS,IAAI;CAChC,MAAM,UAAU,KAAA;CAChB,IAAI,IAAI;CACR,IAAI,SACF,IAAI,aAAa,SAAS,OAAO;CAEnC,IAAI,KAAA,KAAmB,GACrB,OAAO,IAAI,QAAQ,QAAQ,KAAK;EAC9B,OAAO,YACL,kBACA,aACC,QAAQ,GAAmB,IAC5B,SACA,QACF;EACA,UAAU;CACZ;MAEA,OAAO,IAAI,QAAQ,QAAQ,KAAK;EAC9B,MAAM,WAAW,YAAY;EAE7B,IAAI,qBAAqB,UAAU;GACjC,OAAO,YACL,UACA,aACA,UACA,QAAQ,GAAG,IACX,QACF;GACA;EACF;EACA,MAAM,QAAQ;CAChB;AAEJ;AAEA,eAAsB,iBACpB,KACA,IACuB;CACvB,MAAM,OAAgC,CAAC;CACvC,MAAM,OACJ,OAAO,SACH,WAAU;EACR,IAAI;EACJ,KAAK,MAAM;EACX,UAAU,MAAM;CAClB,MACA,WAAU;EACR,IAAI;EACJ,KAAK,MAAM;EACX,UAAU,MAAM;CAClB;CAEN,WAAW,MAAM,SAAS,IAAI,QAAQ,GACpC,KAAK,KAAK,KAAK,KAAK,CAAC;CAEvB,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/dag/gc.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;AAGhD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,IAAI,GAAG,SAAS,CAAC;IACtB,GAAG,EAAE,IAAI,GAAG,SAAS,CAAC;CACvB,CAAC;AAIF,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9D,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,SAAS,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC;IACnE;;;;;;;;;;;;;;;;;;OAkBG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CAC1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,EACjC,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,EAC5B,QAAQ,EAAE,uBAAuB,GAChC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAE5B"}
1
+ {"version":3,"file":"gc.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/dag/gc.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,IAAI,GAAG,SAAS,CAAC;IACtB,GAAG,EAAE,IAAI,GAAG,SAAS,CAAC;CACvB,CAAC;AAIF,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAC9D,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,YAAY,CAAC,SAAS,IAAI,EAAE,GAAG,SAAS,CAAC,CAAC;IACnE;;;;;;;;;;;;;;;;;;OAkBG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CAC1C;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,QAAQ,CAAC,UAAU,CAAC,EACjC,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,EAC5B,QAAQ,EAAE,uBAAuB,GAChC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAE5B"}
@@ -1,9 +1,7 @@
1
1
  import { assert, assertNumber } from "../../../shared/src/asserts.js";
2
2
  import { isProd } from "../../../shared/src/config.js";
3
3
  import "../config.js";
4
- import { InvalidRefCountError } from "./invalid-ref-count-error.js";
5
4
  import { emptyHash } from "../hash.js";
6
- import { getOrInsertComputed } from "../../../shared/src/map.js";
7
5
  //#region ../replicache/src/dag/gc.ts
8
6
  /**
9
7
  * Computes how ref counts should be updated when a dag write is committed.
@@ -60,7 +58,7 @@ var RefCountUpdates = class {
60
58
  } while (refCountsUpdated);
61
59
  }
62
60
  for (const o of this.#oldHeads) await this.#changeRefCount(o, -1);
63
- for (const [hash, update] of this.#refCountUpdates) if (!(update >= 0)) throw new InvalidRefCountError(hash, update);
61
+ if (!isProd) for (const [hash, update] of this.#refCountUpdates) assert(update >= 0, `ref count update must be non-negative. ${hash}:${update}`);
64
62
  return this.#refCountUpdates;
65
63
  }
66
64
  async #changeRefCount(hash, delta) {
@@ -78,11 +76,16 @@ var RefCountUpdates = class {
78
76
  }
79
77
  }
80
78
  #ensureRefCountLoaded(hash) {
81
- return getOrInsertComputed(this.#loadedRefCountPromises, hash, async (hash) => {
82
- const value = await this.#delegate.getRefCount(hash) || 0;
83
- this.#refCountUpdates.set(hash, value);
84
- return value;
85
- });
79
+ let p = this.#loadedRefCountPromises.get(hash);
80
+ if (p === void 0) {
81
+ p = (async () => {
82
+ const value = await this.#delegate.getRefCount(hash) || 0;
83
+ this.#refCountUpdates.set(hash, value);
84
+ return value;
85
+ })();
86
+ this.#loadedRefCountPromises.set(hash, p);
87
+ }
88
+ return p;
86
89
  }
87
90
  #updateRefCount(hash, delta) {
88
91
  const oldCount = this.#refCountUpdates.get(hash);