@rocicorp/zero 1.6.2 → 1.7.0-canary.2

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 (606) hide show
  1. package/README.md +28 -3
  2. package/out/_virtual/{_@oxc-project_runtime@0.122.0 → _@oxc-project_runtime@0.130.0}/helpers/usingCtx.js +1 -1
  3. package/out/analyze-query/src/analyze-cli.js +3 -3
  4. package/out/analyze-query/src/analyze-cli.js.map +1 -1
  5. package/out/analyze-query/src/bin-analyze.js +7 -2
  6. package/out/analyze-query/src/bin-analyze.js.map +1 -1
  7. package/out/analyze-query/src/bin-transform.js.map +1 -1
  8. package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
  9. package/out/ast-to-zql/src/bin.js.map +1 -1
  10. package/out/ast-to-zql/src/format.js.map +1 -1
  11. package/out/datadog/src/datadog-log-sink.js.map +1 -1
  12. package/out/otel/src/enabled.js.map +1 -1
  13. package/out/otel/src/log-options.js.map +1 -1
  14. package/out/otel/src/maybe-time.js.map +1 -1
  15. package/out/otel/src/span.js.map +1 -1
  16. package/out/replicache/src/async-iterable-to-array.js.map +1 -1
  17. package/out/replicache/src/bg-interval.js.map +1 -1
  18. package/out/replicache/src/btree/diff.js.map +1 -1
  19. package/out/replicache/src/btree/node.js.map +1 -1
  20. package/out/replicache/src/btree/read.js.map +1 -1
  21. package/out/replicache/src/btree/splice.js.map +1 -1
  22. package/out/replicache/src/btree/write.js +6 -3
  23. package/out/replicache/src/btree/write.js.map +1 -1
  24. package/out/replicache/src/call-default-fetch.js.map +1 -1
  25. package/out/replicache/src/connection-loop-delegates.js.map +1 -1
  26. package/out/replicache/src/connection-loop.js +13 -13
  27. package/out/replicache/src/connection-loop.js.map +1 -1
  28. package/out/replicache/src/cookies.js.map +1 -1
  29. package/out/replicache/src/dag/chunk.js.map +1 -1
  30. package/out/replicache/src/dag/gc.js.map +1 -1
  31. package/out/replicache/src/dag/key.js.map +1 -1
  32. package/out/replicache/src/dag/lazy-store.js.map +1 -1
  33. package/out/replicache/src/dag/store-impl.js.map +1 -1
  34. package/out/replicache/src/dag/store.js.map +1 -1
  35. package/out/replicache/src/dag/visitor.js.map +1 -1
  36. package/out/replicache/src/db/commit.js.map +1 -1
  37. package/out/replicache/src/db/index.js.map +1 -1
  38. package/out/replicache/src/db/read.js.map +1 -1
  39. package/out/replicache/src/db/rebase.js.map +1 -1
  40. package/out/replicache/src/db/write.js.map +1 -1
  41. package/out/replicache/src/deleted-clients.js.map +1 -1
  42. package/out/replicache/src/error-responses.js.map +1 -1
  43. package/out/replicache/src/frozen-json.js.map +1 -1
  44. package/out/replicache/src/get-default-puller.js.map +1 -1
  45. package/out/replicache/src/get-default-pusher.js.map +1 -1
  46. package/out/replicache/src/get-kv-store-provider.js.map +1 -1
  47. package/out/replicache/src/hash.js.map +1 -1
  48. package/out/replicache/src/http-request-info.js.map +1 -1
  49. package/out/replicache/src/index-defs.js.map +1 -1
  50. package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
  51. package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
  52. package/out/replicache/src/kv/idb-store.js.map +1 -1
  53. package/out/replicache/src/kv/mem-store.js.map +1 -1
  54. package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
  55. package/out/replicache/src/kv/read-impl.js.map +1 -1
  56. package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
  57. package/out/replicache/src/kv/sqlite-store.js +4 -1
  58. package/out/replicache/src/kv/sqlite-store.js.map +1 -1
  59. package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
  60. package/out/replicache/src/kv/write-impl-base.js.map +1 -1
  61. package/out/replicache/src/kv/write-impl.js.map +1 -1
  62. package/out/replicache/src/lazy.js.map +1 -1
  63. package/out/replicache/src/log-options.js.map +1 -1
  64. package/out/replicache/src/make-idb-name.js.map +1 -1
  65. package/out/replicache/src/new-client-channel.js.map +1 -1
  66. package/out/replicache/src/on-persist-channel.js.map +1 -1
  67. package/out/replicache/src/patch-operation.js.map +1 -1
  68. package/out/replicache/src/pending-mutations.js.map +1 -1
  69. package/out/replicache/src/persist/client-gc.js.map +1 -1
  70. package/out/replicache/src/persist/client-group-gc.js.map +1 -1
  71. package/out/replicache/src/persist/client-groups.js +40 -0
  72. package/out/replicache/src/persist/client-groups.js.map +1 -1
  73. package/out/replicache/src/persist/clients.js +28 -0
  74. package/out/replicache/src/persist/clients.js.map +1 -1
  75. package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
  76. package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
  77. package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
  78. package/out/replicache/src/persist/heartbeat.js.map +1 -1
  79. package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
  80. package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
  81. package/out/replicache/src/persist/make-client-id.js.map +1 -1
  82. package/out/replicache/src/persist/persist.js.map +1 -1
  83. package/out/replicache/src/persist/refresh.js.map +1 -1
  84. package/out/replicache/src/process-scheduler.js.map +1 -1
  85. package/out/replicache/src/pusher.js.map +1 -1
  86. package/out/replicache/src/replicache-impl.js.map +1 -1
  87. package/out/replicache/src/report-error.js.map +1 -1
  88. package/out/replicache/src/request-idle.js.map +1 -1
  89. package/out/replicache/src/scan-iterator.js.map +1 -1
  90. package/out/replicache/src/scan-options.js.map +1 -1
  91. package/out/replicache/src/set-interval-with-signal.js.map +1 -1
  92. package/out/replicache/src/subscriptions.js.map +1 -1
  93. package/out/replicache/src/sync/diff.js.map +1 -1
  94. package/out/replicache/src/sync/ids.js.map +1 -1
  95. package/out/replicache/src/sync/patch.js.map +1 -1
  96. package/out/replicache/src/sync/pull-error.js.map +1 -1
  97. package/out/replicache/src/sync/pull.js.map +1 -1
  98. package/out/replicache/src/sync/push.js.map +1 -1
  99. package/out/replicache/src/sync/request-id.js.map +1 -1
  100. package/out/replicache/src/to-error.js.map +1 -1
  101. package/out/replicache/src/transaction-closed-error.js.map +1 -1
  102. package/out/replicache/src/transactions.js.map +1 -1
  103. package/out/replicache/src/with-transactions.js.map +1 -1
  104. package/out/shared/src/abort-error.js.map +1 -1
  105. package/out/shared/src/arrays.js.map +1 -1
  106. package/out/shared/src/asserts.js.map +1 -1
  107. package/out/shared/src/bigint-json.js.map +1 -1
  108. package/out/shared/src/binary-search.js.map +1 -1
  109. package/out/shared/src/broadcast-channel.js.map +1 -1
  110. package/out/shared/src/browser-env.js.map +1 -1
  111. package/out/shared/src/btree-set.js.map +1 -1
  112. package/out/shared/src/cache.js.map +1 -1
  113. package/out/shared/src/centroid.js.map +1 -1
  114. package/out/shared/src/custom-key-map.js.map +1 -1
  115. package/out/shared/src/custom-key-set.js.map +1 -1
  116. package/out/shared/src/deep-clone.js.map +1 -1
  117. package/out/shared/src/deep-merge.js.map +1 -1
  118. package/out/shared/src/document-visible.js.map +1 -1
  119. package/out/shared/src/dotenv.js.map +1 -1
  120. package/out/shared/src/enum.d.ts +1 -1
  121. package/out/shared/src/error.js.map +1 -1
  122. package/out/shared/src/hash.js.map +1 -1
  123. package/out/shared/src/iterables.d.ts +2 -0
  124. package/out/shared/src/iterables.d.ts.map +1 -1
  125. package/out/shared/src/iterables.js +9 -1
  126. package/out/shared/src/iterables.js.map +1 -1
  127. package/out/shared/src/json-schema.js.map +1 -1
  128. package/out/shared/src/json.js.map +1 -1
  129. package/out/shared/src/logging-test-utils.js.map +1 -1
  130. package/out/shared/src/logging.js.map +1 -1
  131. package/out/shared/src/map.js.map +1 -1
  132. package/out/shared/src/must.js.map +1 -1
  133. package/out/shared/src/object-traversal.js.map +1 -1
  134. package/out/shared/src/objects.js.map +1 -1
  135. package/out/shared/src/options.js.map +1 -1
  136. package/out/shared/src/parse-big-int.js.map +1 -1
  137. package/out/shared/src/promise-race.js.map +1 -1
  138. package/out/shared/src/queue.d.ts.map +1 -1
  139. package/out/shared/src/queue.js +15 -21
  140. package/out/shared/src/queue.js.map +1 -1
  141. package/out/shared/src/rand.js.map +1 -1
  142. package/out/shared/src/random-uint64.js.map +1 -1
  143. package/out/shared/src/random-values.js.map +1 -1
  144. package/out/shared/src/record-proxy.js.map +1 -1
  145. package/out/shared/src/resolved-promises.js.map +1 -1
  146. package/out/shared/src/ring-buffer.d.ts +32 -0
  147. package/out/shared/src/ring-buffer.d.ts.map +1 -0
  148. package/out/shared/src/ring-buffer.js +109 -0
  149. package/out/shared/src/ring-buffer.js.map +1 -0
  150. package/out/shared/src/sentinels.js.map +1 -1
  151. package/out/shared/src/set-utils.js.map +1 -1
  152. package/out/shared/src/size-of-value.js.map +1 -1
  153. package/out/shared/src/sleep.js.map +1 -1
  154. package/out/shared/src/sorted-entries.js.map +1 -1
  155. package/out/shared/src/string-compare.js.map +1 -1
  156. package/out/shared/src/subscribable.js.map +1 -1
  157. package/out/shared/src/tdigest-schema.js.map +1 -1
  158. package/out/shared/src/tdigest.js.map +1 -1
  159. package/out/shared/src/valita.js.map +1 -1
  160. package/out/z2s/src/compiler.js.map +1 -1
  161. package/out/z2s/src/sql.d.ts.map +1 -1
  162. package/out/z2s/src/sql.js +3 -2
  163. package/out/z2s/src/sql.js.map +1 -1
  164. package/out/zero/package.js +37 -28
  165. package/out/zero/package.js.map +1 -1
  166. package/out/zero/src/build-schema.js.map +1 -1
  167. package/out/zero/src/zero-cache-dev.js.map +1 -1
  168. package/out/zero/src/zero-out.js.map +1 -1
  169. package/out/zero/src/zero.js +1 -1
  170. package/out/zero-cache/src/auth/auth.js.map +1 -1
  171. package/out/zero-cache/src/auth/jwt.js.map +1 -1
  172. package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
  173. package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
  174. package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
  175. package/out/zero-cache/src/config/network.js.map +1 -1
  176. package/out/zero-cache/src/config/normalize.js.map +1 -1
  177. package/out/zero-cache/src/config/server-context.js.map +1 -1
  178. package/out/zero-cache/src/config/zero-config.js +5 -0
  179. package/out/zero-cache/src/config/zero-config.js.map +1 -1
  180. package/out/zero-cache/src/custom/fetch.js.map +1 -1
  181. package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
  182. package/out/zero-cache/src/db/create.js.map +1 -1
  183. package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
  184. package/out/zero-cache/src/db/lite-tables.js.map +1 -1
  185. package/out/zero-cache/src/db/migration-lite.js +19 -0
  186. package/out/zero-cache/src/db/migration-lite.js.map +1 -1
  187. package/out/zero-cache/src/db/migration.js +19 -0
  188. package/out/zero-cache/src/db/migration.js.map +1 -1
  189. package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
  190. package/out/zero-cache/src/db/pg-copy.js.map +1 -1
  191. package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
  192. package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
  193. package/out/zero-cache/src/db/run-transaction.js.map +1 -1
  194. package/out/zero-cache/src/db/specs.js.map +1 -1
  195. package/out/zero-cache/src/db/statements.js.map +1 -1
  196. package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
  197. package/out/zero-cache/src/db/warmup.js.map +1 -1
  198. package/out/zero-cache/src/observability/events.js.map +1 -1
  199. package/out/zero-cache/src/observability/metrics.js.map +1 -1
  200. package/out/zero-cache/src/scripts/decommission.js.map +1 -1
  201. package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
  202. package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
  203. package/out/zero-cache/src/scripts/permissions.js +1 -2
  204. package/out/zero-cache/src/scripts/permissions.js.map +1 -1
  205. package/out/zero-cache/src/server/anonymous-otel-start.js +8 -7
  206. package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
  207. package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
  208. package/out/zero-cache/src/server/change-streamer.js +2 -2
  209. package/out/zero-cache/src/server/change-streamer.js.map +1 -1
  210. package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
  211. package/out/zero-cache/src/server/logging.js.map +1 -1
  212. package/out/zero-cache/src/server/main.js.map +1 -1
  213. package/out/zero-cache/src/server/mutator.js.map +1 -1
  214. package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
  215. package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
  216. package/out/zero-cache/src/server/otel-start.js.map +1 -1
  217. package/out/zero-cache/src/server/priority-op.js.map +1 -1
  218. package/out/zero-cache/src/server/reaper.js.map +1 -1
  219. package/out/zero-cache/src/server/replicator.js.map +1 -1
  220. package/out/zero-cache/src/server/runner/main.js.map +1 -1
  221. package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
  222. package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
  223. package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
  224. package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
  225. package/out/zero-cache/src/server/syncer.js.map +1 -1
  226. package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
  227. package/out/zero-cache/src/server/worker-urls.js.map +1 -1
  228. package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
  229. package/out/zero-cache/src/services/analyze.js +5 -2
  230. package/out/zero-cache/src/services/analyze.js.map +1 -1
  231. package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
  232. package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
  233. package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
  234. package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
  235. package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
  236. package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
  237. package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
  238. package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
  239. package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
  240. package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
  241. package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
  242. package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
  243. package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
  244. package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
  245. package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
  246. package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
  247. package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
  248. package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
  249. package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
  250. package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
  251. package/out/zero-cache/src/services/change-source/protocol/current/data.js +2 -0
  252. package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
  253. package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
  254. package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
  255. package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
  256. package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
  257. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +46 -1
  258. package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
  259. package/out/zero-cache/src/services/change-streamer/backup-monitor.js +109 -12
  260. package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
  261. package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
  262. package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
  263. package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
  264. package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
  265. package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
  266. package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
  267. package/out/zero-cache/src/services/change-streamer/schema/init.js +21 -25
  268. package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
  269. package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
  270. package/out/zero-cache/src/services/change-streamer/snapshot.js +15 -0
  271. package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
  272. package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
  273. package/out/zero-cache/src/services/change-streamer/storer.js +12 -2
  274. package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
  275. package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
  276. package/out/zero-cache/src/services/heapz.js.map +1 -1
  277. package/out/zero-cache/src/services/http-service.js.map +1 -1
  278. package/out/zero-cache/src/services/life-cycle.js.map +1 -1
  279. package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
  280. package/out/zero-cache/src/services/litestream/commands.d.ts +23 -0
  281. package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
  282. package/out/zero-cache/src/services/litestream/commands.js +89 -1
  283. package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
  284. package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
  285. package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
  286. package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
  287. package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
  288. package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
  289. package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
  290. package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
  291. package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
  292. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts +1 -0
  293. package/out/zero-cache/src/services/replicator/reporter/recorder.d.ts.map +1 -1
  294. package/out/zero-cache/src/services/replicator/reporter/recorder.js +8 -0
  295. package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
  296. package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
  297. package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
  298. package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
  299. package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
  300. package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
  301. package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
  302. package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
  303. package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
  304. package/out/zero-cache/src/services/run-ast.js +1 -0
  305. package/out/zero-cache/src/services/run-ast.js.map +1 -1
  306. package/out/zero-cache/src/services/runner.js.map +1 -1
  307. package/out/zero-cache/src/services/running-state.js.map +1 -1
  308. package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
  309. package/out/zero-cache/src/services/statz.js.map +1 -1
  310. package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
  311. package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
  312. package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
  313. package/out/zero-cache/src/services/view-syncer/client-schema.js +10 -2
  314. package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
  315. package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
  316. package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
  317. package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
  318. package/out/zero-cache/src/services/view-syncer/cvr-store.js +2 -1
  319. package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
  320. package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
  321. package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
  322. package/out/zero-cache/src/services/view-syncer/inspect-handler.js +1 -1
  323. package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
  324. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -1
  325. package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
  326. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +81 -7
  327. package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
  328. package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
  329. package/out/zero-cache/src/services/view-syncer/row-set-signature.js.map +1 -1
  330. package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
  331. package/out/zero-cache/src/services/view-syncer/schema/init.js +97 -113
  332. package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
  333. package/out/zero-cache/src/services/view-syncer/schema/types.js +103 -1
  334. package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
  335. package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
  336. package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
  337. package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
  338. package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
  339. package/out/zero-cache/src/services/view-syncer/view-syncer.js +13 -6
  340. package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
  341. package/out/zero-cache/src/types/configuration-error.js.map +1 -1
  342. package/out/zero-cache/src/types/error-with-level.js.map +1 -1
  343. package/out/zero-cache/src/types/http.js.map +1 -1
  344. package/out/zero-cache/src/types/lexi-version.js.map +1 -1
  345. package/out/zero-cache/src/types/lite.js.map +1 -1
  346. package/out/zero-cache/src/types/names.js.map +1 -1
  347. package/out/zero-cache/src/types/pg-data-type.d.ts +53 -2
  348. package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
  349. package/out/zero-cache/src/types/pg-data-type.js +28 -3
  350. package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
  351. package/out/zero-cache/src/types/pg.js.map +1 -1
  352. package/out/zero-cache/src/types/processes.js.map +1 -1
  353. package/out/zero-cache/src/types/profiler.js.map +1 -1
  354. package/out/zero-cache/src/types/row-key.js.map +1 -1
  355. package/out/zero-cache/src/types/shards.js.map +1 -1
  356. package/out/zero-cache/src/types/sql.js.map +1 -1
  357. package/out/zero-cache/src/types/state-version.js.map +1 -1
  358. package/out/zero-cache/src/types/streams.js.map +1 -1
  359. package/out/zero-cache/src/types/strings.js.map +1 -1
  360. package/out/zero-cache/src/types/subscription.js.map +1 -1
  361. package/out/zero-cache/src/types/timeout.js.map +1 -1
  362. package/out/zero-cache/src/types/url-params.js.map +1 -1
  363. package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
  364. package/out/zero-cache/src/types/ws.js.map +1 -1
  365. package/out/zero-cache/src/workers/connect-params.js.map +1 -1
  366. package/out/zero-cache/src/workers/connection.js.map +1 -1
  367. package/out/zero-cache/src/workers/mutator.js.map +1 -1
  368. package/out/zero-cache/src/workers/replicator.js.map +1 -1
  369. package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
  370. package/out/zero-cache/src/workers/syncer.js.map +1 -1
  371. package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
  372. package/out/zero-client/src/client/connection-manager.js +2 -1
  373. package/out/zero-client/src/client/connection-manager.js.map +1 -1
  374. package/out/zero-client/src/client/connection.js.map +1 -1
  375. package/out/zero-client/src/client/context.js.map +1 -1
  376. package/out/zero-client/src/client/crud-impl.js.map +1 -1
  377. package/out/zero-client/src/client/crud.js.map +1 -1
  378. package/out/zero-client/src/client/custom.js +2 -1
  379. package/out/zero-client/src/client/custom.js.map +1 -1
  380. package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
  381. package/out/zero-client/src/client/enable-analytics.js.map +1 -1
  382. package/out/zero-client/src/client/error.js.map +1 -1
  383. package/out/zero-client/src/client/http-string.js.map +1 -1
  384. package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
  385. package/out/zero-client/src/client/inspector/client.js.map +1 -1
  386. package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
  387. package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
  388. package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
  389. package/out/zero-client/src/client/inspector/query.js.map +1 -1
  390. package/out/zero-client/src/client/ivm-branch.js.map +1 -1
  391. package/out/zero-client/src/client/keys.js.map +1 -1
  392. package/out/zero-client/src/client/log-options.js.map +1 -1
  393. package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
  394. package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
  395. package/out/zero-client/src/client/metrics.js.map +1 -1
  396. package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
  397. package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
  398. package/out/zero-client/src/client/options.js.map +1 -1
  399. package/out/zero-client/src/client/query-manager.js +1 -1
  400. package/out/zero-client/src/client/query-manager.js.map +1 -1
  401. package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
  402. package/out/zero-client/src/client/server-option.js.map +1 -1
  403. package/out/zero-client/src/client/version.js +1 -1
  404. package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
  405. package/out/zero-client/src/client/zero-rep.js.map +1 -1
  406. package/out/zero-client/src/client/zero.d.ts.map +1 -1
  407. package/out/zero-client/src/client/zero.js +58 -32
  408. package/out/zero-client/src/client/zero.js.map +1 -1
  409. package/out/zero-client/src/mod.d.ts +2 -2
  410. package/out/zero-client/src/mod.d.ts.map +1 -1
  411. package/out/zero-client/src/mod.js +1 -1
  412. package/out/zero-client/src/util/nanoid.js.map +1 -1
  413. package/out/{zero-schema → zero-permissions}/src/permissions.d.ts +1 -1
  414. package/out/zero-permissions/src/permissions.d.ts.map +1 -0
  415. package/out/{zero-schema → zero-permissions}/src/permissions.js +2 -2
  416. package/out/zero-permissions/src/permissions.js.map +1 -0
  417. package/out/zero-protocol/src/analyze-query-result.js +3 -0
  418. package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
  419. package/out/zero-protocol/src/application-error.js.map +1 -1
  420. package/out/zero-protocol/src/ast.js.map +1 -1
  421. package/out/zero-protocol/src/change-desired-queries.js +1 -0
  422. package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
  423. package/out/zero-protocol/src/client-schema.js.map +1 -1
  424. package/out/zero-protocol/src/close-connection.js.map +1 -1
  425. package/out/zero-protocol/src/connect.js +7 -0
  426. package/out/zero-protocol/src/connect.js.map +1 -1
  427. package/out/zero-protocol/src/custom-queries.js.map +1 -1
  428. package/out/zero-protocol/src/data.js.map +1 -1
  429. package/out/zero-protocol/src/delete-clients.js.map +1 -1
  430. package/out/zero-protocol/src/down.js.map +1 -1
  431. package/out/zero-protocol/src/error.js +7 -0
  432. package/out/zero-protocol/src/error.js.map +1 -1
  433. package/out/zero-protocol/src/inspect-down.js.map +1 -1
  434. package/out/zero-protocol/src/inspect-up.js +1 -0
  435. package/out/zero-protocol/src/inspect-up.js.map +1 -1
  436. package/out/zero-protocol/src/mutate-server.js.map +1 -1
  437. package/out/zero-protocol/src/mutation-id.js.map +1 -1
  438. package/out/zero-protocol/src/mutation.js.map +1 -1
  439. package/out/zero-protocol/src/mutations-patch.js.map +1 -1
  440. package/out/zero-protocol/src/ping.js.map +1 -1
  441. package/out/zero-protocol/src/poke.js +4 -0
  442. package/out/zero-protocol/src/poke.js.map +1 -1
  443. package/out/zero-protocol/src/pong.js.map +1 -1
  444. package/out/zero-protocol/src/primary-key.js.map +1 -1
  445. package/out/zero-protocol/src/protocol-version.js.map +1 -1
  446. package/out/zero-protocol/src/pull.js.map +1 -1
  447. package/out/zero-protocol/src/push.js +16 -0
  448. package/out/zero-protocol/src/push.js.map +1 -1
  449. package/out/zero-protocol/src/queries-patch.js.map +1 -1
  450. package/out/zero-protocol/src/query-hash.js.map +1 -1
  451. package/out/zero-protocol/src/query-server.js.map +1 -1
  452. package/out/zero-protocol/src/row-patch.js.map +1 -1
  453. package/out/zero-protocol/src/up.js.map +1 -1
  454. package/out/zero-protocol/src/update-auth.js.map +1 -1
  455. package/out/zero-protocol/src/version.js.map +1 -1
  456. package/out/zero-react/src/use-connection-state.js.map +1 -1
  457. package/out/zero-react/src/use-query.d.ts.map +1 -1
  458. package/out/zero-react/src/use-query.js +2 -3
  459. package/out/zero-react/src/use-query.js.map +1 -1
  460. package/out/zero-react/src/use-zero-online.js.map +1 -1
  461. package/out/zero-react/src/zero-provider.js.map +1 -1
  462. package/out/zero-react/src/zero.js +1 -1
  463. package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
  464. package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
  465. package/out/zero-schema/src/builder/table-builder.js.map +1 -1
  466. package/out/zero-schema/src/compiled-permissions.js.map +1 -1
  467. package/out/zero-schema/src/name-mapper.js.map +1 -1
  468. package/out/zero-schema/src/schema-config.js.map +1 -1
  469. package/out/zero-server/src/adapters/drizzle.js.map +1 -1
  470. package/out/zero-server/src/adapters/kysely.js.map +1 -1
  471. package/out/zero-server/src/adapters/pg.js.map +1 -1
  472. package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
  473. package/out/zero-server/src/adapters/prisma.js.map +1 -1
  474. package/out/zero-server/src/custom.js +2 -1
  475. package/out/zero-server/src/custom.js.map +1 -1
  476. package/out/zero-server/src/logging.js.map +1 -1
  477. package/out/zero-server/src/pg-query-executor.js.map +1 -1
  478. package/out/zero-server/src/process-mutations.js.map +1 -1
  479. package/out/zero-server/src/push-processor.js.map +1 -1
  480. package/out/zero-server/src/queries/process-queries.js +1 -1
  481. package/out/zero-server/src/queries/process-queries.js.map +1 -1
  482. package/out/zero-server/src/schema.d.ts.map +1 -1
  483. package/out/zero-server/src/schema.js +1 -0
  484. package/out/zero-server/src/schema.js.map +1 -1
  485. package/out/zero-server/src/zql-database.js.map +1 -1
  486. package/out/zero-solid/src/solid-view.d.ts +42 -0
  487. package/out/zero-solid/src/solid-view.d.ts.map +1 -1
  488. package/out/zero-solid/src/solid-view.js +43 -2
  489. package/out/zero-solid/src/solid-view.js.map +1 -1
  490. package/out/zero-solid/src/use-connection-state.js.map +1 -1
  491. package/out/zero-solid/src/use-query.js +1 -1
  492. package/out/zero-solid/src/use-query.js.map +1 -1
  493. package/out/zero-solid/src/use-zero-online.js.map +1 -1
  494. package/out/zero-solid/src/use-zero.js.map +1 -1
  495. package/out/zero-solid/src/zero.js +1 -1
  496. package/out/zero-types/src/format.js.map +1 -1
  497. package/out/zero-types/src/name-mapper.js.map +1 -1
  498. package/out/zql/src/builder/builder.js.map +1 -1
  499. package/out/zql/src/builder/debug-delegate.d.ts +5 -0
  500. package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
  501. package/out/zql/src/builder/debug-delegate.js +10 -1
  502. package/out/zql/src/builder/debug-delegate.js.map +1 -1
  503. package/out/zql/src/builder/filter.d.ts.map +1 -1
  504. package/out/zql/src/builder/filter.js +5 -4
  505. package/out/zql/src/builder/filter.js.map +1 -1
  506. package/out/zql/src/builder/like.js +1 -1
  507. package/out/zql/src/builder/like.js.map +1 -1
  508. package/out/zql/src/error.js.map +1 -1
  509. package/out/zql/src/ivm/array-view.d.ts.map +1 -1
  510. package/out/zql/src/ivm/array-view.js +5 -3
  511. package/out/zql/src/ivm/array-view.js.map +1 -1
  512. package/out/zql/src/ivm/cap.js.map +1 -1
  513. package/out/zql/src/ivm/change.js.map +1 -1
  514. package/out/zql/src/ivm/constraint.js +1 -1
  515. package/out/zql/src/ivm/constraint.js.map +1 -1
  516. package/out/zql/src/ivm/data.js.map +1 -1
  517. package/out/zql/src/ivm/exists.js.map +1 -1
  518. package/out/zql/src/ivm/fan-in.js.map +1 -1
  519. package/out/zql/src/ivm/fan-out.js.map +1 -1
  520. package/out/zql/src/ivm/filter-operators.js.map +1 -1
  521. package/out/zql/src/ivm/filter-push.js.map +1 -1
  522. package/out/zql/src/ivm/filter.js.map +1 -1
  523. package/out/zql/src/ivm/flipped-join.d.ts +4 -8
  524. package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
  525. package/out/zql/src/ivm/flipped-join.js +59 -63
  526. package/out/zql/src/ivm/flipped-join.js.map +1 -1
  527. package/out/zql/src/ivm/join-utils.js.map +1 -1
  528. package/out/zql/src/ivm/join.js.map +1 -1
  529. package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
  530. package/out/zql/src/ivm/memory-source.js.map +1 -1
  531. package/out/zql/src/ivm/memory-storage.js.map +1 -1
  532. package/out/zql/src/ivm/operator.d.ts +1 -1
  533. package/out/zql/src/ivm/operator.js.map +1 -1
  534. package/out/zql/src/ivm/push-accumulated.js.map +1 -1
  535. package/out/zql/src/ivm/schema.d.ts +0 -8
  536. package/out/zql/src/ivm/schema.d.ts.map +1 -1
  537. package/out/zql/src/ivm/skip-yields.js.map +1 -1
  538. package/out/zql/src/ivm/skip.js.map +1 -1
  539. package/out/zql/src/ivm/source.js.map +1 -1
  540. package/out/zql/src/ivm/stream.js.map +1 -1
  541. package/out/zql/src/ivm/take.js.map +1 -1
  542. package/out/zql/src/ivm/union-fan-in.js.map +1 -1
  543. package/out/zql/src/ivm/union-fan-out.js.map +1 -1
  544. package/out/zql/src/ivm/view-apply-change.d.ts +57 -3
  545. package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
  546. package/out/zql/src/ivm/view-apply-change.js +296 -123
  547. package/out/zql/src/ivm/view-apply-change.js.map +1 -1
  548. package/out/zql/src/mutate/crud.js.map +1 -1
  549. package/out/zql/src/mutate/custom.js.map +1 -1
  550. package/out/zql/src/mutate/mutator-registry.js.map +1 -1
  551. package/out/zql/src/mutate/mutator.js.map +1 -1
  552. package/out/zql/src/planner/planner-builder.js.map +1 -1
  553. package/out/zql/src/planner/planner-connection.js.map +1 -1
  554. package/out/zql/src/planner/planner-constraint.js.map +1 -1
  555. package/out/zql/src/planner/planner-debug.js.map +1 -1
  556. package/out/zql/src/planner/planner-fan-in.js.map +1 -1
  557. package/out/zql/src/planner/planner-fan-out.js.map +1 -1
  558. package/out/zql/src/planner/planner-graph.js.map +1 -1
  559. package/out/zql/src/planner/planner-join.d.ts.map +1 -1
  560. package/out/zql/src/planner/planner-join.js +2 -1
  561. package/out/zql/src/planner/planner-join.js.map +1 -1
  562. package/out/zql/src/planner/planner-node.js.map +1 -1
  563. package/out/zql/src/planner/planner-source.js.map +1 -1
  564. package/out/zql/src/planner/planner-terminus.js.map +1 -1
  565. package/out/zql/src/query/complete-ordering.js.map +1 -1
  566. package/out/zql/src/query/create-builder.js.map +1 -1
  567. package/out/zql/src/query/error.js.map +1 -1
  568. package/out/zql/src/query/escape-like.js.map +1 -1
  569. package/out/zql/src/query/expression.js.map +1 -1
  570. package/out/zql/src/query/measure-push-operator.js.map +1 -1
  571. package/out/zql/src/query/metrics-delegate.js.map +1 -1
  572. package/out/zql/src/query/named.js.map +1 -1
  573. package/out/zql/src/query/query-delegate-base.js +1 -3
  574. package/out/zql/src/query/query-delegate-base.js.map +1 -1
  575. package/out/zql/src/query/query-impl.js.map +1 -1
  576. package/out/zql/src/query/query-internals.js.map +1 -1
  577. package/out/zql/src/query/query-registry.js.map +1 -1
  578. package/out/zql/src/query/runnable-query-impl.js.map +1 -1
  579. package/out/zql/src/query/static-query.js.map +1 -1
  580. package/out/zql/src/query/ttl.js.map +1 -1
  581. package/out/zql/src/query/validate-input.js.map +1 -1
  582. package/out/zqlite/src/database-storage.js.map +1 -1
  583. package/out/zqlite/src/db.d.ts.map +1 -1
  584. package/out/zqlite/src/db.js +1 -0
  585. package/out/zqlite/src/db.js.map +1 -1
  586. package/out/zqlite/src/explain-queries.js.map +1 -1
  587. package/out/zqlite/src/internal/sql-inline.js.map +1 -1
  588. package/out/zqlite/src/internal/sql.js.map +1 -1
  589. package/out/zqlite/src/internal/statement-cache.js.map +1 -1
  590. package/out/zqlite/src/query-builder.d.ts.map +1 -1
  591. package/out/zqlite/src/query-builder.js +12 -1
  592. package/out/zqlite/src/query-builder.js.map +1 -1
  593. package/out/zqlite/src/query-delegate.js.map +1 -1
  594. package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
  595. package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
  596. package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
  597. package/out/zqlite/src/table-source.d.ts.map +1 -1
  598. package/out/zqlite/src/table-source.js +6 -6
  599. package/out/zqlite/src/table-source.js.map +1 -1
  600. package/package.json +45 -28
  601. package/out/zero-client/src/util/socket.d.ts +0 -3
  602. package/out/zero-client/src/util/socket.d.ts.map +0 -1
  603. package/out/zero-client/src/util/socket.js +0 -8
  604. package/out/zero-client/src/util/socket.js.map +0 -1
  605. package/out/zero-schema/src/permissions.d.ts.map +0 -1
  606. package/out/zero-schema/src/permissions.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"diff.js","names":[],"sources":["../../../../../replicache/src/sync/diff.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {diff as btreeDiff} from '../btree/diff.ts';\nimport type {InternalDiff} from '../btree/node.ts';\nimport {allEntriesAsDiff, BTreeRead} from '../btree/read.ts';\nimport type {Read} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {commitFromHash, type Meta} from '../db/commit.ts';\nimport {readIndexesForRead} from '../db/read.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Interface allowing different diff functions to skip costly diff computations.\n */\nexport interface DiffComputationConfig {\n shouldComputeDiffs(): boolean;\n shouldComputeDiffsForIndex(name: string): boolean;\n}\n\n/**\n * The diffs in different indexes. The key of the map is the index name.\n * \"\" is used for the primary index.\n */\nexport class DiffsMap extends Map<string, InternalDiff> {\n override set(key: string, value: InternalDiff): this {\n if (value.length === 0) {\n return this;\n }\n return super.set(key, value);\n }\n}\n\n/**\n * Diffs the state of the db at two different hashes.\n * It will include the primary indexes as well as all the secondary indexes.\n */\nexport async function diff(\n oldHash: Hash,\n newHash: Hash,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const [oldCommit, newCommit] = await Promise.all([\n commitFromHash(oldHash, read),\n commitFromHash(newHash, read),\n ]);\n\n return diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion);\n}\n\n/**\n * Diffs the state of the db at two different commits.\n * It will include the primary indexes as well as all the secondary indexes.\n */\n// TODO: this should probably move to db/\nexport async function diffCommits(\n oldCommit: Commit<Meta>,\n newCommit: Commit<Meta>,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n const oldMap = new BTreeRead(read, formatVersion, oldCommit.valueHash);\n const newMap = new BTreeRead(read, formatVersion, newCommit.valueHash);\n const valueDiff = await btreeDiff(oldMap, newMap);\n diffsMap.set('', valueDiff);\n\n await addDiffsForIndexes(\n oldCommit,\n newCommit,\n read,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n\n return diffsMap;\n}\n\nexport async function addDiffsForIndexes(\n mainCommit: Commit<Meta>,\n syncCommit: Commit<Meta>,\n read: Read,\n diffsMap: DiffsMap,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n) {\n const oldIndexes = readIndexesForRead(mainCommit, read, formatVersion);\n const newIndexes = readIndexesForRead(syncCommit, read, formatVersion);\n\n for (const [oldIndexName, oldIndex] of oldIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(oldIndexName)) {\n continue;\n }\n\n const newIndex = newIndexes.get(oldIndexName);\n if (newIndex !== undefined) {\n assert(\n newIndex !== oldIndex,\n 'Expected newIndex to differ from oldIndex',\n );\n const diffs = await btreeDiff(oldIndex.map, newIndex.map);\n newIndexes.delete(oldIndexName);\n diffsMap.set(oldIndexName, diffs);\n } else {\n // old index name is not in the new indexes. All entries removed!\n const diffs = await allEntriesAsDiff(oldIndex.map, 'del');\n diffsMap.set(oldIndexName, diffs);\n }\n }\n\n for (const [newIndexName, newIndex] of newIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(newIndexName)) {\n continue;\n }\n // new index name is not in the old indexes. All keys added!\n const diffs = await allEntriesAsDiff(newIndex.map, 'add');\n diffsMap.set(newIndexName, diffs);\n }\n}\n"],"mappings":";;;;;;;;;;AA0BA,IAAa,WAAb,cAA8B,IAA0B;CACtD,IAAa,KAAa,OAA2B;AACnD,MAAI,MAAM,WAAW,EACnB,QAAO;AAET,SAAO,MAAM,IAAI,KAAK,MAAM;;;;;;;AAQhC,eAAsB,KACpB,SACA,SACA,MACA,YACA,eACmB;CACnB,MAAM,CAAC,WAAW,aAAa,MAAM,QAAQ,IAAI,CAC/C,eAAe,SAAS,KAAK,EAC7B,eAAe,SAAS,KAAK,CAC9B,CAAC;AAEF,QAAO,YAAY,WAAW,WAAW,MAAM,YAAY,cAAc;;;;;;AAQ3E,eAAsB,YACpB,WACA,WACA,MACA,YACA,eACmB;CACnB,MAAM,WAAW,IAAI,UAAU;AAC/B,KAAI,CAAC,WAAW,oBAAoB,CAClC,QAAO;CAKT,MAAM,YAAY,MAAM,OAFT,IAAI,UAAU,MAAM,eAAe,UAAU,UAAU,EACvD,IAAI,UAAU,MAAM,eAAe,UAAU,UAAU,CACrB;AACjD,UAAS,IAAI,IAAI,UAAU;AAE3B,OAAM,mBACJ,WACA,WACA,MACA,UACA,YACA,cACD;AAED,QAAO;;AAGT,eAAsB,mBACpB,YACA,YACA,MACA,UACA,YACA,eACA;CACA,MAAM,aAAa,mBAAmB,YAAY,MAAM,cAAc;CACtE,MAAM,aAAa,mBAAmB,YAAY,MAAM,cAAc;AAEtE,MAAK,MAAM,CAAC,cAAc,aAAa,YAAY;AACjD,MAAI,CAAC,WAAW,2BAA2B,aAAa,CACtD;EAGF,MAAM,WAAW,WAAW,IAAI,aAAa;AAC7C,MAAI,aAAa,KAAA,GAAW;AAC1B,UACE,aAAa,UACb,4CACD;GACD,MAAM,QAAQ,MAAM,OAAU,SAAS,KAAK,SAAS,IAAI;AACzD,cAAW,OAAO,aAAa;AAC/B,YAAS,IAAI,cAAc,MAAM;SAC5B;GAEL,MAAM,QAAQ,MAAM,iBAAiB,SAAS,KAAK,MAAM;AACzD,YAAS,IAAI,cAAc,MAAM;;;AAIrC,MAAK,MAAM,CAAC,cAAc,aAAa,YAAY;AACjD,MAAI,CAAC,WAAW,2BAA2B,aAAa,CACtD;EAGF,MAAM,QAAQ,MAAM,iBAAiB,SAAS,KAAK,MAAM;AACzD,WAAS,IAAI,cAAc,MAAM"}
