@rocicorp/zero 1.9.1-canary.1 → 1.10.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/analyze-query/src/analyze-cli.js +2 -2
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/replicache/src/db/commit.js +1 -4
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/read.d.ts +1 -0
- package/out/replicache/src/db/read.d.ts.map +1 -1
- package/out/replicache/src/db/read.js +1 -4
- package/out/replicache/src/db/read.js.map +1 -1
- package/out/replicache/src/db/write.d.ts +2 -1
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +4 -51
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/persist/clients.d.ts +1 -0
- package/out/replicache/src/persist/clients.d.ts.map +1 -1
- package/out/replicache/src/persist/clients.js +4 -31
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/process-env.d.ts +28 -0
- package/out/replicache/src/process-env.d.ts.map +1 -0
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/scan-iterator.js +2 -14
- package/out/replicache/src/scan-iterator.js.map +1 -1
- package/out/replicache/src/subscriptions.d.ts +1 -0
- package/out/replicache/src/subscriptions.d.ts.map +1 -1
- package/out/replicache/src/subscriptions.js +2 -10
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/transactions.d.ts +1 -0
- package/out/replicache/src/transactions.d.ts.map +1 -1
- package/out/replicache/src/transactions.js +2 -4
- package/out/replicache/src/transactions.js.map +1 -1
- package/out/zero/package.js +2 -2
- package/out/zero/package.js.map +1 -1
- package/out/zero-cache/src/config/normalize.d.ts +1 -0
- package/out/zero-cache/src/config/normalize.d.ts.map +1 -1
- package/out/zero-cache/src/config/normalize.js +10 -1
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +43 -1
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +139 -20
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +1 -1
- package/out/zero-cache/src/observability/metrics.d.ts +5 -0
- package/out/zero-cache/src/observability/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +15 -1
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/server/backup-watermark-poller.js +31 -0
- package/out/zero-cache/src/server/backup-watermark-poller.js.map +1 -0
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +90 -30
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +5 -15
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +46 -3
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +2 -1
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +1 -1
- package/out/zero-cache/src/server/worker-urls.js +2 -2
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/services/change-source/change-source.d.ts +4 -2
- package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts +35 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.js +34 -0
- package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +2 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +73 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +2 -6
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +16 -7
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +4 -7
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +7 -7
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +75 -23
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts +9 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +34 -4
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts +4 -2
- package/out/zero-cache/src/services/change-source/pg/replication-slots.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js +7 -4
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts +0 -5
- package/out/zero-cache/src/services/change-source/pg/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +29 -41
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +35 -16
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +77 -7
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +1 -12
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +3 -3
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts +6 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js +21 -0
- package/out/zero-cache/src/services/change-source/protocol/current/schema-change-tags.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts +5 -6
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js +32 -9
- package/out/zero-cache/src/services/change-streamer/backup-cleanup-monitor-factory.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +15 -5
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +66 -0
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts +68 -78
- package/out/zero-cache/src/services/change-streamer/broadcast.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +84 -92
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js +50 -0
- package/out/zero-cache/src/services/change-streamer/change-log-codec.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts +141 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js +270 -0
- package/out/zero-cache/src/services/change-streamer/change-log-initializer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js +39 -0
- package/out/zero-cache/src/services/change-streamer/change-log-transaction-hash.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +15 -20
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +69 -24
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +330 -63
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +55 -13
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts +8 -0
- package/out/zero-cache/src/services/change-streamer/error-type-enum.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +14 -3
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +41 -11
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.d.ts → litestream3-prometheus-poller.d.ts} +19 -45
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/{litestream3-backup-monitor.js → litestream3-prometheus-poller.js} +57 -171
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts +15 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.js +55 -0
- package/out/zero-cache/src/services/change-streamer/replica-poller.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +5 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +2 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts +14 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js +86 -0
- package/out/zero-cache/src/services/change-streamer/snapshot-reservations.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +4 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +39 -14
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts +75 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +261 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts +121 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js +391 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-purge-scheduler.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts +62 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js +159 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-reader.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts +109 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js +258 -0
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-writer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +22 -12
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +93 -117
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +61 -10
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +101 -8
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts +34 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js +86 -0
- package/out/zero-cache/src/services/change-streamer/upstream-acker.js.map +1 -0
- package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +3 -2
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +12 -11
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +50 -140
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/config-v5.yml +42 -0
- package/out/zero-cache/src/services/litestream/metrics.d.ts +4 -4
- package/out/zero-cache/src/services/litestream/metrics.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/metrics.js +7 -10
- package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts +57 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.d.ts.map +1 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js +137 -0
- package/out/zero-cache/src/services/litestream/vfs-watermark-poller.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts +169 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.js +434 -0
- package/out/zero-cache/src/services/replicator/change-log-cookies.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-db.d.ts +358 -0
- package/out/zero-cache/src/services/replicator/change-log-db.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-db.js +477 -0
- package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts +55 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +150 -0
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -0
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +44 -17
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +11 -4
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +2 -2
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts +119 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.js +214 -0
- package/out/zero-cache/src/services/replicator/schema/backfilling.js.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +3 -3
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +9 -5
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts +131 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js +413 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-observability.js.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts +120 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js +283 -0
- package/out/zero-cache/src/services/replicator/sqlite-change-log-purger.js.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker.js +9 -6
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +2 -1
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -1
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +1 -0
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts +9 -0
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js +9 -0
- package/out/zero-cache/src/services/view-syncer/e2e-serving-lag.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +18 -3
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +11 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +48 -7
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +1 -2
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +1 -25
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/streams.d.ts +10 -0
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js +25 -4
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +1 -0
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +25 -3
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts +25 -0
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +33 -1
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +12 -0
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +75 -0
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-schema/src/builder/table-builder.d.ts +23 -0
- package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +18 -0
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-types/src/schema.d.ts +11 -0
- package/out/zero-types/src/schema.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +2 -2
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +83 -14
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.d.ts +1 -1
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts +15 -0
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js +20 -13
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/package.json +2 -2
- package/out/replicache/src/db/index.js +0 -91
- package/out/replicache/src/db/index.js.map +0 -1
- package/out/replicache/src/lazy.d.ts +0 -2
- package/out/replicache/src/lazy.d.ts.map +0 -1
- package/out/replicache/src/lazy.js +0 -12
- package/out/replicache/src/lazy.js.map +0 -1
- package/out/zero-cache/src/server/backup-watermark-reader.js +0 -35
- package/out/zero-cache/src/server/backup-watermark-reader.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/litestream3-backup-monitor.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +0 -16
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +0 -54
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts +0 -25
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js +0 -159
- package/out/zero-cache/src/services/change-streamer/vfs-backup-monitor.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts +0 -44
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js +0 -65
- package/out/zero-cache/src/services/litestream/vfs-watermark-reader.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts +0 -11
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js +0 -74
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker-source.js.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts +0 -42
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.d.ts.map +0 -1
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js +0 -117
- package/out/zero-cache/src/services/litestream/vfs-watermark-worker.js.map +0 -1
|
@@ -9,7 +9,7 @@ import { parseOptions } from "../../shared/src/options.js";
|
|
|
9
9
|
import { ZERO_ENV_VAR_PREFIX } from "../../zero-cache/src/config/zero-config.js";
|
|
10
10
|
import { Console } from "node:console";
|
|
11
11
|
import { styleText } from "node:util";
|
|
12
|
-
import { WebSocket
|
|
12
|
+
import { WebSocket } from "ws";
|
|
13
13
|
//#region ../analyze-query/src/analyze-cli.ts
|
|
14
14
|
var options = {
|
|
15
15
|
zeroCacheURL: {
|
|
@@ -223,7 +223,7 @@ function resolveHandshakeHeaders(config) {
|
|
|
223
223
|
return headers;
|
|
224
224
|
}
|
|
225
225
|
function installWebSocketHeaderShim(headers) {
|
|
226
|
-
class HeaderInjectingWebSocket extends WebSocket
|
|
226
|
+
class HeaderInjectingWebSocket extends WebSocket {
|
|
227
227
|
constructor(url, protocols) {
|
|
228
228
|
super(url, protocols, { headers });
|
|
229
229
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analyze-cli.js","names":[],"sources":["../../../../analyze-query/src/analyze-cli.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {Console} from 'node:console';\nimport {styleText} from 'node:util';\nimport type {LogSink} from '@rocicorp/logger';\nimport {WebSocket as NodeWebSocket} from 'ws';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {colorConsole} from '../../shared/src/logging.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {ZERO_ENV_VAR_PREFIX} from '../../zero-cache/src/config/zero-config.ts';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {formatPlannerEvents} from '../../zql/src/planner/planner-debug.ts';\nimport {createBuilder} from '../../zql/src/query/create-builder.ts';\nimport type {AnyQuery} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\n\nexport type AnalyzeCLIOptions = {\n schema: Schema;\n /** Defaults to `process.argv.slice(2)`. */\n argv?: readonly string[] | undefined;\n};\n\nconst options = {\n zeroCacheURL: {\n type: v.string().optional(),\n desc: [\n 'URL of the remote zero-cache to analyze against.',\n 'Accepts http(s):// or ws(s):// (ws(s) is the transport actually used).',\n ],\n },\n adminPassword: {\n type: v.string().optional(),\n desc: [\n 'Admin password for zero-cache.',\n 'Required when the server is configured with one; ignored in dev mode.',\n ],\n },\n authToken: {\n type: v.string().optional(),\n desc: [\n 'Raw JWT forwarded to zero-cache.',\n 'Used server-side to fill permission variables for the query.',\n ],\n },\n cookie: {\n type: v.string().optional(),\n desc: [\n 'Cookie header value sent on the WebSocket upgrade request,',\n 'e.g. `session=abc; foo=bar`. Use this when zero-cache is behind',\n 'a proxy that resolves auth via cookies. Merged with --headers-json',\n '(--cookie wins on conflict).',\n ],\n },\n headersJson: {\n type: v.string().optional(),\n desc: [\n 'JSON object of arbitrary headers to send on the WebSocket upgrade',\n 'request, e.g. `{\"x-api-key\":\"...\"}`. Escape hatch for exotic auth',\n 'schemes; prefer --auth-token or --cookie when possible.',\n ],\n },\n userId: {\n type: v.string().optional(),\n desc: [\n 'Optional userID to report to zero-cache.',\n 'Omit for anonymous analysis.',\n ],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded AST. Exactly one of --ast / --query / --query-name is required.',\n 'The AST is sent to the server verbatim — provide it in server (post-mapping) form.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n 'ZQL query in chain form, e.g. `issue.related(\"comments\").limit(10)`.',\n 'Evaluated against the schema you pass to runAnalyzeCLI.',\n ],\n },\n queryName: {\n type: v.string().optional(),\n desc: [\n 'Name of a server-registered custom (named) query.',\n 'The server resolves the name + args via its registered query handler.',\n ],\n },\n queryArgs: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded array of arguments for --query-name. Defaults to `[]`.',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Include the rows read from the replica to execute the query.',\n 'Each row appears once per read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: ['Include the rows that would be synced to the client.'],\n },\n joinPlans: {\n type: v.boolean().default(false),\n desc: ['Include join planner diagnostics.'],\n },\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\ntype QueryPlan =\n | {kind: 'ast'; ast: AST}\n | {kind: 'zql'; text: string}\n | {kind: 'named'; name: string; args: ReadonlyArray<unknown>};\n\n// Route all Zero client log output to stderr so stdout contains only the\n// analyze result. Shell redirection (`2>/dev/null`) can then cleanly silence\n// logs without affecting output.\nconst stderrConsole = new Console({\n stdout: process.stderr,\n stderr: process.stderr,\n});\nconst stderrLogSink: LogSink = {\n log(level, context, ...args) {\n const ctx = context\n ? Object.entries(context).map(([k, v]) =>\n v === undefined ? k : `${k}=${v}`,\n )\n : [];\n stderrConsole[level](...ctx, ...args);\n },\n};\n\n/**\n * Entry point for a user's `cli.ts`. Parses argv, connects to a remote\n * zero-cache by standing up an in-process Zero client (in-memory storage,\n * no subscriptions), calls the inspector's `analyze-query` RPC, and\n * renders the result. Intended to be called as:\n *\n * ```ts\n * import {schema} from './schema.ts';\n * import {runAnalyzeCLI} from '@rocicorp/zero/analyze';\n * await runAnalyzeCLI({schema});\n * ```\n *\n * Exits the process with code 1 on error.\n */\nexport async function runAnalyzeCLI(opts: AnalyzeCLIOptions): Promise<void> {\n const argv = (opts.argv ?? process.argv.slice(2)).map(s =>\n s.replaceAll('\\n', ' '),\n );\n\n const config = parseOptions(options, {\n argv,\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query (remote)',\n content: `Analyze a ZQL query against a remote zero-cache.\n\n Connects to zero-cache's inspector protocol and reports the server-observed\n row scans, SQLite query plans, and timings.`,\n },\n {\n header: 'Examples',\n content: ` node cli.ts --zero-cache-url=https://zero.example.com \\\\\n --admin-password=\"$ZERO_ADMIN_PASSWORD\" \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n node cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --ast='\\\\{\"table\": \"issue\", \"limit\": 5\\\\}'\n\n node cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --query-name=issueList --query-args='[]'`,\n },\n ],\n });\n\n if (!config.zeroCacheURL) {\n colorConsole.error('--zero-cache-url is required. See --help for usage.');\n process.exit(1);\n }\n\n const plan = buildQueryPlan(config);\n\n const handshakeHeaders = resolveHandshakeHeaders(config);\n if (Object.keys(handshakeHeaders).length > 0) {\n installWebSocketHeaderShim(handshakeHeaders);\n }\n\n // zero-client and replicache reference a build-time `TESTING` global that\n // bundlers replace with a boolean literal; under node there's no replacement,\n // so provide a runtime default.\n (globalThis as {TESTING?: boolean}).TESTING ??= false;\n\n const z = new Zero({\n schema: opts.schema,\n server: config.zeroCacheURL,\n auth: config.authToken,\n userID: config.userId,\n kvStore: 'mem',\n logLevel: config.log.level,\n logSink: stderrLogSink,\n });\n\n let result: AnalyzeQueryResult;\n try {\n const authOk = await z.inspector.authenticate(config.adminPassword ?? '');\n if (!authOk) {\n throw new Error(\n 'admin password rejected (or --admin-password is required)',\n );\n }\n\n const rpcOptions = {\n vendedRows: config.outputVendedRows,\n syncedRows: config.outputSyncedRows,\n joinPlans: config.joinPlans,\n };\n\n if (plan.kind === 'ast') {\n result = await z.inspector.analyzeServerAST(plan.ast, rpcOptions);\n } else if (plan.kind === 'named') {\n result = await z.inspector.analyzeNamedQuery(\n plan.name,\n plan.args as ReadonlyArray<never>,\n rpcOptions,\n );\n } else {\n const built = buildZqlQuery(plan.text, createBuilder(opts.schema));\n result = await z.inspector.analyzeQuery(built, rpcOptions);\n }\n } catch (e) {\n colorConsole.error(e instanceof Error ? e.message : String(e));\n await z.close().catch(() => {});\n process.exit(1);\n }\n\n renderResult(result, {\n outputSyncedRows: config.outputSyncedRows,\n outputVendedRows: config.outputVendedRows,\n });\n\n await z.close();\n}\n\nfunction buildQueryPlan(config: {\n ast?: string | undefined;\n query?: string | undefined;\n queryName?: string | undefined;\n queryArgs?: string | undefined;\n}): QueryPlan {\n const selectors = [\n config.ast !== undefined && 'ast',\n config.query !== undefined && 'query',\n config.queryName !== undefined && 'queryName',\n ].filter(Boolean) as string[];\n\n if (selectors.length === 0) {\n colorConsole.error(\n 'Exactly one of --ast / --query / --query-name is required.',\n );\n process.exit(1);\n }\n if (selectors.length > 1) {\n colorConsole.error(\n `Only one of --ast / --query / --query-name may be provided; got: ${selectors.join(', ')}`,\n );\n process.exit(1);\n }\n\n if (config.ast !== undefined) {\n return {kind: 'ast', ast: JSON.parse(config.ast) as AST};\n }\n if (config.query !== undefined) {\n return {kind: 'zql', text: config.query};\n }\n const args = config.queryArgs\n ? (JSON.parse(config.queryArgs) as ReadonlyArray<unknown>)\n : [];\n return {kind: 'named', name: config.queryName as string, args};\n}\n\nfunction buildZqlQuery(\n queryString: string,\n builder: SchemaQuery<Schema>,\n): AnyQuery {\n const f = new Function('builder', `return builder.${queryString};`);\n return f(builder) as AnyQuery;\n}\n\nfunction resolveHandshakeHeaders(config: {\n cookie?: string | undefined;\n headersJson?: string | undefined;\n}): Record<string, string> {\n const headers: Record<string, string> = {};\n if (config.headersJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(config.headersJson);\n } catch (e) {\n colorConsole.error(\n `--headers-json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`,\n );\n process.exit(1);\n }\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n Array.isArray(parsed)\n ) {\n colorConsole.error('--headers-json must be a JSON object.');\n process.exit(1);\n }\n for (const [k, val] of Object.entries(parsed)) {\n if (typeof val !== 'string') {\n colorConsole.error(\n `--headers-json values must be strings; got ${typeof val} for \"${k}\".`,\n );\n process.exit(1);\n }\n headers[k] = val;\n }\n }\n if (config.cookie !== undefined) {\n headers.cookie = config.cookie;\n }\n return headers;\n}\n\nfunction installWebSocketHeaderShim(headers: Record<string, string>): void {\n class HeaderInjectingWebSocket extends NodeWebSocket {\n constructor(url: string | URL, protocols?: string | string[]) {\n super(url, protocols, {headers});\n }\n }\n (globalThis as {WebSocket?: unknown}).WebSocket = HeaderInjectingWebSocket;\n}\n\nfunction renderResult(\n result: AnalyzeQueryResult,\n opts: {outputSyncedRows: boolean; outputVendedRows: boolean},\n) {\n if (opts.outputSyncedRows) {\n colorConsole.log(styleText(['blue', 'bold'], '=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(styleText('bold', table + ':'), rows);\n }\n }\n\n colorConsole.log(styleText(['blue', 'bold'], '=== Query Stats: ===\\n'));\n colorConsole.log(\n styleText('bold', 'total synced rows:'),\n result.syncedRowCount,\n );\n\n const readRowCountsByQuery = result.readRowCountsByQuery ?? {};\n let totalRowsRead = 0;\n for (const table of Object.keys(readRowCountsByQuery).sort()) {\n const counts = readRowCountsByQuery[table];\n for (const n of Object.values(counts)) {\n totalRowsRead += n;\n }\n colorConsole.log(styleText('bold', `${table} vended:`), counts);\n }\n colorConsole.log(\n styleText('bold', 'Rows Read (into JS):'),\n colorRowsConsidered(totalRowsRead),\n );\n const duration = result.elapsed ?? result.end - result.start;\n colorConsole.log(styleText('bold', 'time:'), colorTime(duration), 'ms');\n\n if (opts.outputVendedRows) {\n colorConsole.log(\n styleText(['blue', 'bold'], '=== JS Row Scan Values: ===\\n'),\n );\n for (const [table, rows] of Object.entries(result.readRows ?? {})) {\n colorConsole.log(styleText('bold', `${table}:`), rows);\n }\n }\n\n colorConsole.log(\n styleText(['blue', 'bold'], '\\n=== Rows Scanned (by SQLite): ===\\n'),\n );\n const dbScansByQuery = result.dbScansByQuery ?? {};\n let totalNVisit = 0;\n for (const [table, queries] of Object.entries(dbScansByQuery)) {\n colorConsole.log(styleText('bold', `${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n }\n colorConsole.log(\n styleText('bold', 'total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n );\n\n colorConsole.log(styleText(['blue', 'bold'], '\\n\\n=== Query Plans: ===\\n'));\n const plans = result.sqlitePlans ?? {};\n for (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(styleText('bold', 'query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n }\n\n if (result.warnings.length > 0) {\n colorConsole.log(styleText(['yellow', 'bold'], '=== Warnings: ===\\n'));\n for (const w of result.warnings) {\n colorConsole.log(styleText('yellow', w));\n }\n }\n\n if (result.joinPlans && result.joinPlans.length > 0) {\n colorConsole.log(styleText(['blue', 'bold'], '\\n=== Join Plans: ===\\n'));\n colorConsole.log(formatPlannerEvents(result.joinPlans));\n }\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return styleText('green', duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return styleText('yellow', duration.toFixed(2) + 'ms');\n }\n return styleText('red', duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return styleText('green', n.toString());\n } else if (n < 10000) {\n return styleText('yellow', n.toString());\n }\n return styleText('red', n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return styleText('yellow', row);\n }\n return styleText('red', row);\n }\n return styleText('green', row);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"analyze-cli.js","names":[],"sources":["../../../../analyze-query/src/analyze-cli.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {Console} from 'node:console';\nimport {styleText} from 'node:util';\nimport type {LogSink} from '@rocicorp/logger';\nimport {WebSocket as NodeWebSocket} from 'ws';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {colorConsole} from '../../shared/src/logging.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {ZERO_ENV_VAR_PREFIX} from '../../zero-cache/src/config/zero-config.ts';\nimport {Zero} from '../../zero-client/src/client/zero.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {formatPlannerEvents} from '../../zql/src/planner/planner-debug.ts';\nimport {createBuilder} from '../../zql/src/query/create-builder.ts';\nimport type {AnyQuery} from '../../zql/src/query/query.ts';\nimport type {SchemaQuery} from '../../zql/src/query/schema-query.ts';\n\nexport type AnalyzeCLIOptions = {\n schema: Schema;\n /** Defaults to `process.argv.slice(2)`. */\n argv?: readonly string[] | undefined;\n};\n\nconst options = {\n zeroCacheURL: {\n type: v.string().optional(),\n desc: [\n 'URL of the remote zero-cache to analyze against.',\n 'Accepts http(s):// or ws(s):// (ws(s) is the transport actually used).',\n ],\n },\n adminPassword: {\n type: v.string().optional(),\n desc: [\n 'Admin password for zero-cache.',\n 'Required when the server is configured with one; ignored in dev mode.',\n ],\n },\n authToken: {\n type: v.string().optional(),\n desc: [\n 'Raw JWT forwarded to zero-cache.',\n 'Used server-side to fill permission variables for the query.',\n ],\n },\n cookie: {\n type: v.string().optional(),\n desc: [\n 'Cookie header value sent on the WebSocket upgrade request,',\n 'e.g. `session=abc; foo=bar`. Use this when zero-cache is behind',\n 'a proxy that resolves auth via cookies. Merged with --headers-json',\n '(--cookie wins on conflict).',\n ],\n },\n headersJson: {\n type: v.string().optional(),\n desc: [\n 'JSON object of arbitrary headers to send on the WebSocket upgrade',\n 'request, e.g. `{\"x-api-key\":\"...\"}`. Escape hatch for exotic auth',\n 'schemes; prefer --auth-token or --cookie when possible.',\n ],\n },\n userId: {\n type: v.string().optional(),\n desc: [\n 'Optional userID to report to zero-cache.',\n 'Omit for anonymous analysis.',\n ],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded AST. Exactly one of --ast / --query / --query-name is required.',\n 'The AST is sent to the server verbatim — provide it in server (post-mapping) form.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n 'ZQL query in chain form, e.g. `issue.related(\"comments\").limit(10)`.',\n 'Evaluated against the schema you pass to runAnalyzeCLI.',\n ],\n },\n queryName: {\n type: v.string().optional(),\n desc: [\n 'Name of a server-registered custom (named) query.',\n 'The server resolves the name + args via its registered query handler.',\n ],\n },\n queryArgs: {\n type: v.string().optional(),\n desc: [\n 'JSON-encoded array of arguments for --query-name. Defaults to `[]`.',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Include the rows read from the replica to execute the query.',\n 'Each row appears once per read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: ['Include the rows that would be synced to the client.'],\n },\n joinPlans: {\n type: v.boolean().default(false),\n desc: ['Include join planner diagnostics.'],\n },\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\ntype QueryPlan =\n | {kind: 'ast'; ast: AST}\n | {kind: 'zql'; text: string}\n | {kind: 'named'; name: string; args: ReadonlyArray<unknown>};\n\n// Route all Zero client log output to stderr so stdout contains only the\n// analyze result. Shell redirection (`2>/dev/null`) can then cleanly silence\n// logs without affecting output.\nconst stderrConsole = new Console({\n stdout: process.stderr,\n stderr: process.stderr,\n});\nconst stderrLogSink: LogSink = {\n log(level, context, ...args) {\n const ctx = context\n ? Object.entries(context).map(([k, v]) =>\n v === undefined ? k : `${k}=${v}`,\n )\n : [];\n stderrConsole[level](...ctx, ...args);\n },\n};\n\n/**\n * Entry point for a user's `cli.ts`. Parses argv, connects to a remote\n * zero-cache by standing up an in-process Zero client (in-memory storage,\n * no subscriptions), calls the inspector's `analyze-query` RPC, and\n * renders the result. Intended to be called as:\n *\n * ```ts\n * import {schema} from './schema.ts';\n * import {runAnalyzeCLI} from '@rocicorp/zero/analyze';\n * await runAnalyzeCLI({schema});\n * ```\n *\n * Exits the process with code 1 on error.\n */\nexport async function runAnalyzeCLI(opts: AnalyzeCLIOptions): Promise<void> {\n const argv = (opts.argv ?? process.argv.slice(2)).map(s =>\n s.replaceAll('\\n', ' '),\n );\n\n const config = parseOptions(options, {\n argv,\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query (remote)',\n content: `Analyze a ZQL query against a remote zero-cache.\n\n Connects to zero-cache's inspector protocol and reports the server-observed\n row scans, SQLite query plans, and timings.`,\n },\n {\n header: 'Examples',\n content: ` node cli.ts --zero-cache-url=https://zero.example.com \\\\\n --admin-password=\"$ZERO_ADMIN_PASSWORD\" \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n node cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --ast='\\\\{\"table\": \"issue\", \"limit\": 5\\\\}'\n\n node cli.ts --zero-cache-url=http://localhost:4848 \\\\\n --query-name=issueList --query-args='[]'`,\n },\n ],\n });\n\n if (!config.zeroCacheURL) {\n colorConsole.error('--zero-cache-url is required. See --help for usage.');\n process.exit(1);\n }\n\n const plan = buildQueryPlan(config);\n\n const handshakeHeaders = resolveHandshakeHeaders(config);\n if (Object.keys(handshakeHeaders).length > 0) {\n installWebSocketHeaderShim(handshakeHeaders);\n }\n\n // zero-client and replicache reference a build-time `TESTING` global that\n // bundlers replace with a boolean literal; under node there's no replacement,\n // so provide a runtime default.\n (globalThis as {TESTING?: boolean}).TESTING ??= false;\n\n const z = new Zero({\n schema: opts.schema,\n server: config.zeroCacheURL,\n auth: config.authToken,\n userID: config.userId,\n kvStore: 'mem',\n logLevel: config.log.level,\n logSink: stderrLogSink,\n });\n\n let result: AnalyzeQueryResult;\n try {\n const authOk = await z.inspector.authenticate(config.adminPassword ?? '');\n if (!authOk) {\n throw new Error(\n 'admin password rejected (or --admin-password is required)',\n );\n }\n\n const rpcOptions = {\n vendedRows: config.outputVendedRows,\n syncedRows: config.outputSyncedRows,\n joinPlans: config.joinPlans,\n };\n\n if (plan.kind === 'ast') {\n result = await z.inspector.analyzeServerAST(plan.ast, rpcOptions);\n } else if (plan.kind === 'named') {\n result = await z.inspector.analyzeNamedQuery(\n plan.name,\n plan.args as ReadonlyArray<never>,\n rpcOptions,\n );\n } else {\n const built = buildZqlQuery(plan.text, createBuilder(opts.schema));\n result = await z.inspector.analyzeQuery(built, rpcOptions);\n }\n } catch (e) {\n colorConsole.error(e instanceof Error ? e.message : String(e));\n await z.close().catch(() => {});\n process.exit(1);\n }\n\n renderResult(result, {\n outputSyncedRows: config.outputSyncedRows,\n outputVendedRows: config.outputVendedRows,\n });\n\n await z.close();\n}\n\nfunction buildQueryPlan(config: {\n ast?: string | undefined;\n query?: string | undefined;\n queryName?: string | undefined;\n queryArgs?: string | undefined;\n}): QueryPlan {\n const selectors = [\n config.ast !== undefined && 'ast',\n config.query !== undefined && 'query',\n config.queryName !== undefined && 'queryName',\n ].filter(Boolean) as string[];\n\n if (selectors.length === 0) {\n colorConsole.error(\n 'Exactly one of --ast / --query / --query-name is required.',\n );\n process.exit(1);\n }\n if (selectors.length > 1) {\n colorConsole.error(\n `Only one of --ast / --query / --query-name may be provided; got: ${selectors.join(', ')}`,\n );\n process.exit(1);\n }\n\n if (config.ast !== undefined) {\n return {kind: 'ast', ast: JSON.parse(config.ast) as AST};\n }\n if (config.query !== undefined) {\n return {kind: 'zql', text: config.query};\n }\n const args = config.queryArgs\n ? (JSON.parse(config.queryArgs) as ReadonlyArray<unknown>)\n : [];\n return {kind: 'named', name: config.queryName as string, args};\n}\n\nfunction buildZqlQuery(\n queryString: string,\n builder: SchemaQuery<Schema>,\n): AnyQuery {\n const f = new Function('builder', `return builder.${queryString};`);\n return f(builder) as AnyQuery;\n}\n\nfunction resolveHandshakeHeaders(config: {\n cookie?: string | undefined;\n headersJson?: string | undefined;\n}): Record<string, string> {\n const headers: Record<string, string> = {};\n if (config.headersJson !== undefined) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(config.headersJson);\n } catch (e) {\n colorConsole.error(\n `--headers-json is not valid JSON: ${e instanceof Error ? e.message : String(e)}`,\n );\n process.exit(1);\n }\n if (\n parsed === null ||\n typeof parsed !== 'object' ||\n Array.isArray(parsed)\n ) {\n colorConsole.error('--headers-json must be a JSON object.');\n process.exit(1);\n }\n for (const [k, val] of Object.entries(parsed)) {\n if (typeof val !== 'string') {\n colorConsole.error(\n `--headers-json values must be strings; got ${typeof val} for \"${k}\".`,\n );\n process.exit(1);\n }\n headers[k] = val;\n }\n }\n if (config.cookie !== undefined) {\n headers.cookie = config.cookie;\n }\n return headers;\n}\n\nfunction installWebSocketHeaderShim(headers: Record<string, string>): void {\n class HeaderInjectingWebSocket extends NodeWebSocket {\n constructor(url: string | URL, protocols?: string | string[]) {\n super(url, protocols, {headers});\n }\n }\n (globalThis as {WebSocket?: unknown}).WebSocket = HeaderInjectingWebSocket;\n}\n\nfunction renderResult(\n result: AnalyzeQueryResult,\n opts: {outputSyncedRows: boolean; outputVendedRows: boolean},\n) {\n if (opts.outputSyncedRows) {\n colorConsole.log(styleText(['blue', 'bold'], '=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(styleText('bold', table + ':'), rows);\n }\n }\n\n colorConsole.log(styleText(['blue', 'bold'], '=== Query Stats: ===\\n'));\n colorConsole.log(\n styleText('bold', 'total synced rows:'),\n result.syncedRowCount,\n );\n\n const readRowCountsByQuery = result.readRowCountsByQuery ?? {};\n let totalRowsRead = 0;\n for (const table of Object.keys(readRowCountsByQuery).sort()) {\n const counts = readRowCountsByQuery[table];\n for (const n of Object.values(counts)) {\n totalRowsRead += n;\n }\n colorConsole.log(styleText('bold', `${table} vended:`), counts);\n }\n colorConsole.log(\n styleText('bold', 'Rows Read (into JS):'),\n colorRowsConsidered(totalRowsRead),\n );\n const duration = result.elapsed ?? result.end - result.start;\n colorConsole.log(styleText('bold', 'time:'), colorTime(duration), 'ms');\n\n if (opts.outputVendedRows) {\n colorConsole.log(\n styleText(['blue', 'bold'], '=== JS Row Scan Values: ===\\n'),\n );\n for (const [table, rows] of Object.entries(result.readRows ?? {})) {\n colorConsole.log(styleText('bold', `${table}:`), rows);\n }\n }\n\n colorConsole.log(\n styleText(['blue', 'bold'], '\\n=== Rows Scanned (by SQLite): ===\\n'),\n );\n const dbScansByQuery = result.dbScansByQuery ?? {};\n let totalNVisit = 0;\n for (const [table, queries] of Object.entries(dbScansByQuery)) {\n colorConsole.log(styleText('bold', `${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n }\n colorConsole.log(\n styleText('bold', 'total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n );\n\n colorConsole.log(styleText(['blue', 'bold'], '\\n\\n=== Query Plans: ===\\n'));\n const plans = result.sqlitePlans ?? {};\n for (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(styleText('bold', 'query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n }\n\n if (result.warnings.length > 0) {\n colorConsole.log(styleText(['yellow', 'bold'], '=== Warnings: ===\\n'));\n for (const w of result.warnings) {\n colorConsole.log(styleText('yellow', w));\n }\n }\n\n if (result.joinPlans && result.joinPlans.length > 0) {\n colorConsole.log(styleText(['blue', 'bold'], '\\n=== Join Plans: ===\\n'));\n colorConsole.log(formatPlannerEvents(result.joinPlans));\n }\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return styleText('green', duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return styleText('yellow', duration.toFixed(2) + 'ms');\n }\n return styleText('red', duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return styleText('green', n.toString());\n } else if (n < 10000) {\n return styleText('yellow', n.toString());\n }\n return styleText('red', n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return styleText('yellow', row);\n }\n return styleText('red', row);\n }\n return styleText('green', row);\n}\n"],"mappings":"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"}
|
|
@@ -178,9 +178,6 @@ function assertMeta(v) {
|
|
|
178
178
|
default: throw new Error(`Invalid enum value ${v.type}`);
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
|
-
function chunkIndexDefinitionEqualIgnoreName(a, b) {
|
|
182
|
-
return a.jsonPointer === b.jsonPointer && (a.allowEmpty ?? false) === (b.allowEmpty ?? false) && a.keyPrefix === b.keyPrefix;
|
|
183
|
-
}
|
|
184
181
|
function assertChunkIndexDefinition(v) {
|
|
185
182
|
assertObject(v);
|
|
186
183
|
assertDeepFrozen(v);
|
|
@@ -279,6 +276,6 @@ function validateChunk(chunk) {
|
|
|
279
276
|
}
|
|
280
277
|
}
|
|
281
278
|
//#endregion
|
|
282
|
-
export { DEFAULT_HEAD_NAME, assertLocalMetaDD31, assertSnapshotCommitDD31, assertSnapshotMetaDD31, baseSnapshotFromCommit, baseSnapshotFromHash, baseSnapshotFromHead, baseSnapshotHashFromHash,
|
|
279
|
+
export { DEFAULT_HEAD_NAME, assertLocalMetaDD31, assertSnapshotCommitDD31, assertSnapshotMetaDD31, baseSnapshotFromCommit, baseSnapshotFromHash, baseSnapshotFromHead, baseSnapshotHashFromHash, commitFromHash, commitFromHead, commitIsLocalDD31, compareCookiesForSnapshots, getMutationID, getRefs, isLocalMetaDD31, localMutations, localMutationsDD31, localMutationsGreaterThan, newLocalDD31, newSnapshotCommitDataDD31, newSnapshotDD31, snapshotMetaParts, toChunkIndexDefinition };
|
|
283
280
|
|
|
284
281
|
//# sourceMappingURL=commit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.js","names":[],"sources":["../../../../../replicache/src/db/commit.ts"],"sourcesContent":["import {\n assert,\n assertArray,\n assertBoolean,\n assertNumber,\n assertObject,\n assertString,\n unreachable,\n} from '../../../shared/src/asserts.ts';\nimport {assertJSONValue} from '../../../shared/src/json.ts';\nimport {skipCommitDataAsserts} from '../config.ts';\nimport {type FrozenCookie, compareCookies} from '../cookies.ts';\nimport {type Chunk, type CreateChunk, type Refs, toRefs} from '../dag/chunk.ts';\nimport {type MustGetChunk, type Read, mustGetHeadHash} from '../dag/store.ts';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.ts';\nimport {type Hash, assertHash} from '../hash.ts';\nimport type {IndexDefinition} from '../index-defs.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport * as MetaType from './meta-type-enum.ts';\n\nexport const DEFAULT_HEAD_NAME = 'main';\n\nexport function commitIsLocalDD31(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31> {\n return isLocalMetaDD31(commit.meta);\n}\n\nexport function commitIsLocal(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31> {\n return commitIsLocalDD31(commit);\n}\n\nexport function commitIsSnapshot(\n commit: Commit<Meta>,\n): commit is Commit<SnapshotMetaDD31> {\n return isSnapshotMetaDD31(commit.meta);\n}\n\nexport class Commit<M extends Meta> {\n readonly chunk: Chunk<CommitData<M>>;\n\n constructor(chunk: Chunk<CommitData<M>>) {\n this.chunk = chunk;\n }\n\n get meta(): M {\n return this.chunk.data.meta;\n }\n\n get valueHash(): Hash {\n // Already validated!\n return this.chunk.data.valueHash;\n }\n\n getMutationID(clientID: ClientID, dagRead: MustGetChunk): Promise<number> {\n return getMutationID(clientID, dagRead, this.meta);\n }\n\n async getNextMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n ): Promise<number> {\n return (await this.getMutationID(clientID, dagRead)) + 1;\n }\n\n get indexes(): readonly IndexRecord[] {\n // Already validated!\n return this.chunk.data.indexes;\n }\n}\n\nexport async function getMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n meta: Meta,\n): Promise<number> {\n switch (meta.type) {\n case MetaType.SnapshotDD31:\n return meta.lastMutationIDs[clientID] ?? 0;\n\n case MetaType.LocalDD31: {\n if (meta.clientID === clientID) {\n return meta.mutationID;\n }\n const {basisHash} = meta;\n const basisCommit = await commitFromHash(basisHash, dagRead);\n return getMutationID(clientID, dagRead, basisCommit.meta);\n }\n\n default:\n unreachable(meta);\n }\n}\n\n/**\n * Returns the set of local commits from the given `fromCommitHash` back to but not\n * including its base snapshot. If `fromCommitHash` is a snapshot, the returned vector\n * will be empty. When, as typical, `fromCommitHash` is the head of the default chain\n * then the returned commits are the set of pending commits, ie the set of local commits\n * that have not yet been pushed to the data layer.\n *\n * The vector of commits is returned in reverse chain order, that is, starting\n * with the commit with hash `fromCommitHash` and walking backwards.\n */\nexport async function localMutations(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocal(c)) as Commit<LocalMetaDD31>[];\n}\n\nexport async function localMutationsDD31(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocalDD31(c)) as Commit<LocalMetaDD31>[];\n}\n\nexport async function localMutationsGreaterThan(\n commit: Commit<Meta>,\n mutationIDLimits: Record<ClientID, number>,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits: Commit<LocalMetaDD31>[] = [];\n const remainingMutationIDLimits = new Map(Object.entries(mutationIDLimits));\n while (!commitIsSnapshot(commit) && remainingMutationIDLimits.size > 0) {\n if (commitIsLocalDD31(commit)) {\n const {meta} = commit;\n const mutationIDLowerLimit = remainingMutationIDLimits.get(meta.clientID);\n if (mutationIDLowerLimit !== undefined) {\n if (meta.mutationID <= mutationIDLowerLimit) {\n remainingMutationIDLimits.delete(meta.clientID);\n } else {\n commits.push(commit as Commit<LocalMetaDD31>);\n }\n }\n }\n const {basisHash} = commit.meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n return commits;\n}\n\nexport async function baseSnapshotFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n const hash = await dagRead.getHead(name);\n assert(hash, `Missing head ${name}`);\n return baseSnapshotFromHash(hash, dagRead);\n}\n\nexport async function baseSnapshotHashFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Hash> {\n return (await baseSnapshotFromHash(hash, dagRead)).chunk.hash;\n}\n\nexport async function baseSnapshotFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n const commit = await commitFromHash(hash, dagRead);\n return baseSnapshotFromCommit(commit, dagRead);\n}\n\nexport async function baseSnapshotFromCommit(\n commit: Commit<Meta>,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n if (isLocalMetaDD31(meta)) {\n commit = await commitFromHash(meta.baseSnapshotHash, dagRead);\n } else {\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n }\n return commit;\n}\n\nexport function snapshotMetaParts(\n c: Commit<SnapshotMetaDD31>,\n clientID: ClientID,\n): [lastMutationID: number, cookie: FrozenCookie | FrozenJSONValue] {\n const m = c.meta;\n const lmid = m.lastMutationIDs[clientID] ?? 0;\n return [lmid, m.cookieJSON];\n}\n\nexport function compareCookiesForSnapshots(\n a: Commit<SnapshotMetaDD31>,\n b: Commit<SnapshotMetaDD31>,\n): number {\n return compareCookies(a.meta.cookieJSON, b.meta.cookieJSON);\n}\n\n/**\n * Returns all commits from the commit with fromCommitHash to its base snapshot,\n * inclusive of both. Resulting vector is in chain-head-first order (so snapshot\n * comes last).\n */\nexport async function commitChain(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<Meta>[]> {\n let commit = await commitFromHash(fromCommitHash, dagRead);\n const commits = [];\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commits.push(commit);\n commit = await commitFromHash(basisHash, dagRead);\n }\n commits.push(commit);\n return commits;\n}\n\nexport async function commitFromHash(\n hash: Hash,\n dagRead: MustGetChunk,\n): Promise<Commit<Meta>> {\n const chunk = await dagRead.mustGetChunk(hash);\n return fromChunk(chunk);\n}\n\nexport async function commitFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<Meta>> {\n const hash = await mustGetHeadHash(name, dagRead);\n return commitFromHash(hash, dagRead);\n}\n\nexport type LocalMetaDD31 = {\n readonly type: MetaType.LocalDD31;\n readonly basisHash: Hash;\n readonly mutationID: number;\n readonly mutatorName: string;\n readonly mutatorArgsJSON: FrozenJSONValue;\n readonly originalHash: Hash | null;\n readonly timestamp: number;\n readonly clientID: ClientID;\n readonly baseSnapshotHash: Hash;\n};\n\nexport type LocalMeta = LocalMetaDD31;\n\nexport function assertLocalMetaDD31(\n v: Record<string, unknown>,\n): asserts v is LocalMetaDD31 {\n // type already asserted\n assertString(v.clientID);\n assertNumber(v.mutationID);\n assertString(v.mutatorName);\n if (!v.mutatorName) {\n throw new Error('Missing mutator name');\n }\n assertJSONValue(v.mutatorArgsJSON);\n if (v.originalHash !== null) {\n assertHash(v.originalHash);\n }\n assertNumber(v.timestamp);\n}\n\nexport function isLocalMetaDD31(meta: Meta): meta is LocalMetaDD31 {\n return meta.type === MetaType.LocalDD31;\n}\n\nexport function assertLocalCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<LocalMetaDD31> {\n assertLocalMetaDD31(c.meta);\n}\n\nexport type SnapshotMetaDD31 = {\n readonly type: MetaType.SnapshotDD31;\n readonly basisHash: Hash | null;\n readonly lastMutationIDs: Record<ClientID, number>;\n readonly cookieJSON: FrozenCookie;\n};\n\nexport type SnapshotMeta = SnapshotMetaDD31;\n\nexport function assertSnapshotMetaDD31(\n v: Record<string, unknown>,\n): asserts v is SnapshotMetaDD31 {\n // type already asserted\n if (v.basisHash !== null) {\n assertHash(v.basisHash);\n }\n assertJSONValue(v.cookieJSON);\n assertLastMutationIDs(v.lastMutationIDs);\n}\n\nfunction assertLastMutationIDs(\n v: unknown,\n): asserts v is Record<ClientID, number> {\n assertObject(v);\n for (const e of Object.values(v)) {\n assertNumber(e);\n }\n}\n\nexport type Meta = LocalMetaDD31 | SnapshotMetaDD31;\n\nexport function assertSnapshotCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<SnapshotMetaDD31> {\n assertSnapshotMetaDD31(c.meta);\n}\n\nfunction isSnapshotMetaDD31(meta: Meta): meta is SnapshotMetaDD31 {\n return meta.type === MetaType.SnapshotDD31;\n}\n\nfunction assertMeta(v: unknown): asserts v is Meta {\n assertObject(v);\n assertDeepFrozen(v);\n if (v.basisHash !== null) {\n assertString(v.basisHash);\n }\n\n assertNumber(v.type);\n switch (v.type) {\n case MetaType.LocalDD31:\n assertLocalMetaDD31(v);\n break;\n case MetaType.SnapshotDD31:\n assertSnapshotMetaDD31(v);\n break;\n default:\n throw new Error(`Invalid enum value ${v.type}`);\n }\n}\n\n/**\n * This is the type used for index definitions as defined in the Commit chunk data.\n *\n * Changing this requires a REPLICACHE_FORMAT_VERSION bump.\n */\nexport type ChunkIndexDefinition = {\n readonly name: string;\n readonly keyPrefix: string;\n readonly jsonPointer: string;\n // Used to not exist\n readonly allowEmpty?: boolean;\n};\n\nexport function chunkIndexDefinitionEqualIgnoreName(\n a: ChunkIndexDefinition,\n b: ChunkIndexDefinition,\n): boolean {\n return (\n a.jsonPointer === b.jsonPointer &&\n (a.allowEmpty ?? false) === (b.allowEmpty ?? false) &&\n a.keyPrefix === b.keyPrefix\n );\n}\n\nfunction assertChunkIndexDefinition(\n v: unknown,\n): asserts v is ChunkIndexDefinition {\n assertObject(v);\n assertDeepFrozen(v);\n assertString(v.name);\n assertString(v.keyPrefix);\n assertString(v.jsonPointer);\n if (v.allowEmpty !== undefined) {\n assertBoolean(v.allowEmpty);\n }\n}\n\nexport function toChunkIndexDefinition(\n name: string,\n indexDefinition: IndexDefinition,\n): Required<ChunkIndexDefinition> {\n return {\n name,\n keyPrefix: indexDefinition.prefix ?? '',\n jsonPointer: indexDefinition.jsonPointer,\n allowEmpty: indexDefinition.allowEmpty ?? false,\n };\n}\n\nexport type IndexRecord = {\n readonly definition: ChunkIndexDefinition;\n readonly valueHash: Hash;\n};\n\nfunction assertIndexRecord(v: unknown): asserts v is IndexRecord {\n assertObject(v);\n assertDeepFrozen(v);\n assertChunkIndexDefinition(v.definition);\n assertString(v.valueHash);\n}\n\nfunction assertIndexRecords(v: unknown): asserts v is IndexRecord[] {\n assertArray(v);\n assertDeepFrozen(v);\n for (const ir of v) {\n assertIndexRecord(ir);\n }\n}\n\nexport function newLocalDD31(\n createChunk: CreateChunk,\n basisHash: Hash,\n baseSnapshotHash: Hash,\n mutationID: number,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n timestamp: number,\n clientID: ClientID,\n): Commit<LocalMetaDD31> {\n const meta: LocalMetaDD31 = {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n clientID,\n };\n return commitFromCommitData(\n createChunk,\n makeCommitData(meta, valueHash, indexes),\n );\n}\n\nexport function newSnapshotDD31(\n createChunk: CreateChunk,\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): Commit<SnapshotMetaDD31> {\n return commitFromCommitData(\n createChunk,\n newSnapshotCommitDataDD31(\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexes,\n ),\n );\n}\n\nexport function newSnapshotCommitDataDD31(\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<SnapshotMetaDD31> {\n const meta: SnapshotMetaDD31 = {\n type: MetaType.SnapshotDD31,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n };\n return makeCommitData(meta, valueHash, indexes);\n}\n\nexport function fromChunk(chunk: Chunk): Commit<Meta> {\n validateChunk(chunk);\n return new Commit(chunk);\n}\n\nfunction commitFromCommitData<M extends Meta>(\n createChunk: CreateChunk,\n data: CommitData<M>,\n): Commit<M> {\n return new Commit(createChunk(data, getRefs(data)));\n}\n\nexport function getRefs(data: CommitData<Meta>): Refs {\n const refs: Set<Hash> = new Set();\n refs.add(data.valueHash);\n const {meta} = data;\n switch (meta.type) {\n case MetaType.LocalDD31:\n meta.basisHash && refs.add(meta.basisHash);\n // Local has weak originalHash\n break;\n case MetaType.SnapshotDD31:\n // Snapshot has weak basisHash\n break;\n default:\n unreachable(meta);\n }\n\n for (const index of data.indexes) {\n refs.add(index.valueHash);\n }\n\n return toRefs(refs);\n}\n\nexport type CommitData<M extends Meta> = FrozenTag<{\n readonly meta: M;\n readonly valueHash: Hash;\n readonly indexes: readonly IndexRecord[];\n}>;\n\nexport function makeCommitData<M extends Meta>(\n meta: M,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<M> {\n return deepFreeze({\n meta,\n valueHash,\n indexes,\n }) as unknown as CommitData<M>;\n}\n\nexport function assertCommitData(v: unknown): asserts v is CommitData<Meta> {\n if (skipCommitDataAsserts) {\n return;\n }\n\n assertObject(v);\n assertDeepFrozen(v);\n assertMeta(v.meta);\n assertString(v.valueHash);\n assertIndexRecords(v.indexes);\n}\n\nfunction validateChunk(chunk: Chunk): asserts chunk is Chunk<CommitData<Meta>> {\n const {data} = chunk;\n assertCommitData(data);\n\n const seen = new Set();\n for (const index of data.indexes) {\n const {name} = index.definition;\n if (seen.has(name)) {\n throw new Error(`Duplicate index ${name}`);\n }\n seen.add(name);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"commit.js","names":[],"sources":["../../../../../replicache/src/db/commit.ts"],"sourcesContent":["import {\n assert,\n assertArray,\n assertBoolean,\n assertNumber,\n assertObject,\n assertString,\n unreachable,\n} from '../../../shared/src/asserts.ts';\nimport {assertJSONValue} from '../../../shared/src/json.ts';\nimport {skipCommitDataAsserts} from '../config.ts';\nimport {type FrozenCookie, compareCookies} from '../cookies.ts';\nimport {type Chunk, type CreateChunk, type Refs, toRefs} from '../dag/chunk.ts';\nimport {type MustGetChunk, type Read, mustGetHeadHash} from '../dag/store.ts';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.ts';\nimport {type Hash, assertHash} from '../hash.ts';\nimport type {IndexDefinition} from '../index-defs.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport * as MetaType from './meta-type-enum.ts';\n\nexport const DEFAULT_HEAD_NAME = 'main';\n\nexport function commitIsLocalDD31(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31> {\n return isLocalMetaDD31(commit.meta);\n}\n\nexport function commitIsLocal(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31> {\n return commitIsLocalDD31(commit);\n}\n\nexport function commitIsSnapshot(\n commit: Commit<Meta>,\n): commit is Commit<SnapshotMetaDD31> {\n return isSnapshotMetaDD31(commit.meta);\n}\n\nexport class Commit<M extends Meta> {\n readonly chunk: Chunk<CommitData<M>>;\n\n constructor(chunk: Chunk<CommitData<M>>) {\n this.chunk = chunk;\n }\n\n get meta(): M {\n return this.chunk.data.meta;\n }\n\n get valueHash(): Hash {\n // Already validated!\n return this.chunk.data.valueHash;\n }\n\n getMutationID(clientID: ClientID, dagRead: MustGetChunk): Promise<number> {\n return getMutationID(clientID, dagRead, this.meta);\n }\n\n async getNextMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n ): Promise<number> {\n return (await this.getMutationID(clientID, dagRead)) + 1;\n }\n\n get indexes(): readonly IndexRecord[] {\n // Already validated!\n return this.chunk.data.indexes;\n }\n}\n\nexport async function getMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n meta: Meta,\n): Promise<number> {\n switch (meta.type) {\n case MetaType.SnapshotDD31:\n return meta.lastMutationIDs[clientID] ?? 0;\n\n case MetaType.LocalDD31: {\n if (meta.clientID === clientID) {\n return meta.mutationID;\n }\n const {basisHash} = meta;\n const basisCommit = await commitFromHash(basisHash, dagRead);\n return getMutationID(clientID, dagRead, basisCommit.meta);\n }\n\n default:\n unreachable(meta);\n }\n}\n\n/**\n * Returns the set of local commits from the given `fromCommitHash` back to but not\n * including its base snapshot. If `fromCommitHash` is a snapshot, the returned vector\n * will be empty. When, as typical, `fromCommitHash` is the head of the default chain\n * then the returned commits are the set of pending commits, ie the set of local commits\n * that have not yet been pushed to the data layer.\n *\n * The vector of commits is returned in reverse chain order, that is, starting\n * with the commit with hash `fromCommitHash` and walking backwards.\n */\nexport async function localMutations(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocal(c)) as Commit<LocalMetaDD31>[];\n}\n\nexport async function localMutationsDD31(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocalDD31(c)) as Commit<LocalMetaDD31>[];\n}\n\nexport async function localMutationsGreaterThan(\n commit: Commit<Meta>,\n mutationIDLimits: Record<ClientID, number>,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits: Commit<LocalMetaDD31>[] = [];\n const remainingMutationIDLimits = new Map(Object.entries(mutationIDLimits));\n while (!commitIsSnapshot(commit) && remainingMutationIDLimits.size > 0) {\n if (commitIsLocalDD31(commit)) {\n const {meta} = commit;\n const mutationIDLowerLimit = remainingMutationIDLimits.get(meta.clientID);\n if (mutationIDLowerLimit !== undefined) {\n if (meta.mutationID <= mutationIDLowerLimit) {\n remainingMutationIDLimits.delete(meta.clientID);\n } else {\n commits.push(commit as Commit<LocalMetaDD31>);\n }\n }\n }\n const {basisHash} = commit.meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n return commits;\n}\n\nexport async function baseSnapshotFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n const hash = await dagRead.getHead(name);\n assert(hash, `Missing head ${name}`);\n return baseSnapshotFromHash(hash, dagRead);\n}\n\nexport async function baseSnapshotHashFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Hash> {\n return (await baseSnapshotFromHash(hash, dagRead)).chunk.hash;\n}\n\nexport async function baseSnapshotFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n const commit = await commitFromHash(hash, dagRead);\n return baseSnapshotFromCommit(commit, dagRead);\n}\n\nexport async function baseSnapshotFromCommit(\n commit: Commit<Meta>,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaDD31>> {\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n if (isLocalMetaDD31(meta)) {\n commit = await commitFromHash(meta.baseSnapshotHash, dagRead);\n } else {\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n }\n return commit;\n}\n\nexport function snapshotMetaParts(\n c: Commit<SnapshotMetaDD31>,\n clientID: ClientID,\n): [lastMutationID: number, cookie: FrozenCookie | FrozenJSONValue] {\n const m = c.meta;\n const lmid = m.lastMutationIDs[clientID] ?? 0;\n return [lmid, m.cookieJSON];\n}\n\nexport function compareCookiesForSnapshots(\n a: Commit<SnapshotMetaDD31>,\n b: Commit<SnapshotMetaDD31>,\n): number {\n return compareCookies(a.meta.cookieJSON, b.meta.cookieJSON);\n}\n\n/**\n * Returns all commits from the commit with fromCommitHash to its base snapshot,\n * inclusive of both. Resulting vector is in chain-head-first order (so snapshot\n * comes last).\n */\nexport async function commitChain(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<Meta>[]> {\n let commit = await commitFromHash(fromCommitHash, dagRead);\n const commits = [];\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commits.push(commit);\n commit = await commitFromHash(basisHash, dagRead);\n }\n commits.push(commit);\n return commits;\n}\n\nexport async function commitFromHash(\n hash: Hash,\n dagRead: MustGetChunk,\n): Promise<Commit<Meta>> {\n const chunk = await dagRead.mustGetChunk(hash);\n return fromChunk(chunk);\n}\n\nexport async function commitFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<Meta>> {\n const hash = await mustGetHeadHash(name, dagRead);\n return commitFromHash(hash, dagRead);\n}\n\nexport type LocalMetaDD31 = {\n readonly type: MetaType.LocalDD31;\n readonly basisHash: Hash;\n readonly mutationID: number;\n readonly mutatorName: string;\n readonly mutatorArgsJSON: FrozenJSONValue;\n readonly originalHash: Hash | null;\n readonly timestamp: number;\n readonly clientID: ClientID;\n readonly baseSnapshotHash: Hash;\n};\n\nexport type LocalMeta = LocalMetaDD31;\n\nexport function assertLocalMetaDD31(\n v: Record<string, unknown>,\n): asserts v is LocalMetaDD31 {\n // type already asserted\n assertString(v.clientID);\n assertNumber(v.mutationID);\n assertString(v.mutatorName);\n if (!v.mutatorName) {\n throw new Error('Missing mutator name');\n }\n assertJSONValue(v.mutatorArgsJSON);\n if (v.originalHash !== null) {\n assertHash(v.originalHash);\n }\n assertNumber(v.timestamp);\n}\n\nexport function isLocalMetaDD31(meta: Meta): meta is LocalMetaDD31 {\n return meta.type === MetaType.LocalDD31;\n}\n\nexport function assertLocalCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<LocalMetaDD31> {\n assertLocalMetaDD31(c.meta);\n}\n\nexport type SnapshotMetaDD31 = {\n readonly type: MetaType.SnapshotDD31;\n readonly basisHash: Hash | null;\n readonly lastMutationIDs: Record<ClientID, number>;\n readonly cookieJSON: FrozenCookie;\n};\n\nexport type SnapshotMeta = SnapshotMetaDD31;\n\nexport function assertSnapshotMetaDD31(\n v: Record<string, unknown>,\n): asserts v is SnapshotMetaDD31 {\n // type already asserted\n if (v.basisHash !== null) {\n assertHash(v.basisHash);\n }\n assertJSONValue(v.cookieJSON);\n assertLastMutationIDs(v.lastMutationIDs);\n}\n\nfunction assertLastMutationIDs(\n v: unknown,\n): asserts v is Record<ClientID, number> {\n assertObject(v);\n for (const e of Object.values(v)) {\n assertNumber(e);\n }\n}\n\nexport type Meta = LocalMetaDD31 | SnapshotMetaDD31;\n\nexport function assertSnapshotCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<SnapshotMetaDD31> {\n assertSnapshotMetaDD31(c.meta);\n}\n\nfunction isSnapshotMetaDD31(meta: Meta): meta is SnapshotMetaDD31 {\n return meta.type === MetaType.SnapshotDD31;\n}\n\nfunction assertMeta(v: unknown): asserts v is Meta {\n assertObject(v);\n assertDeepFrozen(v);\n if (v.basisHash !== null) {\n assertString(v.basisHash);\n }\n\n assertNumber(v.type);\n switch (v.type) {\n case MetaType.LocalDD31:\n assertLocalMetaDD31(v);\n break;\n case MetaType.SnapshotDD31:\n assertSnapshotMetaDD31(v);\n break;\n default:\n throw new Error(`Invalid enum value ${v.type}`);\n }\n}\n\n/**\n * This is the type used for index definitions as defined in the Commit chunk data.\n *\n * Changing this requires a REPLICACHE_FORMAT_VERSION bump.\n */\nexport type ChunkIndexDefinition = {\n readonly name: string;\n readonly keyPrefix: string;\n readonly jsonPointer: string;\n // Used to not exist\n readonly allowEmpty?: boolean;\n};\n\nexport function chunkIndexDefinitionEqualIgnoreName(\n a: ChunkIndexDefinition,\n b: ChunkIndexDefinition,\n): boolean {\n return (\n a.jsonPointer === b.jsonPointer &&\n (a.allowEmpty ?? false) === (b.allowEmpty ?? false) &&\n a.keyPrefix === b.keyPrefix\n );\n}\n\nfunction assertChunkIndexDefinition(\n v: unknown,\n): asserts v is ChunkIndexDefinition {\n assertObject(v);\n assertDeepFrozen(v);\n assertString(v.name);\n assertString(v.keyPrefix);\n assertString(v.jsonPointer);\n if (v.allowEmpty !== undefined) {\n assertBoolean(v.allowEmpty);\n }\n}\n\nexport function toChunkIndexDefinition(\n name: string,\n indexDefinition: IndexDefinition,\n): Required<ChunkIndexDefinition> {\n return {\n name,\n keyPrefix: indexDefinition.prefix ?? '',\n jsonPointer: indexDefinition.jsonPointer,\n allowEmpty: indexDefinition.allowEmpty ?? false,\n };\n}\n\nexport type IndexRecord = {\n readonly definition: ChunkIndexDefinition;\n readonly valueHash: Hash;\n};\n\nfunction assertIndexRecord(v: unknown): asserts v is IndexRecord {\n assertObject(v);\n assertDeepFrozen(v);\n assertChunkIndexDefinition(v.definition);\n assertString(v.valueHash);\n}\n\nfunction assertIndexRecords(v: unknown): asserts v is IndexRecord[] {\n assertArray(v);\n assertDeepFrozen(v);\n for (const ir of v) {\n assertIndexRecord(ir);\n }\n}\n\nexport function newLocalDD31(\n createChunk: CreateChunk,\n basisHash: Hash,\n baseSnapshotHash: Hash,\n mutationID: number,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n timestamp: number,\n clientID: ClientID,\n): Commit<LocalMetaDD31> {\n const meta: LocalMetaDD31 = {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n clientID,\n };\n return commitFromCommitData(\n createChunk,\n makeCommitData(meta, valueHash, indexes),\n );\n}\n\nexport function newSnapshotDD31(\n createChunk: CreateChunk,\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): Commit<SnapshotMetaDD31> {\n return commitFromCommitData(\n createChunk,\n newSnapshotCommitDataDD31(\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexes,\n ),\n );\n}\n\nexport function newSnapshotCommitDataDD31(\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<SnapshotMetaDD31> {\n const meta: SnapshotMetaDD31 = {\n type: MetaType.SnapshotDD31,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n };\n return makeCommitData(meta, valueHash, indexes);\n}\n\nexport function fromChunk(chunk: Chunk): Commit<Meta> {\n validateChunk(chunk);\n return new Commit(chunk);\n}\n\nfunction commitFromCommitData<M extends Meta>(\n createChunk: CreateChunk,\n data: CommitData<M>,\n): Commit<M> {\n return new Commit(createChunk(data, getRefs(data)));\n}\n\nexport function getRefs(data: CommitData<Meta>): Refs {\n const refs: Set<Hash> = new Set();\n refs.add(data.valueHash);\n const {meta} = data;\n switch (meta.type) {\n case MetaType.LocalDD31:\n meta.basisHash && refs.add(meta.basisHash);\n // Local has weak originalHash\n break;\n case MetaType.SnapshotDD31:\n // Snapshot has weak basisHash\n break;\n default:\n unreachable(meta);\n }\n\n for (const index of data.indexes) {\n refs.add(index.valueHash);\n }\n\n return toRefs(refs);\n}\n\nexport type CommitData<M extends Meta> = FrozenTag<{\n readonly meta: M;\n readonly valueHash: Hash;\n readonly indexes: readonly IndexRecord[];\n}>;\n\nexport function makeCommitData<M extends Meta>(\n meta: M,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<M> {\n return deepFreeze({\n meta,\n valueHash,\n indexes,\n }) as unknown as CommitData<M>;\n}\n\nexport function assertCommitData(v: unknown): asserts v is CommitData<Meta> {\n if (skipCommitDataAsserts) {\n return;\n }\n\n assertObject(v);\n assertDeepFrozen(v);\n assertMeta(v.meta);\n assertString(v.valueHash);\n assertIndexRecords(v.indexes);\n}\n\nfunction validateChunk(chunk: Chunk): asserts chunk is Chunk<CommitData<Meta>> {\n const {data} = chunk;\n assertCommitData(data);\n\n const seen = new Set();\n for (const index of data.indexes) {\n const {name} = index.definition;\n if (seen.has(name)) {\n throw new Error(`Duplicate index ${name}`);\n }\n seen.add(name);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,EAAC,IAAI,IAAI,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAEL,KAAK,IAAI,EAGV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAErC,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD,qBAAa,IAAI;;IAEf,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;gBAGvC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAOjC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAItD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAI3B,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAQ5C,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAYD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EACpB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/read.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,EAAC,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAC3C,OAAO,KAAK,EAAC,IAAI,IAAI,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EAEL,KAAK,IAAI,EAGV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,SAAS,EAAC,MAAM,YAAY,CAAC;AAErC,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD,qBAAa,IAAI;;IAEf,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;gBAGvC,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC;IAOjC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAItD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;IAI3B,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAQ5C,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI;CAGd;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,IAAI,CAAC,CAGf;AAYD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EACpB,OAAO,EAAE,OAAO,EAChB,aAAa,EAAE,aAAa,GAC3B,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAexB"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BTreeRead } from "../btree/read.js";
|
|
2
2
|
import { DEFAULT_HEAD_NAME, commitFromHash, commitFromHead } from "./commit.js";
|
|
3
|
-
import { IndexRead } from "./index.js";
|
|
4
3
|
//#region ../replicache/src/db/read.ts
|
|
5
4
|
var Read = class {
|
|
6
5
|
#dagRead;
|
|
@@ -46,9 +45,7 @@ function readFromCommit(commit, dagRead, formatVersion) {
|
|
|
46
45
|
return new Read(dagRead, new BTreeRead(dagRead, formatVersion, commit.valueHash), indexes);
|
|
47
46
|
}
|
|
48
47
|
function readIndexesForRead(commit, dagRead, formatVersion) {
|
|
49
|
-
|
|
50
|
-
for (const index of commit.indexes) m.set(index.definition.name, new IndexRead(index, new BTreeRead(dagRead, formatVersion, index.valueHash)));
|
|
51
|
-
return m;
|
|
48
|
+
return /* @__PURE__ */ new Map();
|
|
52
49
|
}
|
|
53
50
|
//#endregion
|
|
54
51
|
export { Read, readFromDefaultHead, readFromHash, readIndexesForRead };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","names":["#dagRead"],"sources":["../../../../../replicache/src/db/read.ts"],"sourcesContent":["import type {Enum} from '../../../shared/src/enum.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport type {Read as DagRead} from '../dag/store.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport type {Hash} from '../hash.ts';\nimport type {Commit} from './commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type Meta,\n commitFromHash,\n commitFromHead,\n} from './commit.ts';\nimport {IndexRead} from './index.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport class Read {\n readonly #dagRead: DagRead;\n map: BTreeRead;\n readonly indexes: Map<string, IndexRead>;\n\n constructor(\n dagRead: DagRead,\n map: BTreeRead,\n indexes: Map<string, IndexRead>,\n ) {\n this.#dagRead = dagRead;\n this.map = map;\n this.indexes = indexes;\n }\n\n has(key: string): Promise<boolean> {\n return this.map.has(key);\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return this.map.get(key);\n }\n\n isEmpty(): Promise<boolean> {\n return this.map.isEmpty();\n }\n\n getMapForIndex(indexName: string): BTreeRead {\n const idx = this.indexes.get(indexName);\n if (idx === undefined) {\n throw new Error(`Unknown index name: ${indexName}`);\n }\n return idx.map;\n }\n\n get closed(): boolean {\n return this.#dagRead.closed;\n }\n\n close(): void {\n this.#dagRead.release();\n }\n}\n\nexport function readFromDefaultHead(\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n return readFromHead(DEFAULT_HEAD_NAME, dagRead, formatVersion);\n}\n\nexport async function readFromHead(\n name: string,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHead(name, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nexport async function readFromHash(\n hash: Hash,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHash(hash, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nfunction readFromCommit(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Read {\n const indexes = readIndexesForRead(commit, dagRead, formatVersion);\n const map = new BTreeRead(dagRead, formatVersion, commit.valueHash);\n return new Read(dagRead, map, indexes);\n}\n\nexport function readIndexesForRead(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Map<string, IndexRead> {\n const m = new Map();\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexRead(\n index,\n new BTreeRead(dagRead, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"read.js","names":["#dagRead"],"sources":["../../../../../replicache/src/db/read.ts"],"sourcesContent":["import '../process-env.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport type {Read as DagRead} from '../dag/store.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport type {Hash} from '../hash.ts';\nimport type {Commit} from './commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type Meta,\n commitFromHash,\n commitFromHead,\n} from './commit.ts';\nimport {IndexRead} from './index.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport class Read {\n readonly #dagRead: DagRead;\n map: BTreeRead;\n readonly indexes: Map<string, IndexRead>;\n\n constructor(\n dagRead: DagRead,\n map: BTreeRead,\n indexes: Map<string, IndexRead>,\n ) {\n this.#dagRead = dagRead;\n this.map = map;\n this.indexes = indexes;\n }\n\n has(key: string): Promise<boolean> {\n return this.map.has(key);\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return this.map.get(key);\n }\n\n isEmpty(): Promise<boolean> {\n return this.map.isEmpty();\n }\n\n getMapForIndex(indexName: string): BTreeRead {\n const idx = this.indexes.get(indexName);\n if (idx === undefined) {\n throw new Error(`Unknown index name: ${indexName}`);\n }\n return idx.map;\n }\n\n get closed(): boolean {\n return this.#dagRead.closed;\n }\n\n close(): void {\n this.#dagRead.release();\n }\n}\n\nexport function readFromDefaultHead(\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n return readFromHead(DEFAULT_HEAD_NAME, dagRead, formatVersion);\n}\n\nexport async function readFromHead(\n name: string,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHead(name, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nexport async function readFromHash(\n hash: Hash,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHash(hash, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nfunction readFromCommit(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Read {\n const indexes = readIndexesForRead(commit, dagRead, formatVersion);\n const map = new BTreeRead(dagRead, formatVersion, commit.valueHash);\n return new Read(dagRead, map, indexes);\n}\n\nexport function readIndexesForRead(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Map<string, IndexRead> {\n const m: Map<string, IndexRead> = new Map();\n if (process.env.DISABLE_REPLICACHE_INDEXES) {\n return m;\n }\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexRead(\n index,\n new BTreeRead(dagRead, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n"],"mappings":";;;AAkBA,IAAa,OAAb,MAAkB;CAChB;CACA;CACA;CAEA,YACE,SACA,KACA,SACA;EACA,KAAKA,WAAW;EAChB,KAAK,MAAM;EACX,KAAK,UAAU;CACjB;CAEA,IAAI,KAA+B;EACjC,OAAO,KAAK,IAAI,IAAI,GAAG;CACzB;CAEA,IAAI,KAAmD;EACrD,OAAO,KAAK,IAAI,IAAI,GAAG;CACzB;CAEA,UAA4B;EAC1B,OAAO,KAAK,IAAI,QAAQ;CAC1B;CAEA,eAAe,WAA8B;EAC3C,MAAM,MAAM,KAAK,QAAQ,IAAI,SAAS;EACtC,IAAI,QAAQ,KAAA,GACV,MAAM,IAAI,MAAM,uBAAuB,WAAW;EAEpD,OAAO,IAAI;CACb;CAEA,IAAI,SAAkB;EACpB,OAAO,KAAKA,SAAS;CACvB;CAEA,QAAc;EACZ,KAAKA,SAAS,QAAQ;CACxB;AACF;AAEA,SAAgB,oBACd,SACA,eACe;CACf,OAAO,aAAa,mBAAmB,SAAS,aAAa;AAC/D;AAEA,eAAsB,aACpB,MACA,SACA,eACe;CAEf,OAAO,eAAe,MADD,eAAe,MAAM,OAAO,GACnB,SAAS,aAAa;AACtD;AAEA,eAAsB,aACpB,MACA,SACA,eACe;CAEf,OAAO,eAAe,MADD,eAAe,MAAM,OAAO,GACnB,SAAS,aAAa;AACtD;AAEA,SAAS,eACP,QACA,SACA,eACM;CACN,MAAM,UAAU,mBAAmB,QAAQ,SAAS,aAAa;CAEjE,OAAO,IAAI,KAAK,SAAS,IADT,UAAU,SAAS,eAAe,OAAO,SAChC,GAAK,OAAO;AACvC;AAEA,SAAgB,mBACd,QACA,SACA,eACwB;CAGtB,uBAAO,IAF6B,IAE7B;AAYX"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import '../process-env.ts';
|
|
1
2
|
import type { LogContext } from '@rocicorp/logger';
|
|
2
3
|
import type { Enum } from '../../../shared/src/enum.ts';
|
|
3
4
|
import { BTreeRead } from '../btree/read.ts';
|
|
@@ -43,7 +44,7 @@ export declare class Write extends Read {
|
|
|
43
44
|
}
|
|
44
45
|
export declare function newWriteLocal(basisHash: Hash, mutatorName: string, mutatorArgsJSON: FrozenJSONValue, originalHash: Hash | null, dagWrite: DagWrite, timestamp: number, clientID: ClientID, formatVersion: FormatVersion): Promise<Write>;
|
|
45
46
|
export declare function newWriteSnapshotDD31(basisHash: Hash, lastMutationIDs: Record<ClientID, number>, cookieJSON: FrozenCookie, dagWrite: DagWrite, clientID: ClientID, formatVersion: FormatVersion): Promise<Write>;
|
|
46
|
-
export declare function updateIndexes(lc: LogContext, indexes: Map<string, IndexWrite>, key: string,
|
|
47
|
+
export declare function updateIndexes(lc: LogContext, map: BTreeRead, indexes: Map<string, IndexWrite>, key: string, newVal: FrozenJSONValue | undefined): Promise<void>;
|
|
47
48
|
export declare function readIndexesForWrite(commit: Commit<CommitMeta>, dagWrite: DagWrite, formatVersion: FormatVersion): Map<string, IndexWrite>;
|
|
48
49
|
export declare function createIndexBTree(lc: LogContext, dagWrite: DagWrite, valueMap: BTreeRead, prefix: string, jsonPointer: string, allowEmpty: boolean, formatVersion: FormatVersion): Promise<BTreeWrite>;
|
|
49
50
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,EAAC,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAC,KAAK,IAAI,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/db/write.ts"],"names":[],"mappings":"AAAA,OAAO,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAEjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AAGtD,OAAO,EAAC,SAAS,EAAmB,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAC,UAAU,EAAC,MAAM,mBAAmB,CAAC;AAC7C,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,eAAe,CAAC;AAChD,OAAO,KAAK,EAAC,KAAK,IAAI,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAC,KAAK,IAAI,EAAY,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AACzC,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,aAAa,CAAC;AACxC,OAAO,EACL,KAAK,IAAI,IAAI,UAAU,EAQxB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAC,UAAU,EAAa,MAAM,YAAY,CAAC;AAElD,OAAO,EAAC,IAAI,EAAqB,MAAM,WAAW,CAAC;AAEnD,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAEhD,qBAAa,KAAM,SAAQ,IAAI;;IAKrB,GAAG,EAAE,UAAU,CAAC;IAExB,SAAiB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAKhD,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,GAAG,SAAS,EACrC,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAChC,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa;IAwB9B;;;OAGG;IACG,GAAG,CACP,EAAE,EAAE,UAAU,EACd,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,eAAe,GACrB,OAAO,CAAC,IAAI,CAAC;IAOhB;;;;;;OAMG;IACG,OAAO,CACX,EAAE,EAAE,UAAU,EACd,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC,GACzD,OAAO,CAAC,IAAI,CAAC;IAiBhB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAI1B,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOlD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAStB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAmExC,MAAM,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQvC,eAAe,CACnB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAmE5B,KAAK,IAAI,IAAI;CAGd;AAED,wBAAsB,aAAa,CACjC,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,eAAe,EAChC,YAAY,EAAE,IAAI,GAAG,IAAI,EACzB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,KAAK,CAAC,CA6BhB;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,IAAI,EACf,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,EACzC,UAAU,EAAE,YAAY,EACxB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,KAAK,CAAC,CAYhB;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,UAAU,EACd,GAAG,EAAE,SAAS,EACd,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,eAAe,GAAG,SAAS,GAClC,OAAO,CAAC,IAAI,CAAC,CAqCf;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,UAAU,CAAC,EAC1B,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,aAAa,GAC3B,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAezB;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,UAAU,EACd,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,SAAS,EACnB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,OAAO,EACnB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,UAAU,CAAC,CAkBrB"}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { assert } from "../../../shared/src/asserts.js";
|
|
2
2
|
import { emptyHash } from "../hash.js";
|
|
3
|
-
import { BTreeRead
|
|
3
|
+
import { BTreeRead } from "../btree/read.js";
|
|
4
4
|
import { baseSnapshotHashFromHash, commitFromHash, getMutationID, newLocalDD31, newSnapshotDD31 } from "./commit.js";
|
|
5
5
|
import { diff } from "../btree/diff.js";
|
|
6
6
|
import { BTreeWrite } from "../btree/write.js";
|
|
7
|
-
import {
|
|
8
|
-
import { IndexWrite, indexValue } from "./index.js";
|
|
9
|
-
import { Read, readIndexesForRead } from "./read.js";
|
|
7
|
+
import { Read } from "./read.js";
|
|
10
8
|
import { DiffsMap } from "../sync/diff.js";
|
|
11
9
|
//#region ../replicache/src/db/write.ts
|
|
12
10
|
var Write = class extends Read {
|
|
@@ -30,8 +28,6 @@ var Write = class extends Read {
|
|
|
30
28
|
* comparison as well as returned in `get`.
|
|
31
29
|
*/
|
|
32
30
|
async put(lc, key, value) {
|
|
33
|
-
const oldVal = lazy(() => this.map.get(key));
|
|
34
|
-
await updateIndexes(lc, this.indexes, key, oldVal, value);
|
|
35
31
|
await this.map.put(key, value);
|
|
36
32
|
}
|
|
37
33
|
/**
|
|
@@ -43,18 +39,12 @@ var Write = class extends Read {
|
|
|
43
39
|
*/
|
|
44
40
|
async putMany(lc, entries) {
|
|
45
41
|
if (entries.length === 0) return;
|
|
46
|
-
if (this.indexes.size > 0) for (const [key, value] of entries) {
|
|
47
|
-
const oldVal = lazy(() => this.map.get(key));
|
|
48
|
-
await updateIndexes(lc, this.indexes, key, oldVal, value);
|
|
49
|
-
}
|
|
50
42
|
await this.map.putMany(entries);
|
|
51
43
|
}
|
|
52
44
|
getMutationID() {
|
|
53
45
|
return getMutationID(this.#clientID, this.#dagWrite, this.#meta);
|
|
54
46
|
}
|
|
55
47
|
async del(lc, key) {
|
|
56
|
-
const oldVal = lazy(() => this.map.get(key));
|
|
57
|
-
if (oldVal !== void 0) await updateIndexes(lc, this.indexes, key, oldVal, void 0);
|
|
58
48
|
return this.map.del(key);
|
|
59
49
|
}
|
|
60
50
|
async clear() {
|
|
@@ -113,20 +103,6 @@ var Write = class extends Read {
|
|
|
113
103
|
let valueDiff = [];
|
|
114
104
|
if (this.#basis) valueDiff = await diff(new BTreeRead(this.#dagWrite, this.#formatVersion, this.#basis.valueHash), this.map);
|
|
115
105
|
diffsMap.set("", valueDiff);
|
|
116
|
-
let basisIndexes;
|
|
117
|
-
if (this.#basis) basisIndexes = readIndexesForRead(this.#basis, this.#dagWrite, this.#formatVersion);
|
|
118
|
-
else basisIndexes = /* @__PURE__ */ new Map();
|
|
119
|
-
for (const [name, index] of this.indexes) {
|
|
120
|
-
if (!diffConfig.shouldComputeDiffsForIndex(name)) continue;
|
|
121
|
-
const basisIndex = basisIndexes.get(name);
|
|
122
|
-
assert(index !== basisIndex, "Expected index to differ from basisIndex");
|
|
123
|
-
const indexDiffResult = await (basisIndex ? diff(basisIndex.map, index.map) : allEntriesAsDiff(index.map, "add"));
|
|
124
|
-
diffsMap.set(name, indexDiffResult);
|
|
125
|
-
}
|
|
126
|
-
for (const [name, basisIndex] of basisIndexes) if (!this.indexes.has(name) && diffConfig.shouldComputeDiffsForIndex(name)) {
|
|
127
|
-
const indexDiffResult = await allEntriesAsDiff(basisIndex.map, "del");
|
|
128
|
-
diffsMap.set(name, indexDiffResult);
|
|
129
|
-
}
|
|
130
106
|
return diffsMap;
|
|
131
107
|
}
|
|
132
108
|
close() {
|
|
@@ -160,33 +136,10 @@ async function newWriteSnapshotDD31(basisHash, lastMutationIDs, cookieJSON, dagW
|
|
|
160
136
|
cookieJSON
|
|
161
137
|
}, readIndexesForWrite(basis, dagWrite, formatVersion), clientID, formatVersion);
|
|
162
138
|
}
|
|
163
|
-
async function updateIndexes(lc, indexes, key, oldValGetter, newVal) {
|
|
164
|
-
const ps = [];
|
|
165
|
-
for (const idx of indexes.values()) {
|
|
166
|
-
const { keyPrefix } = idx.meta.definition;
|
|
167
|
-
if (!keyPrefix || key.startsWith(keyPrefix)) {
|
|
168
|
-
const oldVal = await oldValGetter();
|
|
169
|
-
if (oldVal !== void 0) ps.push(indexValue(lc, idx.map, 1, key, oldVal, idx.meta.definition.jsonPointer, idx.meta.definition.allowEmpty ?? false));
|
|
170
|
-
if (newVal !== void 0) ps.push(indexValue(lc, idx.map, 0, key, newVal, idx.meta.definition.jsonPointer, idx.meta.definition.allowEmpty ?? false));
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
await Promise.all(ps);
|
|
174
|
-
}
|
|
175
139
|
function readIndexesForWrite(commit, dagWrite, formatVersion) {
|
|
176
|
-
|
|
177
|
-
for (const index of commit.indexes) m.set(index.definition.name, new IndexWrite(index, new BTreeWrite(dagWrite, formatVersion, index.valueHash)));
|
|
178
|
-
return m;
|
|
179
|
-
}
|
|
180
|
-
async function createIndexBTree(lc, dagWrite, valueMap, prefix, jsonPointer, allowEmpty, formatVersion) {
|
|
181
|
-
const indexMap = new BTreeWrite(dagWrite, formatVersion);
|
|
182
|
-
for await (const entry of valueMap.scan(prefix)) {
|
|
183
|
-
const key = entry[0];
|
|
184
|
-
if (!key.startsWith(prefix)) break;
|
|
185
|
-
await indexValue(lc, indexMap, 0, key, entry[1], jsonPointer, allowEmpty);
|
|
186
|
-
}
|
|
187
|
-
return indexMap;
|
|
140
|
+
return /* @__PURE__ */ new Map();
|
|
188
141
|
}
|
|
189
142
|
//#endregion
|
|
190
|
-
export {
|
|
143
|
+
export { newWriteLocal, newWriteSnapshotDD31 };
|
|
191
144
|
|
|
192
145
|
//# sourceMappingURL=write.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","names":["#dagWrite","#basis","#meta","#clientID","#formatVersion","#generateDiffs"],"sources":["../../../../../replicache/src/db/write.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {diff} from '../btree/diff.ts';\nimport type {InternalDiff} from '../btree/node.ts';\nimport {BTreeRead, allEntriesAsDiff} from '../btree/read.ts';\nimport {BTreeWrite} from '../btree/write.ts';\nimport type {FrozenCookie} from '../cookies.ts';\nimport type {Write as DagWrite} from '../dag/store.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {type Hash, emptyHash} from '../hash.ts';\nimport {lazy} from '../lazy.ts';\nimport type {DiffComputationConfig} from '../sync/diff.ts';\nimport {DiffsMap} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {Commit} from './commit.ts';\nimport {\n type Meta as CommitMeta,\n type IndexRecord,\n type Meta,\n baseSnapshotHashFromHash,\n commitFromHash,\n newLocalDD31 as commitNewLocalDD31,\n newSnapshotDD31 as commitNewSnapshotDD31,\n getMutationID,\n} from './commit.ts';\nimport * as IndexOperation from './index-operation-enum.ts';\nimport type {IndexRead} from './index.ts';\nimport {IndexWrite, indexValue} from './index.ts';\nimport * as MetaType from './meta-type-enum.ts';\nimport {Read, readIndexesForRead} from './read.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport class Write extends Read {\n readonly #dagWrite: DagWrite;\n readonly #basis: Commit<CommitMeta> | undefined;\n readonly #meta: CommitMeta;\n\n declare map: BTreeWrite;\n\n declare readonly indexes: Map<string, IndexWrite>;\n readonly #clientID: ClientID;\n readonly #formatVersion: FormatVersion;\n\n constructor(\n dagWrite: DagWrite,\n map: BTreeWrite,\n basis: Commit<CommitMeta> | undefined,\n meta: CommitMeta,\n indexes: Map<string, IndexWrite>,\n clientID: ClientID,\n formatVersion: FormatVersion,\n ) {\n // TypeScript has trouble\n super(dagWrite, map, indexes);\n this.#dagWrite = dagWrite;\n this.#basis = basis;\n this.#meta = meta;\n this.#clientID = clientID;\n this.#formatVersion = formatVersion;\n\n // TODO(arv): if (DEBUG) { ...\n if (basis === undefined) {\n assert(\n meta.basisHash === emptyHash,\n 'Expected basisHash to be emptyHash when basis is undefined',\n );\n } else {\n assert(\n meta.basisHash === basis.chunk.hash,\n 'Expected meta.basisHash to equal basis.chunk.hash',\n );\n }\n }\n\n /**\n * The value needs to be frozen since it is kept in memory and used later for\n * comparison as well as returned in `get`.\n */\n async put(\n lc: LogContext,\n key: string,\n value: FrozenJSONValue,\n ): Promise<void> {\n const oldVal = lazy(() => this.map.get(key));\n await updateIndexes(lc, this.indexes, key, oldVal, value);\n\n await this.map.put(key, value);\n }\n\n /**\n * Inserts or updates multiple entries in a single bulk operation. More\n * efficient than calling {@link put} in a loop because it uses\n * {@link BTreeWrite.putMany} to build or merge tree nodes in one pass.\n *\n * `entries` must be sorted in ascending key order.\n */\n async putMany(\n lc: LogContext,\n entries: ReadonlyArray<readonly [string, FrozenJSONValue]>,\n ): Promise<void> {\n if (entries.length === 0) {\n return;\n }\n\n // Update indexes for all entries\n if (this.indexes.size > 0) {\n // TODO(arv): Indexes can use the optimizePatch pattern too.\n for (const [key, value] of entries) {\n const oldVal = lazy(() => this.map.get(key));\n await updateIndexes(lc, this.indexes, key, oldVal, value);\n }\n }\n\n // BTreeWrite.putMany handles both empty and non-empty trees optimally\n await this.map.putMany(entries);\n }\n\n getMutationID(): Promise<number> {\n return getMutationID(this.#clientID, this.#dagWrite, this.#meta);\n }\n\n async del(lc: LogContext, key: string): Promise<boolean> {\n // TODO(arv): This does the binary search twice. We can do better.\n const oldVal = lazy(() => this.map.get(key));\n if (oldVal !== undefined) {\n await updateIndexes(lc, this.indexes, key, oldVal, undefined);\n }\n return this.map.del(key);\n }\n\n async clear(): Promise<void> {\n await this.map.clear();\n const ps = [];\n for (const idx of this.indexes.values()) {\n ps.push(idx.clear());\n }\n await Promise.all(ps);\n }\n\n async putCommit(): Promise<Commit<CommitMeta>> {\n const valueHash = await this.map.flush();\n const indexRecords: IndexRecord[] = [];\n\n for (const index of this.indexes.values()) {\n const valueHash = await index.flush();\n const indexRecord: IndexRecord = {\n definition: index.meta.definition,\n valueHash,\n };\n indexRecords.push(indexRecord);\n }\n\n let commit: Commit<Meta>;\n const meta = this.#meta;\n switch (meta.type) {\n case MetaType.LocalDD31: {\n assert(\n this.#formatVersion >= FormatVersion.DD31,\n 'Expected formatVersion >= DD31 for LocalDD31 commit',\n );\n const {\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n } = meta;\n commit = commitNewLocalDD31(\n this.#dagWrite.createChunk,\n basisHash,\n await baseSnapshotHashFromHash(basisHash, this.#dagWrite),\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n valueHash,\n indexRecords,\n timestamp,\n this.#clientID,\n );\n break;\n }\n\n case MetaType.SnapshotDD31: {\n assert(\n this.#formatVersion > FormatVersion.DD31,\n 'Expected formatVersion > DD31 for SnapshotDD31 commit',\n );\n const {basisHash, lastMutationIDs, cookieJSON} = meta;\n commit = commitNewSnapshotDD31(\n this.#dagWrite.createChunk,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexRecords,\n );\n break;\n }\n }\n await this.#dagWrite.putChunk(commit.chunk);\n return commit;\n }\n\n // Return value is the hash of the new commit.\n async commit(headName: string): Promise<Hash> {\n const commit = await this.putCommit();\n const commitHash = commit.chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return commitHash;\n }\n\n async commitWithDiffs(\n headName: string,\n diffConfig: DiffComputationConfig,\n ): Promise<[Hash, DiffsMap]> {\n const commit = this.putCommit();\n const diffMap = await this.#generateDiffs(diffConfig);\n const commitHash = (await commit).chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return [commitHash, diffMap];\n }\n\n async #generateDiffs(diffConfig: DiffComputationConfig): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n let valueDiff: InternalDiff = [];\n if (this.#basis) {\n const basisMap = new BTreeRead(\n this.#dagWrite,\n this.#formatVersion,\n this.#basis.valueHash,\n );\n valueDiff = await diff(basisMap, this.map);\n }\n diffsMap.set('', valueDiff);\n let basisIndexes: Map<string, IndexRead>;\n if (this.#basis) {\n basisIndexes = readIndexesForRead(\n this.#basis,\n this.#dagWrite,\n this.#formatVersion,\n );\n } else {\n basisIndexes = new Map();\n }\n\n for (const [name, index] of this.indexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(name)) {\n continue;\n }\n const basisIndex = basisIndexes.get(name);\n assert(index !== basisIndex, 'Expected index to differ from basisIndex');\n\n const indexDiffResult = await (basisIndex\n ? diff(basisIndex.map, index.map)\n : // No basis. All keys are new.\n allEntriesAsDiff(index.map, 'add'));\n diffsMap.set(name, indexDiffResult);\n }\n\n // Handle indexes in basisIndex but not in this.indexes. All keys are\n // deleted.\n for (const [name, basisIndex] of basisIndexes) {\n if (\n !this.indexes.has(name) &&\n diffConfig.shouldComputeDiffsForIndex(name)\n ) {\n const indexDiffResult = await allEntriesAsDiff(basisIndex.map, 'del');\n diffsMap.set(name, indexDiffResult);\n }\n }\n return diffsMap;\n }\n\n close(): void {\n this.#dagWrite.release();\n }\n}\n\nexport async function newWriteLocal(\n basisHash: Hash,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n dagWrite: DagWrite,\n timestamp: number,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n const mutationID = await basis.getNextMutationID(clientID, dagWrite);\n const indexes = readIndexesForWrite(basis, dagWrite, formatVersion);\n assert(\n formatVersion >= FormatVersion.DD31,\n 'Expected formatVersion >= DD31 for newWriteLocal',\n );\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n\n {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash: await baseSnapshotHashFromHash(basisHash, dagWrite),\n mutatorName,\n mutatorArgsJSON,\n mutationID,\n originalHash,\n timestamp,\n clientID,\n },\n indexes,\n clientID,\n formatVersion,\n );\n}\n\nexport async function newWriteSnapshotDD31(\n basisHash: Hash,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n dagWrite: DagWrite,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n {basisHash, type: MetaType.SnapshotDD31, lastMutationIDs, cookieJSON},\n readIndexesForWrite(basis, dagWrite, formatVersion),\n clientID,\n formatVersion,\n );\n}\n\nexport async function updateIndexes(\n lc: LogContext,\n indexes: Map<string, IndexWrite>,\n key: string,\n oldValGetter: () => Promise<FrozenJSONValue | undefined>,\n newVal: FrozenJSONValue | undefined,\n): Promise<void> {\n const ps: Promise<void>[] = [];\n for (const idx of indexes.values()) {\n const {keyPrefix} = idx.meta.definition;\n if (!keyPrefix || key.startsWith(keyPrefix)) {\n const oldVal = await oldValGetter();\n if (oldVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Remove,\n key,\n oldVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n if (newVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Add,\n key,\n newVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n }\n }\n await Promise.all(ps);\n}\n\nexport function readIndexesForWrite(\n commit: Commit<CommitMeta>,\n dagWrite: DagWrite,\n formatVersion: FormatVersion,\n): Map<string, IndexWrite> {\n const m = new Map();\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexWrite(\n index,\n new BTreeWrite(dagWrite, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n\nexport async function createIndexBTree(\n lc: LogContext,\n dagWrite: DagWrite,\n valueMap: BTreeRead,\n prefix: string,\n jsonPointer: string,\n allowEmpty: boolean,\n formatVersion: FormatVersion,\n): Promise<BTreeWrite> {\n const indexMap = new BTreeWrite(dagWrite, formatVersion);\n for await (const entry of valueMap.scan(prefix)) {\n const key = entry[0];\n if (!key.startsWith(prefix)) {\n break;\n }\n await indexValue(\n lc,\n indexMap,\n IndexOperation.Add,\n key,\n entry[1],\n jsonPointer,\n allowEmpty,\n );\n }\n return indexMap;\n}\n"],"mappings":";;;;;;;;;;;AAmCA,IAAa,QAAb,cAA2B,KAAK;CAC9B;CACA;CACA;CAKA;CACA;CAEA,YACE,UACA,KACA,OACA,MACA,SACA,UACA,eACA;EAEA,MAAM,UAAU,KAAK,OAAO;EAC5B,KAAKA,YAAY;EACjB,KAAKC,SAAS;EACd,KAAKC,QAAQ;EACb,KAAKC,YAAY;EACjB,KAAKC,iBAAiB;EAGtB,IAAI,UAAU,KAAA,GACZ,OACE,KAAK,cAAc,WACnB,4DACF;OAEA,OACE,KAAK,cAAc,MAAM,MAAM,MAC/B,mDACF;CAEJ;;;;;CAMA,MAAM,IACJ,IACA,KACA,OACe;EACf,MAAM,SAAS,WAAW,KAAK,IAAI,IAAI,GAAG,CAAC;EAC3C,MAAM,cAAc,IAAI,KAAK,SAAS,KAAK,QAAQ,KAAK;EAExD,MAAM,KAAK,IAAI,IAAI,KAAK,KAAK;CAC/B;;;;;;;;CASA,MAAM,QACJ,IACA,SACe;EACf,IAAI,QAAQ,WAAW,GACrB;EAIF,IAAI,KAAK,QAAQ,OAAO,GAEtB,KAAK,MAAM,CAAC,KAAK,UAAU,SAAS;GAClC,MAAM,SAAS,WAAW,KAAK,IAAI,IAAI,GAAG,CAAC;GAC3C,MAAM,cAAc,IAAI,KAAK,SAAS,KAAK,QAAQ,KAAK;EAC1D;EAIF,MAAM,KAAK,IAAI,QAAQ,OAAO;CAChC;CAEA,gBAAiC;EAC/B,OAAO,cAAc,KAAKD,WAAW,KAAKH,WAAW,KAAKE,KAAK;CACjE;CAEA,MAAM,IAAI,IAAgB,KAA+B;EAEvD,MAAM,SAAS,WAAW,KAAK,IAAI,IAAI,GAAG,CAAC;EAC3C,IAAI,WAAW,KAAA,GACb,MAAM,cAAc,IAAI,KAAK,SAAS,KAAK,QAAQ,KAAA,CAAS;EAE9D,OAAO,KAAK,IAAI,IAAI,GAAG;CACzB;CAEA,MAAM,QAAuB;EAC3B,MAAM,KAAK,IAAI,MAAM;EACrB,MAAM,KAAK,CAAC;EACZ,KAAK,MAAM,OAAO,KAAK,QAAQ,OAAO,GACpC,GAAG,KAAK,IAAI,MAAM,CAAC;EAErB,MAAM,QAAQ,IAAI,EAAE;CACtB;CAEA,MAAM,YAAyC;EAC7C,MAAM,YAAY,MAAM,KAAK,IAAI,MAAM;EACvC,MAAM,eAA8B,CAAC;EAErC,KAAK,MAAM,SAAS,KAAK,QAAQ,OAAO,GAAG;GACzC,MAAM,YAAY,MAAM,MAAM,MAAM;GACpC,MAAM,cAA2B;IAC/B,YAAY,MAAM,KAAK;IACvB;GACF;GACA,aAAa,KAAK,WAAW;EAC/B;EAEA,IAAI;EACJ,MAAM,OAAO,KAAKA;EAClB,QAAQ,KAAK,MAAb;GACE,KAAK,GAAoB;IACvB,OACE,KAAKE,kBAAkB,GACvB,qDACF;IACA,MAAM,EACJ,WACA,YACA,aACA,iBACA,cACA,cACE;IACJ,SAAS,aACP,KAAKJ,UAAU,aACf,WACA,MAAM,yBAAyB,WAAW,KAAKA,SAAS,GACxD,YACA,aACA,iBACA,cACA,WACA,cACA,WACA,KAAKG,SACP;IACA;GACF;GAEA,KAAK,GAAuB;IAC1B,OACE,KAAKC,iBAAiB,GACtB,uDACF;IACA,MAAM,EAAC,WAAW,iBAAiB,eAAc;IACjD,SAAS,gBACP,KAAKJ,UAAU,aACf,WACA,iBACA,YACA,WACA,YACF;IACA;GACF;EACF;EACA,MAAM,KAAKA,UAAU,SAAS,OAAO,KAAK;EAC1C,OAAO;CACT;CAGA,MAAM,OAAO,UAAiC;EAE5C,MAAM,cAAa,MADE,KAAK,UAAU,GACV,MAAM;EAChC,MAAM,KAAKA,UAAU,QAAQ,UAAU,UAAU;EACjD,MAAM,KAAKA,UAAU,OAAO;EAC5B,OAAO;CACT;CAEA,MAAM,gBACJ,UACA,YAC2B;EAC3B,MAAM,SAAS,KAAK,UAAU;EAC9B,MAAM,UAAU,MAAM,KAAKK,eAAe,UAAU;EACpD,MAAM,cAAc,MAAM,QAAQ,MAAM;EACxC,MAAM,KAAKL,UAAU,QAAQ,UAAU,UAAU;EACjD,MAAM,KAAKA,UAAU,OAAO;EAC5B,OAAO,CAAC,YAAY,OAAO;CAC7B;CAEA,MAAMK,eAAe,YAAsD;EACzE,MAAM,WAAW,IAAI,SAAS;EAC9B,IAAI,CAAC,WAAW,mBAAmB,GACjC,OAAO;EAGT,IAAI,YAA0B,CAAC;EAC/B,IAAI,KAAKJ,QAMP,YAAY,MAAM,KAAK,IALF,UACnB,KAAKD,WACL,KAAKI,gBACL,KAAKH,OAAO,SAES,GAAU,KAAK,GAAG;EAE3C,SAAS,IAAI,IAAI,SAAS;EAC1B,IAAI;EACJ,IAAI,KAAKA,QACP,eAAe,mBACb,KAAKA,QACL,KAAKD,WACL,KAAKI,cACP;OAEA,+BAAe,IAAI,IAAI;EAGzB,KAAK,MAAM,CAAC,MAAM,UAAU,KAAK,SAAS;GACxC,IAAI,CAAC,WAAW,2BAA2B,IAAI,GAC7C;GAEF,MAAM,aAAa,aAAa,IAAI,IAAI;GACxC,OAAO,UAAU,YAAY,0CAA0C;GAEvE,MAAM,kBAAkB,OAAO,aAC3B,KAAK,WAAW,KAAK,MAAM,GAAG,IAE9B,iBAAiB,MAAM,KAAK,KAAK;GACrC,SAAS,IAAI,MAAM,eAAe;EACpC;EAIA,KAAK,MAAM,CAAC,MAAM,eAAe,cAC/B,IACE,CAAC,KAAK,QAAQ,IAAI,IAAI,KACtB,WAAW,2BAA2B,IAAI,GAC1C;GACA,MAAM,kBAAkB,MAAM,iBAAiB,WAAW,KAAK,KAAK;GACpE,SAAS,IAAI,MAAM,eAAe;EACpC;EAEF,OAAO;CACT;CAEA,QAAc;EACZ,KAAKJ,UAAU,QAAQ;CACzB;AACF;AAEA,eAAsB,cACpB,WACA,aACA,iBACA,cACA,UACA,WACA,UACA,eACgB;CAChB,MAAM,QAAQ,MAAM,eAAe,WAAW,QAAQ;CACtD,MAAM,aAAa,IAAI,WAAW,UAAU,eAAe,MAAM,SAAS;CAC1E,MAAM,aAAa,MAAM,MAAM,kBAAkB,UAAU,QAAQ;CACnE,MAAM,UAAU,oBAAoB,OAAO,UAAU,aAAa;CAClE,OACE,iBAAiB,GACjB,kDACF;CACA,OAAO,IAAI,MACT,UACA,YACA,OAEA;EACE,MAAM;EACN;EACA,kBAAkB,MAAM,yBAAyB,WAAW,QAAQ;EACpE;EACA;EACA;EACA;EACA;EACA;CACF,GACA,SACA,UACA,aACF;AACF;AAEA,eAAsB,qBACpB,WACA,iBACA,YACA,UACA,UACA,eACgB;CAChB,MAAM,QAAQ,MAAM,eAAe,WAAW,QAAQ;CAEtD,OAAO,IAAI,MACT,UACA,IAHqB,WAAW,UAAU,eAAe,MAAM,SAG/D,GACA,OACA;EAAC;EAAW,MAAM;EAAuB;EAAiB;CAAU,GACpE,oBAAoB,OAAO,UAAU,aAAa,GAClD,UACA,aACF;AACF;AAEA,eAAsB,cACpB,IACA,SACA,KACA,cACA,QACe;CACf,MAAM,KAAsB,CAAC;CAC7B,KAAK,MAAM,OAAO,QAAQ,OAAO,GAAG;EAClC,MAAM,EAAC,cAAa,IAAI,KAAK;EAC7B,IAAI,CAAC,aAAa,IAAI,WAAW,SAAS,GAAG;GAC3C,MAAM,SAAS,MAAM,aAAa;GAClC,IAAI,WAAW,KAAA,GACb,GAAG,KACD,WACE,IACA,IAAI,KACJ,GACA,KACA,QACA,IAAI,KAAK,WAAW,aACpB,IAAI,KAAK,WAAW,cAAc,KACpC,CACF;GAEF,IAAI,WAAW,KAAA,GACb,GAAG,KACD,WACE,IACA,IAAI,KACJ,GACA,KACA,QACA,IAAI,KAAK,WAAW,aACpB,IAAI,KAAK,WAAW,cAAc,KACpC,CACF;EAEJ;CACF;CACA,MAAM,QAAQ,IAAI,EAAE;AACtB;AAEA,SAAgB,oBACd,QACA,UACA,eACyB;CACzB,MAAM,oBAAI,IAAI,IAAI;CAClB,KAAK,MAAM,SAAS,OAAO,SACzB,EAAE,IACA,MAAM,WAAW,MACjB,IAAI,WACF,OACA,IAAI,WAAW,UAAU,eAAe,MAAM,SAAS,CACzD,CACF;CAEF,OAAO;AACT;AAEA,eAAsB,iBACpB,IACA,UACA,UACA,QACA,aACA,YACA,eACqB;CACrB,MAAM,WAAW,IAAI,WAAW,UAAU,aAAa;CACvD,WAAW,MAAM,SAAS,SAAS,KAAK,MAAM,GAAG;EAC/C,MAAM,MAAM,MAAM;EAClB,IAAI,CAAC,IAAI,WAAW,MAAM,GACxB;EAEF,MAAM,WACJ,IACA,UACA,GACA,KACA,MAAM,IACN,aACA,UACF;CACF;CACA,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"write.js","names":["#dagWrite","#basis","#meta","#clientID","#formatVersion","#generateDiffs"],"sources":["../../../../../replicache/src/db/write.ts"],"sourcesContent":["import '../process-env.ts';\nimport type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {diff} from '../btree/diff.ts';\nimport type {InternalDiff} from '../btree/node.ts';\nimport {BTreeRead, allEntriesAsDiff} from '../btree/read.ts';\nimport {BTreeWrite} from '../btree/write.ts';\nimport type {FrozenCookie} from '../cookies.ts';\nimport type {Write as DagWrite} from '../dag/store.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {type Hash, emptyHash} from '../hash.ts';\nimport type {DiffComputationConfig} from '../sync/diff.ts';\nimport {DiffsMap} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {Commit} from './commit.ts';\nimport {\n type Meta as CommitMeta,\n type IndexRecord,\n type Meta,\n baseSnapshotHashFromHash,\n commitFromHash,\n newLocalDD31 as commitNewLocalDD31,\n newSnapshotDD31 as commitNewSnapshotDD31,\n getMutationID,\n} from './commit.ts';\nimport * as IndexOperation from './index-operation-enum.ts';\nimport type {IndexRead} from './index.ts';\nimport {IndexWrite, indexValue} from './index.ts';\nimport * as MetaType from './meta-type-enum.ts';\nimport {Read, readIndexesForRead} from './read.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nexport class Write extends Read {\n readonly #dagWrite: DagWrite;\n readonly #basis: Commit<CommitMeta> | undefined;\n readonly #meta: CommitMeta;\n\n declare map: BTreeWrite;\n\n declare readonly indexes: Map<string, IndexWrite>;\n readonly #clientID: ClientID;\n readonly #formatVersion: FormatVersion;\n\n constructor(\n dagWrite: DagWrite,\n map: BTreeWrite,\n basis: Commit<CommitMeta> | undefined,\n meta: CommitMeta,\n indexes: Map<string, IndexWrite>,\n clientID: ClientID,\n formatVersion: FormatVersion,\n ) {\n // TypeScript has trouble\n super(dagWrite, map, indexes);\n this.#dagWrite = dagWrite;\n this.#basis = basis;\n this.#meta = meta;\n this.#clientID = clientID;\n this.#formatVersion = formatVersion;\n\n // TODO(arv): if (DEBUG) { ...\n if (basis === undefined) {\n assert(\n meta.basisHash === emptyHash,\n 'Expected basisHash to be emptyHash when basis is undefined',\n );\n } else {\n assert(\n meta.basisHash === basis.chunk.hash,\n 'Expected meta.basisHash to equal basis.chunk.hash',\n );\n }\n }\n\n /**\n * The value needs to be frozen since it is kept in memory and used later for\n * comparison as well as returned in `get`.\n */\n async put(\n lc: LogContext,\n key: string,\n value: FrozenJSONValue,\n ): Promise<void> {\n if (!process.env.DISABLE_REPLICACHE_INDEXES && this.indexes.size > 0) {\n await updateIndexes(lc, this.map, this.indexes, key, value);\n }\n await this.map.put(key, value);\n }\n\n /**\n * Inserts or updates multiple entries in a single bulk operation. More\n * efficient than calling {@link put} in a loop because it uses\n * {@link BTreeWrite.putMany} to build or merge tree nodes in one pass.\n *\n * `entries` must be sorted in ascending key order.\n */\n async putMany(\n lc: LogContext,\n entries: ReadonlyArray<readonly [string, FrozenJSONValue]>,\n ): Promise<void> {\n if (entries.length === 0) {\n return;\n }\n\n // Update indexes for all entries\n if (!process.env.DISABLE_REPLICACHE_INDEXES && this.indexes.size > 0) {\n // TODO(arv): Indexes can use the optimizePatch pattern too.\n for (const [key, value] of entries) {\n await updateIndexes(lc, this.map, this.indexes, key, value);\n }\n }\n\n // BTreeWrite.putMany handles both empty and non-empty trees optimally\n await this.map.putMany(entries);\n }\n\n getMutationID(): Promise<number> {\n return getMutationID(this.#clientID, this.#dagWrite, this.#meta);\n }\n\n async del(lc: LogContext, key: string): Promise<boolean> {\n if (!process.env.DISABLE_REPLICACHE_INDEXES && this.indexes.size > 0) {\n await updateIndexes(lc, this.map, this.indexes, key, undefined);\n }\n return this.map.del(key);\n }\n\n async clear(): Promise<void> {\n await this.map.clear();\n const ps = [];\n for (const idx of this.indexes.values()) {\n ps.push(idx.clear());\n }\n await Promise.all(ps);\n }\n\n async putCommit(): Promise<Commit<CommitMeta>> {\n const valueHash = await this.map.flush();\n const indexRecords: IndexRecord[] = [];\n\n for (const index of this.indexes.values()) {\n const valueHash = await index.flush();\n const indexRecord: IndexRecord = {\n definition: index.meta.definition,\n valueHash,\n };\n indexRecords.push(indexRecord);\n }\n\n let commit: Commit<Meta>;\n const meta = this.#meta;\n switch (meta.type) {\n case MetaType.LocalDD31: {\n assert(\n this.#formatVersion >= FormatVersion.DD31,\n 'Expected formatVersion >= DD31 for LocalDD31 commit',\n );\n const {\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n } = meta;\n commit = commitNewLocalDD31(\n this.#dagWrite.createChunk,\n basisHash,\n await baseSnapshotHashFromHash(basisHash, this.#dagWrite),\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n valueHash,\n indexRecords,\n timestamp,\n this.#clientID,\n );\n break;\n }\n\n case MetaType.SnapshotDD31: {\n assert(\n this.#formatVersion > FormatVersion.DD31,\n 'Expected formatVersion > DD31 for SnapshotDD31 commit',\n );\n const {basisHash, lastMutationIDs, cookieJSON} = meta;\n commit = commitNewSnapshotDD31(\n this.#dagWrite.createChunk,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexRecords,\n );\n break;\n }\n }\n await this.#dagWrite.putChunk(commit.chunk);\n return commit;\n }\n\n // Return value is the hash of the new commit.\n async commit(headName: string): Promise<Hash> {\n const commit = await this.putCommit();\n const commitHash = commit.chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return commitHash;\n }\n\n async commitWithDiffs(\n headName: string,\n diffConfig: DiffComputationConfig,\n ): Promise<[Hash, DiffsMap]> {\n const commit = this.putCommit();\n const diffMap = await this.#generateDiffs(diffConfig);\n const commitHash = (await commit).chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return [commitHash, diffMap];\n }\n\n async #generateDiffs(diffConfig: DiffComputationConfig): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n let valueDiff: InternalDiff = [];\n if (this.#basis) {\n const basisMap = new BTreeRead(\n this.#dagWrite,\n this.#formatVersion,\n this.#basis.valueHash,\n );\n valueDiff = await diff(basisMap, this.map);\n }\n diffsMap.set('', valueDiff);\n if (process.env.DISABLE_REPLICACHE_INDEXES) {\n return diffsMap;\n }\n let basisIndexes: Map<string, IndexRead>;\n if (this.#basis) {\n basisIndexes = readIndexesForRead(\n this.#basis,\n this.#dagWrite,\n this.#formatVersion,\n );\n } else {\n basisIndexes = new Map();\n }\n\n for (const [name, index] of this.indexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(name)) {\n continue;\n }\n const basisIndex = basisIndexes.get(name);\n assert(index !== basisIndex, 'Expected index to differ from basisIndex');\n\n const indexDiffResult = await (basisIndex\n ? diff(basisIndex.map, index.map)\n : // No basis. All keys are new.\n allEntriesAsDiff(index.map, 'add'));\n diffsMap.set(name, indexDiffResult);\n }\n\n // Handle indexes in basisIndex but not in this.indexes. All keys are\n // deleted.\n for (const [name, basisIndex] of basisIndexes) {\n if (\n !this.indexes.has(name) &&\n diffConfig.shouldComputeDiffsForIndex(name)\n ) {\n const indexDiffResult = await allEntriesAsDiff(basisIndex.map, 'del');\n diffsMap.set(name, indexDiffResult);\n }\n }\n return diffsMap;\n }\n\n close(): void {\n this.#dagWrite.release();\n }\n}\n\nexport async function newWriteLocal(\n basisHash: Hash,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n dagWrite: DagWrite,\n timestamp: number,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n const mutationID = await basis.getNextMutationID(clientID, dagWrite);\n const indexes = readIndexesForWrite(basis, dagWrite, formatVersion);\n assert(\n formatVersion >= FormatVersion.DD31,\n 'Expected formatVersion >= DD31 for newWriteLocal',\n );\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n\n {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash: await baseSnapshotHashFromHash(basisHash, dagWrite),\n mutatorName,\n mutatorArgsJSON,\n mutationID,\n originalHash,\n timestamp,\n clientID,\n },\n indexes,\n clientID,\n formatVersion,\n );\n}\n\nexport async function newWriteSnapshotDD31(\n basisHash: Hash,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n dagWrite: DagWrite,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n {basisHash, type: MetaType.SnapshotDD31, lastMutationIDs, cookieJSON},\n readIndexesForWrite(basis, dagWrite, formatVersion),\n clientID,\n formatVersion,\n );\n}\n\nexport async function updateIndexes(\n lc: LogContext,\n map: BTreeRead,\n indexes: Map<string, IndexWrite>,\n key: string,\n newVal: FrozenJSONValue | undefined,\n): Promise<void> {\n let oldValPromise: Promise<FrozenJSONValue | undefined> | undefined;\n\n const ps: Promise<void>[] = [];\n for (const idx of indexes.values()) {\n const {keyPrefix} = idx.meta.definition;\n if (!keyPrefix || key.startsWith(keyPrefix)) {\n const oldVal = await (oldValPromise ??= map.get(key));\n if (oldVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Remove,\n key,\n oldVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n if (newVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Add,\n key,\n newVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n }\n }\n await Promise.all(ps);\n}\n\nexport function readIndexesForWrite(\n commit: Commit<CommitMeta>,\n dagWrite: DagWrite,\n formatVersion: FormatVersion,\n): Map<string, IndexWrite> {\n const m: Map<string, IndexWrite> = new Map();\n if (process.env.DISABLE_REPLICACHE_INDEXES) {\n return m;\n }\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexWrite(\n index,\n new BTreeWrite(dagWrite, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n\nexport async function createIndexBTree(\n lc: LogContext,\n dagWrite: DagWrite,\n valueMap: BTreeRead,\n prefix: string,\n jsonPointer: string,\n allowEmpty: boolean,\n formatVersion: FormatVersion,\n): Promise<BTreeWrite> {\n const indexMap = new BTreeWrite(dagWrite, formatVersion);\n for await (const entry of valueMap.scan(prefix)) {\n const key = entry[0];\n if (!key.startsWith(prefix)) {\n break;\n }\n await indexValue(\n lc,\n indexMap,\n IndexOperation.Add,\n key,\n entry[1],\n jsonPointer,\n allowEmpty,\n );\n }\n return indexMap;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/clients.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/clients.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,9 +6,9 @@ import { assert as assert$1, readonlyArray, readonlyObject, valita_exports } fro
|
|
|
6
6
|
import { hashSchema } from "../hash.js";
|
|
7
7
|
import { toRefs } from "../dag/chunk.js";
|
|
8
8
|
import { emptyDataNode } from "../btree/node.js";
|
|
9
|
-
import
|
|
10
|
-
import { assertSnapshotCommitDD31, baseSnapshotFromHash,
|
|
11
|
-
import
|
|
9
|
+
import "../btree/read.js";
|
|
10
|
+
import { assertSnapshotCommitDD31, baseSnapshotFromHash, getRefs, newSnapshotCommitDataDD31, toChunkIndexDefinition } from "../db/commit.js";
|
|
11
|
+
import "../db/write.js";
|
|
12
12
|
import { indexDefinitionsEqual } from "../index-defs.js";
|
|
13
13
|
import { clientGroupIDSchema } from "../sync/ids.js";
|
|
14
14
|
import { withWrite } from "../with-transactions.js";
|
|
@@ -190,36 +190,9 @@ function initClientV6(newClientID, lc, perdag, mutatorNames, indexes, formatVers
|
|
|
190
190
|
}
|
|
191
191
|
assert(res.type === 1, "Expected result type to be FORK");
|
|
192
192
|
const { snapshot } = res;
|
|
193
|
-
|
|
194
|
-
const { valueHash, indexes: oldIndexes } = snapshot;
|
|
195
|
-
const map = new BTreeRead(dagWrite, formatVersion, valueHash);
|
|
196
|
-
for (const [name, indexDefinition] of Object.entries(indexes)) {
|
|
197
|
-
const { prefix = "", jsonPointer, allowEmpty = false } = indexDefinition;
|
|
198
|
-
const chunkIndexDefinition = {
|
|
199
|
-
name,
|
|
200
|
-
keyPrefix: prefix,
|
|
201
|
-
jsonPointer,
|
|
202
|
-
allowEmpty
|
|
203
|
-
};
|
|
204
|
-
const oldIndex = findMatchingOldIndex(oldIndexes, chunkIndexDefinition);
|
|
205
|
-
if (oldIndex) indexRecords.push({
|
|
206
|
-
definition: chunkIndexDefinition,
|
|
207
|
-
valueHash: oldIndex.valueHash
|
|
208
|
-
});
|
|
209
|
-
else {
|
|
210
|
-
const indexBTree = await createIndexBTree(lc, dagWrite, map, prefix, jsonPointer, allowEmpty, formatVersion);
|
|
211
|
-
indexRecords.push({
|
|
212
|
-
definition: chunkIndexDefinition,
|
|
213
|
-
valueHash: await indexBTree.flush()
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return setClientsAndClientGroupAndCommit(snapshot.meta.basisHash, snapshot.meta.cookieJSON, snapshot.valueHash, indexRecords);
|
|
193
|
+
return setClientsAndClientGroupAndCommit(snapshot.meta.basisHash, snapshot.meta.cookieJSON, snapshot.valueHash, []);
|
|
218
194
|
});
|
|
219
195
|
}
|
|
220
|
-
function findMatchingOldIndex(oldIndexes, chunkIndexDefinition) {
|
|
221
|
-
return oldIndexes.find((index) => chunkIndexDefinitionEqualIgnoreName(index.definition, chunkIndexDefinition));
|
|
222
|
-
}
|
|
223
196
|
async function findMatchingClient(dagRead, mutatorNames, indexes) {
|
|
224
197
|
let newestCookie;
|
|
225
198
|
let bestSnapshot;
|