@rocicorp/zero 0.26.0-canary.0 → 0.26.0-canary.10
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/analyze-query/src/bin-transform.js +3 -1
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/analyze-query/src/run-ast.d.ts.map +1 -1
- package/out/analyze-query/src/run-ast.js +2 -1
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +16 -9
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/replicache/src/bg-interval.d.ts.map +1 -1
- package/out/replicache/src/bg-interval.js +3 -0
- package/out/replicache/src/bg-interval.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 +30 -24
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.d.ts +2 -1
- package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js +1 -1
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
- package/out/replicache/src/persist/refresh.d.ts.map +1 -1
- package/out/replicache/src/persist/refresh.js +0 -8
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/process-scheduler.d.ts +23 -0
- package/out/replicache/src/process-scheduler.d.ts.map +1 -1
- package/out/replicache/src/process-scheduler.js +50 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +8 -0
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +11 -2
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/shared/src/bigint-json.js +1 -1
- package/out/shared/src/browser-env.js +0 -4
- package/out/shared/src/browser-env.js.map +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/falsy.d.ts +3 -0
- package/out/shared/src/falsy.d.ts.map +1 -0
- 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/shared/src/options.d.ts +1 -0
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +5 -1
- package/out/shared/src/options.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +23 -0
- package/out/z2s/src/compiler.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/adapters/prisma.d.ts +2 -0
- package/out/zero/src/adapters/prisma.d.ts.map +1 -0
- package/out/zero/src/adapters/prisma.js +6 -0
- package/out/zero/src/adapters/prisma.js.map +1 -0
- package/out/zero/src/pg.js +4 -7
- package/out/zero/src/react.js +3 -1
- package/out/zero/src/react.js.map +1 -1
- package/out/zero/src/server.js +5 -8
- package/out/zero/src/zero-cache-dev.js +9 -6
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero-cache/src/auth/auth.d.ts +45 -0
- package/out/zero-cache/src/auth/auth.d.ts.map +1 -0
- package/out/zero-cache/src/auth/auth.js +179 -0
- package/out/zero-cache/src/auth/auth.js.map +1 -0
- package/out/zero-cache/src/auth/load-permissions.d.ts +3 -2
- package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +17 -9
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.d.ts +3 -3
- package/out/zero-cache/src/auth/read-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +4 -4
- package/out/zero-cache/src/auth/read-authorizer.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 +19 -4
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +53 -9
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +91 -20
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +6 -3
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +142 -76
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +0 -1
- package/out/zero-cache/src/custom-queries/transform-query.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/pg-type-parser.d.ts +9 -1
- package/out/zero-cache/src/db/pg-type-parser.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +13 -4
- package/out/zero-cache/src/db/pg-type-parser.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 +16 -12
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/observability/events.d.ts.map +1 -1
- package/out/zero-cache/src/observability/events.js +15 -5
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +1 -0
- package/out/zero-cache/src/server/anonymous-otel-start.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 +25 -7
- 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 +13 -32
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/main.js +2 -2
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/priority-op.d.ts +8 -0
- package/out/zero-cache/src/server/priority-op.d.ts.map +1 -0
- package/out/zero-cache/src/server/priority-op.js +29 -0
- package/out/zero-cache/src/server/priority-op.js.map +1 -0
- package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +7 -3
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +20 -12
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts +3 -3
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +10 -4
- 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/common/backfill-manager.d.ts +47 -0
- package/out/zero-cache/src/services/change-source/common/backfill-manager.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +426 -0
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -0
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts +55 -0
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +117 -0
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts +9 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +136 -0
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.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/custom/sync-schema.js +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.d.ts +14 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js +15 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts +19 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +205 -0
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -0
- 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 +177 -40
- 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 +11 -0
- 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 +32 -28
- 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 +12 -4
- 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 +20 -11
- 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 +25 -40
- 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 +47 -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 +26 -18
- 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/pg/sync-schema.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +213 -54
- 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 +157 -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 +267 -76
- 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/downstream.js +7 -4
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts +24 -8
- package/out/zero-cache/src/services/change-source/protocol/current/status.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.js +15 -6
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +31 -2
- 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 +14 -2
- 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 +18 -6
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +3 -3
- 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 +40 -18
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +2 -2
- 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 +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 +32 -10
- 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 +89 -26
- 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/forwarder.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +3 -4
- package/out/zero-cache/src/services/change-streamer/forwarder.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 +14 -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 +38 -5
- 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 +12 -5
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +223 -27
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +4 -3
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +22 -13
- 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/litestream/commands.d.ts +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +5 -2
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/config.yml +1 -0
- 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 +8 -6
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +142 -23
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts +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 +182 -68
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +14 -12
- 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 +42 -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 +133 -68
- 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.d.ts +4 -4
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +4 -4
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -0
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +3 -0
- package/out/zero-cache/src/services/running-state.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 +110 -86
- 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 +361 -172
- 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 +392 -333
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -2
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +4 -4
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +15 -23
- 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 +211 -123
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +25 -14
- package/out/zero-cache/src/services/view-syncer/row-record-cache.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 +12 -13
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/tracer.d.ts +2 -0
- package/out/zero-cache/src/services/view-syncer/tracer.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/tracer.js +7 -0
- package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +17 -12
- 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 +374 -344
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js +1 -1
- package/out/zero-cache/src/types/error-with-level.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/pg-data-type.d.ts +2 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js +2 -0
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.js +3 -1
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts +11 -2
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +21 -11
- package/out/zero-cache/src/types/pg.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 +33 -0
- package/out/zero-cache/src/types/state-version.js.map +1 -0
- package/out/zero-cache/src/types/streams.d.ts +8 -1
- package/out/zero-cache/src/types/streams.d.ts.map +1 -1
- package/out/zero-cache/src/types/streams.js +22 -8
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +1 -1
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -1
- package/out/zero-cache/src/types/subscription.js +2 -2
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +7 -1
- package/out/zero-cache/src/types/websocket-handoff.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/connection.js +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +3 -6
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts +2 -2
- 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 +38 -21
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +2 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +48 -49
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +11 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +43 -3
- 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/error.d.ts +5 -1
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js +4 -4
- package/out/zero-client/src/client/error.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/options.d.ts +25 -12
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.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-poke-handler.d.ts +5 -5
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +15 -17
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +12 -8
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +95 -12
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.d.ts +2 -1
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +1 -0
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +7 -2
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +4 -0
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +3 -1
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +26 -0
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +31 -2
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +5 -0
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-protocol/src/up.js +2 -0
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/update-auth.d.ts +11 -0
- package/out/zero-protocol/src/update-auth.d.ts.map +1 -0
- package/out/zero-protocol/src/update-auth.js +13 -0
- package/out/zero-protocol/src/update-auth.js.map +1 -0
- package/out/zero-react/src/mod.d.ts +3 -1
- 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-query.d.ts +14 -4
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +14 -13
- package/out/zero-react/src/use-query.js.map +1 -1
- 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-react/src/zero-provider.d.ts +5 -5
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.js +1 -1
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.d.ts +18 -18
- 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/adapters/pg.d.ts +19 -13
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts +19 -13
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/adapters/prisma.d.ts +66 -0
- package/out/zero-server/src/adapters/prisma.d.ts.map +1 -0
- package/out/zero-server/src/adapters/prisma.js +63 -0
- package/out/zero-server/src/adapters/prisma.js.map +1 -0
- package/out/zero-server/src/custom.js +1 -15
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +9 -8
- package/out/zero-server/src/mod.d.ts.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/mod.d.ts +1 -1
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +42 -0
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +2 -1
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-query.d.ts +12 -3
- package/out/zero-solid/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/use-query.js +22 -5
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero.d.ts +5 -5
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero.js +1 -1
- package/out/zero-solid/src/use-zero.js.map +1 -1
- package/out/zero-types/src/default-types.d.ts +2 -0
- package/out/zero-types/src/default-types.d.ts.map +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +57 -6
- package/out/zql/src/ivm/array-view.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 +25 -2
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/stream.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js +1 -1
- package/out/zql/src/ivm/stream.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/ivm/view-apply-change.d.ts +50 -3
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +358 -105
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts +3 -3
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.js +4 -4
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/query/create-builder.js +3 -5
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/expression.d.ts +7 -7
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js +14 -7
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +1 -3
- package/out/zql/src/query/query-delegate-base.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 +15 -15
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-registry.d.ts +3 -3
- package/out/zql/src/query/query-registry.d.ts.map +1 -1
- package/out/zql/src/query/query-registry.js +4 -4
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/query.d.ts +31 -8
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts +55 -0
- package/out/zqlite/src/resolve-scalar-subqueries.d.ts.map +1 -0
- package/out/zqlite/src/resolve-scalar-subqueries.js +139 -0
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -0
- package/out/zqlite/src/sqlite-cost-model.js.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 +11 -9
- 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/services/change-source/replica-schema.d.ts +0 -7
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +0 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js +0 -76
- package/out/zero-cache/src/services/change-source/replica-schema.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CA,MAAM,UAAU;AAAA,EACd,QAAQ,yBAAyB;AAAA,EACjC,aAAa;AAAA,IACX,GAAG,YAAY,QAAQ;AAAA,IACvB,MAAM,CAAC,0DAA0D;AAAA,EAAA;AAAA,EAEnE,KAAK;AAAA,IACH,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM;AAAA,MACJ;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,OAAO;AAAA,IACL,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,MAAM;AAAA,IACJ,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,kBAAkB;AAAA,IAChB,MAAMC,QAAE,EAAU,QAAQ,KAAK;AAAA,IAC/B,MAAM;AAAA,MACJ;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAMD,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,kBAAkB;AAAA,IAChB,MAAMC,QAAE,EAAU,QAAQ,KAAK;AAAA,IAC/B,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,kBAAkB;AAAA,IAChB,MAAMA,QAAE,EAAU,QAAQ,KAAK;AAAA,IAC/B,MAAM;AAAA,MACJ;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,KAAK;AAAA,IACH,IAAI;AAAA,MACF,MAAMD,OAAE,EAAS,SAAA;AAAA,MACjB,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MAAA;AAAA,IACF;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,IAAI;AAAA,MACF,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,MAAMA,OAAE,EAAS,SAAA;AAAA,IAAS;AAAA,IAE5B,MAAM,YAAY,SAAS;AAAA,EAAA;AAAA,EAE7B,KAAK;AAAA,EACL,OAAO;AAAA,EACP,KAAK;AAAA,IACH,GAAG;AAAA,IACH,OAAO,SAAS,QAAQ,OAAO;AAAA,EAAA;AAEnC;AAEA,MAAM,MAAM,aAAa,SAAS;AAAA;AAAA;AAAA;AAAA,EAIhC,MAAM,QAAQ,KAAK,MAAM,CAAC,EAAE,IAAI,CAAA,MAAK,EAAE,WAAW,MAAM,GAAG,CAAC;AAAA,EAC5D,eAAe;AAAA,EACf,aAAa;AAAA,IACX;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,IAMX;AAAA,MACE,QAAQ;AAAA,MACR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAA;AAAA,EAyBX;AAEJ,CAAC;AACD,MAAM,SAAS;AAAA,EACb,GAAG;AAAA,EACH,KAAK;AAAA,IACH,GAAG,IAAI;AAAA,IACP,IAAI,IAAI,IAAI,MAAM,IAAI,SAAS;AAAA,EAAA;AAEnC;AAEA,kBAAkB,uBAAuB;AACzC,kBAAkB,kBAAkB,OAAO;AAE3C,MAAM,KAAK,iBAAiB;AAAA,EAC1B,KAAK,OAAO;AACd,CAAC;AAED,IAAI,CAAC,GAAG,WAAW,OAAO,WAAW,GAAG;AACtC,eAAa,MAAM,gBAAgB,OAAO,WAAW,iBAAiB;AACtE,UAAQ,KAAK,CAAC;AAChB;AACA,MAAM,KAAK,IAAI,SAAS,IAAI,OAAO,WAAW;AAE9C,MAAM,EAAC,QAAQ,YAAA,IAAe,MAAM;AAAA,EAClC,OAAO,OAAO;AAChB;AACA,MAAM,eAAe,iBAAiB,MAAM,EAAE;AAE9C,MAAM,8BAAc,IAAA;AACpB,MAAM,uBAAuB,eAAe,OAAO,MAAM;AACzD,MAAM,QAAQ,IAAI,MAAA;AAClB,MAAM,aAAa,gBAAgB,IAAI,EAAE;AAEzC,MAAM,6BAA6B,kBAAkB;AAAA,EAC1C,QAAQ;AAAA,EACR,uBAAuB;AAAA,EAEhC,UAAU,iBAA6C;AACrD,QAAI,SAAS,QAAQ,IAAI,eAAe;AACxC,QAAI,QAAQ;AACV,aAAO;AAAA,IACT;AACA,UAAM,YAAY,iBAAiB,YAAY,eAAe;AAC9D,UAAM,EAAC,eAAc,UAAU;AAE/B,aAAS,IAAI;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IAAA;AAGF,YAAQ,IAAI,iBAAiB,MAAM;AACnC,WAAO;AAAA,EACT;AACF;AAEA,MAAM,OAAO,IAAI,qBAAA;AAEjB,IAAI;AAEJ,IAAI,OAAO,KAAK;AAEd,WAAS,MAAM,OAAO,IAAI,cAAc,KAAK,MAAM,OAAO,GAAG,GAAG,MAAM;AAAA,IACpE,kBAAkB,OAAO;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IAGnB;AAAA,EAAA,CACD;AACH,WAAW,OAAO,OAAO;AACvB,WAAS,MAAM,SAAS,OAAO,KAAK;AACtC,WAAW,OAAO,MAAM;AACtB,WAAS,MAAM,QAAQ,OAAO,IAAI;AACpC,OAAO;AACL,eAAa,MAAM,kCAAkC;AACrD,UAAQ,KAAK,CAAC;AAChB;AAEA,SAAS,SAAS,aAAkD;AAClE,QAAM,IAAI;AAAA,IACR,OAAO,OAAO;AAAA,MACZ,OAAO,QAAQ,OAAO,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM;AAAA,QAC5C;AAAA,QACA,SAAS,QAAQ,IAAI;AAAA,MAAA,CACtB;AAAA,IAAA;AAAA,EACH;AAGF,QAAM,IAAI,IAAI,SAAS,KAAK,kBAAkB,WAAW,GAAG;AAC5D,QAAM,IAAoD,EAAE,CAAC;AAE7D,QAAM,MAAM,iBAAiB,CAAC,EAAE;AAChC,SAAO,OAAO,IAAI,cAAc,KAAK,OAAO;AAAA,IAC1C,kBAAkB,OAAO;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IAGnB;AAAA,EAAA,CACD;AACH;AAEA,eAAe,QAAQ,MAAc;AACnC,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA,KAAK,OAAO,IAAI,IAAI,oDAAoD;AAAA,EAAA;AAG1E,QAAM,OAAO,MAAM,4CAA4C;AAAA,IAC7D,eAAe,WAAW,MAAM,CAAC,IAAI;AAAA,EAAA,CACtC,kCAAkC,KAAK,IAAI,CAAC;AAC7C,QAAM,MAAM,IAAA;AAEZ,eAAa,IAAI,gBAAgB;AACjC,QAAM,MAAM,KAAK,CAAC,EAAE;AACpB,eAAa,IAAI,MAAM,aAAa,IAAI,QAAQ,SAAS,GAAG,CAAC,CAAC;AAE9D,SAAO,OAAO,IAAI,cAAc,KAAK,MAAM;AAAA,IACzC,kBAAkB,OAAO;AAAA,IACzB,UAAU,OAAO;AAAA,IACjB;AAAA,IACA;AAAA,IACA,YAAY,OAAO;AAAA,IAGnB;AAAA,EAAA,CACD;AACH;AAEA,IAAI,OAAO,kBAAkB;AAC3B,eAAa,IAAI,MAAM,KAAK,KAAK,wBAAwB,CAAC;AAC1D,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,OAAO,cAAc,CAAA,CAAE,GAAG;AACnE,iBAAa,IAAI,MAAM,KAAK,QAAQ,GAAG,GAAG,IAAI;AAAA,EAChD;AACF;AAEA,aAAa,IAAI,MAAM,KAAK,KAAK,wBAAwB,CAAC;AAC1D,aAAa,IAAI,MAAM,KAAK,oBAAoB,GAAG,OAAO,cAAc;AACxE,UAAA;AACA,IAAI,OAAO,kBAAkB;AAC3B,eAAa,IAAI,MAAM,KAAK,KAAK,+BAA+B,CAAC;AACjE,aAAW,UAAU,QAAQ,UAAU;AACrC,iBAAa;AAAA,MACX,MAAM,KAAK,GAAG,OAAO,YAAY,IAAI,GAAG;AAAA,MACxC,MAAM,cAAA,IAAkB,OAAO,YAAY,IAAI,KAAK,CAAA;AAAA,IAAC;AAAA,EAEzD;AACF;AAEA,aAAa,IAAI,MAAM,KAAK,KAAK,uCAAuC,CAAC;AACzE,MAAM,eAAe,MAAM,gBAAA;AAC3B,IAAI,cAAc;AAClB,WAAW,CAAC,OAAO,OAAO,KAAK,OAAO,QAAQ,YAAY,GAAG;AAC3D,eAAa,IAAI,MAAM,KAAK,GAAG,KAAK,GAAG,GAAG,OAAO;AACjD,aAAW,SAAS,OAAO,OAAO,OAAO,GAAG;AAC1C,mBAAe;AAAA,EACjB;AACF;AACA,aAAa;AAAA,EACX,MAAM,KAAK,qBAAqB;AAAA,EAChC,oBAAoB,WAAW;AACjC;AAEA,aAAa,IAAI,MAAM,KAAK,KAAK,4BAA4B,CAAC;AAC9D,MAAM,QAAQ,eAAe,MAAM,wBAAwB,CAAA,GAAI,EAAE;AACjE,WAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,eAAa,IAAI,MAAM,KAAK,OAAO,GAAG,KAAK;AAC3C,eAAa,IAAI,KAAK,IAAI,CAAC,KAAK,MAAM,aAAa,KAAK,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;AACtE,eAAa,IAAI,IAAI;AACvB;AAEA,SAAS,YAAY;AACnB,MAAI,sBAAsB;AAC1B,aAAW,UAAU,QAAQ,UAAU;AACrC,UAAM,SAAS,OAAO;AAAA,MACpB,MAAM,mBAAA,IAAuB,OAAO,YAAY,IAAI,KAAK,CAAA;AAAA,IAAC;AAE5D,eAAWE,MAAK,QAAQ;AACtB,6BAAuBA;AAAAA,IACzB;AACA,iBAAa;AAAA,MACX,MAAM,KAAK,OAAO,YAAY,OAAO,UAAU;AAAA,MAC/C,MAAM,mBAAA,IAAuB,OAAO,YAAY,IAAI,KAAK,CAAA;AAAA,IAAC;AAAA,EAE9D;AAEA,eAAa;AAAA,IACX,MAAM,KAAK,sBAAsB;AAAA,IACjC,oBAAoB,mBAAmB;AAAA,EAAA;AAEzC,eAAa;AAAA,IACX,MAAM,KAAK,OAAO;AAAA,IAClB,UAAU,OAAO,MAAM,OAAO,KAAK;AAAA,IACnC;AAAA,EAAA;AAEJ;AAEA,SAAS,UAAU,UAAkB;AACnC,MAAI,WAAW,KAAK;AAClB,WAAO,MAAM,MAAM,SAAS,QAAQ,CAAC,IAAI,IAAI;AAAA,EAC/C,WAAW,WAAW,KAAM;AAC1B,WAAO,MAAM,OAAO,SAAS,QAAQ,CAAC,IAAI,IAAI;AAAA,EAChD;AACA,SAAO,MAAM,IAAI,SAAS,QAAQ,CAAC,IAAI,IAAI;AAC7C;AAEA,SAAS,oBAAoB,GAAW;AACtC,MAAI,IAAI,KAAM;AACZ,WAAO,MAAM,MAAM,EAAE,SAAA,CAAU;AAAA,EACjC,WAAW,IAAI,KAAO;AACpB,WAAO,MAAM,OAAO,EAAE,SAAA,CAAU;AAAA,EAClC;AACA,SAAO,MAAM,IAAI,EAAE,SAAA,CAAU;AAC/B;AAEA,SAAS,aAAa,KAAa,GAAW;AAC5C,MAAI,IAAI,SAAS,MAAM,GAAG;AACxB,QAAI,MAAM,GAAG;AACX,aAAO,MAAM,OAAO,GAAG;AAAA,IACzB;AACA,WAAO,MAAM,IAAI,GAAG;AAAA,EACtB;AACA,SAAO,MAAM,MAAM,GAAG;AACxB;"}
|
|
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin-transform.js","sources":["../../../../analyze-query/src/bin-transform.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {loadSchemaAndPermissions} 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';\n\nconst options = {\n cvr: {db: v.string()},\n schema: {\n type: v.string().default('./schema.ts'),\n desc: ['Path to the schema file.'],\n },\n app: appOptions,\n shard: shardOptions,\n hash: {\n type: v.string().optional(),\n desc: ['Hash of the query to fetch the AST for.'],\n },\n};\n\nconst config = parseOptions(options, {envNamePrefix: ZERO_ENV_VAR_PREFIX});\n\nconst lc = new LogContext('debug', {}, consoleLogSink);\nconst {permissions} = await loadSchemaAndPermissions(config.schema);\n\nconst cvrDB = pgClient(lc, config.cvr.db);\n\nconst rows =\n await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(upstreamSchema(getShardID(config)) + '/cvr')}.\"queries\" where \"queryHash\" = ${must(\n config.hash,\n )} limit 1;`;\n\nconst queryAst = transformAndHashQuery(\n lc,\n '',\n rows[0].clientAST,\n permissions,\n {},\n rows[0].internal,\n).transformedAst;\n\n// oxlint-disable no-console\nconsole.log('\\n=== AST ===\\n');\nconsole.log(JSON.stringify(queryAst, null, 2));\nconsole.log('\\n=== ZQL ===\\n');\nconsole.log(await formatOutput(queryAst.table + astToZQL(queryAst)));\n// oxlint-enable no-console\n\nawait cvrDB.end();\n"],"names":["v.string"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,UAAU;AAAA,EACd,KAAK,EAAC,IAAIA,SAAS;AAAA,EACnB,QAAQ;AAAA,IACN,MAAMA,OAAE,EAAS,QAAQ,aAAa;AAAA,IACtC,MAAM,CAAC,0BAA0B;AAAA,EAAA;AAAA,EAEnC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM,CAAC,yCAAyC;AAAA,EAAA;AAEpD;AAEA,MAAM,SAAS,aAAa,SAAS,EAAC,eAAe,qBAAoB;AAEzE,MAAM,KAAK,IAAI,WAAW,SAAS,CAAA,GAAI,cAAc;AACrD,MAAM,EAAC,YAAA,IAAe,MAAM,yBAAyB,OAAO,MAAM;AAElE,MAAM,QAAQ,SAAS,IAAI,OAAO,IAAI,EAAE;AAExC,MAAM,OACJ,MAAM,4CAA4C,MAAM,eAAe,WAAW,MAAM,CAAC,IAAI,MAAM,CAAC,kCAAkC;AAAA,EACpI,OAAO;AACT,CAAC;AAEH,MAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA,KAAK,CAAC,EAAE;AAAA,EACR;AAAA,EACA,CAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"bin-transform.js","sources":["../../../../analyze-query/src/bin-transform.ts"],"sourcesContent":["import '../../shared/src/dotenv.ts';\n\nimport {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {parseOptions} from '../../shared/src/options.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport {\n appOptions,\n shardOptions,\n ZERO_ENV_VAR_PREFIX,\n} from '../../zero-cache/src/config/zero-config.ts';\nimport {loadSchemaAndPermissions} 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';\n\nconst options = {\n cvr: {db: v.string()},\n schema: {\n type: v.string().default('./schema.ts'),\n desc: ['Path to the schema file.'],\n },\n app: appOptions,\n shard: shardOptions,\n hash: {\n type: v.string().optional(),\n desc: ['Hash of the query to fetch the AST for.'],\n },\n};\n\nconst config = parseOptions(options, {envNamePrefix: ZERO_ENV_VAR_PREFIX});\n\nconst lc = new LogContext('debug', {}, consoleLogSink);\nconst {permissions} = await loadSchemaAndPermissions(config.schema);\n\nconst cvrDB = pgClient(lc, config.cvr.db);\n\nconst rows =\n await cvrDB`select \"clientAST\", \"internal\" from ${cvrDB(upstreamSchema(getShardID(config)) + '/cvr')}.\"queries\" where \"queryHash\" = ${must(\n config.hash,\n )} limit 1;`;\n\nconst queryAst = transformAndHashQuery(\n lc,\n '',\n rows[0].clientAST,\n permissions,\n {\n type: 'jwt',\n raw: '',\n decoded: {},\n },\n rows[0].internal,\n).transformedAst;\n\n// oxlint-disable no-console\nconsole.log('\\n=== AST ===\\n');\nconsole.log(JSON.stringify(queryAst, null, 2));\nconsole.log('\\n=== ZQL ===\\n');\nconsole.log(await formatOutput(queryAst.table + astToZQL(queryAst)));\n// oxlint-enable no-console\n\nawait cvrDB.end();\n"],"names":["v.string"],"mappings":";;;;;;;;;;;;;AAkBA,MAAM,UAAU;AAAA,EACd,KAAK,EAAC,IAAIA,SAAS;AAAA,EACnB,QAAQ;AAAA,IACN,MAAMA,OAAE,EAAS,QAAQ,aAAa;AAAA,IACtC,MAAM,CAAC,0BAA0B;AAAA,EAAA;AAAA,EAEnC,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,IACJ,MAAMA,OAAE,EAAS,SAAA;AAAA,IACjB,MAAM,CAAC,yCAAyC;AAAA,EAAA;AAEpD;AAEA,MAAM,SAAS,aAAa,SAAS,EAAC,eAAe,qBAAoB;AAEzE,MAAM,KAAK,IAAI,WAAW,SAAS,CAAA,GAAI,cAAc;AACrD,MAAM,EAAC,YAAA,IAAe,MAAM,yBAAyB,OAAO,MAAM;AAElE,MAAM,QAAQ,SAAS,IAAI,OAAO,IAAI,EAAE;AAExC,MAAM,OACJ,MAAM,4CAA4C,MAAM,eAAe,WAAW,MAAM,CAAC,IAAI,MAAM,CAAC,kCAAkC;AAAA,EACpI,OAAO;AACT,CAAC;AAEH,MAAM,WAAW;AAAA,EACf;AAAA,EACA;AAAA,EACA,KAAK,CAAC,EAAE;AAAA,EACR;AAAA,EACA;AAAA,IAGE,SAAS,CAAA;AAAA,EAAC;AAAA,EAEZ,KAAK,CAAC,EAAE;AACV,EAAE;AAGF,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAC7C,QAAQ,IAAI,iBAAiB;AAC7B,QAAQ,IAAI,MAAM,aAAa,SAAS,QAAQ,SAAS,QAAQ,CAAC,CAAC;AAGnE,MAAM,MAAM,IAAA;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-ast.d.ts","sourceRoot":"","sources":["../../../../analyze-query/src/run-ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-ast.d.ts","sourceRoot":"","sources":["../../../../analyze-query/src/run-ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAOjD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,kCAAkC,CAAC;AAErE,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,iDAAiD,CAAC;AACxF,OAAO,KAAK,EAAC,GAAG,EAAC,MAAM,gCAAgC,CAAC;AAExD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,0CAA0C,CAAC;AAG3E,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,sCAAsC,CAAC;AACrE,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,wBAAwB,CAAC;AAErD,MAAM,MAAM,aAAa,GAAG;IAC1B,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,oBAAoB,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9C,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;IACtB,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAC5C,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAClC,CAAC;AAEF,wBAAsB,MAAM,CAC1B,EAAE,EAAE,UAAU,EACd,YAAY,EAAE,YAAY,EAC1B,GAAG,EAAE,GAAG,EACR,aAAa,EAAE,OAAO,EACtB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,kBAAkB,CAAC,CA8F7B"}
|
|
@@ -33,6 +33,7 @@ async function runAst(lc, clientSchema, ast, isTransformed, options) {
|
|
|
33
33
|
"No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced."
|
|
34
34
|
);
|
|
35
35
|
}
|
|
36
|
+
const auth = { decoded: authData };
|
|
36
37
|
ast = transformAndHashQuery(
|
|
37
38
|
lc,
|
|
38
39
|
"clientGroupIDForAnalyze",
|
|
@@ -41,7 +42,7 @@ async function runAst(lc, clientSchema, ast, isTransformed, options) {
|
|
|
41
42
|
permissions,
|
|
42
43
|
"Permissions are required when applyPermissions is true"
|
|
43
44
|
),
|
|
44
|
-
|
|
45
|
+
auth,
|
|
45
46
|
false
|
|
46
47
|
).transformedAst;
|
|
47
48
|
result.afterPermissions = await formatOutput(ast.table + astToZQL(ast));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-ast.js","sources":["../../../../analyze-query/src/run-ast.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport type {LiteAndZqlSpec} from '../../zero-cache/src/db/specs.ts';\nimport {hydrate} from '../../zero-cache/src/services/view-syncer/pipeline-driver.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport {mapAST} from '../../zero-protocol/src/ast.ts';\nimport type {ClientSchema} from '../../zero-protocol/src/client-schema.ts';\nimport type {Row} from '../../zero-protocol/src/data.ts';\nimport {hashOfAST} from '../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../zero-schema/src/compiled-permissions.ts';\nimport type {NameMapper} from '../../zero-schema/src/name-mapper.ts';\nimport {\n buildPipeline,\n type BuilderDelegate,\n} from '../../zql/src/builder/builder.ts';\nimport type {Database} from '../../zqlite/src/db.ts';\n\nexport type RunAstOptions = {\n applyPermissions?: boolean | undefined;\n authData?: string | undefined;\n clientToServerMapper?: NameMapper | undefined;\n db: Database;\n host: BuilderDelegate;\n permissions?: PermissionsConfig | undefined;\n syncedRows?: boolean | undefined;\n tableSpecs: Map<string, LiteAndZqlSpec>;\n vendedRows?: boolean | undefined;\n};\n\nexport async function runAst(\n lc: LogContext,\n clientSchema: ClientSchema,\n ast: AST,\n isTransformed: boolean,\n options: RunAstOptions,\n): Promise<AnalyzeQueryResult> {\n const {clientToServerMapper, permissions, host} = options;\n const result: AnalyzeQueryResult = {\n warnings: [],\n syncedRows: undefined,\n syncedRowCount: 0,\n start: 0,\n end: 0,\n afterPermissions: undefined,\n readRows: undefined,\n readRowCountsByQuery: {},\n readRowCount: undefined,\n };\n\n if (!isTransformed) {\n // map the AST to server names if not already transformed\n ast = mapAST(ast, must(clientToServerMapper));\n }\n if (options.applyPermissions) {\n result.warnings.push(\n 'Permissions are deprecated and will be removed in an upcoming release. See: https://zero.rocicorp.dev/docs/auth.',\n );\n\n const authData = options.authData ? JSON.parse(options.authData) : {};\n if (!options.authData) {\n result.warnings.push(\n 'No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced.',\n );\n }\n ast = transformAndHashQuery(\n lc,\n 'clientGroupIDForAnalyze',\n ast,\n must(\n permissions,\n 'Permissions are required when applyPermissions is true',\n ),\n
|
|
1
|
+
{"version":3,"file":"run-ast.js","sources":["../../../../analyze-query/src/run-ast.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {astToZQL} from '../../ast-to-zql/src/ast-to-zql.ts';\nimport {formatOutput} from '../../ast-to-zql/src/format.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {JWTAuth} from '../../zero-cache/src/auth/auth.ts';\nimport {transformAndHashQuery} from '../../zero-cache/src/auth/read-authorizer.ts';\nimport type {LiteAndZqlSpec} from '../../zero-cache/src/db/specs.ts';\nimport {hydrate} from '../../zero-cache/src/services/view-syncer/pipeline-driver.ts';\nimport type {AnalyzeQueryResult} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {AST} from '../../zero-protocol/src/ast.ts';\nimport {mapAST} from '../../zero-protocol/src/ast.ts';\nimport type {ClientSchema} from '../../zero-protocol/src/client-schema.ts';\nimport type {Row} from '../../zero-protocol/src/data.ts';\nimport {hashOfAST} from '../../zero-protocol/src/query-hash.ts';\nimport type {PermissionsConfig} from '../../zero-schema/src/compiled-permissions.ts';\nimport type {NameMapper} from '../../zero-schema/src/name-mapper.ts';\nimport {\n buildPipeline,\n type BuilderDelegate,\n} from '../../zql/src/builder/builder.ts';\nimport type {Database} from '../../zqlite/src/db.ts';\n\nexport type RunAstOptions = {\n applyPermissions?: boolean | undefined;\n authData?: string | undefined;\n clientToServerMapper?: NameMapper | undefined;\n db: Database;\n host: BuilderDelegate;\n permissions?: PermissionsConfig | undefined;\n syncedRows?: boolean | undefined;\n tableSpecs: Map<string, LiteAndZqlSpec>;\n vendedRows?: boolean | undefined;\n};\n\nexport async function runAst(\n lc: LogContext,\n clientSchema: ClientSchema,\n ast: AST,\n isTransformed: boolean,\n options: RunAstOptions,\n): Promise<AnalyzeQueryResult> {\n const {clientToServerMapper, permissions, host} = options;\n const result: AnalyzeQueryResult = {\n warnings: [],\n syncedRows: undefined,\n syncedRowCount: 0,\n start: 0,\n end: 0,\n afterPermissions: undefined,\n readRows: undefined,\n readRowCountsByQuery: {},\n readRowCount: undefined,\n };\n\n if (!isTransformed) {\n // map the AST to server names if not already transformed\n ast = mapAST(ast, must(clientToServerMapper));\n }\n if (options.applyPermissions) {\n result.warnings.push(\n 'Permissions are deprecated and will be removed in an upcoming release. See: https://zero.rocicorp.dev/docs/auth.',\n );\n\n const authData = options.authData ? JSON.parse(options.authData) : {};\n if (!options.authData) {\n result.warnings.push(\n 'No auth data provided. Permission rules will compare to `NULL` wherever an auth data field is referenced.',\n );\n }\n const auth: JWTAuth = {type: 'jwt', raw: '', decoded: authData};\n ast = transformAndHashQuery(\n lc,\n 'clientGroupIDForAnalyze',\n ast,\n must(\n permissions,\n 'Permissions are required when applyPermissions is true',\n ),\n auth,\n false,\n ).transformedAst;\n result.afterPermissions = await formatOutput(ast.table + astToZQL(ast));\n }\n const pipeline = buildPipeline(ast, host, 'query-id');\n\n const start = performance.now();\n\n let syncedRowCount = 0;\n const rowsByTable: Record<string, Row[]> = {};\n const seenByTable: Set<string> = new Set();\n for (const rowChange of hydrate(pipeline, hashOfAST(ast), clientSchema)) {\n if (rowChange === 'yield') {\n continue;\n }\n assert(rowChange.type === 'add');\n\n let rows: Row[] = rowsByTable[rowChange.table];\n const s = rowChange.table + '.' + JSON.stringify(rowChange.row);\n if (seenByTable.has(s)) {\n continue; // skip duplicates\n }\n syncedRowCount++;\n seenByTable.add(s);\n if (options.syncedRows) {\n if (!rows) {\n rows = [];\n rowsByTable[rowChange.table] = rows;\n }\n rows.push(rowChange.row);\n }\n }\n\n const end = performance.now();\n if (options.syncedRows) {\n result.syncedRows = rowsByTable;\n }\n result.start = start;\n result.end = end;\n\n // Always include the count of synced and vended rows.\n result.syncedRowCount = syncedRowCount;\n result.readRowCountsByQuery = host.debug?.getVendedRowCounts() ?? {};\n let readRowCount = 0;\n for (const c of Object.values(result.readRowCountsByQuery)) {\n for (const v of Object.values(c)) {\n readRowCount += v;\n }\n }\n result.readRowCount = readRowCount;\n\n if (options.vendedRows) {\n result.readRows = host.debug?.getVendedRows();\n }\n return result;\n}\n"],"names":[],"mappings":";;;;;;;;;AAmCA,eAAsB,OACpB,IACA,cACA,KACA,eACA,SAC6B;AAC7B,QAAM,EAAC,sBAAsB,aAAa,KAAA,IAAQ;AAClD,QAAM,SAA6B;AAAA,IACjC,UAAU,CAAA;AAAA,IACV,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,OAAO;AAAA,IACP,KAAK;AAAA,IACL,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,sBAAsB,CAAA;AAAA,IACtB,cAAc;AAAA,EAAA;AAGhB,MAAI,CAAC,eAAe;AAElB,UAAM,OAAO,KAAK,KAAK,oBAAoB,CAAC;AAAA,EAC9C;AACA,MAAI,QAAQ,kBAAkB;AAC5B,WAAO,SAAS;AAAA,MACd;AAAA,IAAA;AAGF,UAAM,WAAW,QAAQ,WAAW,KAAK,MAAM,QAAQ,QAAQ,IAAI,CAAA;AACnE,QAAI,CAAC,QAAQ,UAAU;AACrB,aAAO,SAAS;AAAA,QACd;AAAA,MAAA;AAAA,IAEJ;AACA,UAAM,OAAgB,EAAuB,SAAS,SAAA;AACtD,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,MAAA;AAAA,MAEF;AAAA,MACA;AAAA,IAAA,EACA;AACF,WAAO,mBAAmB,MAAM,aAAa,IAAI,QAAQ,SAAS,GAAG,CAAC;AAAA,EACxE;AACA,QAAM,WAAW,cAAc,KAAK,MAAM,UAAU;AAEpD,QAAM,QAAQ,YAAY,IAAA;AAE1B,MAAI,iBAAiB;AACrB,QAAM,cAAqC,CAAA;AAC3C,QAAM,kCAA+B,IAAA;AACrC,aAAW,aAAa,QAAQ,UAAU,UAAU,GAAG,GAAG,YAAY,GAAG;AACvE,QAAI,cAAc,SAAS;AACzB;AAAA,IACF;AACA,WAAO,UAAU,SAAS,KAAK;AAE/B,QAAI,OAAc,YAAY,UAAU,KAAK;AAC7C,UAAM,IAAI,UAAU,QAAQ,MAAM,KAAK,UAAU,UAAU,GAAG;AAC9D,QAAI,YAAY,IAAI,CAAC,GAAG;AACtB;AAAA,IACF;AACA;AACA,gBAAY,IAAI,CAAC;AACjB,QAAI,QAAQ,YAAY;AACtB,UAAI,CAAC,MAAM;AACT,eAAO,CAAA;AACP,oBAAY,UAAU,KAAK,IAAI;AAAA,MACjC;AACA,WAAK,KAAK,UAAU,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,MAAM,YAAY,IAAA;AACxB,MAAI,QAAQ,YAAY;AACtB,WAAO,aAAa;AAAA,EACtB;AACA,SAAO,QAAQ;AACf,SAAO,MAAM;AAGb,SAAO,iBAAiB;AACxB,SAAO,uBAAuB,KAAK,OAAO,mBAAA,KAAwB,CAAA;AAClE,MAAI,eAAe;AACnB,aAAW,KAAK,OAAO,OAAO,OAAO,oBAAoB,GAAG;AAC1D,eAAW,KAAK,OAAO,OAAO,CAAC,GAAG;AAChC,sBAAgB;AAAA,IAClB;AAAA,EACF;AACA,SAAO,eAAe;AAEtB,MAAI,QAAQ,YAAY;AACtB,WAAO,WAAW,KAAK,OAAO,cAAA;AAAA,EAChC;AACA,SAAO;AACT;"}
|
|
@@ -77,37 +77,44 @@ function transformExistsCondition(condition, prefix, args) {
|
|
|
77
77
|
const relationship = extractRelationshipName(related);
|
|
78
78
|
const nextSubquery = getNextExistsSubquery(related);
|
|
79
79
|
const hasSubQueryProps = nextSubquery.where || nextSubquery.related && nextSubquery.related.length > 0 || nextSubquery.orderBy || nextSubquery.limit;
|
|
80
|
+
const optionParts = [];
|
|
81
|
+
if (condition.flip !== void 0) {
|
|
82
|
+
optionParts.push(`flip: ${condition.flip}`);
|
|
83
|
+
}
|
|
84
|
+
if (condition.scalar !== void 0) {
|
|
85
|
+
optionParts.push(`scalar: ${condition.scalar}`);
|
|
86
|
+
}
|
|
87
|
+
const optionsStr = optionParts.length > 0 ? `, {${optionParts.join(", ")}}` : "";
|
|
80
88
|
if (op === "EXISTS") {
|
|
81
|
-
const flipped = condition.flip ? ", {flip: true}" : "";
|
|
82
89
|
if (!hasSubQueryProps) {
|
|
83
90
|
if (prefix === ".where") {
|
|
84
|
-
return `.whereExists('${relationship}'${
|
|
91
|
+
return `.whereExists('${relationship}'${optionsStr})`;
|
|
85
92
|
}
|
|
86
93
|
args.add("exists");
|
|
87
|
-
return `exists('${relationship}'${
|
|
94
|
+
return `exists('${relationship}'${optionsStr})`;
|
|
88
95
|
}
|
|
89
96
|
if (prefix === ".where") {
|
|
90
|
-
return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${
|
|
97
|
+
return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;
|
|
91
98
|
}
|
|
92
99
|
args.add("exists");
|
|
93
|
-
return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${
|
|
100
|
+
return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;
|
|
94
101
|
}
|
|
95
102
|
if (hasSubQueryProps) {
|
|
96
103
|
if (prefix === ".where") {
|
|
97
104
|
return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(
|
|
98
105
|
nextSubquery
|
|
99
|
-
)})))`;
|
|
106
|
+
)}${optionsStr})))`;
|
|
100
107
|
}
|
|
101
108
|
args.add("not");
|
|
102
109
|
args.add("exists");
|
|
103
|
-
return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}))`;
|
|
110
|
+
return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr}))`;
|
|
104
111
|
}
|
|
105
112
|
if (prefix === ".where") {
|
|
106
|
-
return `.where(({exists, not}) => not(exists('${relationship}')))`;
|
|
113
|
+
return `.where(({exists, not}) => not(exists('${relationship}'${optionsStr})))`;
|
|
107
114
|
}
|
|
108
115
|
args.add("not");
|
|
109
116
|
args.add("exists");
|
|
110
|
-
return `not(exists('${relationship}')))`;
|
|
117
|
+
return `not(exists('${relationship}'${optionsStr})))`;
|
|
111
118
|
}
|
|
112
119
|
function getNextExistsSubquery(related) {
|
|
113
120
|
if (related.subquery.where?.type === "correlatedSubquery" && related.subquery.where.related.subquery.alias?.includes(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ast-to-zql.js","sources":["../../../../ast-to-zql/src/ast-to-zql.ts"],"sourcesContent":["import {unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralReference,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {SUBQ_PREFIX} from '../../zero-protocol/src/ast.ts';\n\n/**\n * Converts an AST to the equivalent query builder code.\n * This is useful for debugging and understanding queries.\n *\n * @example\n * ```\n * const ast = query.issue.where('id', '=', 123)[astSymbol];\n * console.log(astToZQL(ast)); // outputs: .where('id', '=', 123)\n * ```\n */\nexport function astToZQL(ast: AST): string {\n let code = '';\n\n // Handle where conditions\n if (ast.where) {\n code += transformCondition(ast.where, '.where', new Set());\n }\n\n // Handle related subqueries\n if (ast.related && ast.related.length > 0) {\n for (const related of ast.related) {\n if (related.hidden) {\n const nestedRelated = related.subquery.related?.[0];\n if (nestedRelated) {\n code += transformRelated(nestedRelated);\n }\n } else {\n code += transformRelated(related);\n }\n }\n }\n\n // Handle orderBy\n if (ast.orderBy && ast.orderBy.length > 0) {\n code += transformOrder(ast.orderBy);\n }\n\n // Handle limit\n if (ast.limit !== undefined) {\n code += `.limit(${ast.limit})`;\n }\n\n // Handle start\n if (ast.start) {\n const {row, exclusive} = ast.start;\n code += `.start(${JSON.stringify(row)}${\n exclusive ? '' : ', { inclusive: true }'\n })`;\n }\n\n return code;\n}\n\ntype Args = Set<string>;\n\ntype Prefix = '.where' | 'cmp';\n\nfunction transformCondition(\n condition: Condition,\n prefix: Prefix,\n args: Args,\n): string {\n switch (condition.type) {\n case 'simple':\n return transformSimpleCondition(condition, prefix);\n case 'and':\n case 'or':\n return transformLogicalCondition(condition, prefix, args);\n case 'correlatedSubquery':\n return transformExistsCondition(condition, prefix, args);\n default:\n unreachable(condition);\n }\n}\n\nfunction transformSimpleCondition(\n condition: SimpleCondition,\n prefix: Prefix,\n): string {\n const {left, op, right} = condition;\n\n const leftCode = transformValuePosition(left);\n const rightCode = transformValuePosition(right);\n\n // Handle the shorthand form for equals\n if (op === '=') {\n return `${prefix}(${leftCode}, ${rightCode})`;\n }\n\n return `${prefix}(${leftCode}, '${op}', ${rightCode})`;\n}\n\nfunction transformLogicalCondition(\n condition: Conjunction | Disjunction,\n prefix: Prefix,\n args: Args,\n): string {\n const {type, conditions} = condition;\n\n // For single condition, no need for logical operator\n if (conditions.length === 1) {\n return transformCondition(conditions[0], prefix, args);\n }\n\n // Generate multiple where calls for top-level AND conditions\n if (type === 'and') {\n const parts = conditions.map(c => transformCondition(c, prefix, args));\n // Simply concatenate the where conditions\n if (prefix === '.where') {\n return parts.join('');\n }\n args.add('and');\n return 'and(' + parts.join(', ') + ')';\n }\n\n args = new Set<string>();\n\n // Handle nested conditions with a callback for OR conditions and nested ANDs/ORs\n const conditionsCode = conditions\n .map(c => transformCondition(c, 'cmp', args))\n .join(', ');\n\n args.add('cmp');\n args.add(type);\n const argsCode = [...args].sort().join(', ');\n\n return `.where(({${argsCode}}) => ${type}(${conditionsCode}))`;\n}\n\nfunction transformExistsCondition(\n condition: CorrelatedSubqueryCondition,\n prefix: '.where' | 'cmp',\n args: Set<string>,\n): string {\n const {related, op} = condition;\n const relationship = extractRelationshipName(related);\n\n const nextSubquery = getNextExistsSubquery(related);\n\n // Check if subquery has additional properties\n const hasSubQueryProps =\n nextSubquery.where ||\n (nextSubquery.related && nextSubquery.related.length > 0) ||\n nextSubquery.orderBy ||\n nextSubquery.limit;\n\n if (op === 'EXISTS') {\n const flipped = condition.flip ? ', {flip: true}' : '';\n if (!hasSubQueryProps) {\n if (prefix === '.where') {\n return `.whereExists('${relationship}'${flipped})`;\n }\n args.add('exists');\n return `exists('${relationship}'${flipped})`;\n }\n\n if (prefix === '.where') {\n return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;\n }\n prefix satisfies 'cmp';\n args.add('exists');\n return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${flipped})`;\n }\n\n op satisfies 'NOT EXISTS';\n\n if (hasSubQueryProps) {\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(\n nextSubquery,\n )})))`;\n }\n prefix satisfies 'cmp';\n args.add('not');\n args.add('exists');\n return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}))`;\n }\n\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}')))`;\n }\n args.add('not');\n args.add('exists');\n\n return `not(exists('${relationship}')))`;\n}\n\n// If the `exists` is applied against a junction edge, both hops will have the same alias and both hops will be exists conditions.\nfunction getNextExistsSubquery(related: CorrelatedSubquery): AST {\n if (\n related.subquery.where?.type === 'correlatedSubquery' &&\n related.subquery.where.related.subquery.alias?.includes(\n SUBQ_PREFIX + 'zhidden_',\n )\n ) {\n return getNextExistsSubquery(related.subquery.where.related);\n }\n\n return related.subquery;\n}\n\nfunction extractRelationshipName(related: CorrelatedSubquery): string {\n const alias = must(related.subquery.alias);\n return alias.startsWith(SUBQ_PREFIX)\n ? alias.substring(SUBQ_PREFIX.length)\n : alias;\n}\n\nfunction transformRelated(related: CorrelatedSubquery): string {\n const {alias} = related.subquery;\n if (!alias) return '';\n\n const relationship = alias;\n let code = `.related('${relationship}'`;\n\n // If the subquery has additional filters or configurations\n if (\n related.subquery.where ||\n (related.subquery.related && related.subquery.related.length > 0) ||\n related.subquery.orderBy ||\n related.subquery.limit\n ) {\n code += ', q => q' + astToZQL(related.subquery);\n }\n\n code += ')';\n return code;\n}\n\nfunction transformOrder(orderBy: Ordering): string {\n let code = '';\n for (const [field, direction] of orderBy) {\n code += `.orderBy('${field}', '${direction}')`;\n }\n return code;\n}\n\nfunction transformValuePosition(value: ValuePosition): string {\n switch (value.type) {\n case 'literal':\n return transformLiteral(value);\n case 'column':\n return `'${value.name}'`;\n case 'static':\n return transformParameter(value);\n default:\n unreachable(value);\n }\n}\n\nfunction transformLiteral(literal: LiteralReference): string {\n if (literal.value === null) {\n return 'null';\n }\n if (Array.isArray(literal.value)) {\n return JSON.stringify(literal.value);\n }\n if (typeof literal.value === 'string') {\n return `'${literal.value.replace(/'/g, \"\\\\'\")}'`;\n }\n return String(literal.value);\n}\n\nfunction transformParameter(param: Parameter): string {\n const fieldStr = Array.isArray(param.field)\n ? `[${param.field.map(f => `'${f}'`).join(', ')}]`\n : `'${param.field}'`;\n\n return `authParam(${fieldStr})`;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ast-to-zql.js","sources":["../../../../ast-to-zql/src/ast-to-zql.ts"],"sourcesContent":["import {unreachable} from '../../shared/src/asserts.ts';\nimport {must} from '../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralReference,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../zero-protocol/src/ast.ts';\nimport {SUBQ_PREFIX} from '../../zero-protocol/src/ast.ts';\n\n/**\n * Converts an AST to the equivalent query builder code.\n * This is useful for debugging and understanding queries.\n *\n * @example\n * ```\n * const ast = query.issue.where('id', '=', 123)[astSymbol];\n * console.log(astToZQL(ast)); // outputs: .where('id', '=', 123)\n * ```\n */\nexport function astToZQL(ast: AST): string {\n let code = '';\n\n // Handle where conditions\n if (ast.where) {\n code += transformCondition(ast.where, '.where', new Set());\n }\n\n // Handle related subqueries\n if (ast.related && ast.related.length > 0) {\n for (const related of ast.related) {\n if (related.hidden) {\n const nestedRelated = related.subquery.related?.[0];\n if (nestedRelated) {\n code += transformRelated(nestedRelated);\n }\n } else {\n code += transformRelated(related);\n }\n }\n }\n\n // Handle orderBy\n if (ast.orderBy && ast.orderBy.length > 0) {\n code += transformOrder(ast.orderBy);\n }\n\n // Handle limit\n if (ast.limit !== undefined) {\n code += `.limit(${ast.limit})`;\n }\n\n // Handle start\n if (ast.start) {\n const {row, exclusive} = ast.start;\n code += `.start(${JSON.stringify(row)}${\n exclusive ? '' : ', { inclusive: true }'\n })`;\n }\n\n return code;\n}\n\ntype Args = Set<string>;\n\ntype Prefix = '.where' | 'cmp';\n\nfunction transformCondition(\n condition: Condition,\n prefix: Prefix,\n args: Args,\n): string {\n switch (condition.type) {\n case 'simple':\n return transformSimpleCondition(condition, prefix);\n case 'and':\n case 'or':\n return transformLogicalCondition(condition, prefix, args);\n case 'correlatedSubquery':\n return transformExistsCondition(condition, prefix, args);\n default:\n unreachable(condition);\n }\n}\n\nfunction transformSimpleCondition(\n condition: SimpleCondition,\n prefix: Prefix,\n): string {\n const {left, op, right} = condition;\n\n const leftCode = transformValuePosition(left);\n const rightCode = transformValuePosition(right);\n\n // Handle the shorthand form for equals\n if (op === '=') {\n return `${prefix}(${leftCode}, ${rightCode})`;\n }\n\n return `${prefix}(${leftCode}, '${op}', ${rightCode})`;\n}\n\nfunction transformLogicalCondition(\n condition: Conjunction | Disjunction,\n prefix: Prefix,\n args: Args,\n): string {\n const {type, conditions} = condition;\n\n // For single condition, no need for logical operator\n if (conditions.length === 1) {\n return transformCondition(conditions[0], prefix, args);\n }\n\n // Generate multiple where calls for top-level AND conditions\n if (type === 'and') {\n const parts = conditions.map(c => transformCondition(c, prefix, args));\n // Simply concatenate the where conditions\n if (prefix === '.where') {\n return parts.join('');\n }\n args.add('and');\n return 'and(' + parts.join(', ') + ')';\n }\n\n args = new Set<string>();\n\n // Handle nested conditions with a callback for OR conditions and nested ANDs/ORs\n const conditionsCode = conditions\n .map(c => transformCondition(c, 'cmp', args))\n .join(', ');\n\n args.add('cmp');\n args.add(type);\n const argsCode = [...args].sort().join(', ');\n\n return `.where(({${argsCode}}) => ${type}(${conditionsCode}))`;\n}\n\nfunction transformExistsCondition(\n condition: CorrelatedSubqueryCondition,\n prefix: '.where' | 'cmp',\n args: Set<string>,\n): string {\n const {related, op} = condition;\n const relationship = extractRelationshipName(related);\n\n const nextSubquery = getNextExistsSubquery(related);\n\n // Check if subquery has additional properties\n const hasSubQueryProps =\n nextSubquery.where ||\n (nextSubquery.related && nextSubquery.related.length > 0) ||\n nextSubquery.orderBy ||\n nextSubquery.limit;\n\n // Build options string for flip and scalar\n const optionParts: string[] = [];\n if (condition.flip !== undefined) {\n optionParts.push(`flip: ${condition.flip}`);\n }\n if (condition.scalar !== undefined) {\n optionParts.push(`scalar: ${condition.scalar}`);\n }\n const optionsStr =\n optionParts.length > 0 ? `, {${optionParts.join(', ')}}` : '';\n\n if (op === 'EXISTS') {\n if (!hasSubQueryProps) {\n if (prefix === '.where') {\n return `.whereExists('${relationship}'${optionsStr})`;\n }\n args.add('exists');\n return `exists('${relationship}'${optionsStr})`;\n }\n\n if (prefix === '.where') {\n return `.whereExists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;\n }\n prefix satisfies 'cmp';\n args.add('exists');\n return `exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr})`;\n }\n\n op satisfies 'NOT EXISTS';\n\n if (hasSubQueryProps) {\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}', q => q${astToZQL(\n nextSubquery,\n )}${optionsStr})))`;\n }\n prefix satisfies 'cmp';\n args.add('not');\n args.add('exists');\n return `not(exists('${relationship}', q => q${astToZQL(nextSubquery)}${optionsStr}))`;\n }\n\n if (prefix === '.where') {\n return `.where(({exists, not}) => not(exists('${relationship}'${optionsStr})))`;\n }\n args.add('not');\n args.add('exists');\n\n return `not(exists('${relationship}'${optionsStr})))`;\n}\n\n// If the `exists` is applied against a junction edge, both hops will have the same alias and both hops will be exists conditions.\nfunction getNextExistsSubquery(related: CorrelatedSubquery): AST {\n if (\n related.subquery.where?.type === 'correlatedSubquery' &&\n related.subquery.where.related.subquery.alias?.includes(\n SUBQ_PREFIX + 'zhidden_',\n )\n ) {\n return getNextExistsSubquery(related.subquery.where.related);\n }\n\n return related.subquery;\n}\n\nfunction extractRelationshipName(related: CorrelatedSubquery): string {\n const alias = must(related.subquery.alias);\n return alias.startsWith(SUBQ_PREFIX)\n ? alias.substring(SUBQ_PREFIX.length)\n : alias;\n}\n\nfunction transformRelated(related: CorrelatedSubquery): string {\n const {alias} = related.subquery;\n if (!alias) return '';\n\n const relationship = alias;\n let code = `.related('${relationship}'`;\n\n // If the subquery has additional filters or configurations\n if (\n related.subquery.where ||\n (related.subquery.related && related.subquery.related.length > 0) ||\n related.subquery.orderBy ||\n related.subquery.limit\n ) {\n code += ', q => q' + astToZQL(related.subquery);\n }\n\n code += ')';\n return code;\n}\n\nfunction transformOrder(orderBy: Ordering): string {\n let code = '';\n for (const [field, direction] of orderBy) {\n code += `.orderBy('${field}', '${direction}')`;\n }\n return code;\n}\n\nfunction transformValuePosition(value: ValuePosition): string {\n switch (value.type) {\n case 'literal':\n return transformLiteral(value);\n case 'column':\n return `'${value.name}'`;\n case 'static':\n return transformParameter(value);\n default:\n unreachable(value);\n }\n}\n\nfunction transformLiteral(literal: LiteralReference): string {\n if (literal.value === null) {\n return 'null';\n }\n if (Array.isArray(literal.value)) {\n return JSON.stringify(literal.value);\n }\n if (typeof literal.value === 'string') {\n return `'${literal.value.replace(/'/g, \"\\\\'\")}'`;\n }\n return String(literal.value);\n}\n\nfunction transformParameter(param: Parameter): string {\n const fieldStr = Array.isArray(param.field)\n ? `[${param.field.map(f => `'${f}'`).join(', ')}]`\n : `'${param.field}'`;\n\n return `authParam(${fieldStr})`;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bg-interval.d.ts","sourceRoot":"","sources":["../../../../replicache/src/bg-interval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"bg-interval.d.ts","sourceRoot":"","sources":["../../../../replicache/src/bg-interval.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAKjD,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC/B,OAAO,EAAE,MAAM,MAAM,EACrB,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,WAAW,GAClB,IAAI,CAEN"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AbortError } from "../../shared/src/abort-error.js";
|
|
2
2
|
import { sleep } from "../../shared/src/sleep.js";
|
|
3
|
+
import { IDBNotFoundError } from "./kv/idb-store.js";
|
|
3
4
|
function initBgIntervalProcess(processName, process, delayMs, lc, signal) {
|
|
4
5
|
void runBgIntervalProcess(processName, process, delayMs, lc, signal);
|
|
5
6
|
}
|
|
@@ -24,6 +25,8 @@ async function runBgIntervalProcess(processName, process, delayMs, lc, signal) {
|
|
|
24
25
|
} catch (e) {
|
|
25
26
|
if (signal.aborted) {
|
|
26
27
|
lc.debug?.("Error running most likely due to close.", e);
|
|
28
|
+
} else if (e instanceof IDBNotFoundError) {
|
|
29
|
+
lc.info?.("IndexedDB was deleted externally.", e);
|
|
27
30
|
} else {
|
|
28
31
|
lc.error?.("Error running.", e);
|
|
29
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bg-interval.js","sources":["../../../../replicache/src/bg-interval.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bg-interval.js","sources":["../../../../replicache/src/bg-interval.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\nimport {IDBNotFoundError} from './kv/idb-store.ts';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else if (e instanceof IDBNotFoundError) {\n lc.info?.('IndexedDB was deleted externally.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n"],"names":[],"mappings":";;;AAKO,SAAS,sBACd,aACA,SACA,SACA,IACA,QACM;AACN,OAAK,qBAAqB,aAAa,SAAS,SAAS,IAAI,MAAM;AACrE;AAEA,eAAe,qBACb,aACA,SACA,SACA,IACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB;AAAA,EACF;AACA,OAAK,GAAG,YAAY,qBAAqB,WAAW;AACpD,KAAG,QAAQ,UAAU;AACrB,SAAO,CAAC,OAAO,SAAS;AACtB,QAAI;AACF,YAAM,MAAM,QAAA,GAAW,MAAM;AAAA,IAC/B,SAAS,GAAG;AACV,UAAI,EAAE,aAAa,aAAa;AAC9B,cAAM;AAAA,MACR;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,SAAG,QAAQ,SAAS;AACpB,UAAI;AACF,cAAM,QAAA;AAAA,MACR,SAAS,GAAG;AACV,YAAI,OAAO,SAAS;AAClB,aAAG,QAAQ,2CAA2C,CAAC;AAAA,QACzD,WAAW,aAAa,kBAAkB;AACxC,aAAG,OAAO,qCAAqC,CAAC;AAAA,QAClD,OAAO;AACL,aAAG,QAAQ,kBAAkB,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,KAAG,QAAQ,UAAU;AACvB;"}
|
|
@@ -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;AAmCD;;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,24 +117,22 @@ 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
|
}
|
|
125
|
-
assert(db.lastOpenedTimestampMS !== void 0);
|
|
126
|
-
if (now - db.lastOpenedTimestampMS < maxAge) {
|
|
127
|
-
return [false];
|
|
128
|
-
}
|
|
129
128
|
assert(
|
|
130
129
|
db.replicacheFormatVersion === DD31 || db.replicacheFormatVersion === V6 || db.replicacheFormatVersion === V7
|
|
131
130
|
);
|
|
132
131
|
return canDatabaseBeCollectedAndGetDeletedClientIDs(
|
|
133
132
|
enableMutationRecovery,
|
|
134
|
-
newDagStore(db.name)
|
|
133
|
+
newDagStore(db.name, kvCreateStore),
|
|
134
|
+
now,
|
|
135
|
+
maxAge
|
|
135
136
|
);
|
|
136
137
|
}
|
|
137
138
|
async function dropDatabase(dbName, opts) {
|
|
@@ -155,7 +156,7 @@ async function dropAllDatabases(opts) {
|
|
|
155
156
|
const dbNames = Object.values(databases).map((db) => db.name);
|
|
156
157
|
return dropDatabases(store, dbNames, kvStoreProvider.drop);
|
|
157
158
|
}
|
|
158
|
-
function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, perdag) {
|
|
159
|
+
function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, perdag, now, maxAge) {
|
|
159
160
|
return withRead(perdag, async (read) => {
|
|
160
161
|
if (enableMutationRecovery) {
|
|
161
162
|
const clientGroups = await getClientGroups(read);
|
|
@@ -166,6 +167,11 @@ function canDatabaseBeCollectedAndGetDeletedClientIDs(enableMutationRecovery, pe
|
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
const clients = await getClients(read);
|
|
170
|
+
for (const [, client] of clients) {
|
|
171
|
+
if (now - client.heartbeatTimestampMs < maxAge) {
|
|
172
|
+
return [false];
|
|
173
|
+
}
|
|
174
|
+
}
|
|
169
175
|
const existingDeletedClients = await getDeletedClients(read);
|
|
170
176
|
const deletedClients = [...existingDeletedClients];
|
|
171
177
|
for (const [clientID, client] of clients) {
|