@rocicorp/zero 0.25.12 → 0.25.13-canary.0
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/README.md +1 -1
- package/out/analyze-query/src/bin-analyze.js +1 -1
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts +4 -4
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +22 -19
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/replicache-impl.js +1 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/shared/src/bigint-json.js +1 -1
- package/out/shared/src/custom-key-map.d.ts +4 -4
- package/out/shared/src/custom-key-map.d.ts.map +1 -1
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/iterables.d.ts +6 -8
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +13 -7
- package/out/shared/src/iterables.js.map +1 -1
- package/out/zero/package.json.js +1 -1
- package/out/zero/src/adapters/drizzle.js +1 -2
- package/out/zero/src/react.js +3 -1
- package/out/zero/src/react.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js +2 -3
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +3 -1
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts +6 -0
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +15 -3
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +49 -8
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +65 -13
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +2 -0
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +26 -3
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.d.ts +16 -2
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +34 -28
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +9 -3
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.d.ts.map +1 -1
- package/out/zero-cache/src/db/migration.js +9 -3
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/specs.d.ts +4 -3
- package/out/zero-cache/src/db/specs.d.ts.map +1 -1
- package/out/zero-cache/src/db/specs.js +4 -1
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +9 -3
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +10 -2
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +11 -30
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +1 -8
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +7 -1
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/change-source.d.ts +19 -0
- package/out/zero-cache/src/services/change-source/change-source.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
- 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 +20 -12
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -1
- 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 +88 -22
- 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.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +9 -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.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +7 -4
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.d.ts +3 -3
- package/out/zero-cache/src/services/change-source/pg/lsn.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js +9 -4
- package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +125 -180
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +1 -10
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- 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 +44 -11
- 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/published.d.ts +36 -90
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +65 -14
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +31 -36
- 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 +25 -17
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +2 -4
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +165 -55
- 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 +79 -11
- 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 +216 -72
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +28 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +12 -0
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +8 -3
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts +2 -0
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js +63 -7
- package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +3 -21
- 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 +10 -5
- 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 +73 -25
- 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 +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/init.js +8 -2
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +13 -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 +26 -2
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +6 -2
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +145 -14
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +2 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +14 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.d.ts.map +1 -1
- package/out/zero-cache/src/services/heapz.js +1 -0
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- 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.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +4 -1
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +4 -4
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +10 -24
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +6 -4
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +114 -17
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +87 -57
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +3 -0
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +26 -6
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js +113 -67
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.d.ts +12 -9
- package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts.map +1 -0
- package/out/zero-cache/src/services/{change-source → replicator/schema}/column-metadata.js +56 -28
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +7 -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 +12 -3
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/table-metadata.d.ts +24 -0
- package/out/zero-cache/src/services/replicator/schema/table-metadata.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js +57 -0
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.js +1 -1
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/statz.d.ts +6 -0
- package/out/zero-cache/src/services/statz.d.ts.map +1 -1
- package/out/zero-cache/src/services/statz.js +111 -94
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +5 -6
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +5 -23
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +20 -34
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +1 -2
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +21 -6
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +13 -21
- 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 +51 -66
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +19 -19
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +12 -11
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +0 -2
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +4 -11
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +4 -4
- 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 +165 -218
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.d.ts +0 -1
- package/out/zero-cache/src/types/lexi-version.d.ts.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js +4 -5
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +8 -2
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/shards.js +1 -1
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.d.ts +5 -0
- package/out/zero-cache/src/types/sql.d.ts.map +1 -1
- package/out/zero-cache/src/types/sql.js +5 -1
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/state-version.d.ts +29 -0
- package/out/zero-cache/src/types/state-version.d.ts.map +1 -0
- package/out/zero-cache/src/types/state-version.js +29 -0
- package/out/zero-cache/src/types/state-version.js.map +1 -0
- package/out/zero-cache/src/types/subscription.js +1 -1
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +2 -3
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +2 -5
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +13 -9
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +17 -10
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +8 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +33 -0
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +6 -3
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.js +1 -0
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +15 -1
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +4 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +7 -0
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts +1 -0
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +20 -5
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +16 -0
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +25 -1
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-react/src/mod.d.ts +2 -0
- package/out/zero-react/src/mod.d.ts.map +1 -1
- package/out/zero-react/src/paging-reducer.d.ts +61 -0
- package/out/zero-react/src/paging-reducer.d.ts.map +1 -0
- package/out/zero-react/src/paging-reducer.js +77 -0
- package/out/zero-react/src/paging-reducer.js.map +1 -0
- package/out/zero-react/src/use-rows.d.ts +39 -0
- package/out/zero-react/src/use-rows.d.ts.map +1 -0
- package/out/zero-react/src/use-rows.js +130 -0
- package/out/zero-react/src/use-rows.js.map +1 -0
- package/out/zero-react/src/use-zero-virtualizer.d.ts +122 -0
- package/out/zero-react/src/use-zero-virtualizer.d.ts.map +1 -0
- package/out/zero-react/src/use-zero-virtualizer.js +342 -0
- package/out/zero-react/src/use-zero-virtualizer.js.map +1 -0
- package/out/zero-server/src/adapters/drizzle.d.ts +0 -5
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +8 -22
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts +2 -1
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +39 -4
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.js +1 -1
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/schema.d.ts.map +1 -1
- package/out/zero-server/src/schema.js +4 -1
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +18 -0
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/solid-view.js +1 -0
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-query.d.ts +0 -4
- package/out/zero-solid/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/use-query.js +1 -0
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zql/src/ivm/constraint.d.ts.map +1 -1
- package/out/zql/src/ivm/constraint.js +4 -1
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +4 -1
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
- package/out/zql/src/ivm/join-utils.js +8 -2
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +12 -3
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +8 -2
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +24 -6
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +12 -3
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/query/expression.d.ts +4 -4
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js +11 -6
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +3 -4
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +8 -4
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +3 -3
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +1 -2
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +4 -4
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-source/column-metadata.js.map +0 -1
- package/out/zero-cache/src/types/schema-versions.d.ts +0 -12
- package/out/zero-cache/src/types/schema-versions.d.ts.map +0 -1
- package/out/zero-cache/src/types/schema-versions.js +0 -28
- package/out/zero-cache/src/types/schema-versions.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Documentation
|
|
4
4
|
|
|
5
|
-
[https://zero.rocicorp.dev/docs/introduction](https://zero.rocicorp.dev/
|
|
5
|
+
Read over the [docs](https://zero.rocicorp.dev/docs/introduction). For AI assistants: [llms.txt](https://zero.rocicorp.dev/llms.txt).
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -175,7 +175,7 @@ const clientSchema = clientSchemaFrom(schema).clientSchema;
|
|
|
175
175
|
const sources = /* @__PURE__ */ new Map();
|
|
176
176
|
const clientToServerMapper = clientToServer(schema.tables);
|
|
177
177
|
const debug = new Debug();
|
|
178
|
-
const tableSpecs = computeZqlSpecs(lc, db);
|
|
178
|
+
const tableSpecs = computeZqlSpecs(lc, db, { includeBackfillingColumns: false });
|
|
179
179
|
class AnalyzeQueryDelegate extends QueryDelegateBase {
|
|
180
180
|
debug = debug;
|
|
181
181
|
defaultQueryComplete = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin-analyze.js","sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport chalk from 'chalk';\nimport fs from 'node:fs';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {testLogConfig} from '../../otel/src/test-log-config.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {PullRow, Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\nimport {explainQueries} from './explain-queries.ts';\nimport {runAst} from './run-ast.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: [`File path to the SQLite replica to test queries against.`],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n `Query to be analyzed in the form of: table.where(...).related(...).etc. `,\n `Only one of ast/query/hash should be provided.`,\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n `Hash of the query to be analyzed. This is used to look up the query in the database. `,\n `Only one of ast/query/hash should be provided.`,\n `You should run this script from the directory containing your .env file to reduce the amount of`,\n `configuration required. The .env file should contain the connection URL to the CVR database.`,\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n // the command line parses drops all text after the first newline\n // so we need to replace newlines with spaces\n // before parsing\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug();\nconst tableSpecs = computeZqlSpecs(lc, db);\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n\n getSource(serverTableName: string): Source | undefined {\n let source = sources.get(serverTableName);\n if (source) {\n return source;\n }\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n testLogConfig,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n\n sources.set(serverTableName, source);\n return source;\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n // the user likely has a transformed AST since the wire and storage formats are the transformed AST\n result = await runAst(lc, clientSchema, JSON.parse(config.ast), true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(lc, clientSchema, ast, false, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(lc, clientSchema, ast, true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(chalk.blue.bold('=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(chalk.bold(table + ':'), rows);\n }\n}\n\ncolorConsole.log(chalk.blue.bold('=== Query Stats: ===\\n'));\ncolorConsole.log(chalk.bold('total synced rows:'), result.syncedRowCount);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(chalk.blue.bold('=== JS Row Scan Values: ===\\n'));\n for (const source of sources.values()) {\n colorConsole.log(\n chalk.bold(`${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(chalk.blue.bold('\\n=== Rows Scanned (by SQLite): ===\\n'));\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(chalk.bold(`${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n chalk.bold('total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(chalk.blue.bold('\\n\\n=== Query Plans: ===\\n'));\nconst plans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(chalk.bold('query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n chalk.bold(source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n chalk.bold('Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n chalk.bold('time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return chalk.green(duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return chalk.yellow(duration.toFixed(2) + 'ms');\n }\n return chalk.red(duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return chalk.green(n.toString());\n } else if (n < 10000) {\n return chalk.yellow(n.toString());\n }\n return chalk.red(n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return chalk.yellow(row);\n }\n return chalk.red(row);\n }\n return chalk.green(row);\n}\n"],"names":["v.string","v.boolean","v"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bin-analyze.js","sources":["../../../../analyze-query/src/bin-analyze.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport chalk from 'chalk';\nimport fs from 'node:fs';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {logLevel, logOptions} from '../../otel/src/log-options.ts';\nimport {testLogConfig} from '../../otel/src/test-log-config.ts';\nimport {colorConsole, createLogContext} from '../../shared/src/logging.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n zeroOptions,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {\n computeZqlSpecs,\n mustGetTableSpec,\n} from '../../zero-cache/src/db/lite-tables.ts';\nimport {\n deployPermissionsOptions,\n loadSchemaAndPermissions,\n} from '../../zero-cache/src/scripts/permissions.ts';\nimport {pgClient} from '../../zero-cache/src/types/pg.ts';\nimport {getShardID, upstreamSchema} from '../../zero-cache/src/types/shards.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport {type AST} from '../../zero-protocol/src/ast.ts';\nimport {clientSchemaFrom} from '../../zero-schema/src/builder/schema-builder.ts';\nimport {clientToServer} from '../../zero-schema/src/name-mapper.ts';\nimport type {Schema} from '../../zero-types/src/schema.ts';\nimport {\n Debug,\n runtimeDebugFlags,\n} from '../../zql/src/builder/debug-delegate.ts';\nimport type {Source} from '../../zql/src/ivm/source.ts';\nimport {QueryDelegateBase} from '../../zql/src/query/query-delegate-base.ts';\nimport {newQuery} from '../../zql/src/query/query-impl.ts';\nimport {asQueryInternals} from '../../zql/src/query/query-internals.ts';\nimport type {PullRow, Query} from '../../zql/src/query/query.ts';\nimport {Database} from '../../zqlite/src/db.ts';\nimport {TableSource} from '../../zqlite/src/table-source.ts';\nimport {explainQueries} from './explain-queries.ts';\nimport {runAst} from './run-ast.ts';\n\nconst options = {\n schema: deployPermissionsOptions.schema,\n replicaFile: {\n ...zeroOptions.replica.file,\n desc: [`File path to the SQLite replica to test queries against.`],\n },\n ast: {\n type: v.string().optional(),\n desc: [\n 'AST for the query to be analyzed. Only one of ast/query/hash should be provided.',\n ],\n },\n query: {\n type: v.string().optional(),\n desc: [\n `Query to be analyzed in the form of: table.where(...).related(...).etc. `,\n `Only one of ast/query/hash should be provided.`,\n ],\n },\n hash: {\n type: v.string().optional(),\n desc: [\n `Hash of the query to be analyzed. This is used to look up the query in the database. `,\n `Only one of ast/query/hash should be provided.`,\n `You should run this script from the directory containing your .env file to reduce the amount of`,\n `configuration required. The .env file should contain the connection URL to the CVR database.`,\n ],\n },\n applyPermissions: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to apply permissions (from your schema file) to the provided query.',\n ],\n },\n authData: {\n type: v.string().optional(),\n desc: [\n 'JSON encoded payload of the auth data.',\n 'This will be used to fill permission variables if the \"applyPermissions\" option is set',\n ],\n },\n outputVendedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which were read from the replica in order to execute the analyzed query. ',\n 'If the same row is read more than once it will be logged once for each time it was read.',\n ],\n },\n outputSyncedRows: {\n type: v.boolean().default(false),\n desc: [\n 'Whether to output the rows which would be synced to the client for the analyzed query.',\n ],\n },\n cvr: {\n db: {\n type: v.string().optional(),\n desc: [\n 'Connection URL to the CVR database. If using --hash, either this or --upstream-db',\n 'must be specified.',\n ],\n },\n },\n upstream: {\n db: {\n desc: [\n `Connection URL to the \"upstream\" authoritative postgres database. If using --hash, `,\n 'either this or --cvr-db must be specified.',\n ],\n type: v.string().optional(),\n },\n type: zeroOptions.upstream.type,\n },\n app: appOptions,\n shard: shardOptions,\n log: {\n ...logOptions,\n level: logLevel.default('error'),\n },\n};\n\nconst cfg = parseOptions(options, {\n // the command line parses drops all text after the first newline\n // so we need to replace newlines with spaces\n // before parsing\n argv: process.argv.slice(2).map(s => s.replaceAll('\\n', ' ')),\n envNamePrefix: ZERO_ENV_VAR_PREFIX,\n description: [\n {\n header: 'analyze-query',\n content: `Analyze a ZQL query and show information about how it runs against a SQLite replica.\n\n analyze-query uses the same environment variables and flags as zero-cache-dev. If run from your development environment, it will pick up your ZERO_REPLICA_FILE, ZERO_SCHEMA_PATH, and other env vars automatically.\n\n If run in another environment (e.g., production) you will have to specify these flags. In particular, you must have a copy of the appropriate Zero schema file to give to the --schema-path flag.`,\n },\n {\n header: 'Examples',\n content: `# In development\n npx analyze-query --query='issue.related(\"comments\").limit(10)'\n npx analyze-query --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n npx analyze-query --hash=1234567890\n\n # In production\n # First copy schema.ts to your production environment, then run:\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --query='issue.related(\"comments\").limit(10)'\n\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --ast='\\\\{\"table\": \"artist\",\"limit\": 10\\\\}'\n\n # cvr-db is required when using the hash option.\n # It is typically the same as your upstream db.\n npx analyze-query \\\\\n --schema-path='./schema.ts' \\\\\n --replica-file='/path/to/replica.db' \\\\\n --cvr-db='postgres://user:pass@host:port/db' \\\\\n --hash=1234567890\n `,\n },\n ],\n});\nconst config = {\n ...cfg,\n cvr: {\n ...cfg.cvr,\n db: cfg.cvr.db ?? cfg.upstream.db,\n },\n};\n\nruntimeDebugFlags.trackRowCountsVended = true;\nruntimeDebugFlags.trackRowsVended = config.outputVendedRows;\n\nconst lc = createLogContext({\n log: config.log,\n});\n\nif (!fs.existsSync(config.replicaFile)) {\n colorConsole.error(`Replica file ${config.replicaFile} does not exist`);\n process.exit(1);\n}\nconst db = new Database(lc, config.replicaFile);\n\nconst {schema, permissions} = await loadSchemaAndPermissions(\n config.schema.path,\n);\nconst clientSchema = clientSchemaFrom(schema).clientSchema;\n\nconst sources = new Map<string, TableSource>();\nconst clientToServerMapper = clientToServer(schema.tables);\nconst debug = new Debug();\nconst tableSpecs = computeZqlSpecs(lc, db, {includeBackfillingColumns: false});\n\nclass AnalyzeQueryDelegate extends QueryDelegateBase {\n readonly debug = debug;\n readonly defaultQueryComplete = true;\n\n getSource(serverTableName: string): Source | undefined {\n let source = sources.get(serverTableName);\n if (source) {\n return source;\n }\n const tableSpec = mustGetTableSpec(tableSpecs, serverTableName);\n const {primaryKey} = tableSpec.tableSpec;\n\n source = new TableSource(\n lc,\n testLogConfig,\n db,\n serverTableName,\n tableSpec.zqlSpec,\n primaryKey,\n );\n\n sources.set(serverTableName, source);\n return source;\n }\n}\n\nconst host = new AnalyzeQueryDelegate();\n\nlet result: AnalyzeQueryResult;\n\nif (config.ast) {\n // the user likely has a transformed AST since the wire and storage formats are the transformed AST\n result = await runAst(lc, clientSchema, JSON.parse(config.ast), true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n} else if (config.query) {\n result = await runQuery(config.query);\n} else if (config.hash) {\n result = await runHash(config.hash);\n} else {\n colorConsole.error('No query or AST or hash provided');\n process.exit(1);\n}\n\nfunction runQuery(queryString: string): Promise<AnalyzeQueryResult> {\n const z = {\n query: Object.fromEntries(\n Object.entries(schema.tables).map(([name]) => [\n name,\n newQuery(schema, name),\n ]),\n ),\n };\n\n const f = new Function('z', `return z.query.${queryString};`);\n const q: Query<string, Schema, PullRow<string, Schema>> = f(z);\n\n const ast = asQueryInternals(q).ast;\n return runAst(lc, clientSchema, ast, false, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nasync function runHash(hash: string) {\n const cvrDB = pgClient(\n lc,\n must(config.cvr.db, 'CVR DB must be provided when using the hash option'),\n );\n\n const rows = await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(\n upstreamSchema(getShardID(config)) + '/cvr',\n )}.\"queries\" where \"queryHash\" = ${must(hash)} limit 1;`;\n await cvrDB.end();\n\n colorConsole.log('ZQL from Hash:');\n const ast = rows[0].clientAST as AST;\n colorConsole.log(await formatOutput(ast.table + astToZQL(ast)));\n\n return runAst(lc, clientSchema, ast, true, {\n applyPermissions: config.applyPermissions,\n authData: config.authData,\n clientToServerMapper,\n permissions,\n syncedRows: config.outputSyncedRows,\n db,\n tableSpecs,\n host,\n });\n}\n\nif (config.outputSyncedRows) {\n colorConsole.log(chalk.blue.bold('=== Synced Rows: ===\\n'));\n for (const [table, rows] of Object.entries(result.syncedRows ?? {})) {\n colorConsole.log(chalk.bold(table + ':'), rows);\n }\n}\n\ncolorConsole.log(chalk.blue.bold('=== Query Stats: ===\\n'));\ncolorConsole.log(chalk.bold('total synced rows:'), result.syncedRowCount);\nshowStats();\nif (config.outputVendedRows) {\n colorConsole.log(chalk.blue.bold('=== JS Row Scan Values: ===\\n'));\n for (const source of sources.values()) {\n colorConsole.log(\n chalk.bold(`${source.tableSchema.name}:`),\n debug.getVendedRows()?.[source.tableSchema.name] ?? {},\n );\n }\n}\n\ncolorConsole.log(chalk.blue.bold('\\n=== Rows Scanned (by SQLite): ===\\n'));\nconst nvisitCounts = debug.getNVisitCounts();\nlet totalNVisit = 0;\nfor (const [table, queries] of Object.entries(nvisitCounts)) {\n colorConsole.log(chalk.bold(`${table}:`), queries);\n for (const count of Object.values(queries)) {\n totalNVisit += count;\n }\n}\ncolorConsole.log(\n chalk.bold('total rows scanned:'),\n colorRowsConsidered(totalNVisit),\n);\n\ncolorConsole.log(chalk.blue.bold('\\n\\n=== Query Plans: ===\\n'));\nconst plans = explainQueries(debug.getVendedRowCounts() ?? {}, db);\nfor (const [query, plan] of Object.entries(plans)) {\n colorConsole.log(chalk.bold('query'), query);\n colorConsole.log(plan.map((row, i) => colorPlanRow(row, i)).join('\\n'));\n colorConsole.log('\\n');\n}\n\nfunction showStats() {\n let totalRowsConsidered = 0;\n for (const source of sources.values()) {\n const values = Object.values(\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n for (const v of values) {\n totalRowsConsidered += v;\n }\n colorConsole.log(\n chalk.bold(source.tableSchema.name + ' vended:'),\n debug.getVendedRowCounts()?.[source.tableSchema.name] ?? {},\n );\n }\n\n colorConsole.log(\n chalk.bold('Rows Read (into JS):'),\n colorRowsConsidered(totalRowsConsidered),\n );\n colorConsole.log(\n chalk.bold('time:'),\n colorTime(result.end - result.start),\n 'ms',\n );\n}\n\nfunction colorTime(duration: number) {\n if (duration < 100) {\n return chalk.green(duration.toFixed(2) + 'ms');\n } else if (duration < 1000) {\n return chalk.yellow(duration.toFixed(2) + 'ms');\n }\n return chalk.red(duration.toFixed(2) + 'ms');\n}\n\nfunction colorRowsConsidered(n: number) {\n if (n < 1000) {\n return chalk.green(n.toString());\n } else if (n < 10000) {\n return chalk.yellow(n.toString());\n }\n return chalk.red(n.toString());\n}\n\nfunction colorPlanRow(row: string, i: number) {\n if (row.includes('SCAN')) {\n if (i === 0) {\n return chalk.yellow(row);\n }\n return chalk.red(row);\n }\n return chalk.green(row);\n}\n"],"names":["v.string","v.boolean","v"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LogContext, LogLevel, LogSink } from '@rocicorp/logger';
|
|
2
2
|
import type { Store } from '../dag/store.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { CreateStore, StoreProvider } from '../kv/store.ts';
|
|
4
4
|
import type { OnClientsDeleted } from './clients.ts';
|
|
5
5
|
import { IDBDatabasesStore } from './idb-databases-store.ts';
|
|
6
6
|
/**
|
|
@@ -11,12 +11,12 @@ export declare const COLLECT_IDB_INTERVAL: number;
|
|
|
11
11
|
* We delay the initial collection to prevent doing it at startup.
|
|
12
12
|
*/
|
|
13
13
|
export declare const INITIAL_COLLECT_IDB_DELAY: number;
|
|
14
|
-
export declare function initCollectIDBDatabases(idbDatabasesStore: IDBDatabasesStore,
|
|
14
|
+
export declare function initCollectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, kvStoreProvider: StoreProvider, collectInterval: number, initialCollectDelay: number, maxAge: number, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, lc: LogContext, signal: AbortSignal): void;
|
|
15
15
|
/**
|
|
16
16
|
* Collects IDB databases that are no longer needed.
|
|
17
17
|
*/
|
|
18
|
-
export declare function collectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, now: number, maxAge: number,
|
|
19
|
-
declare function defaultNewDagStore(name: string): Store;
|
|
18
|
+
export declare function collectIDBDatabases(idbDatabasesStore: IDBDatabasesStore, now: number, maxAge: number, kvStoreProvider: StoreProvider, enableMutationRecovery: boolean, onClientsDeleted: OnClientsDeleted, newDagStore?: typeof defaultNewDagStore): Promise<void>;
|
|
19
|
+
declare function defaultNewDagStore(name: string, kvCreateStore: CreateStore): Store;
|
|
20
20
|
/**
|
|
21
21
|
* Options for `dropDatabase` and `dropAllDatabases`.
|
|
22
22
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAKpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"collect-idb-databases.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,kBAAkB,CAAC;AAKpE,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAY3C,OAAO,KAAK,EAAC,WAAW,EAAa,aAAa,EAAC,MAAM,gBAAgB,CAAC;AAO1E,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,cAAc,CAAC;AAGnD,OAAO,EAAC,iBAAiB,EAAC,MAAM,0BAA0B,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAAsB,CAAC;AAExD;;GAEG;AACH,eAAO,MAAM,yBAAyB,QAAgB,CAAC;AAEvD,wBAAgB,uBAAuB,CACrC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,aAAa,EAC9B,eAAe,EAAE,MAAM,EACvB,mBAAmB,EAAE,MAAM,EAC3B,MAAM,EAAE,MAAM,EACd,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAwBN;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,iBAAiB,EAAE,iBAAiB,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,aAAa,EAC9B,sBAAsB,EAAE,OAAO,EAC/B,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,4BAAqB,GAC/B,OAAO,CAAC,IAAI,CAAC,CAmEf;AAsCD,iBAAS,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,WAAW,GAAG,KAAK,CAG3E;AA0CD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,aAAa,GAAG,SAAS,CAAC;IACpD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAChC;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,iBAU5E;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC;IAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB,CAAC,CASD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,CAAC,EAAE,mBAAmB;aArBvD,MAAM,EAAE;YACT,OAAO,EAAE;GAsBlB"}
|
|
@@ -5,7 +5,6 @@ import { addDeletedClients, mergeDeletedClients, normalizeDeletedClients, getDel
|
|
|
5
5
|
import { Latest, DD31, V6, V7 } from "../format-version-enum.js";
|
|
6
6
|
import { getKVStoreProvider } from "../get-kv-store-provider.js";
|
|
7
7
|
import { newRandomHash, assertHash } from "../hash.js";
|
|
8
|
-
import { IDBStore } from "../kv/idb-store.js";
|
|
9
8
|
import { createLogContext } from "../log-options.js";
|
|
10
9
|
import { withWrite, withRead } from "../with-transactions.js";
|
|
11
10
|
import { getClientGroups, clientGroupHasPendingMutations } from "./client-groups.js";
|
|
@@ -13,7 +12,7 @@ import { getClients } from "./clients.js";
|
|
|
13
12
|
import { IDBDatabasesStore } from "./idb-databases-store.js";
|
|
14
13
|
const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1e3;
|
|
15
14
|
const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1e3;
|
|
16
|
-
function initCollectIDBDatabases(idbDatabasesStore,
|
|
15
|
+
function initCollectIDBDatabases(idbDatabasesStore, kvStoreProvider, collectInterval, initialCollectDelay, maxAge, enableMutationRecovery, onClientsDeleted, lc, signal) {
|
|
17
16
|
let initial = true;
|
|
18
17
|
initBgIntervalProcess(
|
|
19
18
|
"CollectIDBDatabases",
|
|
@@ -22,7 +21,7 @@ function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval
|
|
|
22
21
|
idbDatabasesStore,
|
|
23
22
|
Date.now(),
|
|
24
23
|
maxAge,
|
|
25
|
-
|
|
24
|
+
kvStoreProvider,
|
|
26
25
|
enableMutationRecovery,
|
|
27
26
|
onClientsDeleted
|
|
28
27
|
);
|
|
@@ -38,7 +37,7 @@ function initCollectIDBDatabases(idbDatabasesStore, kvDropStore, collectInterval
|
|
|
38
37
|
signal
|
|
39
38
|
);
|
|
40
39
|
}
|
|
41
|
-
async function collectIDBDatabases(idbDatabasesStore, now, maxAge,
|
|
40
|
+
async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvStoreProvider, enableMutationRecovery, onClientsDeleted, newDagStore = defaultNewDagStore) {
|
|
42
41
|
const databases = await idbDatabasesStore.getDatabases();
|
|
43
42
|
const dbs = Object.values(databases);
|
|
44
43
|
const collectResults = await Promise.all(
|
|
@@ -50,6 +49,7 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
|
|
|
50
49
|
now,
|
|
51
50
|
maxAge,
|
|
52
51
|
enableMutationRecovery,
|
|
52
|
+
kvStoreProvider.create,
|
|
53
53
|
newDagStore
|
|
54
54
|
)
|
|
55
55
|
]
|
|
@@ -69,7 +69,7 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
|
|
|
69
69
|
const { errors } = await dropDatabases(
|
|
70
70
|
idbDatabasesStore,
|
|
71
71
|
dbNamesToRemove,
|
|
72
|
-
|
|
72
|
+
kvStoreProvider.drop
|
|
73
73
|
);
|
|
74
74
|
if (errors.length) {
|
|
75
75
|
throw errors[0];
|
|
@@ -77,16 +77,19 @@ async function collectIDBDatabases(idbDatabasesStore, now, maxAge, kvDropStore,
|
|
|
77
77
|
if (deletedClientsToRemove.length > 0) {
|
|
78
78
|
let allDeletedClients = deletedClientsToRemove;
|
|
79
79
|
for (const name of dbNamesToKeep) {
|
|
80
|
-
await withWrite(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
await withWrite(
|
|
81
|
+
newDagStore(name, kvStoreProvider.create),
|
|
82
|
+
async (dagWrite) => {
|
|
83
|
+
const newDeletedClients = await addDeletedClients(
|
|
84
|
+
dagWrite,
|
|
85
|
+
deletedClientsToRemove
|
|
86
|
+
);
|
|
87
|
+
allDeletedClients = mergeDeletedClients(
|
|
88
|
+
allDeletedClients,
|
|
89
|
+
newDeletedClients
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
);
|
|
90
93
|
}
|
|
91
94
|
const normalizedDeletedClients = normalizeDeletedClients(allDeletedClients);
|
|
92
95
|
await onClientsDeleted(normalizedDeletedClients);
|
|
@@ -114,11 +117,11 @@ async function dropDatabases(idbDatabasesStore, namesToRemove, kvDropStore) {
|
|
|
114
117
|
}
|
|
115
118
|
return { dropped, errors };
|
|
116
119
|
}
|
|
117
|
-
function defaultNewDagStore(name) {
|
|
118
|
-
const perKvStore =
|
|
120
|
+
function defaultNewDagStore(name, kvCreateStore) {
|
|
121
|
+
const perKvStore = kvCreateStore(name);
|
|
119
122
|
return new StoreImpl(perKvStore, newRandomHash, assertHash);
|
|
120
123
|
}
|
|
121
|
-
function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, newDagStore) {
|
|
124
|
+
function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, kvCreateStore, newDagStore) {
|
|
122
125
|
if (db.replicacheFormatVersion > Latest) {
|
|
123
126
|
return [false];
|
|
124
127
|
}
|
|
@@ -131,7 +134,7 @@ function gatherDatabaseInfoForCollect(db, now, maxAge, enableMutationRecovery, n
|
|
|
131
134
|
);
|
|
132
135
|
return canDatabaseBeCollectedAndGetDeletedClientIDs(
|
|
133
136
|
enableMutationRecovery,
|
|
134
|
-
newDagStore(db.name)
|
|
137
|
+
newDagStore(db.name, kvCreateStore)
|
|
135
138
|
);
|
|
136
139
|
}
|
|
137
140
|
async function dropDatabase(dbName, opts) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect-idb-databases.js","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"sourcesContent":["import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport {StoreImpl} from '../dag/store-impl.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n getDeletedClients,\n mergeDeletedClients,\n normalizeDeletedClients,\n type DeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {getKVStoreProvider} from '../get-kv-store-provider.ts';\nimport {assertHash, newRandomHash} from '../hash.ts';\nimport {IDBStore} from '../kv/idb-store.ts';\nimport type {DropStore, StoreProvider} from '../kv/store.ts';\nimport {createLogContext} from '../log-options.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.ts';\nimport type {OnClientsDeleted} from './clients.ts';\nimport {getClients} from './clients.ts';\nimport type {IndexedDBDatabase} from './idb-databases-store.ts';\nimport {IDBDatabasesStore} from './idb-databases-store.ts';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n collectInterval: number,\n initialCollectDelay: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n maxAge,\n kvDropStore,\n enableMutationRecovery,\n onClientsDeleted,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n maxAge: number,\n kvDropStore: DropStore,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n newDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases);\n const collectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await gatherDatabaseInfoForCollect(\n db,\n now,\n maxAge,\n enableMutationRecovery,\n newDagStore,\n ),\n ] as const,\n ),\n );\n\n const dbNamesToRemove: string[] = [];\n const dbNamesToKeep: string[] = [];\n const deletedClientsToRemove: WritableDeletedClients = [];\n for (const [dbName, [canCollect, deletedClients]] of collectResults) {\n if (canCollect) {\n dbNamesToRemove.push(dbName);\n deletedClientsToRemove.push(...deletedClients);\n } else {\n dbNamesToKeep.push(dbName);\n }\n }\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n dbNamesToRemove,\n kvDropStore,\n );\n if (errors.length) {\n throw errors[0];\n }\n\n if (deletedClientsToRemove.length > 0) {\n // Add the deleted clients to all the dbs that survived the collection.\n let allDeletedClients: DeletedClients = deletedClientsToRemove;\n for (const name of dbNamesToKeep) {\n await withWrite(newDagStore(name), async dagWrite => {\n const newDeletedClients = await addDeletedClients(\n dagWrite,\n deletedClientsToRemove,\n );\n\n allDeletedClients = mergeDeletedClients(\n allDeletedClients,\n newDeletedClients,\n );\n });\n }\n // normalize and dedupe\n const normalizedDeletedClients = normalizeDeletedClients(allDeletedClients);\n\n // Call the callback with the normalized deleted clients\n await onClientsDeleted(normalizedDeletedClients);\n }\n}\n\nasync function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\nfunction defaultNewDagStore(name: string): Store {\n const perKvStore = new IDBStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\n/**\n * If the database is older than maxAge and there are no pending mutations we\n * return `true` and an array of the deleted clients in that db. If the database is\n * too new or there are pending mutations we return `[false]`.\n */\nfunction gatherDatabaseInfoForCollect(\n db: IndexedDBDatabase,\n now: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n newDagStore: typeof defaultNewDagStore,\n): MaybePromise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return [false];\n }\n\n // 0 is used in testing\n assert(db.lastOpenedTimestampMS !== undefined);\n\n // - For DD31 we can delete the database if it is older than maxAge and\n // there are no pending mutations.\n if (now - db.lastOpenedTimestampMS < maxAge) {\n return [false];\n }\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n );\n return canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery,\n newDagStore(db.name),\n );\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Drops the specified database.\n * @param dbName The name of the database to drop.\n * @param opts Options for dropping the database.\n */\nexport async function dropDatabase(dbName: string, opts?: DropDatabaseOptions) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n await dropDatabaseInternal(\n dbName,\n new IDBDatabasesStore(kvStoreProvider.create),\n kvStoreProvider.drop,\n );\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n */\nexport async function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropAllDatabases: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n const store = new IDBDatabasesStore(kvStoreProvider.create);\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases).map(db => db.name);\n return dropDatabases(store, dbNames, kvStoreProvider.drop);\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(opts?: DropDatabaseOptions) {\n return dropAllDatabases(opts);\n}\n\n/**\n * If there are pending mutations in any of the clients in this db we return\n * `[false]`. Otherwise we return `true` and an array of the deleted clients to\n * remove.\n */\nfunction canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery: boolean,\n perdag: Store,\n): Promise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n return withRead(perdag, async read => {\n // If mutation recovery is disabled we do not care if there are pending\n // mutations when we decide if we can collect the database.\n if (enableMutationRecovery) {\n const clientGroups = await getClientGroups(read);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return [false];\n }\n }\n }\n\n const clients = await getClients(read);\n const existingDeletedClients = await getDeletedClients(read);\n const deletedClients: WritableDeletedClients = [...existingDeletedClients];\n\n // Add all current clients to the deleted clients list\n for (const [clientID, client] of clients) {\n deletedClients.push({\n clientID,\n clientGroupID: client.clientGroupID,\n });\n }\n\n // The normalization (deduping and sorting) will be done when storing\n return [true, deletedClients];\n });\n}\n"],"names":["FormatVersion.Latest","FormatVersion.DD31","FormatVersion.V6","FormatVersion.V7"],"mappings":";;;;;;;;;;;;;AAiCO,MAAM,uBAAuB,KAAK,KAAK,KAAK;AAK5C,MAAM,4BAA4B,IAAI,KAAK;AAE3C,SAAS,wBACd,mBACA,aACA,iBACA,qBACA,QACA,wBACA,kBACA,IACA,QACM;AACN,MAAI,UAAU;AACd;AAAA,IACE;AAAA,IACA,YAAY;AACV,YAAM;AAAA,QACJ;AAAA,QACA,KAAK,IAAA;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,MAAM;AACJ,UAAI,SAAS;AACX,kBAAU;AACV,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAKA,eAAsB,oBACpB,mBACA,KACA,QACA,aACA,wBACA,kBACA,cAAc,oBACC;AACf,QAAM,YAAY,MAAM,kBAAkB,aAAA;AAE1C,QAAM,MAAM,OAAO,OAAO,SAAS;AACnC,QAAM,iBAAiB,MAAM,QAAQ;AAAA,IACnC,IAAI;AAAA,MACF,OAAM,OACJ;AAAA,QACE,GAAG;AAAA,QACH,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,MACF;AAAA,IACF;AAAA,EACJ;AAGF,QAAM,kBAA4B,CAAA;AAClC,QAAM,gBAA0B,CAAA;AAChC,QAAM,yBAAiD,CAAA;AACvD,aAAW,CAAC,QAAQ,CAAC,YAAY,cAAc,CAAC,KAAK,gBAAgB;AACnE,QAAI,YAAY;AACd,sBAAgB,KAAK,MAAM;AAC3B,6BAAuB,KAAK,GAAG,cAAc;AAAA,IAC/C,OAAO;AACL,oBAAc,KAAK,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,EAAC,OAAA,IAAU,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,OAAO,QAAQ;AACjB,UAAM,OAAO,CAAC;AAAA,EAChB;AAEA,MAAI,uBAAuB,SAAS,GAAG;AAErC,QAAI,oBAAoC;AACxC,eAAW,QAAQ,eAAe;AAChC,YAAM,UAAU,YAAY,IAAI,GAAG,OAAM,aAAY;AACnD,cAAM,oBAAoB,MAAM;AAAA,UAC9B;AAAA,UACA;AAAA,QAAA;AAGF,4BAAoB;AAAA,UAClB;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,IACH;AAEA,UAAM,2BAA2B,wBAAwB,iBAAiB;AAG1E,UAAM,iBAAiB,wBAAwB;AAAA,EACjD;AACF;AAEA,eAAe,qBACb,MACA,mBACA,aACA;AACA,QAAM,YAAY,IAAI;AACtB,QAAM,kBAAkB,gBAAgB,CAAC,IAAI,CAAC;AAChD;AAEA,eAAe,cACb,mBACA,eACA,aACiD;AAGjD,QAAM,mBAAmB,MAAM,QAAQ;AAAA,IACrC,cAAc,IAAI,OAAM,SAAQ;AAC9B,YAAM,qBAAqB,MAAM,mBAAmB,WAAW;AAC/D,aAAO;AAAA,IACT,CAAC;AAAA,EAAA;AAGH,QAAM,UAAoB,CAAA;AAC1B,QAAM,SAAoB,CAAA;AAC1B,aAAW,UAAU,kBAAkB;AACrC,QAAI,OAAO,WAAW,aAAa;AACjC,cAAQ,KAAK,OAAO,KAAK;AAAA,IAC3B,OAAO;AACL,aAAO,KAAK,OAAO,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,EAAC,SAAS,OAAA;AACnB;AAEA,SAAS,mBAAmB,MAAqB;AAC/C,QAAM,aAAa,IAAI,SAAS,IAAI;AACpC,SAAO,IAAI,UAAU,YAAY,eAAe,UAAU;AAC5D;AAOA,SAAS,6BACP,IACA,KACA,QACA,wBACA,aAGA;AACA,MAAI,GAAG,0BAA0BA,QAAsB;AACrD,WAAO,CAAC,KAAK;AAAA,EACf;AAGA,SAAO,GAAG,0BAA0B,MAAS;AAI7C,MAAI,MAAM,GAAG,wBAAwB,QAAQ;AAC3C,WAAO,CAAC,KAAK;AAAA,EACf;AAGA;AAAA,IACE,GAAG,4BAA4BC,QAC7B,GAAG,4BAA4BC,MAC/B,GAAG,4BAA4BC;AAAAA,EAAc;AAEjD,SAAO;AAAA,IACL;AAAA,IACA,YAAY,GAAG,IAAI;AAAA,EAAA;AAEvB;AA0CA,eAAsB,aAAa,QAAgB,MAA4B;AAC7E,QAAM,aAAa,iBAAiB,MAAM,UAAU,MAAM,UAAU;AAAA,IAClE,cAAc;AAAA,EAAA,CACf;AACD,QAAM,kBAAkB,mBAAmB,YAAY,MAAM,OAAO;AACpE,QAAM;AAAA,IACJ;AAAA,IACA,IAAI,kBAAkB,gBAAgB,MAAM;AAAA,IAC5C,gBAAgB;AAAA,EAAA;AAEpB;AAQA,eAAsB,iBAAiB,MAGpC;AACD,QAAM,aAAa,iBAAiB,MAAM,UAAU,MAAM,UAAU;AAAA,IAClE,kBAAkB;AAAA,EAAA,CACnB;AACD,QAAM,kBAAkB,mBAAmB,YAAY,MAAM,OAAO;AACpE,QAAM,QAAQ,IAAI,kBAAkB,gBAAgB,MAAM;AAC1D,QAAM,YAAY,MAAM,MAAM,aAAA;AAC9B,QAAM,UAAU,OAAO,OAAO,SAAS,EAAE,IAAI,CAAA,OAAM,GAAG,IAAI;AAC1D,SAAO,cAAc,OAAO,SAAS,gBAAgB,IAAI;AAC3D;AAmBA,SAAS,6CACP,wBACA,QAGA;AACA,SAAO,SAAS,QAAQ,OAAM,SAAQ;AAGpC,QAAI,wBAAwB;AAC1B,YAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,iBAAW,eAAe,aAAa,UAAU;AAC/C,YAAI,+BAA+B,WAAW,GAAG;AAC/C,iBAAO,CAAC,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,WAAW,IAAI;AACrC,UAAM,yBAAyB,MAAM,kBAAkB,IAAI;AAC3D,UAAM,iBAAyC,CAAC,GAAG,sBAAsB;AAGzE,eAAW,CAAC,UAAU,MAAM,KAAK,SAAS;AACxC,qBAAe,KAAK;AAAA,QAClB;AAAA,QACA,eAAe,OAAO;AAAA,MAAA,CACvB;AAAA,IACH;AAGA,WAAO,CAAC,MAAM,cAAc;AAAA,EAC9B,CAAC;AACH;"}
|
|
1
|
+
{"version":3,"file":"collect-idb-databases.js","sources":["../../../../../replicache/src/persist/collect-idb-databases.ts"],"sourcesContent":["import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport {StoreImpl} from '../dag/store-impl.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n getDeletedClients,\n mergeDeletedClients,\n normalizeDeletedClients,\n type DeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {getKVStoreProvider} from '../get-kv-store-provider.ts';\nimport {assertHash, newRandomHash} from '../hash.ts';\nimport type {CreateStore, DropStore, StoreProvider} from '../kv/store.ts';\nimport {createLogContext} from '../log-options.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.ts';\nimport type {OnClientsDeleted} from './clients.ts';\nimport {getClients} from './clients.ts';\nimport type {IndexedDBDatabase} from './idb-databases-store.ts';\nimport {IDBDatabasesStore} from './idb-databases-store.ts';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvStoreProvider: StoreProvider,\n collectInterval: number,\n initialCollectDelay: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n maxAge,\n kvStoreProvider,\n enableMutationRecovery,\n onClientsDeleted,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n maxAge: number,\n kvStoreProvider: StoreProvider,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n newDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases);\n const collectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await gatherDatabaseInfoForCollect(\n db,\n now,\n maxAge,\n enableMutationRecovery,\n kvStoreProvider.create,\n newDagStore,\n ),\n ] as const,\n ),\n );\n\n const dbNamesToRemove: string[] = [];\n const dbNamesToKeep: string[] = [];\n const deletedClientsToRemove: WritableDeletedClients = [];\n for (const [dbName, [canCollect, deletedClients]] of collectResults) {\n if (canCollect) {\n dbNamesToRemove.push(dbName);\n deletedClientsToRemove.push(...deletedClients);\n } else {\n dbNamesToKeep.push(dbName);\n }\n }\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n dbNamesToRemove,\n kvStoreProvider.drop,\n );\n if (errors.length) {\n throw errors[0];\n }\n\n if (deletedClientsToRemove.length > 0) {\n // Add the deleted clients to all the dbs that survived the collection.\n let allDeletedClients: DeletedClients = deletedClientsToRemove;\n for (const name of dbNamesToKeep) {\n await withWrite(\n newDagStore(name, kvStoreProvider.create),\n async dagWrite => {\n const newDeletedClients = await addDeletedClients(\n dagWrite,\n deletedClientsToRemove,\n );\n\n allDeletedClients = mergeDeletedClients(\n allDeletedClients,\n newDeletedClients,\n );\n },\n );\n }\n // normalize and dedupe\n const normalizedDeletedClients = normalizeDeletedClients(allDeletedClients);\n\n // Call the callback with the normalized deleted clients\n await onClientsDeleted(normalizedDeletedClients);\n }\n}\n\nasync function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\nfunction defaultNewDagStore(name: string, kvCreateStore: CreateStore): Store {\n const perKvStore = kvCreateStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\n/**\n * If the database is older than maxAge and there are no pending mutations we\n * return `true` and an array of the deleted clients in that db. If the database is\n * too new or there are pending mutations we return `[false]`.\n */\nfunction gatherDatabaseInfoForCollect(\n db: IndexedDBDatabase,\n now: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n kvCreateStore: CreateStore,\n newDagStore: typeof defaultNewDagStore,\n): MaybePromise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return [false];\n }\n\n // 0 is used in testing\n assert(db.lastOpenedTimestampMS !== undefined);\n\n // - For DD31 we can delete the database if it is older than maxAge and\n // there are no pending mutations.\n if (now - db.lastOpenedTimestampMS < maxAge) {\n return [false];\n }\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n );\n return canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery,\n newDagStore(db.name, kvCreateStore),\n );\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Drops the specified database.\n * @param dbName The name of the database to drop.\n * @param opts Options for dropping the database.\n */\nexport async function dropDatabase(dbName: string, opts?: DropDatabaseOptions) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n await dropDatabaseInternal(\n dbName,\n new IDBDatabasesStore(kvStoreProvider.create),\n kvStoreProvider.drop,\n );\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n */\nexport async function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropAllDatabases: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n const store = new IDBDatabasesStore(kvStoreProvider.create);\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases).map(db => db.name);\n return dropDatabases(store, dbNames, kvStoreProvider.drop);\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(opts?: DropDatabaseOptions) {\n return dropAllDatabases(opts);\n}\n\n/**\n * If there are pending mutations in any of the clients in this db we return\n * `[false]`. Otherwise we return `true` and an array of the deleted clients to\n * remove.\n */\nfunction canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery: boolean,\n perdag: Store,\n): Promise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n return withRead(perdag, async read => {\n // If mutation recovery is disabled we do not care if there are pending\n // mutations when we decide if we can collect the database.\n if (enableMutationRecovery) {\n const clientGroups = await getClientGroups(read);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return [false];\n }\n }\n }\n\n const clients = await getClients(read);\n const existingDeletedClients = await getDeletedClients(read);\n const deletedClients: WritableDeletedClients = [...existingDeletedClients];\n\n // Add all current clients to the deleted clients list\n for (const [clientID, client] of clients) {\n deletedClients.push({\n clientID,\n clientGroupID: client.clientGroupID,\n });\n }\n\n // The normalization (deduping and sorting) will be done when storing\n return [true, deletedClients];\n });\n}\n"],"names":["FormatVersion.Latest","FormatVersion.DD31","FormatVersion.V6","FormatVersion.V7"],"mappings":"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"}
|