1
+ {"version":3,"file":"diff.js","names":[],"sources":["../../../../../replicache/src/sync/diff.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {diff as btreeDiff} from '../btree/diff.ts';\nimport type {InternalDiff} from '../btree/node.ts';\nimport {allEntriesAsDiff, BTreeRead} from '../btree/read.ts';\nimport type {Read} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {commitFromHash, type Meta} from '../db/commit.ts';\nimport {readIndexesForRead} from '../db/read.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Interface allowing different diff functions to skip costly diff computations.\n */\nexport interface DiffComputationConfig {\n shouldComputeDiffs(): boolean;\n shouldComputeDiffsForIndex(name: string): boolean;\n}\n\n/**\n * The diffs in different indexes. The key of the map is the index name.\n * \"\" is used for the primary index.\n */\nexport class DiffsMap extends Map<string, InternalDiff> {\n override set(key: string, value: InternalDiff): this {\n if (value.length === 0) {\n return this;\n }\n return super.set(key, value);\n }\n}\n\n/**\n * Diffs the state of the db at two different hashes.\n * It will include the primary indexes as well as all the secondary indexes.\n */\nexport async function diff(\n oldHash: Hash,\n newHash: Hash,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const [oldCommit, newCommit] = await Promise.all([\n commitFromHash(oldHash, read),\n commitFromHash(newHash, read),\n ]);\n\n return diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion);\n}\n\n/**\n * Diffs the state of the db at two different commits.\n * It will include the primary indexes as well as all the secondary indexes.\n */\n// TODO: this should probably move to db/\nexport async function diffCommits(\n oldCommit: Commit<Meta>,\n newCommit: Commit<Meta>,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n const oldMap = new BTreeRead(read, formatVersion, oldCommit.valueHash);\n const newMap = new BTreeRead(read, formatVersion, newCommit.valueHash);\n const valueDiff = await btreeDiff(oldMap, newMap);\n diffsMap.set('', valueDiff);\n\n await addDiffsForIndexes(\n oldCommit,\n newCommit,\n read,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n\n return diffsMap;\n}\n\nexport async function addDiffsForIndexes(\n mainCommit: Commit<Meta>,\n syncCommit: Commit<Meta>,\n read: Read,\n diffsMap: DiffsMap,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n) {\n const oldIndexes = readIndexesForRead(mainCommit, read, formatVersion);\n const newIndexes = readIndexesForRead(syncCommit, read, formatVersion);\n\n for (const [oldIndexName, oldIndex] of oldIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(oldIndexName)) {\n continue;\n }\n\n const newIndex = newIndexes.get(oldIndexName);\n if (newIndex !== undefined) {\n assert(\n newIndex !== oldIndex,\n 'Expected newIndex to differ from oldIndex',\n );\n const diffs = await btreeDiff(oldIndex.map, newIndex.map);\n newIndexes.delete(oldIndexName);\n diffsMap.set(oldIndexName, diffs);\n } else {\n // old index name is not in the new indexes. All entries removed!\n const diffs = await allEntriesAsDiff(oldIndex.map, 'del');\n diffsMap.set(oldIndexName, diffs);\n }\n }\n\n for (const [newIndexName, newIndex] of newIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(newIndexName)) {\n continue;\n }\n // new index name is not in the old indexes. All keys added!\n const diffs = await allEntriesAsDiff(newIndex.map, 'add');\n diffsMap.set(newIndexName, diffs);\n }\n}\n"],"mappings":";;;;;;;;;;AA0BA,IAAa,WAAb,cAA8B,IAA0B;CACtD,IAAa,KAAa,OAA2B;EACnD,IAAI,MAAM,WAAW,GACnB,OAAO;EAET,OAAO,MAAM,IAAI,KAAK,KAAK;CAC7B;AACF;;;;;AAMA,eAAsB,KACpB,SACA,SACA,MACA,YACA,eACmB;CACnB,MAAM,CAAC,WAAW,aAAa,MAAM,QAAQ,IAAI,CAC/C,eAAe,SAAS,IAAI,GAC5B,eAAe,SAAS,IAAI,CAC9B,CAAC;CAED,OAAO,YAAY,WAAW,WAAW,MAAM,YAAY,aAAa;AAC1E;;;;;AAOA,eAAsB,YACpB,WACA,WACA,MACA,YACA,eACmB;CACnB,MAAM,WAAW,IAAI,SAAS;CAC9B,IAAI,CAAC,WAAW,mBAAmB,GACjC,OAAO;CAKT,MAAM,YAAY,MAAM,OAAU,IAFf,UAAU,MAAM,eAAe,UAAU,SAE1B,GAAQ,IADvB,UAAU,MAAM,eAAe,UAAU,SAClB,CAAM;CAChD,SAAS,IAAI,IAAI,SAAS;CAE1B,MAAM,mBACJ,WACA,WACA,MACA,UACA,YACA,aACF;CAEA,OAAO;AACT;AAEA,eAAsB,mBACpB,YACA,YACA,MACA,UACA,YACA,eACA;CACA,MAAM,aAAa,mBAAmB,YAAY,MAAM,aAAa;CACrE,MAAM,aAAa,mBAAmB,YAAY,MAAM,aAAa;CAErE,KAAK,MAAM,CAAC,cAAc,aAAa,YAAY;EACjD,IAAI,CAAC,WAAW,2BAA2B,YAAY,GACrD;EAGF,MAAM,WAAW,WAAW,IAAI,YAAY;EAC5C,IAAI,aAAa,KAAA,GAAW;GAC1B,OACE,aAAa,UACb,2CACF;GACA,MAAM,QAAQ,MAAM,OAAU,SAAS,KAAK,SAAS,GAAG;GACxD,WAAW,OAAO,YAAY;GAC9B,SAAS,IAAI,cAAc,KAAK;EAClC,OAAO;GAEL,MAAM,QAAQ,MAAM,iBAAiB,SAAS,KAAK,KAAK;GACxD,SAAS,IAAI,cAAc,KAAK;EAClC;CACF;CAEA,KAAK,MAAM,CAAC,cAAc,aAAa,YAAY;EACjD,IAAI,CAAC,WAAW,2BAA2B,YAAY,GACrD;EAGF,MAAM,QAAQ,MAAM,iBAAiB,SAAS,KAAK,KAAK;EACxD,SAAS,IAAI,cAAc,KAAK;CAClC;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"ids.js","names":[],"sources":["../../../../../replicache/src/sync/ids.ts"],"sourcesContent":["import * as valita from '../../../shared/src/valita.ts';\n\n/**\n * The ID describing a group of clients. All clients in the same group share a\n * persistent storage (IDB).\n */\nexport type ClientGroupID = string;\n\nexport const clientGroupIDSchema: valita.Type<ClientGroupID> = valita.string();\n\n/**\n * The ID describing a client.\n */\nexport type ClientID = string;\n\nexport const clientIDSchema: valita.Type<ClientID> = valita.string();\n"],"mappings":";;AAQA,IAAa,sBAAkD,eAAO,QAAQ;AAO9E,IAAa,iBAAwC,eAAO,QAAQ"}
1
+ {"version":3,"file":"ids.js","names":[],"sources":["../../../../../replicache/src/sync/ids.ts"],"sourcesContent":["import * as valita from '../../../shared/src/valita.ts';\n\n/**\n * The ID describing a group of clients. All clients in the same group share a\n * persistent storage (IDB).\n */\nexport type ClientGroupID = string;\n\nexport const clientGroupIDSchema: valita.Type<ClientGroupID> = valita.string();\n\n/**\n * The ID describing a client.\n */\nexport type ClientID = string;\n\nexport const clientIDSchema: valita.Type<ClientID> = valita.string();\n"],"mappings":";;AAQA,IAAa,sBAAkD,eAAO,OAAO;AAO7E,IAAa,iBAAwC,eAAO,OAAO"}
@@ -1 +1 @@
1
- {"version":3,"file":"patch.js","names":[],"sources":["../../../../../replicache/src/sync/patch.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {compareUTF8} from 'compare-utf8';\nimport {assertObject} from '../../../shared/src/asserts.ts';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport type {DiffOperation} from '../btree/node.ts';\nimport type {Write} from '../db/write.ts';\nimport {\n type FrozenJSONObject,\n type FrozenJSONValue,\n deepFreeze,\n} from '../frozen-json.ts';\nimport type {PatchOperationInternal} from '../patch-operation.ts';\n\nexport type Diff =\n | DiffOperation<string>\n | {\n op: 'clear';\n };\n\n/**\n * Optimizes a patch array by:\n * 1. Dropping all operations before the last 'clear'\n * 2. For each key: put/del replace all previous operations\n * 3. Removing standalone 'del' operations after a clear (deleting from empty tree)\n * 4. Update are not used in Zero/Replicache so just return original patch.\n * Note: Order is preserved for operations on the same key, but operations\n * on different keys can be reordered.\n */\nexport function optimizePatch(\n patch: readonly PatchOperationInternal[],\n): readonly PatchOperationInternal[] {\n if (patch.length === 0) {\n return [];\n }\n\n // Build result array\n const result: PatchOperationInternal[] = [];\n\n // Find the last clear operation, add it to result, and track start index\n let i = 0;\n let clearIndex = -1;\n for (i = patch.length - 1; i >= 0; i--) {\n if (patch[i].op === 'clear') {\n result.push(patch[i]);\n clearIndex = i;\n break;\n }\n }\n // After loop: i is either the clear index (if found) or -1 (if not found)\n // Increment to get the start index for processing remaining operations\n i++;\n\n // Track operations for each key\n // del and put replace all previous operations\n // updates are not used so if we see one we return the original patch.\n const keyOps = new Map<string, PatchOperationInternal>();\n\n for (; i < patch.length; i++) {\n const p = patch[i];\n\n switch (p.op) {\n case 'put':\n case 'del': {\n // put and del replaces all previous operations on that key\n keyOps.set(p.key, p);\n break;\n }\n case 'update': {\n // 'update' is not used but to be safe just exit early.\n return clearIndex === -1 ? patch : patch.slice(clearIndex);\n }\n }\n }\n\n // Add all remaining key operations, but skip standalone del after clear\n for (const op of keyOps.values()) {\n // Skip standalone del operations after clear (deleting from empty tree is pointless)\n if (clearIndex !== -1 && op.op === 'del') {\n continue;\n }\n result.push(op);\n }\n\n return result.sort((a, b) => {\n if (a.op === 'clear') return -1;\n if (b.op === 'clear') return 1;\n return compareUTF8(a.key, b.key);\n });\n}\n\nexport async function apply(\n lc: LogContext,\n dbWrite: Write,\n patch: readonly PatchOperationInternal[],\n): Promise<void> {\n // Optimize the patch to remove redundant operations\n const optimized = optimizePatch(patch);\n\n let i = 0;\n\n // Handle clear if present (always at index 0 after optimization)\n if (optimized.length > 0 && optimized[0].op === 'clear') {\n await dbWrite.clear();\n i = 1;\n }\n\n // Check if we can bulk load put some operations\n const bulkLoadStart = i;\n while (i < optimized.length && optimized[i].op === 'put') {\n i++;\n }\n\n if (i > bulkLoadStart) {\n await bulkLoadPuts(lc, dbWrite, optimized.slice(bulkLoadStart, i));\n }\n\n // Apply remaining operations individually\n for (; i < optimized.length; i++) {\n const op = optimized[i];\n\n switch (op.op) {\n case 'put': {\n const frozen = deepFreeze(op.value);\n await dbWrite.put(lc, op.key, frozen);\n break;\n }\n case 'update': {\n const existing = await dbWrite.get(op.key);\n if (existing !== undefined) {\n assertObject(existing);\n }\n const frozen = mergeUpdate(op, existing);\n await dbWrite.put(lc, op.key, frozen);\n break;\n }\n case 'del': {\n const existing = await dbWrite.get(op.key);\n if (existing !== undefined) {\n await dbWrite.del(lc, op.key);\n }\n break;\n }\n }\n }\n}\n\nexport function mergeUpdate(\n op: Extract<PatchOperationInternal, {op: 'update'}>,\n existing: ReadonlyJSONObject | undefined,\n) {\n const entries: [string, FrozenJSONValue | ReadonlyJSONValue | undefined][] =\n [];\n const addToEntries = (toAdd: FrozenJSONObject | ReadonlyJSONObject) => {\n for (const [key, value] of Object.entries(toAdd)) {\n if (\n !op.constrain ||\n op.constrain.length === 0 ||\n op.constrain.includes(key)\n ) {\n entries.push([key, value]);\n }\n }\n };\n if (existing !== undefined) {\n addToEntries(existing);\n }\n if (op.merge) {\n addToEntries(op.merge);\n }\n return deepFreeze(Object.fromEntries(entries));\n}\n\nasync function bulkLoadPuts(\n lc: LogContext,\n dbWrite: Write,\n puts: readonly PatchOperationInternal[],\n): Promise<void> {\n if (puts.length === 0) {\n return;\n }\n\n // Sort entries by key for bulk loading\n const entries: [string, FrozenJSONValue][] = puts.map(p => {\n if (p.op !== 'put') {\n throw new Error('Expected put operation');\n }\n return [p.key, deepFreeze(p.value)];\n });\n\n // already sorted\n\n await dbWrite.putMany(lc, entries);\n}\n"],"mappings":";;;;;;;;;;;;;AA+BA,SAAgB,cACd,OACmC;AACnC,KAAI,MAAM,WAAW,EACnB,QAAO,EAAE;CAIX,MAAM,SAAmC,EAAE;CAG3C,IAAI,IAAI;CACR,IAAI,aAAa;AACjB,MAAK,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,IACjC,KAAI,MAAM,GAAG,OAAO,SAAS;AAC3B,SAAO,KAAK,MAAM,GAAG;AACrB,eAAa;AACb;;AAKJ;CAKA,MAAM,yBAAS,IAAI,KAAqC;AAExD,QAAO,IAAI,MAAM,QAAQ,KAAK;EAC5B,MAAM,IAAI,MAAM;AAEhB,UAAQ,EAAE,IAAV;GACE,KAAK;GACL,KAAK;AAEH,WAAO,IAAI,EAAE,KAAK,EAAE;AACpB;GAEF,KAAK,SAEH,QAAO,eAAe,KAAK,QAAQ,MAAM,MAAM,WAAW;;;AAMhE,MAAK,MAAM,MAAM,OAAO,QAAQ,EAAE;AAEhC,MAAI,eAAe,MAAM,GAAG,OAAO,MACjC;AAEF,SAAO,KAAK,GAAG;;AAGjB,QAAO,OAAO,MAAM,GAAG,MAAM;AAC3B,MAAI,EAAE,OAAO,QAAS,QAAO;AAC7B,MAAI,EAAE,OAAO,QAAS,QAAO;AAC7B,SAAO,YAAY,EAAE,KAAK,EAAE,IAAI;GAChC;;AAGJ,eAAsB,MACpB,IACA,SACA,OACe;CAEf,MAAM,YAAY,cAAc,MAAM;CAEtC,IAAI,IAAI;AAGR,KAAI,UAAU,SAAS,KAAK,UAAU,GAAG,OAAO,SAAS;AACvD,QAAM,QAAQ,OAAO;AACrB,MAAI;;CAIN,MAAM,gBAAgB;AACtB,QAAO,IAAI,UAAU,UAAU,UAAU,GAAG,OAAO,MACjD;AAGF,KAAI,IAAI,cACN,OAAM,aAAa,IAAI,SAAS,UAAU,MAAM,eAAe,EAAE,CAAC;AAIpE,QAAO,IAAI,UAAU,QAAQ,KAAK;EAChC,MAAM,KAAK,UAAU;AAErB,UAAQ,GAAG,IAAX;GACE,KAAK,OAAO;IACV,MAAM,SAAS,WAAW,GAAG,MAAM;AACnC,UAAM,QAAQ,IAAI,IAAI,GAAG,KAAK,OAAO;AACrC;;GAEF,KAAK,UAAU;IACb,MAAM,WAAW,MAAM,QAAQ,IAAI,GAAG,IAAI;AAC1C,QAAI,aAAa,KAAA,EACf,cAAa,SAAS;IAExB,MAAM,SAAS,YAAY,IAAI,SAAS;AACxC,UAAM,QAAQ,IAAI,IAAI,GAAG,KAAK,OAAO;AACrC;;GAEF,KAAK;AAEH,QADiB,MAAM,QAAQ,IAAI,GAAG,IAAI,KACzB,KAAA,EACf,OAAM,QAAQ,IAAI,IAAI,GAAG,IAAI;AAE/B;;;;AAMR,SAAgB,YACd,IACA,UACA;CACA,MAAM,UACJ,EAAE;CACJ,MAAM,gBAAgB,UAAiD;AACrE,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,KACE,CAAC,GAAG,aACJ,GAAG,UAAU,WAAW,KACxB,GAAG,UAAU,SAAS,IAAI,CAE1B,SAAQ,KAAK,CAAC,KAAK,MAAM,CAAC;;AAIhC,KAAI,aAAa,KAAA,EACf,cAAa,SAAS;AAExB,KAAI,GAAG,MACL,cAAa,GAAG,MAAM;AAExB,QAAO,WAAW,OAAO,YAAY,QAAQ,CAAC;;AAGhD,eAAe,aACb,IACA,SACA,MACe;AACf,KAAI,KAAK,WAAW,EAClB;CAIF,MAAM,UAAuC,KAAK,KAAI,MAAK;AACzD,MAAI,EAAE,OAAO,MACX,OAAM,IAAI,MAAM,yBAAyB;AAE3C,SAAO,CAAC,EAAE,KAAK,WAAW,EAAE,MAAM,CAAC;GACnC;AAIF,OAAM,QAAQ,QAAQ,IAAI,QAAQ"}
1
+ {"version":3,"file":"patch.js","names":[],"sources":["../../../../../replicache/src/sync/patch.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {compareUTF8} from 'compare-utf8';\nimport {assertObject} from '../../../shared/src/asserts.ts';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport type {DiffOperation} from '../btree/node.ts';\nimport type {Write} from '../db/write.ts';\nimport {\n type FrozenJSONObject,\n type FrozenJSONValue,\n deepFreeze,\n} from '../frozen-json.ts';\nimport type {PatchOperationInternal} from '../patch-operation.ts';\n\nexport type Diff =\n | DiffOperation<string>\n | {\n op: 'clear';\n };\n\n/**\n * Optimizes a patch array by:\n * 1. Dropping all operations before the last 'clear'\n * 2. For each key: put/del replace all previous operations\n * 3. Removing standalone 'del' operations after a clear (deleting from empty tree)\n * 4. Update are not used in Zero/Replicache so just return original patch.\n * Note: Order is preserved for operations on the same key, but operations\n * on different keys can be reordered.\n */\nexport function optimizePatch(\n patch: readonly PatchOperationInternal[],\n): readonly PatchOperationInternal[] {\n if (patch.length === 0) {\n return [];\n }\n\n // Build result array\n const result: PatchOperationInternal[] = [];\n\n // Find the last clear operation, add it to result, and track start index\n let i = 0;\n let clearIndex = -1;\n for (i = patch.length - 1; i >= 0; i--) {\n if (patch[i].op === 'clear') {\n result.push(patch[i]);\n clearIndex = i;\n break;\n }\n }\n // After loop: i is either the clear index (if found) or -1 (if not found)\n // Increment to get the start index for processing remaining operations\n i++;\n\n // Track operations for each key\n // del and put replace all previous operations\n // updates are not used so if we see one we return the original patch.\n const keyOps = new Map<string, PatchOperationInternal>();\n\n for (; i < patch.length; i++) {\n const p = patch[i];\n\n switch (p.op) {\n case 'put':\n case 'del': {\n // put and del replaces all previous operations on that key\n keyOps.set(p.key, p);\n break;\n }\n case 'update': {\n // 'update' is not used but to be safe just exit early.\n return clearIndex === -1 ? patch : patch.slice(clearIndex);\n }\n }\n }\n\n // Add all remaining key operations, but skip standalone del after clear\n for (const op of keyOps.values()) {\n // Skip standalone del operations after clear (deleting from empty tree is pointless)\n if (clearIndex !== -1 && op.op === 'del') {\n continue;\n }\n result.push(op);\n }\n\n return result.sort((a, b) => {\n if (a.op === 'clear') return -1;\n if (b.op === 'clear') return 1;\n return compareUTF8(a.key, b.key);\n });\n}\n\nexport async function apply(\n lc: LogContext,\n dbWrite: Write,\n patch: readonly PatchOperationInternal[],\n): Promise<void> {\n // Optimize the patch to remove redundant operations\n const optimized = optimizePatch(patch);\n\n let i = 0;\n\n // Handle clear if present (always at index 0 after optimization)\n if (optimized.length > 0 && optimized[0].op === 'clear') {\n await dbWrite.clear();\n i = 1;\n }\n\n // Check if we can bulk load put some operations\n const bulkLoadStart = i;\n while (i < optimized.length && optimized[i].op === 'put') {\n i++;\n }\n\n if (i > bulkLoadStart) {\n await bulkLoadPuts(lc, dbWrite, optimized.slice(bulkLoadStart, i));\n }\n\n // Apply remaining operations individually\n for (; i < optimized.length; i++) {\n const op = optimized[i];\n\n switch (op.op) {\n case 'put': {\n const frozen = deepFreeze(op.value);\n await dbWrite.put(lc, op.key, frozen);\n break;\n }\n case 'update': {\n const existing = await dbWrite.get(op.key);\n if (existing !== undefined) {\n assertObject(existing);\n }\n const frozen = mergeUpdate(op, existing);\n await dbWrite.put(lc, op.key, frozen);\n break;\n }\n case 'del': {\n const existing = await dbWrite.get(op.key);\n if (existing !== undefined) {\n await dbWrite.del(lc, op.key);\n }\n break;\n }\n }\n }\n}\n\nexport function mergeUpdate(\n op: Extract<PatchOperationInternal, {op: 'update'}>,\n existing: ReadonlyJSONObject | undefined,\n) {\n const entries: [string, FrozenJSONValue | ReadonlyJSONValue | undefined][] =\n [];\n const addToEntries = (toAdd: FrozenJSONObject | ReadonlyJSONObject) => {\n for (const [key, value] of Object.entries(toAdd)) {\n if (\n !op.constrain ||\n op.constrain.length === 0 ||\n op.constrain.includes(key)\n ) {\n entries.push([key, value]);\n }\n }\n };\n if (existing !== undefined) {\n addToEntries(existing);\n }\n if (op.merge) {\n addToEntries(op.merge);\n }\n return deepFreeze(Object.fromEntries(entries));\n}\n\nasync function bulkLoadPuts(\n lc: LogContext,\n dbWrite: Write,\n puts: readonly PatchOperationInternal[],\n): Promise<void> {\n if (puts.length === 0) {\n return;\n }\n\n // Sort entries by key for bulk loading\n const entries: [string, FrozenJSONValue][] = puts.map(p => {\n if (p.op !== 'put') {\n throw new Error('Expected put operation');\n }\n return [p.key, deepFreeze(p.value)];\n });\n\n // already sorted\n\n await dbWrite.putMany(lc, entries);\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"pull-error.js","names":[],"sources":["../../../../../replicache/src/sync/pull-error.ts"],"sourcesContent":["/**\n * This error is thrown when the puller fails for any reason.\n */\n\nexport class PullError extends Error {\n name = 'PullError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to pull');\n this.causedBy = causedBy;\n }\n}\n"],"mappings":";;;;AAIA,IAAa,YAAb,cAA+B,MAAM;CACnC,OAAO;CAKP;CACA,YAAY,UAAkB;AAC5B,QAAM,iBAAiB;AACvB,OAAK,WAAW"}
1
+ {"version":3,"file":"pull-error.js","names":[],"sources":["../../../../../replicache/src/sync/pull-error.ts"],"sourcesContent":["/**\n * This error is thrown when the puller fails for any reason.\n */\n\nexport class PullError extends Error {\n name = 'PullError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to pull');\n this.causedBy = causedBy;\n }\n}\n"],"mappings":";;;;AAIA,IAAa,YAAb,cAA+B,MAAM;CACnC,OAAO;CAKP;CACA,YAAY,UAAkB;EAC5B,MAAM,gBAAgB;EACtB,KAAK,WAAW;CAClB;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"pull.js","names":[],"sources":["../../../../../replicache/src/sync/pull.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {diff} from '../btree/diff.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport {compareCookies, type Cookie} from '../cookies.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n localMutations,\n snapshotMetaParts,\n} from '../db/commit.ts';\nimport {newWriteSnapshotDD31} from '../db/write.ts';\nimport {isErrorResponse} from '../error-responses.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.ts';\nimport {assertPullerResultV1} from '../get-default-puller.ts';\nimport {emptyHash, type Hash} from '../hash.ts';\nimport type {HTTPRequestInfo} from '../http-request-info.ts';\nimport type {\n Puller,\n PullerResult,\n PullResponseOKV1Internal,\n PullResponseV1,\n} from '../puller.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.ts';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.ts';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './ids.ts';\nimport * as patch from './patch.ts';\nimport {PullError} from './pull-error.ts';\nimport {SYNC_HEAD_NAME} from './sync-head-name.ts';\n\ntype FormatVersion = (typeof FormatVersion)[keyof typeof FormatVersion];\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n );\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n assertPullerResultV1(pullerResult);\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<{\n syncHead: Hash;\n mainHead: Hash;\n oldMainHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const [syncHead, commits] = await Promise.all([\n commitFromHash(syncHeadHash, dagRead),\n localMutations(mainHeadHash, dagRead),\n ]);\n const syncHeadMutationIDs = new Map<ClientID, Promise<number>>();\n const pending: Commit<M>[] = [];\n // Kick off all mutation ID loads before awaiting.\n for (const commit of commits) {\n assert(\n commitIsLocalDD31(commit),\n 'Expected commit to be a local DD31 commit',\n );\n const cid = commit.meta.clientID;\n if (!syncHeadMutationIDs.has(cid)) {\n syncHeadMutationIDs.set(cid, syncHead.getMutationID(cid, dagRead));\n }\n }\n for (const commit of commits) {\n const cid = commit.meta.clientID;\n if (commit.meta.mutationID > (await syncHeadMutationIDs.get(cid)!)) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: mainHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n // main head was set to sync head\n const newMainHeadHash = syncHeadHash;\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: newMainHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pull.js","names":[],"sources":["../../../../../replicache/src/sync/pull.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {diff} from '../btree/diff.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport {compareCookies, type Cookie} from '../cookies.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n localMutations,\n snapshotMetaParts,\n} from '../db/commit.ts';\nimport {newWriteSnapshotDD31} from '../db/write.ts';\nimport {isErrorResponse} from '../error-responses.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.ts';\nimport {assertPullerResultV1} from '../get-default-puller.ts';\nimport {emptyHash, type Hash} from '../hash.ts';\nimport type {HTTPRequestInfo} from '../http-request-info.ts';\nimport type {\n Puller,\n PullerResult,\n PullResponseOKV1Internal,\n PullResponseV1,\n} from '../puller.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.ts';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.ts';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './ids.ts';\nimport * as patch from './patch.ts';\nimport {PullError} from './pull-error.ts';\nimport {SYNC_HEAD_NAME} from './sync-head-name.ts';\n\ntype FormatVersion = (typeof FormatVersion)[keyof typeof FormatVersion];\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n );\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n assertPullerResultV1(pullerResult);\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<{\n syncHead: Hash;\n mainHead: Hash;\n oldMainHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const [syncHead, commits] = await Promise.all([\n commitFromHash(syncHeadHash, dagRead),\n localMutations(mainHeadHash, dagRead),\n ]);\n const syncHeadMutationIDs = new Map<ClientID, Promise<number>>();\n const pending: Commit<M>[] = [];\n // Kick off all mutation ID loads before awaiting.\n for (const commit of commits) {\n assert(\n commitIsLocalDD31(commit),\n 'Expected commit to be a local DD31 commit',\n );\n const cid = commit.meta.clientID;\n if (!syncHeadMutationIDs.has(cid)) {\n syncHeadMutationIDs.set(cid, syncHead.getMutationID(cid, dagRead));\n }\n }\n for (const commit of commits) {\n const cid = commit.meta.clientID;\n if (commit.meta.mutationID > (await syncHeadMutationIDs.get(cid)!)) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: mainHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n // main head was set to sync head\n const newMainHeadHash = syncHeadHash;\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: newMainHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"push.js","names":[],"sources":["../../../../../replicache/src/sync/push.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {jsonSchema} from '../../../shared/src/json-schema.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n commitIsLocalDD31,\n localMutations,\n} from '../db/commit.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead} from '../with-transactions.ts';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.ts';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nexport type Mutation = MutationV1;\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV1;\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: FrozenJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n _clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n assert(\n pushVersion === PUSH_VERSION_DD31,\n 'Expected pushVersion to be PUSH_VERSION_DD31',\n );\n\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n const pushReq: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n"],"mappings":";;;;;;;;;AA6CA,IAAM,mBAA4C,eAAsB;CACtE,IAAI,eAAO,QAAQ;CACnB,MAAM,eAAO,QAAQ;CACrB,MAAM;CACN,WAAW,eAAO,QAAQ;CAC1B,UAAU;CACX,CAAC;AAoB0B,eAAO,OAAO;CACxC,aAAa,eAAO,QAAQ,EAAE;CAC9B,eAAe,eAAO,QAAQ;CAC9B,WAAW,eAAO,QAAQ;CAC1B,eAAe;CACf,WAAW,eAAO,MAAM,iBAAiB;CAC1C,CAAC;AAqBF,SAAS,YAAY,IAAqC;AACxD,QAAO;EACL,IAAI,GAAG;EACP,MAAM,GAAG;EACT,MAAM,GAAG;EACT,WAAW,GAAG;EACd,UAAU,GAAG;EACd;;AAGH,eAAsB,KACpB,WACA,OACA,IACA,WACA,eACA,WACA,QACA,eACA,aACmC;CAGnC,MAAM,UAAU,MAAM,SAAS,OAAO,OAAM,YAAW;EACrD,MAAM,eAAe,MAAM,QAAQ,QAAQ,kBAAkB;AAC7D,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,wBAAwB;AAE1C,SAAO,eAAe,cAAc,QAAQ;GAE5C;AAEF,KAAI,QAAQ,WAAW,EACrB;AAKF,SAAQ,SAAS;AAEjB,QACE,gBAAA,GACA,+CACD;CAED,MAAM,gBAAoC,EAAE;AAC5C,MAAK,MAAM,UAAU,QACnB,KAAI,kBAAkB,OAAO,CAC3B,eAAc,KAAK,YAAY,OAAO,KAAK,CAAC;KAE5C,OAAM,IAAI,MAAM,oCAAoC;AAGxD,QAAO,eAAe,uCAAuC;CAC7D,MAAM,UAAyB;EAC7B;EACA;EACA,WAAW;EACX,aAAA;EACA;EACD;AAED,IAAG,QAAQ,mBAAmB;CAC9B,MAAM,YAAY,KAAK,KAAK;CAC5B,MAAM,eAAe,MAAM,WAAW,QAAQ,SAAS,UAAU;AACjE,IAAG,QAAQ,wBAAwB,KAAK,KAAK,GAAG,WAAW,KAAK;AAChE,QAAO;;AAGT,eAAe,WACb,QACA,MACA,WACuB;CACvB,IAAI;AACJ,KAAI;AACF,iBAAe,MAAM,OAAO,MAAM,UAAU;UACrC,GAAG;AACV,QAAM,IAAI,UAAU,QAAQ,EAAE,CAAC;;AAEjC,KAAI;AACF,qBAAmB,aAAa;AAChC,SAAO;UACA,GAAG;AACV,QAAM,IAAI,YAAY,yBAAyB,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"push.js","names":[],"sources":["../../../../../replicache/src/sync/push.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {jsonSchema} from '../../../shared/src/json-schema.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n commitIsLocalDD31,\n localMutations,\n} from '../db/commit.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead} from '../with-transactions.ts';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.ts';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nexport type Mutation = MutationV1;\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV1;\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: FrozenJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n _clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n assert(\n pushVersion === PUSH_VERSION_DD31,\n 'Expected pushVersion to be PUSH_VERSION_DD31',\n );\n\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID, 'Expected clientGroupID to be defined');\n const pushReq: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n"],"mappings":";;;;;;;;;AA6CA,IAAM,mBAA4C,eAAsB;CACtE,IAAI,eAAO,OAAO;CAClB,MAAM,eAAO,OAAO;CACpB,MAAM;CACN,WAAW,eAAO,OAAO;CACzB,UAAU;AACZ,CAAC;AAoB2B,eAAO,OAAO;CACxC,aAAa,eAAO,QAAQ,CAAC;CAC7B,eAAe,eAAO,OAAO;CAC7B,WAAW,eAAO,OAAO;CACzB,eAAe;CACf,WAAW,eAAO,MAAM,gBAAgB;AAC1C,CAAC;AAqBD,SAAS,YAAY,IAAqC;CACxD,OAAO;EACL,IAAI,GAAG;EACP,MAAM,GAAG;EACT,MAAM,GAAG;EACT,WAAW,GAAG;EACd,UAAU,GAAG;CACf;AACF;AAEA,eAAsB,KACpB,WACA,OACA,IACA,WACA,eACA,WACA,QACA,eACA,aACmC;CAGnC,MAAM,UAAU,MAAM,SAAS,OAAO,OAAM,YAAW;EACrD,MAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;EAC5D,IAAI,CAAC,cACH,MAAM,IAAI,MAAM,uBAAuB;EAEzC,OAAO,eAAe,cAAc,OAAO;CAE7C,CAAC;CAED,IAAI,QAAQ,WAAW,GACrB;CAKF,QAAQ,QAAQ;CAEhB,OACE,gBAAA,GACA,8CACF;CAEA,MAAM,gBAAoC,CAAC;CAC3C,KAAK,MAAM,UAAU,SACnB,IAAI,kBAAkB,MAAM,GAC1B,cAAc,KAAK,YAAY,OAAO,IAAI,CAAC;MAE3C,MAAM,IAAI,MAAM,mCAAmC;CAGvD,OAAO,eAAe,sCAAsC;CAC5D,MAAM,UAAyB;EAC7B;EACA;EACA,WAAW;EACX,aAAA;EACA;CACF;CAEA,GAAG,QAAQ,kBAAkB;CAC7B,MAAM,YAAY,KAAK,IAAI;CAC3B,MAAM,eAAe,MAAM,WAAW,QAAQ,SAAS,SAAS;CAChE,GAAG,QAAQ,wBAAwB,KAAK,IAAI,IAAI,WAAW,IAAI;CAC/D,OAAO;AACT;AAEA,eAAe,WACb,QACA,MACA,WACuB;CACvB,IAAI;CACJ,IAAI;EACF,eAAe,MAAM,OAAO,MAAM,SAAS;CAC7C,SAAS,GAAG;EACV,MAAM,IAAI,UAAU,QAAQ,CAAC,CAAC;CAChC;CACA,IAAI;EACF,mBAAmB,YAAY;EAC/B,OAAO;CACT,SAAS,GAAG;EACV,MAAM,IAAI,YAAY,yBAAyB,QAAQ,CAAC,CAAC;CAC3D;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"request-id.js","names":[],"sources":["../../../../../replicache/src/sync/request-id.ts"],"sourcesContent":["import {getNonCryptoRandomValues} from '../../../shared/src/random-values.ts';\nimport type {ClientID} from './ids.ts';\n\nlet sessionID = '';\nfunction getSessionID() {\n if (sessionID === '') {\n const buf = new Uint8Array(4);\n getNonCryptoRandomValues(buf);\n sessionID = Array.from(buf, x => x.toString(16)).join('');\n }\n return sessionID;\n}\n\nconst REQUEST_COUNTERS: Map<string, number> = new Map();\n\n/**\n * Returns a new requestID of the form <client ID>-<session ID>-<request\n * count>. The request count enables one to find the request following or\n * preceding a given request. The sessionid scopes the request count, ensuring\n * the requestID is probabilistically unique across restarts (which is good\n * enough).\n */\nexport function newRequestID(clientID: ClientID): string {\n const counter = REQUEST_COUNTERS.get(clientID) ?? 0;\n REQUEST_COUNTERS.set(clientID, counter + 1);\n return `${clientID}-${getSessionID()}-${counter}`;\n}\n"],"mappings":";;AAGA,IAAI,YAAY;AAChB,SAAS,eAAe;AACtB,KAAI,cAAc,IAAI;EACpB,MAAM,MAAM,IAAI,WAAW,EAAE;AAC7B,2BAAyB,IAAI;AAC7B,cAAY,MAAM,KAAK,MAAK,MAAK,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,GAAG;;AAE3D,QAAO;;AAGT,IAAM,mCAAwC,IAAI,KAAK;;;;;;;;AASvD,SAAgB,aAAa,UAA4B;CACvD,MAAM,UAAU,iBAAiB,IAAI,SAAS,IAAI;AAClD,kBAAiB,IAAI,UAAU,UAAU,EAAE;AAC3C,QAAO,GAAG,SAAS,GAAG,cAAc,CAAC,GAAG"}
1
+ {"version":3,"file":"request-id.js","names":[],"sources":["../../../../../replicache/src/sync/request-id.ts"],"sourcesContent":["import {getNonCryptoRandomValues} from '../../../shared/src/random-values.ts';\nimport type {ClientID} from './ids.ts';\n\nlet sessionID = '';\nfunction getSessionID() {\n if (sessionID === '') {\n const buf = new Uint8Array(4);\n getNonCryptoRandomValues(buf);\n sessionID = Array.from(buf, x => x.toString(16)).join('');\n }\n return sessionID;\n}\n\nconst REQUEST_COUNTERS: Map<string, number> = new Map();\n\n/**\n * Returns a new requestID of the form <client ID>-<session ID>-<request\n * count>. The request count enables one to find the request following or\n * preceding a given request. The sessionid scopes the request count, ensuring\n * the requestID is probabilistically unique across restarts (which is good\n * enough).\n */\nexport function newRequestID(clientID: ClientID): string {\n const counter = REQUEST_COUNTERS.get(clientID) ?? 0;\n REQUEST_COUNTERS.set(clientID, counter + 1);\n return `${clientID}-${getSessionID()}-${counter}`;\n}\n"],"mappings":";;AAGA,IAAI,YAAY;AAChB,SAAS,eAAe;CACtB,IAAI,cAAc,IAAI;EACpB,MAAM,MAAM,IAAI,WAAW,CAAC;EAC5B,yBAAyB,GAAG;EAC5B,YAAY,MAAM,KAAK,MAAK,MAAK,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE;CAC1D;CACA,OAAO;AACT;AAEA,IAAM,mCAAwC,IAAI,IAAI;;;;;;;;AAStD,SAAgB,aAAa,UAA4B;CACvD,MAAM,UAAU,iBAAiB,IAAI,QAAQ,KAAK;CAClD,iBAAiB,IAAI,UAAU,UAAU,CAAC;CAC1C,OAAO,GAAG,SAAS,GAAG,aAAa,EAAE,GAAG;AAC1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"to-error.js","names":[],"sources":["../../../../replicache/src/to-error.ts"],"sourcesContent":["export function toError(e: unknown): Error {\n if (e instanceof Error) {\n return e;\n }\n return new Error(String(e));\n}\n"],"mappings":";AAAA,SAAgB,QAAQ,GAAmB;AACzC,KAAI,aAAa,MACf,QAAO;AAET,QAAO,IAAI,MAAM,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"to-error.js","names":[],"sources":["../../../../replicache/src/to-error.ts"],"sourcesContent":["export function toError(e: unknown): Error {\n if (e instanceof Error) {\n return e;\n }\n return new Error(String(e));\n}\n"],"mappings":";AAAA,SAAgB,QAAQ,GAAmB;CACzC,IAAI,aAAa,OACf,OAAO;CAET,OAAO,IAAI,MAAM,OAAO,CAAC,CAAC;AAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"transaction-closed-error.js","names":[],"sources":["../../../../replicache/src/transaction-closed-error.ts"],"sourcesContent":["/**\n * This error is thrown when you try to call methods on a closed transaction.\n */\nexport class TransactionClosedError extends Error {\n constructor() {\n super('Transaction is closed');\n }\n}\n\nexport type Closed = {closed: boolean};\n\nexport function throwIfClosed(tx: Closed): void {\n if (tx.closed) {\n throw new TransactionClosedError();\n }\n}\n\nexport function rejectIfClosed(tx: Closed): undefined | Promise<never> {\n return tx.closed ? Promise.reject(new TransactionClosedError()) : undefined;\n}\n"],"mappings":";;;;AAGA,IAAa,yBAAb,cAA4C,MAAM;CAChD,cAAc;AACZ,QAAM,wBAAwB;;;AAMlC,SAAgB,cAAc,IAAkB;AAC9C,KAAI,GAAG,OACL,OAAM,IAAI,wBAAwB;;AAItC,SAAgB,eAAe,IAAwC;AACrE,QAAO,GAAG,SAAS,QAAQ,OAAO,IAAI,wBAAwB,CAAC,GAAG,KAAA"}
1
+ {"version":3,"file":"transaction-closed-error.js","names":[],"sources":["../../../../replicache/src/transaction-closed-error.ts"],"sourcesContent":["/**\n * This error is thrown when you try to call methods on a closed transaction.\n */\nexport class TransactionClosedError extends Error {\n constructor() {\n super('Transaction is closed');\n }\n}\n\nexport type Closed = {closed: boolean};\n\nexport function throwIfClosed(tx: Closed): void {\n if (tx.closed) {\n throw new TransactionClosedError();\n }\n}\n\nexport function rejectIfClosed(tx: Closed): undefined | Promise<never> {\n return tx.closed ? Promise.reject(new TransactionClosedError()) : undefined;\n}\n"],"mappings":";;;;AAGA,IAAa,yBAAb,cAA4C,MAAM;CAChD,cAAc;EACZ,MAAM,uBAAuB;CAC/B;AACF;AAIA,SAAgB,cAAc,IAAkB;CAC9C,IAAI,GAAG,QACL,MAAM,IAAI,uBAAuB;AAErC;AAEA,SAAgB,eAAe,IAAwC;CACrE,OAAO,GAAG,SAAS,QAAQ,OAAO,IAAI,uBAAuB,CAAC,IAAI,KAAA;AACpE"}
@@ -1 +1 @@
1
- {"version":3,"file":"transactions.js","names":["#keys","#scans","#tx"],"sources":["../../../../replicache/src/transactions.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {greaterThan} from 'compare-utf8';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {type IndexKey, decodeIndexKey} from './db/index.ts';\nimport type {Read} from './db/read.ts';\nimport type {Write} from './db/write.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport type {IndexDefinition} from './index-defs.ts';\nimport type {ZeroTxData} from './replicache-options.ts';\nimport type {ScanResult} from './scan-iterator.ts';\nimport {ScanResultImpl, fromKeyForIndexScanInternal} from './scan-iterator.ts';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanNoIndexOptions,\n type ScanOptions,\n isScanIndexOptions,\n toDbScanOptions,\n} from './scan-options.ts';\nimport type {ScanSubscriptionInfo} from './subscriptions.ts';\nimport type {ClientID} from './sync/ids.ts';\nimport {rejectIfClosed, throwIfClosed} from './transaction-closed-error.ts';\n\nexport type TransactionEnvironment = 'client' | 'server';\nexport type TransactionLocation = TransactionEnvironment;\nexport type TransactionReason = 'initial' | 'rebase' | 'authoritative';\n\n/**\n * Basic deep readonly type. It works for {@link JSONValue}.\n */\nexport type DeepReadonly<T> = T extends\n | null\n | boolean\n | string\n | number\n | undefined\n ? T\n : DeepReadonlyObject<T>;\n\nexport type DeepReadonlyObject<T> = {\n readonly [K in keyof T]: DeepReadonly<T[K]>;\n};\n\n/**\n * ReadTransactions are used with {@link Replicache.query} and\n * {@link Replicache.subscribe} and allows read operations on the\n * database.\n */\nexport interface ReadTransaction {\n readonly clientID: ClientID;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n readonly location: TransactionLocation;\n\n /**\n * Get a single value from the database. If the `key` is not present this\n * returns `undefined`.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined>;\n\n /** Determines if a single `key` is present in the database. */\n has(key: string): Promise<boolean>;\n\n /** Whether the database is empty. */\n isEmpty(): Promise<boolean>;\n\n /**\n * Gets many values from the database. This returns a {@link ScanResult} which\n * implements `AsyncIterable`. It also has methods to iterate over the\n * {@link ScanResult.keys | keys} and {@link ScanResult.entries | entries}.\n *\n * If `options` has an `indexName`, then this does a scan over an index with\n * that name. A scan over an index uses a tuple for the key consisting of\n * `[secondary: string, primary: string]`.\n *\n * If the {@link ScanResult} is used after the `ReadTransaction` has been closed\n * it will throw a {@link TransactionClosedError}.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n}\n\nlet transactionIDCounter = 0;\n\nexport class ReadTransactionImpl implements ReadTransaction {\n readonly clientID: ClientID;\n readonly dbtx: Read;\n protected readonly _lc: LogContext;\n\n /**\n * The location in which this transaction is being used. This is either `client` or `server`.\n */\n readonly location: TransactionLocation;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n\n constructor(\n clientID: ClientID,\n dbRead: Read,\n lc: LogContext,\n rpcName = 'openReadTransaction',\n ) {\n this.clientID = clientID;\n this.dbtx = dbRead;\n this._lc = lc\n .withContext(rpcName)\n .withContext('txid', transactionIDCounter++);\n this.environment = 'client';\n this.location = 'client';\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<V extends JSONValue>(key: string): Promise<DeepReadonly<V> | undefined> {\n return (\n rejectIfClosed(this.dbtx) ||\n (this.dbtx.get(key) as Promise<DeepReadonly<V> | undefined>)\n );\n }\n\n // oxlint-disable-next-line require-await\n async has(key: string): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.has(key);\n }\n\n // oxlint-disable-next-line require-await\n async isEmpty(): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.isEmpty();\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n return scan(options, this.dbtx, noop);\n }\n}\n\nfunction noop(_: unknown): void {\n // empty\n}\n\nfunction scan<Options extends ScanOptions, V extends JSONValue>(\n options: Options | undefined,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n const iter = getScanIterator<Options, V>(dbRead, options);\n return makeScanResultFromScanIteratorInternal(\n iter,\n options ?? ({} as Options),\n dbRead,\n onLimitKey,\n );\n}\n\n// An implementation of ReadTransaction that keeps track of `keys` and `scans`\n// for use with Subscriptions.\nexport class SubscriptionTransactionWrapper implements ReadTransaction {\n readonly #keys: Set<string> = new Set();\n readonly #scans: ScanSubscriptionInfo[] = [];\n readonly #tx: ReadTransactionImpl;\n\n constructor(tx: ReadTransactionImpl) {\n this.#tx = tx;\n }\n\n get environment(): TransactionLocation {\n return this.#tx.location;\n }\n\n get location(): TransactionLocation {\n return this.#tx.location;\n }\n\n get clientID(): string {\n return this.#tx.clientID;\n }\n\n isEmpty(): Promise<boolean> {\n // Any change to the subscription requires rerunning it.\n this.#scans.push({options: {}});\n return this.#tx.isEmpty();\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined> {\n this.#keys.add(key);\n return this.#tx.get(key) as Promise<DeepReadonly<T> | undefined>;\n }\n\n has(key: string): Promise<boolean> {\n this.#keys.add(key);\n return this.#tx.has(key);\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n const scanInfo: ScanSubscriptionInfo = {\n options: toDbScanOptions(options),\n inclusiveLimitKey: undefined,\n };\n this.#scans.push(scanInfo);\n return scan(options, this.#tx.dbtx, inclusiveLimitKey => {\n scanInfo.inclusiveLimitKey = inclusiveLimitKey;\n });\n }\n\n get keys(): ReadonlySet<string> {\n return this.#keys;\n }\n\n get scans(): ScanSubscriptionInfo[] {\n return this.#scans;\n }\n}\n\n/**\n * WriteTransactions are used with *mutators* which are registered using\n * {@link ReplicacheOptions.mutators} and allows read and write operations on the\n * database.\n */\nexport interface WriteTransaction extends ReadTransaction {\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction. This can be `initial`, `rebase` or `authoriative`.\n */\n readonly reason: TransactionReason;\n\n /**\n * Sets a single `value` in the database. The value will be frozen (using\n * `Object.freeze`) in debug mode.\n */\n set(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * @deprecated Use {@link WriteTransaction.set} instead.\n */\n put(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * Removes a `key` and its value from the database. Returns `true` if there was a\n * `key` to remove.\n */\n del(key: string): Promise<boolean>;\n}\n\n// Internal symbol, not exported by Replicache\n// but accessible to Zero.\nexport const zeroData = Symbol();\n\nexport class WriteTransactionImpl\n extends ReadTransactionImpl\n implements WriteTransaction\n{\n // use `declare` to specialize the type.\n declare readonly dbtx: Write;\n readonly reason: TransactionReason;\n readonly mutationID: number;\n readonly [zeroData]: ZeroTxData | undefined;\n\n constructor(\n clientID: ClientID,\n mutationID: number,\n reason: TransactionReason,\n zData: ZeroTxData | undefined,\n dbWrite: Write,\n lc: LogContext,\n rpcName = 'openWriteTransaction',\n ) {\n super(clientID, dbWrite, lc, rpcName);\n this.mutationID = mutationID;\n this.reason = reason;\n this[zeroData] = zData;\n }\n\n put(key: string, value: ReadonlyJSONValue): Promise<void> {\n return this.set(key, value);\n }\n\n async set(key: string, value: ReadonlyJSONValue): Promise<void> {\n throwIfClosed(this.dbtx);\n await this.dbtx.put(this._lc, key, deepFreeze(value));\n }\n\n del(key: string): Promise<boolean> {\n return rejectIfClosed(this.dbtx) ?? this.dbtx.del(this._lc, key);\n }\n}\n\nexport type CreateIndexDefinition = IndexDefinition & {name: string};\n\ntype Entry<Key, Value> = readonly [key: Key, value: Value];\n\ntype IndexKeyEntry<Value> = Entry<IndexKey, Value>;\n\ntype StringKeyEntry<Value> = Entry<string, Value>;\n\nexport type EntryForOptions<\n Options extends ScanOptions,\n V,\n> = Options extends ScanIndexOptions ? IndexKeyEntry<V> : StringKeyEntry<V>;\n\nfunction getScanIterator<Options extends ScanOptions, V>(\n dbRead: Read,\n options: Options | undefined,\n): AsyncIterable<EntryForOptions<Options, V>> {\n if (options && isScanIndexOptions(options)) {\n return getScanIteratorForIndexMap(dbRead, options) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n }\n\n return dbRead.map.scan(fromKeyForNonIndexScan(options)) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n}\n\nexport function fromKeyForNonIndexScan(\n options: ScanNoIndexOptions | undefined,\n): string {\n if (!options) {\n return '';\n }\n\n const {prefix = '', start} = options;\n if (start && greaterThan(start.key, prefix)) {\n return start.key;\n }\n return prefix;\n}\n\nfunction makeScanResultFromScanIteratorInternal<\n Options extends ScanOptions,\n V extends JSONValue,\n>(\n iter: AsyncIterable<EntryForOptions<Options, V>>,\n options: Options,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n return new ScanResultImpl(iter, options, dbRead, onLimitKey);\n}\n\nasync function* getScanIteratorForIndexMap(\n dbRead: Read,\n options: ScanIndexOptions,\n): AsyncIterable<IndexKeyEntry<ReadonlyJSONValue>> {\n const map = dbRead.getMapForIndex(options.indexName);\n for await (const entry of map.scan(fromKeyForIndexScanInternal(options))) {\n yield [decodeIndexKey(entry[0]), entry[1]];\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"transactions.js","names":["#keys","#scans","#tx"],"sources":["../../../../replicache/src/transactions.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {greaterThan} from 'compare-utf8';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {type IndexKey, decodeIndexKey} from './db/index.ts';\nimport type {Read} from './db/read.ts';\nimport type {Write} from './db/write.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport type {IndexDefinition} from './index-defs.ts';\nimport type {ZeroTxData} from './replicache-options.ts';\nimport type {ScanResult} from './scan-iterator.ts';\nimport {ScanResultImpl, fromKeyForIndexScanInternal} from './scan-iterator.ts';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanNoIndexOptions,\n type ScanOptions,\n isScanIndexOptions,\n toDbScanOptions,\n} from './scan-options.ts';\nimport type {ScanSubscriptionInfo} from './subscriptions.ts';\nimport type {ClientID} from './sync/ids.ts';\nimport {rejectIfClosed, throwIfClosed} from './transaction-closed-error.ts';\n\nexport type TransactionEnvironment = 'client' | 'server';\nexport type TransactionLocation = TransactionEnvironment;\nexport type TransactionReason = 'initial' | 'rebase' | 'authoritative';\n\n/**\n * Basic deep readonly type. It works for {@link JSONValue}.\n */\nexport type DeepReadonly<T> = T extends\n | null\n | boolean\n | string\n | number\n | undefined\n ? T\n : DeepReadonlyObject<T>;\n\nexport type DeepReadonlyObject<T> = {\n readonly [K in keyof T]: DeepReadonly<T[K]>;\n};\n\n/**\n * ReadTransactions are used with {@link Replicache.query} and\n * {@link Replicache.subscribe} and allows read operations on the\n * database.\n */\nexport interface ReadTransaction {\n readonly clientID: ClientID;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n readonly location: TransactionLocation;\n\n /**\n * Get a single value from the database. If the `key` is not present this\n * returns `undefined`.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined>;\n\n /** Determines if a single `key` is present in the database. */\n has(key: string): Promise<boolean>;\n\n /** Whether the database is empty. */\n isEmpty(): Promise<boolean>;\n\n /**\n * Gets many values from the database. This returns a {@link ScanResult} which\n * implements `AsyncIterable`. It also has methods to iterate over the\n * {@link ScanResult.keys | keys} and {@link ScanResult.entries | entries}.\n *\n * If `options` has an `indexName`, then this does a scan over an index with\n * that name. A scan over an index uses a tuple for the key consisting of\n * `[secondary: string, primary: string]`.\n *\n * If the {@link ScanResult} is used after the `ReadTransaction` has been closed\n * it will throw a {@link TransactionClosedError}.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n}\n\nlet transactionIDCounter = 0;\n\nexport class ReadTransactionImpl implements ReadTransaction {\n readonly clientID: ClientID;\n readonly dbtx: Read;\n protected readonly _lc: LogContext;\n\n /**\n * The location in which this transaction is being used. This is either `client` or `server`.\n */\n readonly location: TransactionLocation;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n\n constructor(\n clientID: ClientID,\n dbRead: Read,\n lc: LogContext,\n rpcName = 'openReadTransaction',\n ) {\n this.clientID = clientID;\n this.dbtx = dbRead;\n this._lc = lc\n .withContext(rpcName)\n .withContext('txid', transactionIDCounter++);\n this.environment = 'client';\n this.location = 'client';\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<V extends JSONValue>(key: string): Promise<DeepReadonly<V> | undefined> {\n return (\n rejectIfClosed(this.dbtx) ||\n (this.dbtx.get(key) as Promise<DeepReadonly<V> | undefined>)\n );\n }\n\n // oxlint-disable-next-line require-await\n async has(key: string): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.has(key);\n }\n\n // oxlint-disable-next-line require-await\n async isEmpty(): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.isEmpty();\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n return scan(options, this.dbtx, noop);\n }\n}\n\nfunction noop(_: unknown): void {\n // empty\n}\n\nfunction scan<Options extends ScanOptions, V extends JSONValue>(\n options: Options | undefined,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n const iter = getScanIterator<Options, V>(dbRead, options);\n return makeScanResultFromScanIteratorInternal(\n iter,\n options ?? ({} as Options),\n dbRead,\n onLimitKey,\n );\n}\n\n// An implementation of ReadTransaction that keeps track of `keys` and `scans`\n// for use with Subscriptions.\nexport class SubscriptionTransactionWrapper implements ReadTransaction {\n readonly #keys: Set<string> = new Set();\n readonly #scans: ScanSubscriptionInfo[] = [];\n readonly #tx: ReadTransactionImpl;\n\n constructor(tx: ReadTransactionImpl) {\n this.#tx = tx;\n }\n\n get environment(): TransactionLocation {\n return this.#tx.location;\n }\n\n get location(): TransactionLocation {\n return this.#tx.location;\n }\n\n get clientID(): string {\n return this.#tx.clientID;\n }\n\n isEmpty(): Promise<boolean> {\n // Any change to the subscription requires rerunning it.\n this.#scans.push({options: {}});\n return this.#tx.isEmpty();\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined> {\n this.#keys.add(key);\n return this.#tx.get(key) as Promise<DeepReadonly<T> | undefined>;\n }\n\n has(key: string): Promise<boolean> {\n this.#keys.add(key);\n return this.#tx.has(key);\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n const scanInfo: ScanSubscriptionInfo = {\n options: toDbScanOptions(options),\n inclusiveLimitKey: undefined,\n };\n this.#scans.push(scanInfo);\n return scan(options, this.#tx.dbtx, inclusiveLimitKey => {\n scanInfo.inclusiveLimitKey = inclusiveLimitKey;\n });\n }\n\n get keys(): ReadonlySet<string> {\n return this.#keys;\n }\n\n get scans(): ScanSubscriptionInfo[] {\n return this.#scans;\n }\n}\n\n/**\n * WriteTransactions are used with *mutators* which are registered using\n * {@link ReplicacheOptions.mutators} and allows read and write operations on the\n * database.\n */\nexport interface WriteTransaction extends ReadTransaction {\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction. This can be `initial`, `rebase` or `authoriative`.\n */\n readonly reason: TransactionReason;\n\n /**\n * Sets a single `value` in the database. The value will be frozen (using\n * `Object.freeze`) in debug mode.\n */\n set(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * @deprecated Use {@link WriteTransaction.set} instead.\n */\n put(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * Removes a `key` and its value from the database. Returns `true` if there was a\n * `key` to remove.\n */\n del(key: string): Promise<boolean>;\n}\n\n// Internal symbol, not exported by Replicache\n// but accessible to Zero.\nexport const zeroData = Symbol();\n\nexport class WriteTransactionImpl\n extends ReadTransactionImpl\n implements WriteTransaction\n{\n // use `declare` to specialize the type.\n declare readonly dbtx: Write;\n readonly reason: TransactionReason;\n readonly mutationID: number;\n readonly [zeroData]: ZeroTxData | undefined;\n\n constructor(\n clientID: ClientID,\n mutationID: number,\n reason: TransactionReason,\n zData: ZeroTxData | undefined,\n dbWrite: Write,\n lc: LogContext,\n rpcName = 'openWriteTransaction',\n ) {\n super(clientID, dbWrite, lc, rpcName);\n this.mutationID = mutationID;\n this.reason = reason;\n this[zeroData] = zData;\n }\n\n put(key: string, value: ReadonlyJSONValue): Promise<void> {\n return this.set(key, value);\n }\n\n async set(key: string, value: ReadonlyJSONValue): Promise<void> {\n throwIfClosed(this.dbtx);\n await this.dbtx.put(this._lc, key, deepFreeze(value));\n }\n\n del(key: string): Promise<boolean> {\n return rejectIfClosed(this.dbtx) ?? this.dbtx.del(this._lc, key);\n }\n}\n\nexport type CreateIndexDefinition = IndexDefinition & {name: string};\n\ntype Entry<Key, Value> = readonly [key: Key, value: Value];\n\ntype IndexKeyEntry<Value> = Entry<IndexKey, Value>;\n\ntype StringKeyEntry<Value> = Entry<string, Value>;\n\nexport type EntryForOptions<\n Options extends ScanOptions,\n V,\n> = Options extends ScanIndexOptions ? IndexKeyEntry<V> : StringKeyEntry<V>;\n\nfunction getScanIterator<Options extends ScanOptions, V>(\n dbRead: Read,\n options: Options | undefined,\n): AsyncIterable<EntryForOptions<Options, V>> {\n if (options && isScanIndexOptions(options)) {\n return getScanIteratorForIndexMap(dbRead, options) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n }\n\n return dbRead.map.scan(fromKeyForNonIndexScan(options)) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n}\n\nexport function fromKeyForNonIndexScan(\n options: ScanNoIndexOptions | undefined,\n): string {\n if (!options) {\n return '';\n }\n\n const {prefix = '', start} = options;\n if (start && greaterThan(start.key, prefix)) {\n return start.key;\n }\n return prefix;\n}\n\nfunction makeScanResultFromScanIteratorInternal<\n Options extends ScanOptions,\n V extends JSONValue,\n>(\n iter: AsyncIterable<EntryForOptions<Options, V>>,\n options: Options,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n return new ScanResultImpl(iter, options, dbRead, onLimitKey);\n}\n\nasync function* getScanIteratorForIndexMap(\n dbRead: Read,\n options: ScanIndexOptions,\n): AsyncIterable<IndexKeyEntry<ReadonlyJSONValue>> {\n const map = dbRead.getMapForIndex(options.indexName);\n for await (const entry of map.scan(fromKeyForIndexScanInternal(options))) {\n yield [decodeIndexKey(entry[0]), entry[1]];\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"with-transactions.js","names":[],"sources":["../../../../replicache/src/with-transactions.ts"],"sourcesContent":["export interface Release {\n release(): void;\n}\n\nexport interface Commit {\n commit(): Promise<void>;\n}\n\ninterface ReadStore<Read extends Release> {\n read(): Promise<Read>;\n}\n\ninterface WriteStore<Write extends Release> {\n write(): Promise<Write>;\n}\n\nexport function withRead<Read extends Release, Return>(\n store: ReadStore<Read>,\n fn: (read: Read) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.read(), fn);\n}\n\nexport function withWriteNoImplicitCommit<Write extends Release, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), fn);\n}\n\nexport function withWrite<Write extends Release & Commit, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), async write => {\n const result = await fn(write);\n await write.commit();\n return result;\n });\n}\n\n/**\n * This function takes a promise for a resource and a function that uses that\n * resource. It will release the resource after the function returns by calling\n * the `release` function\n */\nexport async function using<TX extends Release, Return>(\n x: Promise<TX>,\n fn: (tx: TX) => Return | Promise<Return>,\n): Promise<Return> {\n const write = await x;\n let result: Return | undefined;\n let operationError: unknown;\n try {\n result = await fn(write);\n } catch (e) {\n operationError = e;\n }\n\n try {\n write.release();\n } catch (releaseError) {\n if (operationError !== undefined) {\n const combinedError = new Error(\n `Transaction operation failed and release also failed: operation error = ${String(\n operationError,\n )}; release error = ${String(releaseError)}`,\n );\n combinedError.cause = operationError;\n throw combinedError;\n }\n throw releaseError;\n }\n\n if (operationError !== undefined) {\n throw operationError;\n }\n return result as Return;\n}\n"],"mappings":";AAgBA,SAAgB,SACd,OACA,IACiB;AACjB,QAAO,MAAM,MAAM,MAAM,EAAE,GAAG;;AAGhC,SAAgB,0BACd,OACA,IACiB;AACjB,QAAO,MAAM,MAAM,OAAO,EAAE,GAAG;;AAGjC,SAAgB,UACd,OACA,IACiB;AACjB,QAAO,MAAM,MAAM,OAAO,EAAE,OAAM,UAAS;EACzC,MAAM,SAAS,MAAM,GAAG,MAAM;AAC9B,QAAM,MAAM,QAAQ;AACpB,SAAO;GACP;;;;;;;AAQJ,eAAsB,MACpB,GACA,IACiB;CACjB,MAAM,QAAQ,MAAM;CACpB,IAAI;CACJ,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,GAAG,MAAM;UACjB,GAAG;AACV,mBAAiB;;AAGnB,KAAI;AACF,QAAM,SAAS;UACR,cAAc;AACrB,MAAI,mBAAmB,KAAA,GAAW;GAChC,MAAM,gCAAgB,IAAI,MACxB,2EAA2E,OACzE,eACD,CAAC,oBAAoB,OAAO,aAAa,GAC3C;AACD,iBAAc,QAAQ;AACtB,SAAM;;AAER,QAAM;;AAGR,KAAI,mBAAmB,KAAA,EACrB,OAAM;AAER,QAAO"}
1
+ {"version":3,"file":"with-transactions.js","names":[],"sources":["../../../../replicache/src/with-transactions.ts"],"sourcesContent":["export interface Release {\n release(): void;\n}\n\nexport interface Commit {\n commit(): Promise<void>;\n}\n\ninterface ReadStore<Read extends Release> {\n read(): Promise<Read>;\n}\n\ninterface WriteStore<Write extends Release> {\n write(): Promise<Write>;\n}\n\nexport function withRead<Read extends Release, Return>(\n store: ReadStore<Read>,\n fn: (read: Read) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.read(), fn);\n}\n\nexport function withWriteNoImplicitCommit<Write extends Release, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), fn);\n}\n\nexport function withWrite<Write extends Release & Commit, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), async write => {\n const result = await fn(write);\n await write.commit();\n return result;\n });\n}\n\n/**\n * This function takes a promise for a resource and a function that uses that\n * resource. It will release the resource after the function returns by calling\n * the `release` function\n */\nexport async function using<TX extends Release, Return>(\n x: Promise<TX>,\n fn: (tx: TX) => Return | Promise<Return>,\n): Promise<Return> {\n const write = await x;\n let result: Return | undefined;\n let operationError: unknown;\n try {\n result = await fn(write);\n } catch (e) {\n operationError = e;\n }\n\n try {\n write.release();\n } catch (releaseError) {\n if (operationError !== undefined) {\n const combinedError = new Error(\n `Transaction operation failed and release also failed: operation error = ${String(\n operationError,\n )}; release error = ${String(releaseError)}`,\n );\n combinedError.cause = operationError;\n throw combinedError;\n }\n throw releaseError;\n }\n\n if (operationError !== undefined) {\n throw operationError;\n }\n return result as Return;\n}\n"],"mappings":";AAgBA,SAAgB,SACd,OACA,IACiB;CACjB,OAAO,MAAM,MAAM,KAAK,GAAG,EAAE;AAC/B;AAEA,SAAgB,0BACd,OACA,IACiB;CACjB,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE;AAChC;AAEA,SAAgB,UACd,OACA,IACiB;CACjB,OAAO,MAAM,MAAM,MAAM,GAAG,OAAM,UAAS;EACzC,MAAM,SAAS,MAAM,GAAG,KAAK;EAC7B,MAAM,MAAM,OAAO;EACnB,OAAO;CACT,CAAC;AACH;;;;;;AAOA,eAAsB,MACpB,GACA,IACiB;CACjB,MAAM,QAAQ,MAAM;CACpB,IAAI;CACJ,IAAI;CACJ,IAAI;EACF,SAAS,MAAM,GAAG,KAAK;CACzB,SAAS,GAAG;EACV,iBAAiB;CACnB;CAEA,IAAI;EACF,MAAM,QAAQ;CAChB,SAAS,cAAc;EACrB,IAAI,mBAAmB,KAAA,GAAW;GAChC,MAAM,gCAAgB,IAAI,MACxB,2EAA2E,OACzE,cACF,EAAE,oBAAoB,OAAO,YAAY,GAC3C;GACA,cAAc,QAAQ;GACtB,MAAM;EACR;EACA,MAAM;CACR;CAEA,IAAI,mBAAmB,KAAA,GACrB,MAAM;CAER,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"abort-error.js","names":[],"sources":["../../../../shared/src/abort-error.ts"],"sourcesContent":["export class AbortError extends Error {\n name = 'AbortError';\n}\n"],"mappings":";AAAA,IAAa,aAAb,cAAgC,MAAM;CACpC,OAAO"}
1
+ {"version":3,"file":"abort-error.js","names":[],"sources":["../../../../shared/src/abort-error.ts"],"sourcesContent":["export class AbortError extends Error {\n name = 'AbortError';\n}\n"],"mappings":";AAAA,IAAa,aAAb,cAAgC,MAAM;CACpC,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"arrays.js","names":[],"sources":["../../../../shared/src/arrays.ts"],"sourcesContent":["import {assert} from './asserts.ts';\n\n/**\n * Returns `arr` as is if none of the elements are `undefined`.\n * Otherwise returns a new array with only defined elements in `arr`.\n */\nexport function defined<T>(arr: (T | undefined)[]): T[] {\n // avoid an array copy if possible\n let i = arr.findIndex(x => x === undefined);\n if (i < 0) {\n return arr as T[];\n }\n const defined: T[] = arr.slice(0, i) as T[];\n for (i++; i < arr.length; i++) {\n const x = arr[i];\n if (x !== undefined) {\n defined.push(x);\n }\n }\n return defined;\n}\n\nexport function areEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean {\n return arr1.length === arr2.length && arr1.every((e, i) => e === arr2[i]);\n}\n\nexport function zip<T1, T2>(a1: readonly T1[], a2: readonly T2[]): [T1, T2][] {\n assert(a1.length === a2.length, 'zip: arrays must have equal length');\n const result: [T1, T2][] = [];\n for (let i = 0; i < a1.length; i++) {\n result.push([a1[i], a2[i]]);\n }\n return result;\n}\n\nexport function last<T>(arr: T[]): T | undefined {\n return arr.at(-1);\n}\n\nexport function groupBy<T, K>(\n arr: readonly T[],\n keyFn: (el: T) => K,\n): Map<K, T[]> {\n const groups = new Map<K, T[]>();\n for (const el of arr) {\n const key = keyFn(el);\n let group = groups.get(key);\n if (group === undefined) {\n group = [];\n groups.set(key, group);\n }\n group.push(el);\n }\n return groups;\n}\n"],"mappings":";;;;;;AAMA,SAAgB,QAAW,KAA6B;CAEtD,IAAI,IAAI,IAAI,WAAU,MAAK,MAAM,KAAA,EAAU;AAC3C,KAAI,IAAI,EACN,QAAO;CAET,MAAM,UAAe,IAAI,MAAM,GAAG,EAAE;AACpC,MAAK,KAAK,IAAI,IAAI,QAAQ,KAAK;EAC7B,MAAM,IAAI,IAAI;AACd,MAAI,MAAM,KAAA,EACR,SAAQ,KAAK,EAAE;;AAGnB,QAAO;;AAGT,SAAgB,SAAY,MAAoB,MAA6B;AAC3E,QAAO,KAAK,WAAW,KAAK,UAAU,KAAK,OAAO,GAAG,MAAM,MAAM,KAAK,GAAG;;AAG3E,SAAgB,IAAY,IAAmB,IAA+B;AAC5E,QAAO,GAAG,WAAW,GAAG,QAAQ,qCAAqC;CACrE,MAAM,SAAqB,EAAE;AAC7B,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,IAC7B,QAAO,KAAK,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC;AAE7B,QAAO;;AAGT,SAAgB,KAAQ,KAAyB;AAC/C,QAAO,IAAI,GAAG,GAAG;;AAGnB,SAAgB,QACd,KACA,OACa;CACb,MAAM,yBAAS,IAAI,KAAa;AAChC,MAAK,MAAM,MAAM,KAAK;EACpB,MAAM,MAAM,MAAM,GAAG;EACrB,IAAI,QAAQ,OAAO,IAAI,IAAI;AAC3B,MAAI,UAAU,KAAA,GAAW;AACvB,WAAQ,EAAE;AACV,UAAO,IAAI,KAAK,MAAM;;AAExB,QAAM,KAAK,GAAG;;AAEhB,QAAO"}
1
+ {"version":3,"file":"arrays.js","names":[],"sources":["../../../../shared/src/arrays.ts"],"sourcesContent":["import {assert} from './asserts.ts';\n\n/**\n * Returns `arr` as is if none of the elements are `undefined`.\n * Otherwise returns a new array with only defined elements in `arr`.\n */\nexport function defined<T>(arr: (T | undefined)[]): T[] {\n // avoid an array copy if possible\n let i = arr.findIndex(x => x === undefined);\n if (i < 0) {\n return arr as T[];\n }\n const defined: T[] = arr.slice(0, i) as T[];\n for (i++; i < arr.length; i++) {\n const x = arr[i];\n if (x !== undefined) {\n defined.push(x);\n }\n }\n return defined;\n}\n\nexport function areEqual<T>(arr1: readonly T[], arr2: readonly T[]): boolean {\n return arr1.length === arr2.length && arr1.every((e, i) => e === arr2[i]);\n}\n\nexport function zip<T1, T2>(a1: readonly T1[], a2: readonly T2[]): [T1, T2][] {\n assert(a1.length === a2.length, 'zip: arrays must have equal length');\n const result: [T1, T2][] = [];\n for (let i = 0; i < a1.length; i++) {\n result.push([a1[i], a2[i]]);\n }\n return result;\n}\n\nexport function last<T>(arr: T[]): T | undefined {\n return arr.at(-1);\n}\n\nexport function groupBy<T, K>(\n arr: readonly T[],\n keyFn: (el: T) => K,\n): Map<K, T[]> {\n const groups = new Map<K, T[]>();\n for (const el of arr) {\n const key = keyFn(el);\n let group = groups.get(key);\n if (group === undefined) {\n group = [];\n groups.set(key, group);\n }\n group.push(el);\n }\n return groups;\n}\n"],"mappings":";;;;;;AAMA,SAAgB,QAAW,KAA6B;CAEtD,IAAI,IAAI,IAAI,WAAU,MAAK,MAAM,KAAA,CAAS;CAC1C,IAAI,IAAI,GACN,OAAO;CAET,MAAM,UAAe,IAAI,MAAM,GAAG,CAAC;CACnC,KAAK,KAAK,IAAI,IAAI,QAAQ,KAAK;EAC7B,MAAM,IAAI,IAAI;EACd,IAAI,MAAM,KAAA,GACR,QAAQ,KAAK,CAAC;CAElB;CACA,OAAO;AACT;AAEA,SAAgB,SAAY,MAAoB,MAA6B;CAC3E,OAAO,KAAK,WAAW,KAAK,UAAU,KAAK,OAAO,GAAG,MAAM,MAAM,KAAK,EAAE;AAC1E;AAEA,SAAgB,IAAY,IAAmB,IAA+B;CAC5E,OAAO,GAAG,WAAW,GAAG,QAAQ,oCAAoC;CACpE,MAAM,SAAqB,CAAC;CAC5B,KAAK,IAAI,IAAI,GAAG,IAAI,GAAG,QAAQ,KAC7B,OAAO,KAAK,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;CAE5B,OAAO;AACT;AAEA,SAAgB,KAAQ,KAAyB;CAC/C,OAAO,IAAI,GAAG,EAAE;AAClB;AAEA,SAAgB,QACd,KACA,OACa;CACb,MAAM,yBAAS,IAAI,IAAY;CAC/B,KAAK,MAAM,MAAM,KAAK;EACpB,MAAM,MAAM,MAAM,EAAE;EACpB,IAAI,QAAQ,OAAO,IAAI,GAAG;EAC1B,IAAI,UAAU,KAAA,GAAW;GACvB,QAAQ,CAAC;GACT,OAAO,IAAI,KAAK,KAAK;EACvB;EACA,MAAM,KAAK,EAAE;CACf;CACA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"asserts.js","names":[],"sources":["../../../../shared/src/asserts.ts"],"sourcesContent":["export function assert(b: unknown, msg: string | (() => string)): asserts b {\n if (!b) {\n throw new Error(typeof msg === 'string' ? msg : msg());\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n"],"mappings":";AAAA,SAAgB,OAAO,GAAY,KAAyC;AAC1E,KAAI,CAAC,EACH,OAAM,IAAI,MAAM,OAAO,QAAQ,WAAW,MAAM,KAAK,CAAC;;AAI1D,SAAgB,aAAa,GAAiC;AAC5D,YAAW,GAAG,SAAS;;AAGzB,SAAgB,aAAa,GAAiC;AAC5D,YAAW,GAAG,SAAS;;AAGzB,SAAgB,cAAc,GAAkC;AAC9D,YAAW,GAAG,UAAU;;AAG1B,SAAS,WAAW,GAAY,GAAW;AACzC,KAAI,OAAO,MAAM,EACf,kBAAiB,GAAG,EAAE;;AAI1B,SAAgB,aAAa,GAAkD;AAC7E,KAAI,MAAM,KACR,kBAAiB,GAAG,SAAS;AAE/B,YAAW,GAAG,SAAS;;AAGzB,SAAgB,YAAY,GAAoC;AAC9D,KAAI,CAAC,MAAM,QAAQ,EAAE,CACnB,kBAAiB,GAAG,QAAQ;;AAIhC,SAAgB,YAAY,GAAY,GAAmB;CACzD,IAAI,IAAI;AACR,KAAI,MAAM,QAAQ,MAAM,KAAA,EACtB,MAAK;KAEL,MAAK,GAAG,OAAO,EAAE,KAAK,EAAE;AAE1B,QAAO,IAAI,cAAc;;AAG3B,SAAgB,iBAAiB,GAAY,GAAkB;AAC7D,OAAM,IAAI,MAAM,YAAY,GAAG,EAAE,CAAC;;AAGpC,SAAgB,cAAiB,GAA6B;AAC5D,KAAI,MAAM,KACR,OAAM,IAAI,MAAM,0BAA0B;;AAa9C,SAAgB,mBACd,GACA,MAAM,gCACU;AAChB,KAAI,MAAM,KAAA,EACR,OAAM,IAAI,MAAM,IAAI;;AAmBxB,SAAgB,YAAY,GAAkB;AAC5C,OAAM,IAAI,MAAM,cAAc"}
1
+ {"version":3,"file":"asserts.js","names":[],"sources":["../../../../shared/src/asserts.ts"],"sourcesContent":["export function assert(b: unknown, msg: string | (() => string)): asserts b {\n if (!b) {\n throw new Error(typeof msg === 'string' ? msg : msg());\n }\n}\n\nexport function assertString(v: unknown): asserts v is string {\n assertType(v, 'string');\n}\n\nexport function assertNumber(v: unknown): asserts v is number {\n assertType(v, 'number');\n}\n\nexport function assertBoolean(v: unknown): asserts v is boolean {\n assertType(v, 'boolean');\n}\n\nfunction assertType(v: unknown, t: string) {\n if (typeof v !== t) {\n throwInvalidType(v, t);\n }\n}\n\nexport function assertObject(v: unknown): asserts v is Record<string, unknown> {\n if (v === null) {\n throwInvalidType(v, 'object');\n }\n assertType(v, 'object');\n}\n\nexport function assertArray(v: unknown): asserts v is unknown[] {\n if (!Array.isArray(v)) {\n throwInvalidType(v, 'array');\n }\n}\n\nexport function invalidType(v: unknown, t: string): string {\n let s = 'Invalid type: ';\n if (v === null || v === undefined) {\n s += v;\n } else {\n s += `${typeof v} \\`${v}\\``;\n }\n return s + `, expected ${t}`;\n}\n\nexport function throwInvalidType(v: unknown, t: string): never {\n throw new Error(invalidType(v, t));\n}\n\nexport function assertNotNull<T>(v: T | null): asserts v is T {\n if (v === null) {\n throw new Error('Expected non-null value');\n }\n}\n\nexport function assertUndefined<T>(\n v: T | undefined,\n msg = 'Expected undefined value',\n): asserts v is T {\n if (v !== undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertNotUndefined<T>(\n v: T | undefined,\n msg = 'Expected non undefined value',\n): asserts v is T {\n if (v === undefined) {\n throw new Error(msg);\n }\n}\n\nexport function assertInstanceof<T>(\n v: unknown,\n t: new (...args: unknown[]) => T,\n): asserts v is T {\n if (!(v instanceof t)) {\n throw new Error(`Expected instanceof ${t.name}`);\n }\n}\n\nexport function assertUint8Array(v: unknown): asserts v is Uint8Array {\n assertInstanceof(v, Uint8Array);\n}\n\nexport function unreachable(): never;\nexport function unreachable(v: never): never;\nexport function unreachable(_?: never): never {\n throw new Error('Unreachable');\n}\n\nexport function notImplemented(): never {\n throw new Error('Not implemented');\n}\n"],"mappings":";AAAA,SAAgB,OAAO,GAAY,KAAyC;CAC1E,IAAI,CAAC,GACH,MAAM,IAAI,MAAM,OAAO,QAAQ,WAAW,MAAM,IAAI,CAAC;AAEzD;AAEA,SAAgB,aAAa,GAAiC;CAC5D,WAAW,GAAG,QAAQ;AACxB;AAEA,SAAgB,aAAa,GAAiC;CAC5D,WAAW,GAAG,QAAQ;AACxB;AAEA,SAAgB,cAAc,GAAkC;CAC9D,WAAW,GAAG,SAAS;AACzB;AAEA,SAAS,WAAW,GAAY,GAAW;CACzC,IAAI,OAAO,MAAM,GACf,iBAAiB,GAAG,CAAC;AAEzB;AAEA,SAAgB,aAAa,GAAkD;CAC7E,IAAI,MAAM,MACR,iBAAiB,GAAG,QAAQ;CAE9B,WAAW,GAAG,QAAQ;AACxB;AAEA,SAAgB,YAAY,GAAoC;CAC9D,IAAI,CAAC,MAAM,QAAQ,CAAC,GAClB,iBAAiB,GAAG,OAAO;AAE/B;AAEA,SAAgB,YAAY,GAAY,GAAmB;CACzD,IAAI,IAAI;CACR,IAAI,MAAM,QAAQ,MAAM,KAAA,GACtB,KAAK;MAEL,KAAK,GAAG,OAAO,EAAE,KAAK,EAAE;CAE1B,OAAO,IAAI,cAAc;AAC3B;AAEA,SAAgB,iBAAiB,GAAY,GAAkB;CAC7D,MAAM,IAAI,MAAM,YAAY,GAAG,CAAC,CAAC;AACnC;AAEA,SAAgB,cAAiB,GAA6B;CAC5D,IAAI,MAAM,MACR,MAAM,IAAI,MAAM,yBAAyB;AAE7C;AAWA,SAAgB,mBACd,GACA,MAAM,gCACU;CAChB,IAAI,MAAM,KAAA,GACR,MAAM,IAAI,MAAM,GAAG;AAEvB;AAiBA,SAAgB,YAAY,GAAkB;CAC5C,MAAM,IAAI,MAAM,aAAa;AAC/B"}
@@ -1 +1 @@
1
- {"version":3,"file":"bigint-json.js","names":[],"sources":["../../../../shared/src/bigint-json.ts"],"sourcesContent":["/**\n * Background for using `json-custom-numbers`:\n *\n * https://neon.tech/blog/parsing-json-from-postgres-in-js\n */\nimport {\n parse as customParse,\n stringify as customStringify,\n} from 'json-custom-numbers';\nimport * as v from './valita.ts';\n\nfunction numberParser(_: unknown, v: string) {\n const n = +v;\n if (n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER) return n;\n if (v.includes('.') || v.includes('e') || v.includes('E')) {\n return n;\n }\n return BigInt(v);\n}\n\n// Variant of postgres.JSONValue adapted to include bigints\nexport type JSONValue =\n | null\n | string\n | number\n | bigint\n | boolean\n | readonly JSONValue[]\n | JSONObject;\n\nexport type JSONObject = {readonly [prop: string]: JSONValue | undefined};\n\nexport const jsonValueSchema: v.Type<JSONValue> = v.lazy(() => {\n const jsonObjectSchema = v.readonly(v.record(jsonValueSchema));\n\n return v.union(\n v.null(),\n v.string(),\n v.number(),\n v.bigint(),\n v.boolean(),\n v.readonly(v.array(jsonValueSchema)),\n jsonObjectSchema,\n );\n});\n\nexport const jsonObjectSchema = v.readonly(v.record(jsonValueSchema));\n\n/**\n * Parses JSON strings that may contain arbitrarily large integers. Integers\n * larger than {@link Number.MAX_SAFE_INTEGER} are deserialized as a `bigint`.\n */\nexport function parse(\n str: string,\n reviver?: (k: string, v: unknown) => unknown,\n): JSONValue {\n return customParse(str, reviver, numberParser);\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction customSerializer(_: string, v: any, type: string) {\n if (type === 'bigint') return v.toString();\n}\n\n/**\n * Stringifies objects to JSON, supporting objects containing bigint values.\n * Note that the resulting JSON string may not be deserializable by\n * all environments, but it is supported by Postgres. The string should be\n * deserialized with the corresponding {@link parse} method that will represent\n * large numbers as bigints. From there it is up to the application to suitably\n * handle bigints passed to downstream logic.\n */\nexport function stringify(\n obj: unknown,\n replacer?:\n | (string | number)[]\n | ((key: string, value: unknown) => unknown)\n | null,\n indent?: string | number,\n) {\n return customStringify(obj, replacer, indent, customSerializer);\n}\n\nexport const BigIntJSON = {\n parse,\n stringify,\n} as const;\n"],"mappings":";;;;;;;;AAWA,SAAS,aAAa,GAAY,GAAW;CAC3C,MAAM,IAAI,CAAC;AACX,KAAI,KAAK,OAAO,oBAAoB,KAAK,OAAO,iBAAkB,QAAO;AACzE,KAAI,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,IAAI,IAAI,EAAE,SAAS,IAAI,CACvD,QAAO;AAET,QAAO,OAAO,EAAE;;AAelB,IAAa,kBAAqC,eAAE,WAAW;CAC7D,MAAM,mBAAmB,SAAW,eAAE,OAAO,gBAAgB,CAAC;AAE9D,QAAO,eAAE,MACP,eAAE,MAAM,EACR,eAAE,QAAQ,EACV,eAAE,QAAQ,EACV,eAAE,QAAQ,EACV,eAAE,SAAS,EACX,SAAW,eAAE,MAAM,gBAAgB,CAAC,EACpC,iBACD;EACD;AAEF,IAAa,mBAAmB,SAAW,eAAE,OAAO,gBAAgB,CAAC;;;;;AAMrE,SAAgB,QACd,KACA,SACW;AACX,QAAO,MAAY,KAAK,SAAS,aAAa;;AAIhD,SAAS,iBAAiB,GAAW,GAAQ,MAAc;AACzD,KAAI,SAAS,SAAU,QAAO,EAAE,UAAU;;;;;;;;;;AAW5C,SAAgB,YACd,KACA,UAIA,QACA;AACA,QAAO,UAAgB,KAAK,UAAU,QAAQ,iBAAiB;;AAGjE,IAAa,aAAa;CACxB,OAAA;CACA,WAAA;CACD"}
1
+ {"version":3,"file":"bigint-json.js","names":[],"sources":["../../../../shared/src/bigint-json.ts"],"sourcesContent":["/**\n * Background for using `json-custom-numbers`:\n *\n * https://neon.tech/blog/parsing-json-from-postgres-in-js\n */\nimport {\n parse as customParse,\n stringify as customStringify,\n} from 'json-custom-numbers';\nimport * as v from './valita.ts';\n\nfunction numberParser(_: unknown, v: string) {\n const n = +v;\n if (n >= Number.MIN_SAFE_INTEGER && n <= Number.MAX_SAFE_INTEGER) return n;\n if (v.includes('.') || v.includes('e') || v.includes('E')) {\n return n;\n }\n return BigInt(v);\n}\n\n// Variant of postgres.JSONValue adapted to include bigints\nexport type JSONValue =\n | null\n | string\n | number\n | bigint\n | boolean\n | readonly JSONValue[]\n | JSONObject;\n\nexport type JSONObject = {readonly [prop: string]: JSONValue | undefined};\n\nexport const jsonValueSchema: v.Type<JSONValue> = v.lazy(() => {\n const jsonObjectSchema = v.readonly(v.record(jsonValueSchema));\n\n return v.union(\n v.null(),\n v.string(),\n v.number(),\n v.bigint(),\n v.boolean(),\n v.readonly(v.array(jsonValueSchema)),\n jsonObjectSchema,\n );\n});\n\nexport const jsonObjectSchema = v.readonly(v.record(jsonValueSchema));\n\n/**\n * Parses JSON strings that may contain arbitrarily large integers. Integers\n * larger than {@link Number.MAX_SAFE_INTEGER} are deserialized as a `bigint`.\n */\nexport function parse(\n str: string,\n reviver?: (k: string, v: unknown) => unknown,\n): JSONValue {\n return customParse(str, reviver, numberParser);\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nfunction customSerializer(_: string, v: any, type: string) {\n if (type === 'bigint') return v.toString();\n}\n\n/**\n * Stringifies objects to JSON, supporting objects containing bigint values.\n * Note that the resulting JSON string may not be deserializable by\n * all environments, but it is supported by Postgres. The string should be\n * deserialized with the corresponding {@link parse} method that will represent\n * large numbers as bigints. From there it is up to the application to suitably\n * handle bigints passed to downstream logic.\n */\nexport function stringify(\n obj: unknown,\n replacer?:\n | (string | number)[]\n | ((key: string, value: unknown) => unknown)\n | null,\n indent?: string | number,\n) {\n return customStringify(obj, replacer, indent, customSerializer);\n}\n\nexport const BigIntJSON = {\n parse,\n stringify,\n} as const;\n"],"mappings":";;;;;;;;AAWA,SAAS,aAAa,GAAY,GAAW;CAC3C,MAAM,IAAI,CAAC;CACX,IAAI,KAAK,OAAO,oBAAoB,KAAK,OAAO,kBAAkB,OAAO;CACzE,IAAI,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,GACtD,OAAO;CAET,OAAO,OAAO,CAAC;AACjB;AAcA,IAAa,kBAAqC,eAAE,WAAW;CAC7D,MAAM,mBAAmB,SAAW,eAAE,OAAO,eAAe,CAAC;CAE7D,OAAO,eAAE,MACP,eAAE,KAAK,GACP,eAAE,OAAO,GACT,eAAE,OAAO,GACT,eAAE,OAAO,GACT,eAAE,QAAQ,GACV,SAAW,eAAE,MAAM,eAAe,CAAC,GACnC,gBACF;AACF,CAAC;AAED,IAAa,mBAAmB,SAAW,eAAE,OAAO,eAAe,CAAC;;;;;AAMpE,SAAgB,QACd,KACA,SACW;CACX,OAAO,MAAY,KAAK,SAAS,YAAY;AAC/C;AAGA,SAAS,iBAAiB,GAAW,GAAQ,MAAc;CACzD,IAAI,SAAS,UAAU,OAAO,EAAE,SAAS;AAC3C;;;;;;;;;AAUA,SAAgB,YACd,KACA,UAIA,QACA;CACA,OAAO,UAAgB,KAAK,UAAU,QAAQ,gBAAgB;AAChE;AAEA,IAAa,aAAa;CACxB,OAAA;CACA,WAAA;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"binary-search.js","names":[],"sources":["../../../../shared/src/binary-search.ts"],"sourcesContent":["/**\n * This is a binary search that returns the index of the first element in the\n * array that is greater than or equal to the given value.\n *\n * Typical usage:\n *\n * ```\n * const haystack = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n * const needle = 3;\n * const index = binarySearch(haystack.length, i => needle - haystack[i]);\n * const found = index < haystack.length && haystack[index] === needle;\n * ```\n */\nexport function binarySearch(high: number, compare: (i: number) => number) {\n let low = 0;\n while (low < high) {\n const mid = low + ((high - low) >> 1);\n const i = compare(mid);\n if (i === 0) {\n return mid;\n }\n if (i > 0) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return low;\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,aAAa,MAAc,SAAgC;CACzE,IAAI,MAAM;AACV,QAAO,MAAM,MAAM;EACjB,MAAM,MAAM,OAAQ,OAAO,OAAQ;EACnC,MAAM,IAAI,QAAQ,IAAI;AACtB,MAAI,MAAM,EACR,QAAO;AAET,MAAI,IAAI,EACN,OAAM,MAAM;MAEZ,QAAO;;AAGX,QAAO"}
1
+ {"version":3,"file":"binary-search.js","names":[],"sources":["../../../../shared/src/binary-search.ts"],"sourcesContent":["/**\n * This is a binary search that returns the index of the first element in the\n * array that is greater than or equal to the given value.\n *\n * Typical usage:\n *\n * ```\n * const haystack = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n * const needle = 3;\n * const index = binarySearch(haystack.length, i => needle - haystack[i]);\n * const found = index < haystack.length && haystack[index] === needle;\n * ```\n */\nexport function binarySearch(high: number, compare: (i: number) => number) {\n let low = 0;\n while (low < high) {\n const mid = low + ((high - low) >> 1);\n const i = compare(mid);\n if (i === 0) {\n return mid;\n }\n if (i > 0) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return low;\n}\n"],"mappings":";;;;;;;;;;;;;;AAaA,SAAgB,aAAa,MAAc,SAAgC;CACzE,IAAI,MAAM;CACV,OAAO,MAAM,MAAM;EACjB,MAAM,MAAM,OAAQ,OAAO,OAAQ;EACnC,MAAM,IAAI,QAAQ,GAAG;EACrB,IAAI,MAAM,GACR,OAAO;EAET,IAAI,IAAI,GACN,MAAM,MAAM;OAEZ,OAAO;CAEX;CACA,OAAO;AACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"broadcast-channel.js","names":[],"sources":["../../../../shared/src/broadcast-channel.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n\nclass NoopBroadcastChannel implements BroadcastChannel {\n readonly name: string;\n\n onmessage: ((this: BroadcastChannel, ev: MessageEvent<any>) => any) | null =\n null;\n\n onmessageerror:\n | ((this: BroadcastChannel, ev: MessageEvent<any>) => any)\n | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n addEventListener(): void {\n // noop\n }\n removeEventListener(): void {\n // noop\n }\n dispatchEvent(): boolean {\n return false;\n }\n\n close(): void {\n // noop\n }\n\n postMessage(): void {\n // noop\n }\n}\n\nconst bc: typeof BroadcastChannel =\n typeof BroadcastChannel === 'undefined'\n ? NoopBroadcastChannel\n : BroadcastChannel;\n\nexport {bc as BroadcastChannel};\n"],"mappings":";AAEA,IAAM,uBAAN,MAAuD;CACrD;CAEA,YACE;CAEF,iBAEW;CAEX,YAAY,MAAc;AACxB,OAAK,OAAO;;CAGd,mBAAyB;CAGzB,sBAA4B;CAG5B,gBAAyB;AACvB,SAAO;;CAGT,QAAc;CAId,cAAoB;;AAKtB,IAAM,KACJ,OAAO,qBAAqB,cACxB,uBACA"}
1
+ {"version":3,"file":"broadcast-channel.js","names":[],"sources":["../../../../shared/src/broadcast-channel.ts"],"sourcesContent":["/* oxlint-disable @typescript-eslint/no-explicit-any */\n\nclass NoopBroadcastChannel implements BroadcastChannel {\n readonly name: string;\n\n onmessage: ((this: BroadcastChannel, ev: MessageEvent<any>) => any) | null =\n null;\n\n onmessageerror:\n | ((this: BroadcastChannel, ev: MessageEvent<any>) => any)\n | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n addEventListener(): void {\n // noop\n }\n removeEventListener(): void {\n // noop\n }\n dispatchEvent(): boolean {\n return false;\n }\n\n close(): void {\n // noop\n }\n\n postMessage(): void {\n // noop\n }\n}\n\nconst bc: typeof BroadcastChannel =\n typeof BroadcastChannel === 'undefined'\n ? NoopBroadcastChannel\n : BroadcastChannel;\n\nexport {bc as BroadcastChannel};\n"],"mappings":";AAEA,IAAM,uBAAN,MAAuD;CACrD;CAEA,YACE;CAEF,iBAEW;CAEX,YAAY,MAAc;EACxB,KAAK,OAAO;CACd;CAEA,mBAAyB,CAEzB;CACA,sBAA4B,CAE5B;CACA,gBAAyB;EACvB,OAAO;CACT;CAEA,QAAc,CAEd;CAEA,cAAoB,CAEpB;AACF;AAEA,IAAM,KACJ,OAAO,qBAAqB,cACxB,uBACA"}
@@ -1 +1 @@
1
- {"version":3,"file":"browser-env.js","names":[],"sources":["../../../../shared/src/browser-env.ts"],"sourcesContent":["// Helpers for some objects from the browser environment. These are wrapped in\n// functions because Replicache runs in environments that do not have these\n// objects (such as Web Workers, Deno etc).\n\ntype GlobalThis = typeof globalThis;\n\nconst overrides = new Map<keyof GlobalThis, GlobalThis[keyof GlobalThis]>();\n\nexport function overrideBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n value: GlobalThis[T],\n) {\n overrides.set(name, value);\n}\n\nexport function clearBrowserOverrides() {\n overrides.clear();\n}\n\nexport function getBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n if (overrides.has(name)) {\n return overrides.get(name);\n }\n return globalThis[name];\n}\n\n/**\n * Returns the global method with the given name, bound to the global object.\n * This is important because some methods (e.g. `requestAnimationFrame`) are not\n * bound to the global object by default.\n *\n * If you end up using {@linkcode getBrowserGlobal} instead in a case like this:\n *\n * ```js\n * this.#raf = getBrowserGlobal('requestAnimationFrame') ?? rafFallback;\n * ...\n * this.#raf(() => ...);\n * ```\n *\n * You will end up with `Uncaught TypeError: Illegal invocation` because `this`\n * is not bound to the global object\n */\nexport function getBrowserGlobalMethod<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n return getBrowserGlobal(name)?.bind(globalThis);\n}\n\nexport function mustGetBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] {\n const r = getBrowserGlobal(name);\n if (r === undefined) {\n throw new Error(\n `Unsupported JavaScript environment: Could not find ${name}.`,\n );\n }\n return r;\n}\n"],"mappings":";AAMA,IAAM,4BAAY,IAAI,KAAqD;AAa3E,SAAgB,iBACd,MAC2B;AAC3B,KAAI,UAAU,IAAI,KAAK,CACrB,QAAO,UAAU,IAAI,KAAK;AAE5B,QAAO,WAAW;;AAyBpB,SAAgB,qBACd,MACe;CACf,MAAM,IAAI,iBAAiB,KAAK;AAChC,KAAI,MAAM,KAAA,EACR,OAAM,IAAI,MACR,sDAAsD,KAAK,GAC5D;AAEH,QAAO"}
1
+ {"version":3,"file":"browser-env.js","names":[],"sources":["../../../../shared/src/browser-env.ts"],"sourcesContent":["// Helpers for some objects from the browser environment. These are wrapped in\n// functions because Replicache runs in environments that do not have these\n// objects (such as Web Workers, Deno etc).\n\ntype GlobalThis = typeof globalThis;\n\nconst overrides = new Map<keyof GlobalThis, GlobalThis[keyof GlobalThis]>();\n\nexport function overrideBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n value: GlobalThis[T],\n) {\n overrides.set(name, value);\n}\n\nexport function clearBrowserOverrides() {\n overrides.clear();\n}\n\nexport function getBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n if (overrides.has(name)) {\n return overrides.get(name);\n }\n return globalThis[name];\n}\n\n/**\n * Returns the global method with the given name, bound to the global object.\n * This is important because some methods (e.g. `requestAnimationFrame`) are not\n * bound to the global object by default.\n *\n * If you end up using {@linkcode getBrowserGlobal} instead in a case like this:\n *\n * ```js\n * this.#raf = getBrowserGlobal('requestAnimationFrame') ?? rafFallback;\n * ...\n * this.#raf(() => ...);\n * ```\n *\n * You will end up with `Uncaught TypeError: Illegal invocation` because `this`\n * is not bound to the global object\n */\nexport function getBrowserGlobalMethod<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n return getBrowserGlobal(name)?.bind(globalThis);\n}\n\nexport function mustGetBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] {\n const r = getBrowserGlobal(name);\n if (r === undefined) {\n throw new Error(\n `Unsupported JavaScript environment: Could not find ${name}.`,\n );\n }\n return r;\n}\n"],"mappings":";AAMA,IAAM,4BAAY,IAAI,IAAoD;AAa1E,SAAgB,iBACd,MAC2B;CAC3B,IAAI,UAAU,IAAI,IAAI,GACpB,OAAO,UAAU,IAAI,IAAI;CAE3B,OAAO,WAAW;AACpB;AAwBA,SAAgB,qBACd,MACe;CACf,MAAM,IAAI,iBAAiB,IAAI;CAC/B,IAAI,MAAM,KAAA,GACR,MAAM,IAAI,MACR,sDAAsD,KAAK,EAC7D;CAEF,OAAO;AACT"}