@rocicorp/zero 1.6.0-canary.11 → 1.6.0-canary.13
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 +3 -28
- package/out/_virtual/{_@oxc-project_runtime@0.130.0 → _@oxc-project_runtime@0.122.0}/helpers/usingCtx.js +1 -1
- package/out/_virtual/_rolldown/runtime.js +1 -12
- package/out/analyze-query/src/analyze-cli.js.map +1 -1
- package/out/analyze-query/src/bin-analyze.js +1 -6
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/ast-to-zql/src/bin.js.map +1 -1
- package/out/ast-to-zql/src/format.js.map +1 -1
- package/out/datadog/src/datadog-log-sink.js.map +1 -1
- package/out/otel/src/enabled.js.map +1 -1
- package/out/otel/src/log-options.js.map +1 -1
- package/out/otel/src/maybe-time.js.map +1 -1
- package/out/otel/src/span.js.map +1 -1
- package/out/replicache/src/async-iterable-to-array.js.map +1 -1
- package/out/replicache/src/bg-interval.js.map +1 -1
- package/out/replicache/src/btree/diff.js.map +1 -1
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/btree/read.js.map +1 -1
- package/out/replicache/src/btree/splice.js.map +1 -1
- package/out/replicache/src/btree/write.js +3 -6
- package/out/replicache/src/btree/write.js.map +1 -1
- package/out/replicache/src/call-default-fetch.js.map +1 -1
- package/out/replicache/src/connection-loop-delegates.js.map +1 -1
- package/out/replicache/src/connection-loop.js.map +1 -1
- package/out/replicache/src/cookies.js.map +1 -1
- package/out/replicache/src/dag/chunk.js.map +1 -1
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/key.js.map +1 -1
- package/out/replicache/src/dag/lazy-store.js.map +1 -1
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/dag/store.js.map +1 -1
- package/out/replicache/src/dag/visitor.js.map +1 -1
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/index.js.map +1 -1
- package/out/replicache/src/db/read.js.map +1 -1
- package/out/replicache/src/db/rebase.js.map +1 -1
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/deleted-clients.js.map +1 -1
- package/out/replicache/src/error-responses.js.map +1 -1
- package/out/replicache/src/frozen-json.js.map +1 -1
- package/out/replicache/src/get-default-puller.js.map +1 -1
- package/out/replicache/src/get-default-pusher.js.map +1 -1
- package/out/replicache/src/get-kv-store-provider.js.map +1 -1
- package/out/replicache/src/hash.js.map +1 -1
- package/out/replicache/src/http-request-info.js.map +1 -1
- package/out/replicache/src/index-defs.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/read-impl.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +1 -4
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
- package/out/replicache/src/kv/write-impl-base.js.map +1 -1
- package/out/replicache/src/kv/write-impl.js.map +1 -1
- package/out/replicache/src/lazy.js.map +1 -1
- package/out/replicache/src/log-options.js.map +1 -1
- package/out/replicache/src/make-idb-name.js.map +1 -1
- package/out/replicache/src/new-client-channel.js.map +1 -1
- package/out/replicache/src/on-persist-channel.js.map +1 -1
- package/out/replicache/src/patch-operation.js.map +1 -1
- package/out/replicache/src/pending-mutations.js.map +1 -1
- package/out/replicache/src/persist/client-gc.js.map +1 -1
- package/out/replicache/src/persist/client-group-gc.js.map +1 -1
- package/out/replicache/src/persist/client-groups.js +0 -40
- package/out/replicache/src/persist/client-groups.js.map +1 -1
- package/out/replicache/src/persist/clients.js +0 -28
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
- package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
- package/out/replicache/src/persist/heartbeat.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
- package/out/replicache/src/persist/make-client-id.js.map +1 -1
- package/out/replicache/src/persist/persist.js.map +1 -1
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/pusher.js.map +1 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/report-error.js.map +1 -1
- package/out/replicache/src/request-idle.js.map +1 -1
- package/out/replicache/src/scan-iterator.js.map +1 -1
- package/out/replicache/src/scan-options.js.map +1 -1
- package/out/replicache/src/set-interval-with-signal.js.map +1 -1
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/sync/diff.js.map +1 -1
- package/out/replicache/src/sync/ids.js.map +1 -1
- package/out/replicache/src/sync/patch.js.map +1 -1
- package/out/replicache/src/sync/pull-error.js.map +1 -1
- package/out/replicache/src/sync/pull.js.map +1 -1
- package/out/replicache/src/sync/push.js.map +1 -1
- package/out/replicache/src/sync/request-id.js.map +1 -1
- package/out/replicache/src/to-error.js.map +1 -1
- package/out/replicache/src/transaction-closed-error.js.map +1 -1
- package/out/replicache/src/transactions.js.map +1 -1
- package/out/replicache/src/with-transactions.js.map +1 -1
- package/out/shared/src/abort-error.js.map +1 -1
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/binary-search.js.map +1 -1
- package/out/shared/src/broadcast-channel.js.map +1 -1
- package/out/shared/src/browser-env.js.map +1 -1
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/cache.js.map +1 -1
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/custom-key-set.js.map +1 -1
- package/out/shared/src/deep-clone.js.map +1 -1
- package/out/shared/src/deep-merge.js.map +1 -1
- package/out/shared/src/document-visible.js.map +1 -1
- package/out/shared/src/dotenv.js.map +1 -1
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json-schema.js.map +1 -1
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/map.js.map +1 -1
- package/out/shared/src/must.js.map +1 -1
- package/out/shared/src/object-traversal.js.map +1 -1
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/parse-big-int.js.map +1 -1
- package/out/shared/src/promise-race.js.map +1 -1
- package/out/shared/src/queue.d.ts.map +1 -1
- package/out/shared/src/queue.js +21 -15
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/rand.js.map +1 -1
- package/out/shared/src/random-uint64.js.map +1 -1
- package/out/shared/src/random-values.js.map +1 -1
- package/out/shared/src/record-proxy.js.map +1 -1
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/sentinels.js.map +1 -1
- package/out/shared/src/set-utils.js.map +1 -1
- package/out/shared/src/size-of-value.js.map +1 -1
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/sorted-entries.js.map +1 -1
- package/out/shared/src/string-compare.js.map +1 -1
- package/out/shared/src/subscribable.js.map +1 -1
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +23 -23
- package/out/zero/package.js.map +1 -1
- package/out/zero/src/build-schema.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.js.map +1 -1
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/server-context.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +0 -5
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +0 -19
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +0 -19
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/run-transaction.js.map +1 -1
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/statements.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.js.map +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +10 -11
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +1 -1
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/priority-op.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/shadow-syncer.js.map +1 -1
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +2 -5
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
- 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/binary-reader.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
- 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.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- 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.js.map +1 -1
- 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.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +0 -2
- 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.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
- 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.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- 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.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/init.js +25 -21
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +0 -15
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +0 -1
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/shadow-sync/shadow-sync-service.js.map +1 -1
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +1 -2
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +14 -0
- 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 +25 -2
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- 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.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-set-signature.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +113 -97
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +1 -103
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +1 -4
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/configuration-error.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js.map +1 -1
- package/out/zero-cache/src/types/http.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/names.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/state-version.js.map +1 -1
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/strings.js.map +1 -1
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/timeout.js.map +1 -1
- package/out/zero-cache/src/types/url-params.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +1 -2
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/crud-impl.js.map +1 -1
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.js +1 -2
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/enable-analytics.js.map +1 -1
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/http-string.js.map +1 -1
- package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
- package/out/zero-client/src/client/inspector/client.js.map +1 -1
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/query.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/keys.js.map +1 -1
- package/out/zero-client/src/client/log-options.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
- package/out/zero-client/src/client/metrics.js.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
- package/out/zero-client/src/client/server-option.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +32 -58
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/util/nanoid.js.map +1 -1
- package/out/zero-client/src/util/socket.d.ts +3 -0
- package/out/zero-client/src/util/socket.d.ts.map +1 -0
- package/out/zero-client/src/util/socket.js +8 -0
- package/out/zero-client/src/util/socket.js.map +1 -0
- package/out/zero-protocol/src/analyze-query-result.js +0 -3
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/application-error.js.map +1 -1
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.js +0 -1
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.js +0 -7
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/delete-clients.js.map +1 -1
- package/out/zero-protocol/src/down.js.map +1 -1
- package/out/zero-protocol/src/error.js +0 -7
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +0 -1
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutate-server.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.js.map +1 -1
- package/out/zero-protocol/src/mutation.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.js +0 -4
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.js +0 -16
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-protocol/src/query-server.js.map +1 -1
- package/out/zero-protocol/src/row-patch.js.map +1 -1
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/update-auth.js.map +1 -1
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/use-connection-state.js +2 -4
- package/out/zero-react/src/use-connection-state.js.map +1 -1
- package/out/zero-react/src/use-query.js +4 -6
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/use-zero-online.js +2 -4
- package/out/zero-react/src/use-zero-online.js.map +1 -1
- package/out/zero-react/src/zero-provider.js +12 -15
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/compiled-permissions.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-schema/src/permissions.js.map +1 -1
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/kysely.js.map +1 -1
- package/out/zero-server/src/adapters/pg.js +1 -1
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/adapters/prisma.js.map +1 -1
- package/out/zero-server/src/custom.js +1 -2
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/pg-query-executor.js.map +1 -1
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/solid-view.js +1 -1
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-connection-state.js +1 -1
- package/out/zero-solid/src/use-connection-state.js.map +1 -1
- package/out/zero-solid/src/use-query.js +2 -2
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +1 -1
- package/out/zero-solid/src/use-zero-online.js.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/format.js.map +1 -1
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.d.ts +0 -5
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +1 -10
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/cap.js.map +1 -1
- package/out/zql/src/ivm/change.js.map +1 -1
- package/out/zql/src/ivm/constraint.js +1 -1
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts +8 -4
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +63 -59
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +1 -1
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/schema.d.ts +8 -0
- package/out/zql/src/ivm/schema.d.ts.map +1 -1
- package/out/zql/src/ivm/skip-yields.js.map +1 -1
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.js.map +1 -1
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/crud.js.map +1 -1
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-constraint.js.map +1 -1
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-fan-in.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.d.ts.map +1 -1
- package/out/zql/src/planner/planner-join.js +1 -2
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/planner/planner-terminus.js.map +1 -1
- package/out/zql/src/query/complete-ordering.js.map +1 -1
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/error.js.map +1 -1
- package/out/zql/src/query/escape-like.js.map +1 -1
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.js.map +1 -1
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-impl.js +1 -1
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zql/src/query/validate-input.js.map +1 -1
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/explain-queries.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.js.map +1 -1
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/internal/statement-cache.js.map +1 -1
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +6 -6
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +23 -23
- package/out/_virtual/__vite-optional-peer-dep_pg-native_pg.js +0 -13
- package/out/_virtual/__vite-optional-peer-dep_pg-native_pg.js.map +0 -1
- package/out/node_modules/.pnpm/@opentelemetry_semantic-conventions@1.41.1/node_modules/@opentelemetry/semantic-conventions/build/esm/stable_attributes.js +0 -12
- package/out/node_modules/.pnpm/@opentelemetry_semantic-conventions@1.41.1/node_modules/@opentelemetry/semantic-conventions/build/esm/stable_attributes.js.map +0 -1
- package/out/node_modules/.pnpm/pg-cloudflare@1.3.0/node_modules/pg-cloudflare/dist/empty.js +0 -11
- package/out/node_modules/.pnpm/pg-cloudflare@1.3.0/node_modules/pg-cloudflare/dist/empty.js.map +0 -1
- package/out/node_modules/.pnpm/pg-connection-string@2.12.0/node_modules/pg-connection-string/index.js +0 -130
- package/out/node_modules/.pnpm/pg-connection-string@2.12.0/node_modules/pg-connection-string/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg-int8@1.0.1/node_modules/pg-int8/index.js +0 -62
- package/out/node_modules/.pnpm/pg-int8@1.0.1/node_modules/pg-int8/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg-pool@3.13.0_pg@8.20.0/node_modules/pg-pool/index.js +0 -353
- package/out/node_modules/.pnpm/pg-pool@3.13.0_pg@8.20.0/node_modules/pg-pool/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/buffer-reader.js +0 -60
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/buffer-reader.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/buffer-writer.js +0 -81
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/buffer-writer.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/index.js +0 -35
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/messages.js +0 -167
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/messages.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/parser.js +0 -288
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/parser.js.map +0 -1
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/serializer.js +0 -177
- package/out/node_modules/.pnpm/pg-protocol@1.13.0/node_modules/pg-protocol/dist/serializer.js.map +0 -1
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/index.js +0 -46
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/arrayParser.js +0 -16
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/arrayParser.js.map +0 -1
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/binaryParsers.js +0 -165
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/binaryParsers.js.map +0 -1
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/builtins.js +0 -81
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/builtins.js.map +0 -1
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/textParsers.js +0 -167
- package/out/node_modules/.pnpm/pg-types@2.2.0/node_modules/pg-types/lib/textParsers.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/esm/index.js +0 -19
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/esm/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/client.js +0 -508
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/client.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/connection-parameters.js +0 -104
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/connection-parameters.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/connection.js +0 -160
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/connection.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/cert-signatures.js +0 -97
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/cert-signatures.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/sasl.js +0 -131
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/sasl.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils-legacy.js +0 -39
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils-legacy.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils-webcrypto.js +0 -89
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils-webcrypto.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils.js +0 -13
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/crypto/utils.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/defaults.js +0 -46
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/defaults.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/index.js +0 -71
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/client.js +0 -226
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/client.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/index.js +0 -11
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/index.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/query.js +0 -117
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/native/query.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/query.js +0 -151
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/query.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/result.js +0 -76
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/result.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/stream.js +0 -73
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/stream.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/type-overrides.js +0 -35
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/type-overrides.js.map +0 -1
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/utils.js +0 -118
- package/out/node_modules/.pnpm/pg@8.20.0/node_modules/pg/lib/utils.js.map +0 -1
- package/out/node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/helper.js +0 -147
- package/out/node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/helper.js.map +0 -1
- package/out/node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js +0 -21
- package/out/node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js.map +0 -1
- package/out/node_modules/.pnpm/postgres-array@2.0.0/node_modules/postgres-array/index.js +0 -84
- package/out/node_modules/.pnpm/postgres-array@2.0.0/node_modules/postgres-array/index.js.map +0 -1
- package/out/node_modules/.pnpm/postgres-bytea@1.0.1/node_modules/postgres-bytea/index.js +0 -28
- package/out/node_modules/.pnpm/postgres-bytea@1.0.1/node_modules/postgres-bytea/index.js.map +0 -1
- package/out/node_modules/.pnpm/postgres-date@1.0.7/node_modules/postgres-date/index.js +0 -65
- package/out/node_modules/.pnpm/postgres-date@1.0.7/node_modules/postgres-date/index.js.map +0 -1
- package/out/node_modules/.pnpm/postgres-interval@1.2.0/node_modules/postgres-interval/index.js +0 -107
- package/out/node_modules/.pnpm/postgres-interval@1.2.0/node_modules/postgres-interval/index.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.development.js +0 -696
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.development.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.production.min.js +0 -44
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react-jsx-runtime.production.min.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.development.js +0 -1585
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.development.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js +0 -329
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/index.js +0 -13
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/index.js.map +0 -1
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/jsx-runtime.js +0 -13
- package/out/node_modules/.pnpm/react@18.3.1/node_modules/react/jsx-runtime.js.map +0 -1
- package/out/node_modules/.pnpm/solid-js@1.9.13/node_modules/solid-js/dist/server.js +0 -131
- package/out/node_modules/.pnpm/solid-js@1.9.13/node_modules/solid-js/dist/server.js.map +0 -1
- package/out/node_modules/.pnpm/solid-js@1.9.13/node_modules/solid-js/store/dist/server.js +0 -96
- package/out/node_modules/.pnpm/solid-js@1.9.13/node_modules/solid-js/store/dist/server.js.map +0 -1
- package/out/node_modules/.pnpm/split2@4.2.0/node_modules/split2/index.js +0 -95
- package/out/node_modules/.pnpm/split2@4.2.0/node_modules/split2/index.js.map +0 -1
- package/out/node_modules/.pnpm/xtend@4.0.2/node_modules/xtend/mutable.js +0 -18
- package/out/node_modules/.pnpm/xtend@4.0.2/node_modules/xtend/mutable.js.map +0 -1
- package/out/shared/src/ring-buffer.d.ts +0 -32
- package/out/shared/src/ring-buffer.d.ts.map +0 -1
- package/out/shared/src/ring-buffer.js +0 -109
- package/out/shared/src/ring-buffer.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-impl.js","names":["#schema","#tableName","#ast","#system","#currentJunction","#newQuery","#hash","#exists"],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type Parameter,\n type SimpleOperator,\n type System,\n SUBQ_PREFIX,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfAST} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryImpl(schema, table, {table}, defaultFormat, 'client');\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n return inner(tableName, ast, format, undefined, undefined);\n}\n\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: AST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfAST(this.#ast) + (this.format.singular ? 't' : 'f');\n }\n return this.#hash;\n }\n\n one = (): Query<TTable, TSchema, TReturn | undefined> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit: 1,\n },\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n );\n\n whereExists = (\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> => {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n };\n\n related = (\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> => {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n const q: AnyQuery = this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ),\n );\n\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n hidden: true,\n subquery: {\n table: junctionSchema,\n alias: relationship,\n related: [\n {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: sq.#ast,\n },\n ],\n },\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n where = function (\n this: QueryImpl<TTable, TSchema, TReturn>,\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n if (arguments.length === 2) {\n cond = cmp(fieldOrExpressionFactory, opOrValue);\n } else {\n cond = cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n }\n\n const existingWhere = this.#ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n const where = simplifyCondition(cond);\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n where,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }.bind(this);\n\n start = (\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n\n limit = (limit: number): Query<TTable, TSchema, TReturn> => {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n orderBy = <TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> => {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [...(this.#ast.orderBy ?? []), [field as string, direction]],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n #exists = (\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition => {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#newQuery(\n destTableName,\n {\n table: destTableName,\n alias: `${SUBQ_PREFIX}${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ),\n );\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}zhidden_${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n relationship,\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n table: junctionSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n where: {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n },\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n get ast(): AST {\n return this.#ast;\n }\n\n expressionBuilder() {\n return new ExpressionBuilder(this.#exists);\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"query-impl.js","names":["#schema","#tableName","#ast","#system","#currentJunction","#newQuery","#hash","#exists"],"sources":["../../../../../zql/src/query/query-impl.ts"],"sourcesContent":["// oxlint-disable no-explicit-any\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n type AST,\n type CompoundKey,\n type Condition,\n type Parameter,\n type SimpleOperator,\n type System,\n SUBQ_PREFIX,\n} from '../../../zero-protocol/src/ast.ts';\nimport {hashOfAST} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n type ExpressionFactory,\n ExpressionBuilder,\n and,\n cmp,\n simplifyCondition,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport {type QueryInternals, queryInternalsTag} from './query-internals.ts';\nimport type {\n AnyQuery,\n ExistsOptions,\n GetFilterType,\n HumanReadable,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype GetFilterTypeAny = GetFilterType<any, any, any>;\n\ntype NewQueryFunction<TSchema extends Schema> = <\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n>(\n this: unknown,\n tableName: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n) => QueryImpl<TTable, TSchema, TReturn>;\n\nexport function newQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, table: TTable): Query<TTable, TSchema> {\n return newQueryImpl(schema, table, {table}, defaultFormat, 'client');\n}\n\nexport function newQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n): QueryImpl<TTable, TSchema, TReturn> {\n const inner: NewQueryFunction<TSchema> = (\n tableName,\n ast,\n format,\n customQueryID,\n currentJunction,\n ) =>\n new QueryImpl(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n inner,\n );\n\n return inner(tableName, ast, format, undefined, undefined);\n}\n\nexport class QueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n implements\n Query<TTable, TSchema, TReturn>,\n QueryInternals<TTable, TSchema, TReturn>\n{\n readonly [queryInternalsTag] = true;\n\n readonly #schema: TSchema;\n readonly #tableName: TTable;\n readonly #ast: AST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n readonly #newQuery: NewQueryFunction<TSchema>;\n\n constructor(\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n newQuery: NewQueryFunction<TSchema>,\n ) {\n this.#schema = schema;\n this.#tableName = tableName;\n this.#ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n this.#newQuery = newQuery;\n }\n\n run(_options?: RunOptions): Promise<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n preload(_options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n throwQueryNotRunnable();\n }\n\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n materialize<T>(\n _factoryOrTTL?: ViewFactory<TTable, TSchema, TReturn, T> | TTL,\n _ttl?: TTL,\n ): T | TypedView<HumanReadable<TReturn>> {\n throwQueryNotRunnable();\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn> {\n return this.#newQuery(\n this.#tableName,\n this.#ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n );\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfAST(this.#ast);\n }\n return this.#hash;\n }\n\n one = (): Query<TTable, TSchema, TReturn | undefined> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit: 1,\n },\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n );\n\n whereExists = (\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TTable, TSchema, TReturn> => {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n return this.where(({exists}) => exists(relationship, cb, opts)) as Query<\n TTable,\n TSchema,\n TReturn\n >;\n };\n\n related = (\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): Query<TTable, TSchema, any> => {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n const q: AnyQuery = this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const subQuery = asQueryImpl(cb(q));\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: subQuery.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = asQueryImpl(\n cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ),\n ),\n );\n\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n hidden: true,\n subquery: {\n table: junctionSchema,\n alias: relationship,\n related: [\n {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: sq.#ast,\n },\n ],\n },\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n where = function (\n this: QueryImpl<TTable, TSchema, TReturn>,\n fieldOrExpressionFactory: string | ExpressionFactory<TTable, TSchema>,\n opOrValue?: SimpleOperator | GetFilterTypeAny | Parameter,\n value?: GetFilterTypeAny | Parameter,\n ): Query<TTable, TSchema, TReturn> {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(this.expressionBuilder());\n } else {\n assert(arguments.length >= 2, 'Invalid condition. Too few arguments.');\n // Distinguish between 2-arg form (field, value) and 3-arg form (field, op, value)\n // using arguments.length to allow explicit undefined in 3-arg form.\n if (arguments.length === 2) {\n cond = cmp(fieldOrExpressionFactory, opOrValue);\n } else {\n cond = cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n }\n\n const existingWhere = this.#ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n const where = simplifyCondition(cond);\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n where,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }.bind(this);\n\n start = (\n row: Partial<Record<string, ReadonlyJSONValue | undefined>>,\n opts?: {inclusive: boolean},\n ): Query<TTable, TSchema, TReturn> =>\n this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n\n limit = (limit: number): Query<TTable, TSchema, TReturn> => {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n limit,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n orderBy = <TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TTable, TSchema, TReturn> => {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this.#newQuery(\n this.#tableName,\n {\n ...this.#ast,\n orderBy: [...(this.#ast.orderBy ?? []), [field as string, direction]],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n #exists = (\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition => {\n cb = cb ?? (q => q);\n const flip = options?.flip;\n const scalar = options?.scalar;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema: destTableName, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const subQuery = asQueryImpl(\n cb(\n this.#newQuery(\n destTableName,\n {\n table: destTableName,\n alias: `${SUBQ_PREFIX}${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n undefined,\n ),\n ),\n );\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: subQuery.#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this.#newQuery(\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}zhidden_${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n relationship,\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n table: junctionSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n where: {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: asQueryImpl(queryToDest).#ast,\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n ...(scalar !== undefined ? {scalar} : {}),\n },\n },\n },\n op: 'EXISTS',\n ...(flip !== undefined ? {flip} : {}),\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n get ast(): AST {\n return this.#ast;\n }\n\n expressionBuilder() {\n return new ExpressionBuilder(this.#exists);\n }\n}\n\nexport function asQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn,\n>(q: Query<TTable, TSchema, TReturn>): QueryImpl<TTable, TSchema, TReturn> {\n assert(q instanceof QueryImpl, 'Expected QueryImpl instance');\n return q;\n}\n\nfunction throwQueryNotRunnable(): never {\n throw new Error('Query is not runnable');\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-internals.js","names":[],"sources":["../../../../../zql/src/query/query-internals.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema as ZeroSchema} from '../../../zero-types/src/schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {Query} from './query.ts';\n\nexport const queryInternalsTag = Symbol();\n\n/**\n * Internal interface for query implementation details.\n * This is not part of the public API and should only be accessed via\n * the {@linkcode asQueryInternals} function.\n *\n * @typeParam TSchema The database schema type extending ZeroSchema\n * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']\n * @typeParam TReturn The return type of the query, defaults to PullRow<TTable, TSchema>\n */\nexport interface QueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n> {\n readonly [queryInternalsTag]: true;\n\n /**\n * Format is used to specify the shape of the query results. This is used by\n * {@linkcode one} and it also describes the shape when using\n * {@linkcode related}.\n */\n readonly format: Format;\n\n /**\n * A string that uniquely identifies this query. This can be used to determine\n * if two queries are the same.\n *\n * The hash of a custom query, on the client, is the hash of its AST.\n * The hash of a custom query, on the server, is the hash of its name and args.\n *\n * The first allows many client-side queries to be pinned to the same backend query.\n * The second ensures we do not invoke a named query on the backend more than once for the same `name:arg` pairing.\n *\n * If the query.hash was of `name:args` then `useQuery` would de-dupe\n * queries with divergent ASTs.\n *\n * QueryManager will hash based on `name:args` since it is speaking with\n * the server which tracks queries by `name:args`.\n */\n hash(): string;\n\n /**\n * The completed AST for this query, with any missing primary keys added to\n * orderBy and start.\n */\n readonly ast: AST;\n\n readonly customQueryID: CustomQueryID | undefined;\n\n /**\n * Associates a name and arguments with this query for custom query tracking.\n * This is used internally to track named queries on the server.\n *\n * @internal\n */\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn>;\n}\n\n/**\n * Helper function to cast a Query to QueryInternals.\n * This is used in tests and internal code to access query implementation details.\n * The function asserts that the query has the queryInternalsTag to ensure it\n * properly implements the QueryInternals interface.\n *\n * @internal\n */\nexport function asQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n): QueryInternals<TTable, TSchema, TReturn> {\n assert(\n queryInternalsTag in query,\n 'Query does not implement QueryInternals. This likely means there are two copies of Zero in your runtime.',\n );\n return query as unknown as QueryInternals<TTable, TSchema, TReturn>;\n}\n\nexport function isQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(obj: unknown): obj is QueryInternals<TTable, TSchema, TReturn> {\n return typeof obj === 'object' && obj !== null && queryInternalsTag in obj;\n}\n\nexport function asQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n queryInternals: QueryInternals<TTable, TSchema, TReturn>,\n): Query<TTable, TSchema, TReturn> {\n assert(queryInternalsTag in queryInternals, 'Expected query internals tag');\n return queryInternals as unknown as Query<TTable, TSchema, TReturn>;\n}\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryInternals = QueryInternals<string, ZeroSchema, any>;\n"],"mappings":";;AAQA,IAAa,oBAAoB,
|
|
1
|
+
{"version":3,"file":"query-internals.js","names":[],"sources":["../../../../../zql/src/query/query-internals.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema as ZeroSchema} from '../../../zero-types/src/schema.ts';\nimport type {Format} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {Query} from './query.ts';\n\nexport const queryInternalsTag = Symbol();\n\n/**\n * Internal interface for query implementation details.\n * This is not part of the public API and should only be accessed via\n * the {@linkcode asQueryInternals} function.\n *\n * @typeParam TSchema The database schema type extending ZeroSchema\n * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']\n * @typeParam TReturn The return type of the query, defaults to PullRow<TTable, TSchema>\n */\nexport interface QueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n> {\n readonly [queryInternalsTag]: true;\n\n /**\n * Format is used to specify the shape of the query results. This is used by\n * {@linkcode one} and it also describes the shape when using\n * {@linkcode related}.\n */\n readonly format: Format;\n\n /**\n * A string that uniquely identifies this query. This can be used to determine\n * if two queries are the same.\n *\n * The hash of a custom query, on the client, is the hash of its AST.\n * The hash of a custom query, on the server, is the hash of its name and args.\n *\n * The first allows many client-side queries to be pinned to the same backend query.\n * The second ensures we do not invoke a named query on the backend more than once for the same `name:arg` pairing.\n *\n * If the query.hash was of `name:args` then `useQuery` would de-dupe\n * queries with divergent ASTs.\n *\n * QueryManager will hash based on `name:args` since it is speaking with\n * the server which tracks queries by `name:args`.\n */\n hash(): string;\n\n /**\n * The completed AST for this query, with any missing primary keys added to\n * orderBy and start.\n */\n readonly ast: AST;\n\n readonly customQueryID: CustomQueryID | undefined;\n\n /**\n * Associates a name and arguments with this query for custom query tracking.\n * This is used internally to track named queries on the server.\n *\n * @internal\n */\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TTable, TSchema, TReturn>;\n}\n\n/**\n * Helper function to cast a Query to QueryInternals.\n * This is used in tests and internal code to access query implementation details.\n * The function asserts that the query has the queryInternalsTag to ensure it\n * properly implements the QueryInternals interface.\n *\n * @internal\n */\nexport function asQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n query: Query<TTable, TSchema, TReturn>,\n): QueryInternals<TTable, TSchema, TReturn> {\n assert(\n queryInternalsTag in query,\n 'Query does not implement QueryInternals. This likely means there are two copies of Zero in your runtime.',\n );\n return query as unknown as QueryInternals<TTable, TSchema, TReturn>;\n}\n\nexport function isQueryInternals<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(obj: unknown): obj is QueryInternals<TTable, TSchema, TReturn> {\n return typeof obj === 'object' && obj !== null && queryInternalsTag in obj;\n}\n\nexport function asQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends ZeroSchema,\n TReturn,\n>(\n queryInternals: QueryInternals<TTable, TSchema, TReturn>,\n): Query<TTable, TSchema, TReturn> {\n assert(queryInternalsTag in queryInternals, 'Expected query internals tag');\n return queryInternals as unknown as Query<TTable, TSchema, TReturn>;\n}\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryInternals = QueryInternals<string, ZeroSchema, any>;\n"],"mappings":";;AAQA,IAAa,oBAAoB,QAAQ;;;;;;;;;AAuEzC,SAAgB,iBAKd,OAC0C;AAC1C,QACE,qBAAqB,OACrB,2GACD;AACD,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"query-registry.js","names":[],"sources":["../../../../../zql/src/query/query-registry.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\nimport {\n deepMerge,\n isPlainObject,\n type DeepMerge,\n} from '../../../shared/src/deep-merge.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {getValueAtPath} from '../../../shared/src/object-traversal.ts';\nimport type {\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n IsUnknown,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport type {PullRow, Query} from './query.ts';\nimport {validateInput} from './validate-input.ts';\n\n// ----------------------------------------------------------------------------\n// CustomQuery and QueryRequest types\n// ----------------------------------------------------------------------------\n\nexport type CustomQueryTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'Query' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * CustomQuery is returned from defineQueries. It is a callable that captures\n * args and can be turned into a Query via {@link QueryRequest}.\n */\nexport type CustomQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined = TInput,\n TSchema extends Schema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext = DefaultContext,\n> = {\n readonly 'queryName': string;\n readonly 'fn': QueryExecutionFunction<TTable, TInput, TReturn, TContext>;\n readonly '~': CustomQueryTypes<TTable, TInput, TSchema, TReturn, TContext>;\n} & CustomQueryCallable<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n\ntype CustomQueryCallable<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = [TInput] extends [undefined]\n ? () => QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n : undefined extends TInput\n ? {\n (): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n (\n args?: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n }\n : {\n (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n };\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyCustomQuery = CustomQuery<string, any, any, Schema, any, any>;\n\nexport function isQuery<S extends Schema>(\n value: unknown,\n // oxlint-disable-next-line no-explicit-any\n): value is CustomQuery<string, any, any, S, any, any> {\n return (\n typeof value === 'function' &&\n typeof (value as {queryName?: unknown}).queryName === 'string' &&\n typeof (value as {fn?: unknown}).fn === 'function'\n );\n}\n\nexport type QueryRequestTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'QueryRequest' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\nexport type QueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = {\n readonly 'query': CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n readonly 'args': TInput;\n readonly '~': QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n};\n\n/**\n * A shared type that can be a query request or a query builder.\n *\n * If it is a query request, it will be converted to a {@link Query} using the context.\n * Otherwise, it will be returned as is.\n */\nexport type QueryOrQueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> =\n | QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Query<TTable, TSchema, TReturn>;\n\n/**\n * Converts a query request to a {@link Query} using the context,\n * or returns the query as is.\n *\n * @param query - The query request or query builder to convert\n * @param context - The context to use to convert the query request\n */\nexport const addContextToQuery = <\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n context: TContext,\n): Query<TTable, TSchema, TReturn> =>\n 'query' in query ? query.query.fn({ctx: context, args: query.args}) : query;\n\n// ----------------------------------------------------------------------------\n// QueryRegistry types\n// ----------------------------------------------------------------------------\n\nexport function isQueryRegistry(obj: unknown): obj is AnyQueryRegistry {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as unknown as {['~']: string})?.['~'] === 'QueryRegistry'\n );\n}\n\nexport type QueryRegistryTypes<TSchema extends Schema> = 'QueryRegistry' & {\n readonly $schema: TSchema;\n};\n\nexport type QueryRegistry<\n QD extends QueryDefinitions,\n S extends Schema,\n> = ToQueryTree<QD, S> & {\n ['~']: QueryRegistryTypes<S>;\n};\n\nexport type AnyQueryRegistry = {\n ['~']: QueryRegistryTypes<Schema>;\n [key: string]: unknown;\n};\n\ntype ToQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? // pull types from the phantom property\n CustomQuery<\n QD[K]['~']['$tableName'],\n QD[K]['~']['$input'],\n QD[K]['~']['$output'],\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? ToQueryTree<QD[K], S>\n : never;\n};\n\nexport type FromQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? CustomQuery<\n QD[K]['~']['$tableName'],\n // intentionally left as generic to avoid variance issues\n ReadonlyJSONValue | undefined,\n ReadonlyJSONValue | undefined,\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? FromQueryTree<QD[K], S>\n : never;\n}[keyof QD];\n\nexport type QueryDefinitions = {\n readonly [key: string]: AnyQueryDefinition | QueryDefinitions;\n};\n\n// ----------------------------------------------------------------------------\n// defineQuery\n// ----------------------------------------------------------------------------\n\nexport type QueryDefinitionTypes<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput,\n TReturn,\n TContext,\n> = 'QueryDefinition' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * A query definition is the return type of `defineQuery()`.\n */\nexport type QueryDefinition<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext = DefaultContext,\n> = {\n readonly 'fn': QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>;\n readonly 'validator': StandardSchemaV1<TInput, TOutput> | undefined;\n readonly '~': QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >;\n};\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryDefinition = QueryDefinition<any, any, any, any, any>;\n\nexport function isQueryDefinition(f: unknown): f is AnyQueryDefinition {\n return (\n typeof f === 'object' &&\n f !== null &&\n (f as {['~']?: unknown})['~'] === 'QueryDefinition'\n );\n}\n\nexport type QueryDefinitionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (options: {args: TInput; ctx: TContext}) => Query<TTable, Schema, TReturn>;\n\nexport type QueryExecutionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (\n options: QueryExecutionOptions<TInput, TContext>,\n) => Query<TTable, Schema, TReturn>;\n\ntype QueryExecutionOptions<\n TInput extends ReadonlyJSONValue | undefined,\n TContext,\n> = undefined extends TInput\n ? IsUnknown<TContext> extends true\n ? {args?: TInput | undefined; ctx?: TContext | undefined}\n : {args?: TInput | undefined; ctx: TContext}\n : IsUnknown<TContext> extends true\n ? {args: TInput; ctx?: TContext | undefined}\n : {args: TInput; ctx: TContext};\n\n/**\n * Defines a query to be used with {@link defineQueries}.\n *\n * The query function receives an object with `args` (the query arguments) and\n * `ctx` (the context). It should return a {@link Query} built using a builder\n * created from {@link createBuilder}.\n *\n * Note: A query defined with `defineQuery` must be passed to\n * {@link defineQueries} to be usable. The query name is derived from its\n * position in the `defineQueries` object.\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * // Simple query with no arguments\n * allIssues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n *\n * // Query with typed arguments\n * issueById: defineQuery(({args}: {args: {id: string}}) =>\n * builder.issue.where('id', args.id).one(),\n * ),\n *\n * // Query with validation using a Standard Schema validator (e.g., Zod)\n * issuesByStatus: defineQuery(\n * z.object({status: z.enum(['open', 'closed'])}),\n * ({args}) => builder.issue.where('status', args.status),\n * ),\n *\n * // Query using context\n * myIssues: defineQuery(({ctx}: {ctx: {userID: string}}) =>\n * builder.issue.where('creatorID', ctx.userID),\n * ),\n * });\n * ```\n *\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} that can be passed to {@link defineQueries}.\n *\n * @overload\n * @param validator - A Standard Schema validator for the arguments.\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} with validated arguments.\n */\n// Overload for no validator parameter with default inference for untyped functions\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n queryFn: QueryDefinitionFunction<TTable, TInput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TInput, TReturn, TContext>;\n\n// Overload for validator parameter - Input and Output can be different\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n\n// Implementation\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validatorOrQueryFn:\n | StandardSchemaV1<TInput, TOutput>\n | QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n queryFn?: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext> {\n // Handle different parameter patterns\n let validator: StandardSchemaV1<TInput, TOutput> | undefined;\n let actualQueryFn: QueryDefinitionFunction<\n TTable,\n TOutput,\n TReturn,\n TContext\n >;\n\n if ('~standard' in validatorOrQueryFn) {\n // defineQuery(validator, queryFn) - with validator\n validator = validatorOrQueryFn;\n actualQueryFn = must(queryFn);\n } else {\n // defineQuery(queryFn) - no validator\n validator = undefined;\n actualQueryFn = validatorOrQueryFn;\n }\n\n const queryDefinition: QueryDefinition<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n > = {\n 'fn': actualQueryFn,\n 'validator': validator,\n '~': 'QueryDefinition' as unknown as QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >,\n };\n return queryDefinition;\n}\n\n/**\n * Returns a typed version of {@link defineQuery} with the schema and context\n * types pre-specified. This enables better type inference when defining\n * queries.\n *\n * @example\n * ```ts\n * const zql = createBuilder(schema);\n *\n * // With both Schema and Context types\n * const defineAppQuery = defineQueryWithType<AppSchema, AppContext>();\n * const myQuery = defineAppQuery(({ctx}) =>\n * zql.issue.where('userID', ctx.userID),\n * );\n *\n * // With just Context type (Schema inferred)\n * const defineAppQuery = defineQueryWithType<AppContext>();\n * ```\n *\n * @typeParam S - The Zero schema type.\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with types\n * pre-bound.\n */\nexport function defineQueryWithType<\n S extends Schema,\n C = unknown,\n>(): TypedDefineQuery<S, C>;\n\n/**\n * Returns a typed version of {@link defineQuery} with the context type\n * pre-specified.\n *\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with the context\n * type pre-bound.\n */\nexport function defineQueryWithType<C>(): TypedDefineQuery<Schema, C>;\n\nexport function defineQueryWithType() {\n return defineQuery;\n}\n\n/**\n * The return type of defineQueryWithType. A function matching the\n * defineQuery overloads but with Schema and Context pre-bound.\n */\ntype TypedDefineQuery<TSchema extends Schema, TContext> = {\n // Without validator\n <\n TArgs extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n queryFn: QueryDefinitionFunction<TTable, TArgs, TReturn, TContext>,\n ): QueryDefinition<TTable, TArgs, TArgs, TReturn, TContext>;\n\n // With validator\n <\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n ): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n};\n\n// ----------------------------------------------------------------------------\n// createQuery\n// ----------------------------------------------------------------------------\n\nexport function createQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n name: string,\n definition: QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>,\n): CustomQuery<TTable, TInput, TOutput, TSchema, TReturn, TContext> {\n const {validator} = definition;\n\n const fn: QueryExecutionFunction<\n TTable,\n TInput,\n TReturn,\n TContext\n > = options => {\n const validatedArgs = validator\n ? validateInput(name, options.args, validator, 'query')\n : (options.args as unknown as TOutput);\n\n return asQueryInternals(\n definition.fn({\n args: validatedArgs,\n ctx: options.ctx as TContext,\n }),\n ).nameAndArgs(\n name,\n // TODO(arv): Get rid of the array?\n // Send original input args to server (not transformed output)\n options.args === undefined ? [] : [options.args],\n );\n };\n\n const query = (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext> => ({\n args,\n '~': 'QueryRequest' as QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n 'query': query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n });\n\n query.queryName = name;\n query.fn = fn;\n query['~'] = 'Query' as CustomQueryTypes<\n TTable,\n TInput,\n TSchema,\n TReturn,\n TContext\n >;\n\n return query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n}\n\n// ----------------------------------------------------------------------------\n// defineQueries\n// ----------------------------------------------------------------------------\n\n/**\n * Converts query definitions created with {@link defineQuery} into callable\n * {@link Query} objects that can be invoked with arguments and a context.\n *\n * Query definitions can be nested for organization. The resulting query names\n * are dot-separated paths (e.g., `users.byId`).\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * issues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n * users: {\n * byId: defineQuery(({args}: {args: {id: string}}) =>\n * builder.user.where('id', args.id),\n * ),\n * },\n * });\n *\n * // Usage:\n * const request = queries.issues.byId({id: '123'});\n * const [data] = zero.useQuery(request);\n * ```\n *\n * @param defs - An object containing query definitions or nested objects of\n * query definitions.\n * @returns An object with the same structure where each query definition is\n * converted to a {@link CustomQuery}.\n */\nexport function defineQueries<\n // let QD infer freely so defaults aren't erased by a QueryDefinitions<any, any> constraint\n const QD,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n defs: QD & AssertQueryDefinitions<QD>,\n): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\nexport function defineQueries<\n const TBase,\n const TOverrides,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n>;\n\nexport function defineQueries<QD extends QueryDefinitions, S extends Schema>(\n defsOrBase: QD | QueryRegistry<QD, S>,\n overrides?: QueryDefinitions,\n): QueryRegistry<QD, S> {\n function processDefinitions(\n definitions: QueryDefinitions,\n path: string[],\n ): Record<string | symbol, unknown> {\n const result: Record<string | symbol, unknown> = {\n ['~']: 'QueryRegistry',\n };\n\n for (const [key, value] of Object.entries(definitions)) {\n path.push(key);\n const defaultName = path.join('.');\n\n if (isQueryDefinition(value)) {\n result[key] = createQuery(defaultName, value);\n } else {\n // Nested definitions\n result[key] = processDefinitions(value, path);\n }\n path.pop();\n }\n\n return result;\n }\n\n if (overrides !== undefined) {\n // Merge base and overrides\n\n let base: Record<string | symbol, unknown>;\n if (!isQueryRegistry(defsOrBase)) {\n base = processDefinitions(defsOrBase, []);\n } else {\n base = defsOrBase;\n }\n\n const processed = processDefinitions(overrides, []);\n\n const merged = deepMerge(base, processed, isQueryLeaf);\n merged['~'] = 'QueryRegistry';\n return merged as QueryRegistry<QD, S>;\n }\n\n return processDefinitions(defsOrBase as QD, []) as QueryRegistry<QD, S>;\n}\n\nconst isQueryLeaf = (value: unknown): boolean =>\n !isPlainObject(value) || isQuery(value);\n\nexport type AssertQueryDefinitions<QD> = QD extends QueryDefinitions\n ? unknown\n : never;\n\nexport type EnsureQueryDefinitions<QD> = QD extends QueryDefinitions\n ? QD\n : QD extends QueryRegistry<infer InnerQD, infer _S>\n ? InnerQD\n : never;\n\n/**\n * Creates a function that can be used to define queries with a specific schema.\n */\nexport function defineQueriesWithType<\n TSchema extends Schema,\n>(): TypedDefineQueries<TSchema> {\n return defineQueries;\n}\n\n/**\n * The return type of defineQueriesWithType. A function matching the\n * defineQueries overloads but with Schema pre-bound.\n */\ntype TypedDefineQueries<S extends Schema> = {\n // Single definitions\n <QD>(\n definitions: QD & AssertQueryDefinitions<QD>,\n ): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\n // Base and overrides\n <TBase, TOverrides>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n ): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n >;\n};\n\nconst separatorRe = /[.|]/;\n\n// ----------------------------------------------------------------------------\n// getQuery / mustGetQuery\n// ----------------------------------------------------------------------------\n\nexport function getQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> | undefined {\n const q = getValueAtPath(queries, name, separatorRe);\n return q as FromQueryTree<QD, S> | undefined;\n}\n\nexport function mustGetQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> {\n const query = getQuery(queries, name);\n if (query === undefined) {\n throw new Error(`Query not found: ${name}`);\n }\n return query;\n}\n"],"mappings":";;;;;;AAgFA,SAAgB,QACd,OAEqD;CACrD,OACE,OAAO,UAAU,cACjB,OAAQ,MAAgC,cAAc,YACtD,OAAQ,MAAyB,OAAO;AAE5C;;;;;;;;AAqEA,IAAa,qBAQX,OAQA,YAEA,WAAW,QAAQ,MAAM,MAAM,GAAG;CAAC,KAAK;CAAS,MAAM,MAAM;AAAI,CAAC,IAAI;AAMxE,SAAgB,gBAAgB,KAAuC;CACrE,OACE,OAAO,QAAQ,YACf,QAAQ,QACP,MAAqC,SAAS;AAEnD;AAgGA,SAAgB,kBAAkB,GAAqC;CACrE,OACE,OAAO,MAAM,YACb,MAAM,QACL,EAAwB,SAAS;AAEtC;AAqGA,SAAgB,YASd,oBAGA,SAC6D;CAE7D,IAAI;CACJ,IAAI;CAOJ,IAAI,eAAe,oBAAoB;EAErC,YAAY;EACZ,gBAAgB,KAAK,OAAO;CAC9B,OAAO;EAEL,YAAY,KAAA;EACZ,gBAAgB;CAClB;CAmBA,OAAO;EAVL,MAAM;EACN,aAAa;EACb,KAAK;CAQA;AACT;AAyCA,SAAgB,sBAAsB;CACpC,OAAO;AACT;AAkCA,SAAgB,YAQd,MACA,YACkE;CAClE,MAAM,EAAC,cAAa;CAEpB,MAAM,MAKF,YAAW;EACb,MAAM,gBAAgB,YAClB,cAAc,MAAM,QAAQ,MAAM,WAAW,OAAO,IACnD,QAAQ;EAEb,OAAO,iBACL,WAAW,GAAG;GACZ,MAAM;GACN,KAAK,QAAQ;EACf,CAAC,CACH,EAAE,YACA,MAGA,QAAQ,SAAS,KAAA,IAAY,CAAC,IAAI,CAAC,QAAQ,IAAI,CACjD;CACF;CAEA,MAAM,SACJ,UACuE;EACvE;EACA,KAAK;EAQL,SAAS;CAQX;CAEA,MAAM,YAAY;CAClB,MAAM,KAAK;CACX,MAAM,OAAO;CAQb,OAAO;AAQT;AA8DA,SAAgB,cACd,YACA,WACsB;CACtB,SAAS,mBACP,aACA,MACkC;EAClC,MAAM,SAA2C,GAC9C,MAAM,gBACT;EAEA,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,WAAW,GAAG;GACtD,KAAK,KAAK,GAAG;GACb,MAAM,cAAc,KAAK,KAAK,GAAG;GAEjC,IAAI,kBAAkB,KAAK,GACzB,OAAO,OAAO,YAAY,aAAa,KAAK;QAG5C,OAAO,OAAO,mBAAmB,OAAO,IAAI;GAE9C,KAAK,IAAI;EACX;EAEA,OAAO;CACT;CAEA,IAAI,cAAc,KAAA,GAAW;EAG3B,IAAI;EACJ,IAAI,CAAC,gBAAgB,UAAU,GAC7B,OAAO,mBAAmB,YAAY,CAAC,CAAC;OAExC,OAAO;EAGT,MAAM,YAAY,mBAAmB,WAAW,CAAC,CAAC;EAElD,MAAM,SAAS,UAAU,MAAM,WAAW,WAAW;EACrD,OAAO,OAAO;EACd,OAAO;CACT;CAEA,OAAO,mBAAmB,YAAkB,CAAC,CAAC;AAChD;AAEA,IAAM,eAAe,UACnB,CAAC,cAAc,KAAK,KAAK,QAAQ,KAAK;;;;AAexC,SAAgB,wBAEiB;CAC/B,OAAO;AACT;AA4BA,IAAM,cAAc;AAMpB,SAAgB,SACd,SACA,MACkC;CAElC,OADU,eAAe,SAAS,MAAM,WACjC;AACT;AAEA,SAAgB,aACd,SACA,MACsB;CACtB,MAAM,QAAQ,SAAS,SAAS,IAAI;CACpC,IAAI,UAAU,KAAA,GACZ,MAAM,IAAI,MAAM,oBAAoB,MAAM;CAE5C,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"query-registry.js","names":[],"sources":["../../../../../zql/src/query/query-registry.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\nimport {\n deepMerge,\n isPlainObject,\n type DeepMerge,\n} from '../../../shared/src/deep-merge.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {getValueAtPath} from '../../../shared/src/object-traversal.ts';\nimport type {\n BaseDefaultSchema,\n DefaultContext,\n DefaultSchema,\n IsUnknown,\n} from '../../../zero-types/src/default-types.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {asQueryInternals} from './query-internals.ts';\nimport type {PullRow, Query} from './query.ts';\nimport {validateInput} from './validate-input.ts';\n\n// ----------------------------------------------------------------------------\n// CustomQuery and QueryRequest types\n// ----------------------------------------------------------------------------\n\nexport type CustomQueryTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'Query' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * CustomQuery is returned from defineQueries. It is a callable that captures\n * args and can be turned into a Query via {@link QueryRequest}.\n */\nexport type CustomQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined = TInput,\n TSchema extends Schema = DefaultSchema,\n TReturn = PullRow<TTable, TSchema>,\n TContext = DefaultContext,\n> = {\n readonly 'queryName': string;\n readonly 'fn': QueryExecutionFunction<TTable, TInput, TReturn, TContext>;\n readonly '~': CustomQueryTypes<TTable, TInput, TSchema, TReturn, TContext>;\n} & CustomQueryCallable<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n\ntype CustomQueryCallable<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = [TInput] extends [undefined]\n ? () => QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n : undefined extends TInput\n ? {\n (): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n (\n args?: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n }\n : {\n (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>;\n };\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyCustomQuery = CustomQuery<string, any, any, Schema, any, any>;\n\nexport function isQuery<S extends Schema>(\n value: unknown,\n // oxlint-disable-next-line no-explicit-any\n): value is CustomQuery<string, any, any, S, any, any> {\n return (\n typeof value === 'function' &&\n typeof (value as {queryName?: unknown}).queryName === 'string' &&\n typeof (value as {fn?: unknown}).fn === 'function'\n );\n}\n\nexport type QueryRequestTypes<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = 'QueryRequest' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $schema: TSchema;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\nexport type QueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> = {\n readonly 'query': CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n readonly 'args': TInput;\n readonly '~': QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n};\n\n/**\n * A shared type that can be a query request or a query builder.\n *\n * If it is a query request, it will be converted to a {@link Query} using the context.\n * Otherwise, it will be returned as is.\n */\nexport type QueryOrQueryRequest<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n> =\n | QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext>\n | Query<TTable, TSchema, TReturn>;\n\n/**\n * Converts a query request to a {@link Query} using the context,\n * or returns the query as is.\n *\n * @param query - The query request or query builder to convert\n * @param context - The context to use to convert the query request\n */\nexport const addContextToQuery = <\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n query: QueryOrQueryRequest<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n context: TContext,\n): Query<TTable, TSchema, TReturn> =>\n 'query' in query ? query.query.fn({ctx: context, args: query.args}) : query;\n\n// ----------------------------------------------------------------------------\n// QueryRegistry types\n// ----------------------------------------------------------------------------\n\nexport function isQueryRegistry(obj: unknown): obj is AnyQueryRegistry {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as unknown as {['~']: string})?.['~'] === 'QueryRegistry'\n );\n}\n\nexport type QueryRegistryTypes<TSchema extends Schema> = 'QueryRegistry' & {\n readonly $schema: TSchema;\n};\n\nexport type QueryRegistry<\n QD extends QueryDefinitions,\n S extends Schema,\n> = ToQueryTree<QD, S> & {\n ['~']: QueryRegistryTypes<S>;\n};\n\nexport type AnyQueryRegistry = {\n ['~']: QueryRegistryTypes<Schema>;\n [key: string]: unknown;\n};\n\ntype ToQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? // pull types from the phantom property\n CustomQuery<\n QD[K]['~']['$tableName'],\n QD[K]['~']['$input'],\n QD[K]['~']['$output'],\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? ToQueryTree<QD[K], S>\n : never;\n};\n\nexport type FromQueryTree<QD extends QueryDefinitions, S extends Schema> = {\n readonly [K in keyof QD]: QD[K] extends AnyQueryDefinition\n ? CustomQuery<\n QD[K]['~']['$tableName'],\n // intentionally left as generic to avoid variance issues\n ReadonlyJSONValue | undefined,\n ReadonlyJSONValue | undefined,\n S,\n QD[K]['~']['$return'],\n QD[K]['~']['$context']\n >\n : QD[K] extends QueryDefinitions\n ? FromQueryTree<QD[K], S>\n : never;\n}[keyof QD];\n\nexport type QueryDefinitions = {\n readonly [key: string]: AnyQueryDefinition | QueryDefinitions;\n};\n\n// ----------------------------------------------------------------------------\n// defineQuery\n// ----------------------------------------------------------------------------\n\nexport type QueryDefinitionTypes<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput,\n TReturn,\n TContext,\n> = 'QueryDefinition' & {\n readonly $tableName: TTable;\n readonly $input: TInput;\n readonly $output: TOutput;\n readonly $return: TReturn;\n readonly $context: TContext;\n};\n\n/**\n * A query definition is the return type of `defineQuery()`.\n */\nexport type QueryDefinition<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext = DefaultContext,\n> = {\n readonly 'fn': QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>;\n readonly 'validator': StandardSchemaV1<TInput, TOutput> | undefined;\n readonly '~': QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >;\n};\n\n// oxlint-disable-next-line no-explicit-any\nexport type AnyQueryDefinition = QueryDefinition<any, any, any, any, any>;\n\nexport function isQueryDefinition(f: unknown): f is AnyQueryDefinition {\n return (\n typeof f === 'object' &&\n f !== null &&\n (f as {['~']?: unknown})['~'] === 'QueryDefinition'\n );\n}\n\nexport type QueryDefinitionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (options: {args: TInput; ctx: TContext}) => Query<TTable, Schema, TReturn>;\n\nexport type QueryExecutionFunction<\n TTable extends string,\n TInput extends ReadonlyJSONValue | undefined,\n TReturn,\n TContext,\n> = (\n options: QueryExecutionOptions<TInput, TContext>,\n) => Query<TTable, Schema, TReturn>;\n\ntype QueryExecutionOptions<\n TInput extends ReadonlyJSONValue | undefined,\n TContext,\n> = undefined extends TInput\n ? IsUnknown<TContext> extends true\n ? {args?: TInput | undefined; ctx?: TContext | undefined}\n : {args?: TInput | undefined; ctx: TContext}\n : IsUnknown<TContext> extends true\n ? {args: TInput; ctx?: TContext | undefined}\n : {args: TInput; ctx: TContext};\n\n/**\n * Defines a query to be used with {@link defineQueries}.\n *\n * The query function receives an object with `args` (the query arguments) and\n * `ctx` (the context). It should return a {@link Query} built using a builder\n * created from {@link createBuilder}.\n *\n * Note: A query defined with `defineQuery` must be passed to\n * {@link defineQueries} to be usable. The query name is derived from its\n * position in the `defineQueries` object.\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * // Simple query with no arguments\n * allIssues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n *\n * // Query with typed arguments\n * issueById: defineQuery(({args}: {args: {id: string}}) =>\n * builder.issue.where('id', args.id).one(),\n * ),\n *\n * // Query with validation using a Standard Schema validator (e.g., Zod)\n * issuesByStatus: defineQuery(\n * z.object({status: z.enum(['open', 'closed'])}),\n * ({args}) => builder.issue.where('status', args.status),\n * ),\n *\n * // Query using context\n * myIssues: defineQuery(({ctx}: {ctx: {userID: string}}) =>\n * builder.issue.where('creatorID', ctx.userID),\n * ),\n * });\n * ```\n *\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} that can be passed to {@link defineQueries}.\n *\n * @overload\n * @param validator - A Standard Schema validator for the arguments.\n * @param queryFn - A function that receives `{args, ctx}` and returns a Query.\n * @returns A {@link QueryDefinition} with validated arguments.\n */\n// Overload for no validator parameter with default inference for untyped functions\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n queryFn: QueryDefinitionFunction<TTable, TInput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TInput, TReturn, TContext>;\n\n// Overload for validator parameter - Input and Output can be different\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n\n// Implementation\nexport function defineQuery<\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TContext = DefaultContext,\n TSchema extends Schema = DefaultSchema,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n TReturn = PullRow<TTable, TSchema>,\n>(\n validatorOrQueryFn:\n | StandardSchemaV1<TInput, TOutput>\n | QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n queryFn?: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext> {\n // Handle different parameter patterns\n let validator: StandardSchemaV1<TInput, TOutput> | undefined;\n let actualQueryFn: QueryDefinitionFunction<\n TTable,\n TOutput,\n TReturn,\n TContext\n >;\n\n if ('~standard' in validatorOrQueryFn) {\n // defineQuery(validator, queryFn) - with validator\n validator = validatorOrQueryFn;\n actualQueryFn = must(queryFn);\n } else {\n // defineQuery(queryFn) - no validator\n validator = undefined;\n actualQueryFn = validatorOrQueryFn;\n }\n\n const queryDefinition: QueryDefinition<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n > = {\n 'fn': actualQueryFn,\n 'validator': validator,\n '~': 'QueryDefinition' as unknown as QueryDefinitionTypes<\n TTable,\n TInput,\n TOutput,\n TReturn,\n TContext\n >,\n };\n return queryDefinition;\n}\n\n/**\n * Returns a typed version of {@link defineQuery} with the schema and context\n * types pre-specified. This enables better type inference when defining\n * queries.\n *\n * @example\n * ```ts\n * const zql = createBuilder(schema);\n *\n * // With both Schema and Context types\n * const defineAppQuery = defineQueryWithType<AppSchema, AppContext>();\n * const myQuery = defineAppQuery(({ctx}) =>\n * zql.issue.where('userID', ctx.userID),\n * );\n *\n * // With just Context type (Schema inferred)\n * const defineAppQuery = defineQueryWithType<AppContext>();\n * ```\n *\n * @typeParam S - The Zero schema type.\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with types\n * pre-bound.\n */\nexport function defineQueryWithType<\n S extends Schema,\n C = unknown,\n>(): TypedDefineQuery<S, C>;\n\n/**\n * Returns a typed version of {@link defineQuery} with the context type\n * pre-specified.\n *\n * @typeParam C - The context type passed to query functions.\n * @returns A function equivalent to {@link defineQuery} but with the context\n * type pre-bound.\n */\nexport function defineQueryWithType<C>(): TypedDefineQuery<Schema, C>;\n\nexport function defineQueryWithType() {\n return defineQuery;\n}\n\n/**\n * The return type of defineQueryWithType. A function matching the\n * defineQuery overloads but with Schema and Context pre-bound.\n */\ntype TypedDefineQuery<TSchema extends Schema, TContext> = {\n // Without validator\n <\n TArgs extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n queryFn: QueryDefinitionFunction<TTable, TArgs, TReturn, TContext>,\n ): QueryDefinition<TTable, TArgs, TArgs, TReturn, TContext>;\n\n // With validator\n <\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TReturn,\n TTable extends keyof TSchema['tables'] & string = keyof TSchema['tables'] &\n string,\n >(\n validator: StandardSchemaV1<TInput, TOutput>,\n queryFn: QueryDefinitionFunction<TTable, TOutput, TReturn, TContext>,\n ): QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>;\n};\n\n// ----------------------------------------------------------------------------\n// createQuery\n// ----------------------------------------------------------------------------\n\nexport function createQuery<\n TTable extends keyof TSchema['tables'] & string,\n TInput extends ReadonlyJSONValue | undefined,\n TOutput extends ReadonlyJSONValue | undefined,\n TSchema extends Schema,\n TReturn,\n TContext,\n>(\n name: string,\n definition: QueryDefinition<TTable, TInput, TOutput, TReturn, TContext>,\n): CustomQuery<TTable, TInput, TOutput, TSchema, TReturn, TContext> {\n const {validator} = definition;\n\n const fn: QueryExecutionFunction<\n TTable,\n TInput,\n TReturn,\n TContext\n > = options => {\n const validatedArgs = validator\n ? validateInput(name, options.args, validator, 'query')\n : (options.args as unknown as TOutput);\n\n return asQueryInternals(\n definition.fn({\n args: validatedArgs,\n ctx: options.ctx as TContext,\n }),\n ).nameAndArgs(\n name,\n // TODO(arv): Get rid of the array?\n // Send original input args to server (not transformed output)\n options.args === undefined ? [] : [options.args],\n );\n };\n\n const query = (\n args: TInput,\n ): QueryRequest<TTable, TInput, TOutput, TSchema, TReturn, TContext> => ({\n args,\n '~': 'QueryRequest' as QueryRequestTypes<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n 'query': query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >,\n });\n\n query.queryName = name;\n query.fn = fn;\n query['~'] = 'Query' as CustomQueryTypes<\n TTable,\n TInput,\n TSchema,\n TReturn,\n TContext\n >;\n\n return query as unknown as CustomQuery<\n TTable,\n TInput,\n TOutput,\n TSchema,\n TReturn,\n TContext\n >;\n}\n\n// ----------------------------------------------------------------------------\n// defineQueries\n// ----------------------------------------------------------------------------\n\n/**\n * Converts query definitions created with {@link defineQuery} into callable\n * {@link Query} objects that can be invoked with arguments and a context.\n *\n * Query definitions can be nested for organization. The resulting query names\n * are dot-separated paths (e.g., `users.byId`).\n *\n * @example\n * ```ts\n * const builder = createBuilder(schema);\n *\n * const queries = defineQueries({\n * issues: defineQuery(() => builder.issue.orderBy('created', 'desc')),\n * users: {\n * byId: defineQuery(({args}: {args: {id: string}}) =>\n * builder.user.where('id', args.id),\n * ),\n * },\n * });\n *\n * // Usage:\n * const request = queries.issues.byId({id: '123'});\n * const [data] = zero.useQuery(request);\n * ```\n *\n * @param defs - An object containing query definitions or nested objects of\n * query definitions.\n * @returns An object with the same structure where each query definition is\n * converted to a {@link CustomQuery}.\n */\nexport function defineQueries<\n // let QD infer freely so defaults aren't erased by a QueryDefinitions<any, any> constraint\n const QD,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n defs: QD & AssertQueryDefinitions<QD>,\n): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\nexport function defineQueries<\n const TBase,\n const TOverrides,\n S extends BaseDefaultSchema = DefaultSchema,\n>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n>;\n\nexport function defineQueries<QD extends QueryDefinitions, S extends Schema>(\n defsOrBase: QD | QueryRegistry<QD, S>,\n overrides?: QueryDefinitions,\n): QueryRegistry<QD, S> {\n function processDefinitions(\n definitions: QueryDefinitions,\n path: string[],\n ): Record<string | symbol, unknown> {\n const result: Record<string | symbol, unknown> = {\n ['~']: 'QueryRegistry',\n };\n\n for (const [key, value] of Object.entries(definitions)) {\n path.push(key);\n const defaultName = path.join('.');\n\n if (isQueryDefinition(value)) {\n result[key] = createQuery(defaultName, value);\n } else {\n // Nested definitions\n result[key] = processDefinitions(value, path);\n }\n path.pop();\n }\n\n return result;\n }\n\n if (overrides !== undefined) {\n // Merge base and overrides\n\n let base: Record<string | symbol, unknown>;\n if (!isQueryRegistry(defsOrBase)) {\n base = processDefinitions(defsOrBase, []);\n } else {\n base = defsOrBase;\n }\n\n const processed = processDefinitions(overrides, []);\n\n const merged = deepMerge(base, processed, isQueryLeaf);\n merged['~'] = 'QueryRegistry';\n return merged as QueryRegistry<QD, S>;\n }\n\n return processDefinitions(defsOrBase as QD, []) as QueryRegistry<QD, S>;\n}\n\nconst isQueryLeaf = (value: unknown): boolean =>\n !isPlainObject(value) || isQuery(value);\n\nexport type AssertQueryDefinitions<QD> = QD extends QueryDefinitions\n ? unknown\n : never;\n\nexport type EnsureQueryDefinitions<QD> = QD extends QueryDefinitions\n ? QD\n : QD extends QueryRegistry<infer InnerQD, infer _S>\n ? InnerQD\n : never;\n\n/**\n * Creates a function that can be used to define queries with a specific schema.\n */\nexport function defineQueriesWithType<\n TSchema extends Schema,\n>(): TypedDefineQueries<TSchema> {\n return defineQueries;\n}\n\n/**\n * The return type of defineQueriesWithType. A function matching the\n * defineQueries overloads but with Schema pre-bound.\n */\ntype TypedDefineQueries<S extends Schema> = {\n // Single definitions\n <QD>(\n definitions: QD & AssertQueryDefinitions<QD>,\n ): QueryRegistry<EnsureQueryDefinitions<QD>, S>;\n\n // Base and overrides\n <TBase, TOverrides>(\n base:\n | QueryRegistry<EnsureQueryDefinitions<TBase>, S>\n | (TBase & AssertQueryDefinitions<TBase>),\n overrides: TOverrides & AssertQueryDefinitions<TOverrides>,\n ): QueryRegistry<\n DeepMerge<\n EnsureQueryDefinitions<TBase>,\n EnsureQueryDefinitions<TOverrides>,\n AnyQueryDefinition\n >,\n S\n >;\n};\n\nconst separatorRe = /[.|]/;\n\n// ----------------------------------------------------------------------------\n// getQuery / mustGetQuery\n// ----------------------------------------------------------------------------\n\nexport function getQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> | undefined {\n const q = getValueAtPath(queries, name, separatorRe);\n return q as FromQueryTree<QD, S> | undefined;\n}\n\nexport function mustGetQuery<QD extends QueryDefinitions, S extends Schema>(\n queries: QueryRegistry<QD, S>,\n name: string,\n): FromQueryTree<QD, S> {\n const query = getQuery(queries, name);\n if (query === undefined) {\n throw new Error(`Query not found: ${name}`);\n }\n return query;\n}\n"],"mappings":";;;;;;AAgFA,SAAgB,QACd,OAEqD;AACrD,QACE,OAAO,UAAU,cACjB,OAAQ,MAAgC,cAAc,YACtD,OAAQ,MAAyB,OAAO;;;;;;;;;AAuE5C,IAAa,qBAQX,OAQA,YAEA,WAAW,QAAQ,MAAM,MAAM,GAAG;CAAC,KAAK;CAAS,MAAM,MAAM;CAAK,CAAC,GAAG;AAMxE,SAAgB,gBAAgB,KAAuC;AACrE,QACE,OAAO,QAAQ,YACf,QAAQ,QACP,MAAqC,SAAS;;AAkGnD,SAAgB,kBAAkB,GAAqC;AACrE,QACE,OAAO,MAAM,YACb,MAAM,QACL,EAAwB,SAAS;;AAuGtC,SAAgB,YASd,oBAGA,SAC6D;CAE7D,IAAI;CACJ,IAAI;AAOJ,KAAI,eAAe,oBAAoB;AAErC,cAAY;AACZ,kBAAgB,KAAK,QAAQ;QACxB;AAEL,cAAY,KAAA;AACZ,kBAAgB;;AAoBlB,QAXI;EACF,MAAM;EACN,aAAa;EACb,KAAK;EAON;;AA2CH,SAAgB,sBAAsB;AACpC,QAAO;;AAmCT,SAAgB,YAQd,MACA,YACkE;CAClE,MAAM,EAAC,cAAa;CAEpB,MAAM,MAKF,YAAW;EACb,MAAM,gBAAgB,YAClB,cAAc,MAAM,QAAQ,MAAM,WAAW,QAAQ,GACpD,QAAQ;AAEb,SAAO,iBACL,WAAW,GAAG;GACZ,MAAM;GACN,KAAK,QAAQ;GACd,CAAC,CACH,CAAC,YACA,MAGA,QAAQ,SAAS,KAAA,IAAY,EAAE,GAAG,CAAC,QAAQ,KAAK,CACjD;;CAGH,MAAM,SACJ,UACuE;EACvE;EACA,KAAK;EAQL,SAAS;EAQV;AAED,OAAM,YAAY;AAClB,OAAM,KAAK;AACX,OAAM,OAAO;AAQb,QAAO;;AAsET,SAAgB,cACd,YACA,WACsB;CACtB,SAAS,mBACP,aACA,MACkC;EAClC,MAAM,SAA2C,GAC9C,MAAM,iBACR;AAED,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,EAAE;AACtD,QAAK,KAAK,IAAI;GACd,MAAM,cAAc,KAAK,KAAK,IAAI;AAElC,OAAI,kBAAkB,MAAM,CAC1B,QAAO,OAAO,YAAY,aAAa,MAAM;OAG7C,QAAO,OAAO,mBAAmB,OAAO,KAAK;AAE/C,QAAK,KAAK;;AAGZ,SAAO;;AAGT,KAAI,cAAc,KAAA,GAAW;EAG3B,IAAI;AACJ,MAAI,CAAC,gBAAgB,WAAW,CAC9B,QAAO,mBAAmB,YAAY,EAAE,CAAC;MAEzC,QAAO;EAGT,MAAM,YAAY,mBAAmB,WAAW,EAAE,CAAC;EAEnD,MAAM,SAAS,UAAU,MAAM,WAAW,YAAY;AACtD,SAAO,OAAO;AACd,SAAO;;AAGT,QAAO,mBAAmB,YAAkB,EAAE,CAAC;;AAGjD,IAAM,eAAe,UACnB,CAAC,cAAc,MAAM,IAAI,QAAQ,MAAM;;;;AAezC,SAAgB,wBAEiB;AAC/B,QAAO;;AA6BT,IAAM,cAAc;AAMpB,SAAgB,SACd,SACA,MACkC;AAElC,QADU,eAAe,SAAS,MAAM,YAAY;;AAItD,SAAgB,aACd,SACA,MACsB;CACtB,MAAM,QAAQ,SAAS,SAAS,KAAK;AACrC,KAAI,UAAU,KAAA,EACZ,OAAM,IAAI,MAAM,oBAAoB,OAAO;AAE7C,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runnable-query-impl.js","names":["#delegate"],"sources":["../../../../../zql/src/query/runnable-query-impl.ts"],"sourcesContent":["import type {AST, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {QueryDelegate} from './query-delegate.ts';\nimport {QueryImpl} from './query-impl.ts';\nimport type {\n HumanReadable,\n MaterializeOptions,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\nexport function newRunnableQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(\n delegate: QueryDelegate,\n schema: TSchema,\n table: TTable,\n): Query<TTable, TSchema> {\n return new RunnableQueryImpl(\n delegate,\n schema,\n table,\n {table},\n defaultFormat,\n undefined,\n );\n}\n\nexport class RunnableQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n extends QueryImpl<TTable, TSchema, TReturn>\n implements Query<TTable, TSchema, TReturn>\n{\n readonly #delegate: QueryDelegate;\n\n constructor(\n delegate: QueryDelegate,\n schema: TSchema,\n tableName: TTable,\n ast: AST = {table: tableName},\n format: Format = defaultFormat,\n system: System = 'client',\n customQueryID?: CustomQueryID,\n currentJunction?: string,\n ) {\n super(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n (tableName, ast, format, customQueryID, currentJunction) =>\n new RunnableQueryImpl(\n delegate,\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n ),\n );\n this.#delegate = delegate;\n }\n\n override run(options?: RunOptions): Promise<HumanReadable<TReturn>> {\n return this.#delegate.run(this, options);\n }\n\n override preload(options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n return this.#delegate.preload(this, options);\n }\n\n override materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n override materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n override materialize<T>(\n factory?: unknown,\n ttl?: unknown,\n ): T | TypedView<HumanReadable<TReturn>> {\n let actualFactory: ViewFactory<TTable, TSchema, TReturn, T> | undefined;\n let options: MaterializeOptions | undefined;\n\n if (typeof factory === 'function') {\n actualFactory = factory as ViewFactory<TTable, TSchema, TReturn, T>;\n options = {ttl: ttl as TTL | undefined};\n } else {\n actualFactory = undefined;\n options = {ttl: factory as TTL | undefined};\n }\n\n return this.#delegate.materialize(this, actualFactory, options);\n }\n}\n"],"mappings":";;;AAkBA,SAAgB,iBAId,UACA,QACA,OACwB;
|
|
1
|
+
{"version":3,"file":"runnable-query-impl.js","names":["#delegate"],"sources":["../../../../../zql/src/query/runnable-query-impl.ts"],"sourcesContent":["import type {AST, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {QueryDelegate} from './query-delegate.ts';\nimport {QueryImpl} from './query-impl.ts';\nimport type {\n HumanReadable,\n MaterializeOptions,\n PreloadOptions,\n PullRow,\n Query,\n RunOptions,\n} from './query.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\nexport function newRunnableQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(\n delegate: QueryDelegate,\n schema: TSchema,\n table: TTable,\n): Query<TTable, TSchema> {\n return new RunnableQueryImpl(\n delegate,\n schema,\n table,\n {table},\n defaultFormat,\n undefined,\n );\n}\n\nexport class RunnableQueryImpl<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>\n extends QueryImpl<TTable, TSchema, TReturn>\n implements Query<TTable, TSchema, TReturn>\n{\n readonly #delegate: QueryDelegate;\n\n constructor(\n delegate: QueryDelegate,\n schema: TSchema,\n tableName: TTable,\n ast: AST = {table: tableName},\n format: Format = defaultFormat,\n system: System = 'client',\n customQueryID?: CustomQueryID,\n currentJunction?: string,\n ) {\n super(\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n (tableName, ast, format, customQueryID, currentJunction) =>\n new RunnableQueryImpl(\n delegate,\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n ),\n );\n this.#delegate = delegate;\n }\n\n override run(options?: RunOptions): Promise<HumanReadable<TReturn>> {\n return this.#delegate.run(this, options);\n }\n\n override preload(options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n return this.#delegate.preload(this, options);\n }\n\n override materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n override materialize<T>(\n factory: ViewFactory<TTable, TSchema, TReturn, T>,\n ttl?: TTL,\n ): T;\n override materialize<T>(\n factory?: unknown,\n ttl?: unknown,\n ): T | TypedView<HumanReadable<TReturn>> {\n let actualFactory: ViewFactory<TTable, TSchema, TReturn, T> | undefined;\n let options: MaterializeOptions | undefined;\n\n if (typeof factory === 'function') {\n actualFactory = factory as ViewFactory<TTable, TSchema, TReturn, T>;\n options = {ttl: ttl as TTL | undefined};\n } else {\n actualFactory = undefined;\n options = {ttl: factory as TTL | undefined};\n }\n\n return this.#delegate.materialize(this, actualFactory, options);\n }\n}\n"],"mappings":";;;AAkBA,SAAgB,iBAId,UACA,QACA,OACwB;AACxB,QAAO,IAAI,kBACT,UACA,QACA,OACA,EAAC,OAAM,EACP,eACA,KAAA,EACD;;AAGH,IAAa,oBAAb,MAAa,0BAKH,UAEV;CACE;CAEA,YACE,UACA,QACA,WACA,MAAW,EAAC,OAAO,WAAU,EAC7B,SAAiB,eACjB,SAAiB,UACjB,eACA,iBACA;AACA,QACE,QACA,WACA,KACA,QACA,QACA,eACA,kBACC,WAAW,KAAK,QAAQ,eAAe,oBACtC,IAAI,kBACF,UACA,QACA,WACA,KACA,QACA,QACA,eACA,gBACD,CACJ;AACD,QAAA,WAAiB;;CAGnB,IAAa,SAAuD;AAClE,SAAO,MAAA,SAAe,IAAI,MAAM,QAAQ;;CAG1C,QAAiB,SAGf;AACA,SAAO,MAAA,SAAe,QAAQ,MAAM,QAAQ;;CAQ9C,YACE,SACA,KACuC;EACvC,IAAI;EACJ,IAAI;AAEJ,MAAI,OAAO,YAAY,YAAY;AACjC,mBAAgB;AAChB,aAAU,EAAM,KAAuB;SAClC;AACL,mBAAgB,KAAA;AAChB,aAAU,EAAC,KAAK,SAA2B;;AAG7C,SAAO,MAAA,SAAe,YAAY,MAAM,eAAe,QAAQ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-query.js","names":[],"sources":["../../../../../zql/src/query/static-query.ts"],"sourcesContent":["import type {Schema} from '../../../zero-types/src/schema.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport {newQueryImpl, type QueryImpl} from './query-impl.ts';\nimport type {PullRow, Query} from './query.ts';\n\nexport function newStaticQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(schema: TSchema, tableName: TTable): Query<TTable, TSchema, TReturn> {\n return newQueryImpl(\n schema,\n tableName,\n {table: tableName},\n defaultFormat,\n 'permissions',\n );\n}\n\nexport function newExpressionBuilder<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, tableName: TTable) {\n const q = newStaticQuery(schema, tableName);\n return (q as QueryImpl<TTable, TSchema>).expressionBuilder();\n}\n"],"mappings":";;;AAKA,SAAgB,eAId,QAAiB,WAAoD;
|
|
1
|
+
{"version":3,"file":"static-query.js","names":[],"sources":["../../../../../zql/src/query/static-query.ts"],"sourcesContent":["import type {Schema} from '../../../zero-types/src/schema.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport {newQueryImpl, type QueryImpl} from './query-impl.ts';\nimport type {PullRow, Query} from './query.ts';\n\nexport function newStaticQuery<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n TReturn = PullRow<TTable, TSchema>,\n>(schema: TSchema, tableName: TTable): Query<TTable, TSchema, TReturn> {\n return newQueryImpl(\n schema,\n tableName,\n {table: tableName},\n defaultFormat,\n 'permissions',\n );\n}\n\nexport function newExpressionBuilder<\n TTable extends keyof TSchema['tables'] & string,\n TSchema extends Schema,\n>(schema: TSchema, tableName: TTable) {\n const q = newStaticQuery(schema, tableName);\n return (q as QueryImpl<TTable, TSchema>).expressionBuilder();\n}\n"],"mappings":";;;AAKA,SAAgB,eAId,QAAiB,WAAoD;AACrE,QAAO,aACL,QACA,WACA,EAAC,OAAO,WAAU,EAClB,eACA,cACD;;AAGH,SAAgB,qBAGd,QAAiB,WAAmB;AAEpC,QADU,eAAe,QAAQ,UAAU,CACF,mBAAmB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ttl.js","names":[],"sources":["../../../../../zql/src/query/ttl.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\n\nexport type TimeUnit = 's' | 'm' | 'h' | 'd' | 'y';\n\n/**\n * Time To Live. This is used for query expiration.\n * - `forever` means the query will never expire.\n * - `none` means the query will expire immediately.\n * - A number means the query will expire after that many milliseconds.\n * - A negative number means the query will never expire, this is same as 'forever'.\n * - A string like `1s` means the query will expire after that many seconds.\n * - A string like `1m` means the query will expire after that many minutes.\n * - A string like `1h` means the query will expire after that many hours.\n * - A string like `1d` means the query will expire after that many days.\n * - A string like `1y` means the query will expire after that many years.\n */\nexport type TTL = `${number}${TimeUnit}` | 'forever' | 'none' | number;\n\nexport const DEFAULT_TTL: TTL = '5m';\nexport const DEFAULT_TTL_MS = 1_000 * 60 * 5;\n\nexport const DEFAULT_PRELOAD_TTL: TTL = 'none';\nexport const DEFAULT_PRELOAD_TTL_MS = 0;\n\nexport const MAX_TTL: TTL = '10m';\nexport const MAX_TTL_MS = 1_000 * 60 * 10;\n\nconst multiplier = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n y: 365 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport function parseTTL(ttl: TTL): number {\n if (typeof ttl === 'number') {\n return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;\n }\n if (ttl === 'none') {\n return 0;\n }\n if (ttl === 'forever') {\n return -1;\n }\n const multi = multiplier[ttl.at(-1) as TimeUnit];\n return Number(ttl.slice(0, -1)) * multi;\n}\n\nexport function compareTTL(a: TTL, b: TTL): number {\n const ap = parseTTL(a);\n const bp = parseTTL(b);\n if (ap === -1 && bp !== -1) {\n return 1;\n }\n if (ap !== -1 && bp === -1) {\n return -1;\n }\n return ap - bp;\n}\n\nexport function normalizeTTL(ttl: TTL): TTL {\n if (typeof ttl === 'string') {\n return ttl;\n }\n\n if (ttl < 0) {\n return 'forever';\n }\n\n if (ttl === 0) {\n return 'none';\n }\n\n let shortest = ttl.toString();\n const lengthOfNumber = shortest.length;\n for (const unit of ['y', 'd', 'h', 'm', 's'] as const) {\n const multi = multiplier[unit];\n const value = ttl / multi;\n const candidate = `${value}${unit}`;\n if (candidate.length < shortest.length) {\n shortest = candidate;\n }\n }\n\n return (shortest.length < lengthOfNumber ? shortest : ttl) as TTL;\n}\n\nexport function clampTTL(ttl: TTL, lc?: Pick<LogContext, 'warn'>): number {\n const parsedTTL = parseTTL(ttl);\n if (parsedTTL === -1 || parsedTTL > 10 * 60 * 1000) {\n // 10 minutes in milliseconds\n lc?.warn?.(`TTL (${ttl}) is too high, clamping to ${MAX_TTL}`);\n return parseTTL(MAX_TTL);\n }\n return parsedTTL;\n}\n"],"mappings":";AAmBA,IAAa,iBAAiB,MAAQ,KAAK;AAM3C,IAAa,aAAa,MAAQ,KAAK;AAEvC,IAAM,aAAa;CACjB,GAAG;CACH,GAAG,KAAK;CACR,GAAG,OAAU;CACb,GAAG,OAAU,KAAK;CAClB,GAAG,MAAM,KAAK,KAAK,KAAK;
|
|
1
|
+
{"version":3,"file":"ttl.js","names":[],"sources":["../../../../../zql/src/query/ttl.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\n\nexport type TimeUnit = 's' | 'm' | 'h' | 'd' | 'y';\n\n/**\n * Time To Live. This is used for query expiration.\n * - `forever` means the query will never expire.\n * - `none` means the query will expire immediately.\n * - A number means the query will expire after that many milliseconds.\n * - A negative number means the query will never expire, this is same as 'forever'.\n * - A string like `1s` means the query will expire after that many seconds.\n * - A string like `1m` means the query will expire after that many minutes.\n * - A string like `1h` means the query will expire after that many hours.\n * - A string like `1d` means the query will expire after that many days.\n * - A string like `1y` means the query will expire after that many years.\n */\nexport type TTL = `${number}${TimeUnit}` | 'forever' | 'none' | number;\n\nexport const DEFAULT_TTL: TTL = '5m';\nexport const DEFAULT_TTL_MS = 1_000 * 60 * 5;\n\nexport const DEFAULT_PRELOAD_TTL: TTL = 'none';\nexport const DEFAULT_PRELOAD_TTL_MS = 0;\n\nexport const MAX_TTL: TTL = '10m';\nexport const MAX_TTL_MS = 1_000 * 60 * 10;\n\nconst multiplier = {\n s: 1000,\n m: 60 * 1000,\n h: 60 * 60 * 1000,\n d: 24 * 60 * 60 * 1000,\n y: 365 * 24 * 60 * 60 * 1000,\n} as const;\n\nexport function parseTTL(ttl: TTL): number {\n if (typeof ttl === 'number') {\n return Number.isNaN(ttl) ? 0 : !Number.isFinite(ttl) || ttl < 0 ? -1 : ttl;\n }\n if (ttl === 'none') {\n return 0;\n }\n if (ttl === 'forever') {\n return -1;\n }\n const multi = multiplier[ttl.at(-1) as TimeUnit];\n return Number(ttl.slice(0, -1)) * multi;\n}\n\nexport function compareTTL(a: TTL, b: TTL): number {\n const ap = parseTTL(a);\n const bp = parseTTL(b);\n if (ap === -1 && bp !== -1) {\n return 1;\n }\n if (ap !== -1 && bp === -1) {\n return -1;\n }\n return ap - bp;\n}\n\nexport function normalizeTTL(ttl: TTL): TTL {\n if (typeof ttl === 'string') {\n return ttl;\n }\n\n if (ttl < 0) {\n return 'forever';\n }\n\n if (ttl === 0) {\n return 'none';\n }\n\n let shortest = ttl.toString();\n const lengthOfNumber = shortest.length;\n for (const unit of ['y', 'd', 'h', 'm', 's'] as const) {\n const multi = multiplier[unit];\n const value = ttl / multi;\n const candidate = `${value}${unit}`;\n if (candidate.length < shortest.length) {\n shortest = candidate;\n }\n }\n\n return (shortest.length < lengthOfNumber ? shortest : ttl) as TTL;\n}\n\nexport function clampTTL(ttl: TTL, lc?: Pick<LogContext, 'warn'>): number {\n const parsedTTL = parseTTL(ttl);\n if (parsedTTL === -1 || parsedTTL > 10 * 60 * 1000) {\n // 10 minutes in milliseconds\n lc?.warn?.(`TTL (${ttl}) is too high, clamping to ${MAX_TTL}`);\n return parseTTL(MAX_TTL);\n }\n return parsedTTL;\n}\n"],"mappings":";AAmBA,IAAa,iBAAiB,MAAQ,KAAK;AAM3C,IAAa,aAAa,MAAQ,KAAK;AAEvC,IAAM,aAAa;CACjB,GAAG;CACH,GAAG,KAAK;CACR,GAAG,OAAU;CACb,GAAG,OAAU,KAAK;CAClB,GAAG,MAAM,KAAK,KAAK,KAAK;CACzB;AAED,SAAgB,SAAS,KAAkB;AACzC,KAAI,OAAO,QAAQ,SACjB,QAAO,OAAO,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,SAAS,IAAI,IAAI,MAAM,IAAI,KAAK;AAEzE,KAAI,QAAQ,OACV,QAAO;AAET,KAAI,QAAQ,UACV,QAAO;CAET,MAAM,QAAQ,WAAW,IAAI,GAAG,GAAG;AACnC,QAAO,OAAO,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG;;AAGpC,SAAgB,WAAW,GAAQ,GAAgB;CACjD,MAAM,KAAK,SAAS,EAAE;CACtB,MAAM,KAAK,SAAS,EAAE;AACtB,KAAI,OAAO,MAAM,OAAO,GACtB,QAAO;AAET,KAAI,OAAO,MAAM,OAAO,GACtB,QAAO;AAET,QAAO,KAAK;;AAGd,SAAgB,aAAa,KAAe;AAC1C,KAAI,OAAO,QAAQ,SACjB,QAAO;AAGT,KAAI,MAAM,EACR,QAAO;AAGT,KAAI,QAAQ,EACV,QAAO;CAGT,IAAI,WAAW,IAAI,UAAU;CAC7B,MAAM,iBAAiB,SAAS;AAChC,MAAK,MAAM,QAAQ;EAAC;EAAK;EAAK;EAAK;EAAK;EAAI,EAAW;EAGrD,MAAM,YAAY,GADJ,MADA,WAAW,QAEI;AAC7B,MAAI,UAAU,SAAS,SAAS,OAC9B,YAAW;;AAIf,QAAQ,SAAS,SAAS,iBAAiB,WAAW;;AAGxD,SAAgB,SAAS,KAAU,IAAuC;CACxE,MAAM,YAAY,SAAS,IAAI;AAC/B,KAAI,cAAc,MAAM,YAAY,MAAU,KAAM;AAElD,MAAI,OAAO,QAAQ,IAAI,gCAAuC;AAC9D,SAAO,SAAA,MAAiB;;AAE1B,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-input.js","names":[],"sources":["../../../../../zql/src/query/validate-input.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\n\nexport class InputValidationError extends Error {\n readonly result: StandardSchemaV1.FailureResult;\n\n // will get picked up by `getErrorDetails` when mapping to an `ApplicationError`\n readonly details: {\n type: 'InputValidationError';\n result: StandardSchemaV1.FailureResult;\n };\n\n constructor(message: string, result: StandardSchemaV1.FailureResult) {\n super(message);\n this.name = 'InputValidationError';\n this.result = result;\n this.details = {type: 'InputValidationError', result};\n }\n}\n\n/**\n * Validates input using a StandardSchema validator if provided.\n * This is shared validation logic used by both defineQuery and defineMutator.\n *\n * @param name - The name of the query or mutator (for error messages)\n * @param input - The input value to validate\n * @param validator - Optional StandardSchema validator\n * @param kind - Type of definition ('query' or 'mutator') for error messages\n * @returns The validated output (either transformed by validator or input as-is)\n * @throws Error if validation fails or if an async validator is used\n * @internal\n */\nexport function validateInput<TInput, TOutput>(\n name: string,\n input: TInput,\n validator: StandardSchemaV1<TInput, TOutput> | undefined,\n kind: 'query' | 'mutator',\n): TOutput {\n if (!validator) {\n // No validator, so input and output are the same\n return input as unknown as TOutput;\n }\n\n const result = validator['~standard'].validate(input);\n if (result instanceof Promise) {\n throw new Error(\n `Async validators are not supported. ${titleCase(kind)} name ${name}`,\n );\n }\n if (result.issues) {\n throw new InputValidationError(\n `Validation failed for ${kind} ${name}: ${result.issues\n .map(issue => issue.message)\n .join(', ')}`,\n result,\n );\n }\n return result.value;\n}\n\nfunction titleCase(kind: string): string {\n return kind.charAt(0).toUpperCase() + kind.slice(1);\n}\n"],"mappings":";AAEA,IAAa,uBAAb,cAA0C,MAAM;CAC9C;CAGA;CAKA,YAAY,SAAiB,QAAwC;
|
|
1
|
+
{"version":3,"file":"validate-input.js","names":[],"sources":["../../../../../zql/src/query/validate-input.ts"],"sourcesContent":["import type {StandardSchemaV1} from '@standard-schema/spec';\n\nexport class InputValidationError extends Error {\n readonly result: StandardSchemaV1.FailureResult;\n\n // will get picked up by `getErrorDetails` when mapping to an `ApplicationError`\n readonly details: {\n type: 'InputValidationError';\n result: StandardSchemaV1.FailureResult;\n };\n\n constructor(message: string, result: StandardSchemaV1.FailureResult) {\n super(message);\n this.name = 'InputValidationError';\n this.result = result;\n this.details = {type: 'InputValidationError', result};\n }\n}\n\n/**\n * Validates input using a StandardSchema validator if provided.\n * This is shared validation logic used by both defineQuery and defineMutator.\n *\n * @param name - The name of the query or mutator (for error messages)\n * @param input - The input value to validate\n * @param validator - Optional StandardSchema validator\n * @param kind - Type of definition ('query' or 'mutator') for error messages\n * @returns The validated output (either transformed by validator or input as-is)\n * @throws Error if validation fails or if an async validator is used\n * @internal\n */\nexport function validateInput<TInput, TOutput>(\n name: string,\n input: TInput,\n validator: StandardSchemaV1<TInput, TOutput> | undefined,\n kind: 'query' | 'mutator',\n): TOutput {\n if (!validator) {\n // No validator, so input and output are the same\n return input as unknown as TOutput;\n }\n\n const result = validator['~standard'].validate(input);\n if (result instanceof Promise) {\n throw new Error(\n `Async validators are not supported. ${titleCase(kind)} name ${name}`,\n );\n }\n if (result.issues) {\n throw new InputValidationError(\n `Validation failed for ${kind} ${name}: ${result.issues\n .map(issue => issue.message)\n .join(', ')}`,\n result,\n );\n }\n return result.value;\n}\n\nfunction titleCase(kind: string): string {\n return kind.charAt(0).toUpperCase() + kind.slice(1);\n}\n"],"mappings":";AAEA,IAAa,uBAAb,cAA0C,MAAM;CAC9C;CAGA;CAKA,YAAY,SAAiB,QAAwC;AACnE,QAAM,QAAQ;AACd,OAAK,OAAO;AACZ,OAAK,SAAS;AACd,OAAK,UAAU;GAAC,MAAM;GAAwB;GAAO;;;;;;;;;;;;;;;AAgBzD,SAAgB,cACd,MACA,OACA,WACA,MACS;AACT,KAAI,CAAC,UAEH,QAAO;CAGT,MAAM,SAAS,UAAU,aAAa,SAAS,MAAM;AACrD,KAAI,kBAAkB,QACpB,OAAM,IAAI,MACR,uCAAuC,UAAU,KAAK,CAAC,QAAQ,OAChE;AAEH,KAAI,OAAO,OACT,OAAM,IAAI,qBACR,yBAAyB,KAAK,GAAG,KAAK,IAAI,OAAO,OAC9C,KAAI,UAAS,MAAM,QAAQ,CAC3B,KAAK,KAAK,IACb,OACD;AAEH,QAAO,OAAO;;AAGhB,SAAS,UAAU,MAAsB;AACvC,QAAO,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-storage.js","names":["#stmts","#options","#db","#checkpoint","#maybeCheckpoint","#numWrites","#scan","#get","#set","#del"],"sources":["../../../../zqlite/src/database-storage.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JSONValue} from '../../shared/src/json.ts';\nimport type {Storage} from '../../zql/src/ivm/operator.ts';\nimport type {Stream} from '../../zql/src/ivm/stream.ts';\nimport type {Statement} from './db.ts';\nimport {Database} from './db.ts';\n\nexport interface ClientGroupStorage {\n /** Creates a {@link Storage} instance for a single operator. */\n createStorage(): Storage;\n\n /** Deletes all storage for the client group. */\n destroy(): void;\n}\n\ntype Statements = {\n get: Statement;\n set: Statement;\n del: Statement;\n scan: Statement;\n clear: Statement;\n commit: Statement;\n begin: Statement;\n};\n\n// Exported for testing.\nexport const CREATE_STORAGE_TABLE = `\n CREATE TABLE storage (\n clientGroupID TEXT,\n op NUMBER,\n key TEXT,\n val TEXT,\n PRIMARY KEY(clientGroupID, op, key)\n )\n `;\n\nconst defaultOptions = {\n commitInterval: 5_000,\n compactionThresholdBytes: 50 * 1024 * 1024,\n};\n\nexport class DatabaseStorage {\n static create(\n lc: LogContext,\n path: string,\n options = defaultOptions,\n ): DatabaseStorage {\n // SQLite is used for ephemeral storage (i.e. similar to RAM) that can spill to\n // disk to avoid consuming too much memory. Each worker thread gets its own\n // database (file) and acts as the single reader/writer of the DB, so\n // `locking_mode` is set to `EXCLUSIVE` for performance. Similarly, since\n // durability is not important, `synchronous` is set to `OFF` for performance.\n const db = new Database(lc, path);\n db.unsafeMode(true); // Allows journal_mode = OFF\n db.pragma('locking_mode = EXCLUSIVE');\n db.pragma('foreign_keys = OFF');\n db.pragma('journal_mode = OFF');\n db.pragma('synchronous = OFF');\n db.pragma('auto_vacuum = INCREMENTAL');\n\n db.prepare(CREATE_STORAGE_TABLE).run();\n lc.debug?.(`Created DatabaseStorage backed by ${path}`);\n return new DatabaseStorage(db, options);\n }\n\n readonly #stmts: Statements;\n readonly #options: typeof defaultOptions;\n readonly #db: Database;\n #numWrites = 0;\n\n constructor(db: Database, options = defaultOptions) {\n this.#stmts = {\n get: db.prepare(`\n SELECT val FROM storage WHERE\n clientGroupID = ? AND op = ? AND key = ?\n `),\n set: db.prepare(`\n INSERT INTO storage (clientGroupID, op, key, val)\n VALUES(?, ?, ?, ?)\n ON CONFLICT(clientGroupID, op, key) \n DO \n UPDATE SET val = excluded.val\n `),\n del: db.prepare(`\n DELETE FROM storage WHERE\n clientGroupID = ? AND op = ? AND key = ?\n `),\n scan: db.prepare(`\n SELECT key, val FROM storage WHERE\n clientGroupID = ? AND op = ? AND key >= ?\n `),\n clear: db.prepare(`\n DELETE FROM storage WHERE clientGroupID = ?\n `),\n commit: db.prepare('COMMIT'),\n begin: db.prepare('BEGIN'),\n };\n this.#stmts.begin.run();\n this.#options = options;\n this.#db = db;\n }\n\n close() {\n this.#checkpoint();\n this.#db.close();\n }\n\n #get(\n cgID: string,\n opID: number,\n key: string,\n def?: JSONValue,\n ): JSONValue | undefined {\n this.#maybeCheckpoint();\n const row = this.#stmts.get.get<{val: string}>(cgID, opID, key);\n return row ? JSON.parse(row.val) : def;\n }\n\n #set(cgID: string, opID: number, key: string, val: JSONValue) {\n this.#maybeCheckpoint();\n this.#stmts.set.run(cgID, opID, key, JSON.stringify(val));\n }\n\n #del(cgID: string, opID: number, key: string) {\n this.#maybeCheckpoint();\n this.#stmts.del.run(cgID, opID, key);\n }\n\n /**\n * We don't need to commit every single write to the DB\n * since we're not concerned with durability.\n * Waiting on commits can be expensive, so we commit\n * every `COMMIT_INTERVAL` writes.\n */\n #maybeCheckpoint() {\n if (++this.#numWrites >= this.#options.commitInterval) {\n this.#checkpoint();\n }\n }\n\n #checkpoint() {\n this.#stmts.commit.run();\n this.#stmts.begin.run();\n this.#numWrites = 0;\n }\n\n *#scan(\n cgID: string,\n opID: number,\n opts: {prefix: string} = {prefix: ''},\n ): Stream<[string, JSONValue]> {\n const {prefix} = opts;\n for (const {key, val} of this.#stmts.scan.iterate<{\n key: string;\n val: string;\n }>(cgID, opID, prefix)) {\n if (!key.startsWith(prefix)) {\n return;\n }\n yield [key, JSON.parse(val)];\n }\n }\n\n createClientGroupStorage(cgID: string): ClientGroupStorage {\n const destroy = () => {\n this.#stmts.clear.run(cgID);\n this.#checkpoint();\n this.#db.compact(this.#options.compactionThresholdBytes);\n };\n this.#stmts.clear.run(cgID);\n\n let nextOpID = 1;\n return {\n createStorage: () => {\n const opID = nextOpID++;\n return {\n get: (key, def?) => this.#get(cgID, opID, key, def),\n set: (key, val) => this.#set(cgID, opID, key, val),\n del: key => this.#del(cgID, opID, key),\n scan: opts => this.#scan(cgID, opID, opts),\n };\n },\n\n destroy,\n };\n }\n}\n"],"mappings":";;AA0BA,IAAa,uBAAuB;;;;;;;;;AAUpC,IAAM,iBAAiB;CACrB,gBAAgB;CAChB,0BAA0B,KAAK,OAAO;
|
|
1
|
+
{"version":3,"file":"database-storage.js","names":["#stmts","#options","#db","#checkpoint","#maybeCheckpoint","#numWrites","#scan","#get","#set","#del"],"sources":["../../../../zqlite/src/database-storage.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {JSONValue} from '../../shared/src/json.ts';\nimport type {Storage} from '../../zql/src/ivm/operator.ts';\nimport type {Stream} from '../../zql/src/ivm/stream.ts';\nimport type {Statement} from './db.ts';\nimport {Database} from './db.ts';\n\nexport interface ClientGroupStorage {\n /** Creates a {@link Storage} instance for a single operator. */\n createStorage(): Storage;\n\n /** Deletes all storage for the client group. */\n destroy(): void;\n}\n\ntype Statements = {\n get: Statement;\n set: Statement;\n del: Statement;\n scan: Statement;\n clear: Statement;\n commit: Statement;\n begin: Statement;\n};\n\n// Exported for testing.\nexport const CREATE_STORAGE_TABLE = `\n CREATE TABLE storage (\n clientGroupID TEXT,\n op NUMBER,\n key TEXT,\n val TEXT,\n PRIMARY KEY(clientGroupID, op, key)\n )\n `;\n\nconst defaultOptions = {\n commitInterval: 5_000,\n compactionThresholdBytes: 50 * 1024 * 1024,\n};\n\nexport class DatabaseStorage {\n static create(\n lc: LogContext,\n path: string,\n options = defaultOptions,\n ): DatabaseStorage {\n // SQLite is used for ephemeral storage (i.e. similar to RAM) that can spill to\n // disk to avoid consuming too much memory. Each worker thread gets its own\n // database (file) and acts as the single reader/writer of the DB, so\n // `locking_mode` is set to `EXCLUSIVE` for performance. Similarly, since\n // durability is not important, `synchronous` is set to `OFF` for performance.\n const db = new Database(lc, path);\n db.unsafeMode(true); // Allows journal_mode = OFF\n db.pragma('locking_mode = EXCLUSIVE');\n db.pragma('foreign_keys = OFF');\n db.pragma('journal_mode = OFF');\n db.pragma('synchronous = OFF');\n db.pragma('auto_vacuum = INCREMENTAL');\n\n db.prepare(CREATE_STORAGE_TABLE).run();\n lc.debug?.(`Created DatabaseStorage backed by ${path}`);\n return new DatabaseStorage(db, options);\n }\n\n readonly #stmts: Statements;\n readonly #options: typeof defaultOptions;\n readonly #db: Database;\n #numWrites = 0;\n\n constructor(db: Database, options = defaultOptions) {\n this.#stmts = {\n get: db.prepare(`\n SELECT val FROM storage WHERE\n clientGroupID = ? AND op = ? AND key = ?\n `),\n set: db.prepare(`\n INSERT INTO storage (clientGroupID, op, key, val)\n VALUES(?, ?, ?, ?)\n ON CONFLICT(clientGroupID, op, key) \n DO \n UPDATE SET val = excluded.val\n `),\n del: db.prepare(`\n DELETE FROM storage WHERE\n clientGroupID = ? AND op = ? AND key = ?\n `),\n scan: db.prepare(`\n SELECT key, val FROM storage WHERE\n clientGroupID = ? AND op = ? AND key >= ?\n `),\n clear: db.prepare(`\n DELETE FROM storage WHERE clientGroupID = ?\n `),\n commit: db.prepare('COMMIT'),\n begin: db.prepare('BEGIN'),\n };\n this.#stmts.begin.run();\n this.#options = options;\n this.#db = db;\n }\n\n close() {\n this.#checkpoint();\n this.#db.close();\n }\n\n #get(\n cgID: string,\n opID: number,\n key: string,\n def?: JSONValue,\n ): JSONValue | undefined {\n this.#maybeCheckpoint();\n const row = this.#stmts.get.get<{val: string}>(cgID, opID, key);\n return row ? JSON.parse(row.val) : def;\n }\n\n #set(cgID: string, opID: number, key: string, val: JSONValue) {\n this.#maybeCheckpoint();\n this.#stmts.set.run(cgID, opID, key, JSON.stringify(val));\n }\n\n #del(cgID: string, opID: number, key: string) {\n this.#maybeCheckpoint();\n this.#stmts.del.run(cgID, opID, key);\n }\n\n /**\n * We don't need to commit every single write to the DB\n * since we're not concerned with durability.\n * Waiting on commits can be expensive, so we commit\n * every `COMMIT_INTERVAL` writes.\n */\n #maybeCheckpoint() {\n if (++this.#numWrites >= this.#options.commitInterval) {\n this.#checkpoint();\n }\n }\n\n #checkpoint() {\n this.#stmts.commit.run();\n this.#stmts.begin.run();\n this.#numWrites = 0;\n }\n\n *#scan(\n cgID: string,\n opID: number,\n opts: {prefix: string} = {prefix: ''},\n ): Stream<[string, JSONValue]> {\n const {prefix} = opts;\n for (const {key, val} of this.#stmts.scan.iterate<{\n key: string;\n val: string;\n }>(cgID, opID, prefix)) {\n if (!key.startsWith(prefix)) {\n return;\n }\n yield [key, JSON.parse(val)];\n }\n }\n\n createClientGroupStorage(cgID: string): ClientGroupStorage {\n const destroy = () => {\n this.#stmts.clear.run(cgID);\n this.#checkpoint();\n this.#db.compact(this.#options.compactionThresholdBytes);\n };\n this.#stmts.clear.run(cgID);\n\n let nextOpID = 1;\n return {\n createStorage: () => {\n const opID = nextOpID++;\n return {\n get: (key, def?) => this.#get(cgID, opID, key, def),\n set: (key, val) => this.#set(cgID, opID, key, val),\n del: key => this.#del(cgID, opID, key),\n scan: opts => this.#scan(cgID, opID, opts),\n };\n },\n\n destroy,\n };\n }\n}\n"],"mappings":";;AA0BA,IAAa,uBAAuB;;;;;;;;;AAUpC,IAAM,iBAAiB;CACrB,gBAAgB;CAChB,0BAA0B,KAAK,OAAO;CACvC;AAED,IAAa,kBAAb,MAAa,gBAAgB;CAC3B,OAAO,OACL,IACA,MACA,UAAU,gBACO;EAMjB,MAAM,KAAK,IAAI,SAAS,IAAI,KAAK;AACjC,KAAG,WAAW,KAAK;AACnB,KAAG,OAAO,2BAA2B;AACrC,KAAG,OAAO,qBAAqB;AAC/B,KAAG,OAAO,qBAAqB;AAC/B,KAAG,OAAO,oBAAoB;AAC9B,KAAG,OAAO,4BAA4B;AAEtC,KAAG,QAAQ,qBAAqB,CAAC,KAAK;AACtC,KAAG,QAAQ,qCAAqC,OAAO;AACvD,SAAO,IAAI,gBAAgB,IAAI,QAAQ;;CAGzC;CACA;CACA;CACA,aAAa;CAEb,YAAY,IAAc,UAAU,gBAAgB;AAClD,QAAA,QAAc;GACZ,KAAK,GAAG,QAAQ;;;QAGd;GACF,KAAK,GAAG,QAAQ;;;;;;QAMd;GACF,KAAK,GAAG,QAAQ;;;QAGd;GACF,MAAM,GAAG,QAAQ;;;QAGf;GACF,OAAO,GAAG,QAAQ;;QAEhB;GACF,QAAQ,GAAG,QAAQ,SAAS;GAC5B,OAAO,GAAG,QAAQ,QAAQ;GAC3B;AACD,QAAA,MAAY,MAAM,KAAK;AACvB,QAAA,UAAgB;AAChB,QAAA,KAAW;;CAGb,QAAQ;AACN,QAAA,YAAkB;AAClB,QAAA,GAAS,OAAO;;CAGlB,KACE,MACA,MACA,KACA,KACuB;AACvB,QAAA,iBAAuB;EACvB,MAAM,MAAM,MAAA,MAAY,IAAI,IAAmB,MAAM,MAAM,IAAI;AAC/D,SAAO,MAAM,KAAK,MAAM,IAAI,IAAI,GAAG;;CAGrC,KAAK,MAAc,MAAc,KAAa,KAAgB;AAC5D,QAAA,iBAAuB;AACvB,QAAA,MAAY,IAAI,IAAI,MAAM,MAAM,KAAK,KAAK,UAAU,IAAI,CAAC;;CAG3D,KAAK,MAAc,MAAc,KAAa;AAC5C,QAAA,iBAAuB;AACvB,QAAA,MAAY,IAAI,IAAI,MAAM,MAAM,IAAI;;;;;;;;CAStC,mBAAmB;AACjB,MAAI,EAAE,MAAA,aAAmB,MAAA,QAAc,eACrC,OAAA,YAAkB;;CAItB,cAAc;AACZ,QAAA,MAAY,OAAO,KAAK;AACxB,QAAA,MAAY,MAAM,KAAK;AACvB,QAAA,YAAkB;;CAGpB,EAAA,KACE,MACA,MACA,OAAyB,EAAC,QAAQ,IAAG,EACR;EAC7B,MAAM,EAAC,WAAU;AACjB,OAAK,MAAM,EAAC,KAAK,SAAQ,MAAA,MAAY,KAAK,QAGvC,MAAM,MAAM,OAAO,EAAE;AACtB,OAAI,CAAC,IAAI,WAAW,OAAO,CACzB;AAEF,SAAM,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC;;;CAIhC,yBAAyB,MAAkC;EACzD,MAAM,gBAAgB;AACpB,SAAA,MAAY,MAAM,IAAI,KAAK;AAC3B,SAAA,YAAkB;AAClB,SAAA,GAAS,QAAQ,MAAA,QAAc,yBAAyB;;AAE1D,QAAA,MAAY,MAAM,IAAI,KAAK;EAE3B,IAAI,WAAW;AACf,SAAO;GACL,qBAAqB;IACnB,MAAM,OAAO;AACb,WAAO;KACL,MAAM,KAAK,QAAS,MAAA,IAAU,MAAM,MAAM,KAAK,IAAI;KACnD,MAAM,KAAK,QAAQ,MAAA,IAAU,MAAM,MAAM,KAAK,IAAI;KAClD,MAAK,QAAO,MAAA,IAAU,MAAM,MAAM,IAAI;KACtC,OAAM,SAAQ,MAAA,KAAW,MAAM,MAAM,KAAK;KAC3C;;GAGH;GACD"}
|
package/out/zqlite/src/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","names":["#db","#threshold","#lc","#pageSize","#run","#bytes","#stmt","#attrs","#it","#start","#sqliteRowTimeSum","#log"],"sources":["../../../../zqlite/src/db.ts"],"sourcesContent":["import {trace, type Attributes} from '@opentelemetry/api';\nimport type {LogContext} from '@rocicorp/logger';\nimport SQLite3Database, {\n SqliteError,\n type RunResult,\n type Statement as SQLite3Statement,\n} from '@rocicorp/zero-sqlite3';\nimport {manualSpan} from '../../otel/src/span.ts';\nimport {version} from '../../otel/src/version.ts';\n\nconst tracer = trace.getTracer('view-syncer', version);\n\n// https://www.sqlite.org/pragma.html#pragma_auto_vacuum\nconst AUTO_VACUUM_INCREMENTAL = 2;\n\nconst MB = 1024 * 1024;\n\nfunction mb(bytes: number): string {\n return (bytes / MB).toFixed(2);\n}\n\nexport class Database implements Disposable {\n readonly #db: SQLite3Database.Database;\n readonly #threshold: number;\n readonly #lc: LogContext;\n readonly #pageSize: number;\n\n constructor(\n lc: LogContext,\n path: string,\n options?: SQLite3Database.Options,\n slowQueryThreshold = 100,\n ) {\n try {\n this.#lc = lc.withContext('class', 'Database').withContext('path', path);\n this.#db = new SQLite3Database(path, options);\n this.#threshold = slowQueryThreshold;\n\n const [{page_size: pageSize}] = this.pragma<{page_size: number}>(\n 'page_size',\n );\n this.#pageSize = pageSize;\n } catch (cause) {\n throw new DatabaseInitError(String(cause), {cause});\n }\n }\n\n prepare(sql: string): Statement {\n return this.#run(\n 'prepare',\n sql,\n () =>\n new Statement(\n this.#lc.withContext('sql', sql),\n {class: 'Statement', sql},\n this.#db.prepare(sql),\n this.#threshold,\n ),\n );\n }\n\n exec(sql: string): void {\n this.#run('exec', sql, () => this.#db.exec(sql));\n }\n\n pragma<T = unknown>(sql: string): T[] {\n return this.#run<T[]>('pragma', sql, () => this.#db.pragma(sql) as T[]);\n }\n\n #bytes(pages: number) {\n return pages * this.#pageSize;\n }\n\n compact(freeableBytesThreshold: number) {\n const [{freelist_count: freelistCount}] = this.pragma<{\n freelist_count: number;\n }>('freelist_count');\n\n const freeable = this.#bytes(freelistCount);\n if (freeable < freeableBytesThreshold) {\n this.#lc.debug?.(\n `Not compacting ${this.#db.name}: ${mb(freeable)} freeable MB`,\n );\n return;\n }\n const [{auto_vacuum: autoVacuumMode}] = this.pragma<{auto_vacuum: number}>(\n 'auto_vacuum',\n );\n if (autoVacuumMode !== AUTO_VACUUM_INCREMENTAL) {\n this.#lc.warn?.(\n `Cannot compact ${mb(freeable)} MB of ` +\n `${this.#db.name} because AUTO_VACUUM mode is ${autoVacuumMode}.`,\n );\n return;\n }\n const start = Date.now();\n const [{page_count: pageCountBefore}] = this.pragma<{page_count: number}>(\n 'page_count',\n );\n\n this.pragma('incremental_vacuum');\n\n const [{page_count: pageCountAfter}] = this.pragma<{page_count: number}>(\n 'page_count',\n );\n\n this.#lc.info?.(\n `Compacted ${this.#db.name} from ` +\n `${mb(this.#bytes(pageCountBefore))} MB to ` +\n `${mb(this.#bytes(pageCountAfter))} MB ` +\n `(${Date.now() - start} ms)`,\n );\n }\n\n unsafeMode(unsafe: boolean) {\n this.#db.unsafeMode(unsafe);\n }\n\n #run<T>(method: string, sql: string, fn: () => T): T {\n const start = performance.now();\n try {\n return fn();\n } catch (e) {\n if (e instanceof SqliteError) {\n e.message += `: ${sql}`;\n }\n throw e;\n } finally {\n logIfSlow(\n this.#lc.withContext('method', method),\n performance.now() - start,\n {method},\n this.#threshold,\n );\n }\n }\n\n close(): void {\n const start = Date.now();\n if (!this.#db.readonly) {\n try {\n this.#db.pragma('optimize');\n const elapsed = Date.now() - start;\n if (elapsed > 2) {\n this.#lc.debug?.(`PRAGMA optimized (${elapsed} ms)`);\n }\n } catch (e) {\n this.#lc.warn?.('error running PRAGMA optimize', e);\n }\n }\n this.#db.close();\n }\n\n transaction<T>(fn: () => T): T {\n return this.#db.transaction(fn)();\n }\n\n get name() {\n return this.#db.name;\n }\n\n get inTransaction() {\n return this.#db.inTransaction;\n }\n\n [Symbol.dispose](): void {\n this.close();\n }\n}\n\nexport class Statement {\n readonly #stmt: SQLite3Statement;\n readonly #lc: LogContext;\n readonly #threshold: number;\n readonly #attrs: Attributes;\n readonly scanStatus: SQLite3Statement['scanStatusV2'];\n readonly scanStatusReset: SQLite3Statement['scanStatusReset'];\n\n constructor(\n lc: LogContext,\n attrs: Attributes,\n stmt: SQLite3Statement,\n threshold: number,\n ) {\n this.#lc = lc.withContext('class', 'Statement');\n this.#attrs = attrs;\n this.#stmt = stmt;\n this.#threshold = threshold;\n this.scanStatus = this.#stmt.scanStatusV2.bind(this.#stmt);\n this.scanStatusReset = this.#stmt.scanStatusReset.bind(this.#stmt);\n }\n\n safeIntegers(useBigInt: boolean): this {\n this.#stmt.safeIntegers(useBigInt);\n return this;\n }\n\n run(...params: unknown[]): RunResult {\n const start = performance.now();\n const ret = this.#stmt.run(...params);\n logIfSlow(\n this.#lc.withContext('method', 'run'),\n performance.now() - start,\n {...this.#attrs, method: 'run'},\n this.#threshold,\n );\n return ret;\n }\n\n get<T>(...params: unknown[]): T {\n const start = performance.now();\n const ret = this.#stmt.get(...params);\n logIfSlow(\n this.#lc.withContext('method', 'get'),\n performance.now() - start,\n {...this.#attrs, method: 'get'},\n this.#threshold,\n );\n return ret as T;\n }\n\n all<T>(...params: unknown[]): T[] {\n const start = performance.now();\n const ret = this.#stmt.all(...params);\n logIfSlow(\n this.#lc.withContext('method', 'all'),\n performance.now() - start,\n {...this.#attrs, method: 'all'},\n this.#threshold,\n );\n return ret as T[];\n }\n\n iterate<T>(...params: unknown[]): IterableIterator<T> {\n return new LoggingIterableIterator(\n this.#lc.withContext('method', 'iterate'),\n this.#attrs,\n this.#stmt.iterate(...params),\n this.#threshold,\n ) as IterableIterator<T>;\n }\n}\n\nclass LoggingIterableIterator<T> implements IterableIterator<T> {\n readonly #lc: LogContext;\n readonly #it: IterableIterator<T>;\n readonly #threshold: number;\n readonly #attrs: Attributes;\n #start: number;\n #sqliteRowTimeSum: number;\n\n constructor(\n lc: LogContext,\n attrs: Attributes,\n it: IterableIterator<T>,\n slowQueryThreshold: number,\n ) {\n this.#lc = lc;\n this.#attrs = attrs;\n this.#it = it;\n this.#start = performance.now();\n this.#threshold = slowQueryThreshold;\n this.#sqliteRowTimeSum = 0;\n }\n\n next(): IteratorResult<T> {\n const start = performance.now();\n const ret = this.#it.next();\n const elapsed = performance.now() - start;\n this.#sqliteRowTimeSum += elapsed;\n if (ret.done) {\n this.#log();\n }\n return ret;\n }\n\n #log() {\n logIfSlow(\n this.#lc.withContext('type', 'total'),\n performance.now() - this.#start,\n {...this.#attrs, type: 'total', method: 'iterate'},\n this.#threshold,\n );\n logIfSlow(\n this.#lc.withContext('type', 'sqlite'),\n this.#sqliteRowTimeSum,\n {...this.#attrs, type: 'sqlite', method: 'iterate'},\n this.#threshold,\n );\n }\n\n [Symbol.iterator](): IterableIterator<T> {\n return this;\n }\n\n return(): IteratorResult<T> {\n this.#log();\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return this.#it.return?.() as any;\n }\n\n throw(e: unknown): IteratorResult<T> {\n this.#log();\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return this.#it.throw?.(e) as any;\n }\n}\n\nfunction logIfSlow(\n lc: LogContext,\n elapsed: number,\n attrs: Attributes,\n threshold: number,\n): void {\n if (elapsed >= threshold) {\n for (const [key, value] of Object.entries(attrs)) {\n lc = lc.withContext(key, value);\n }\n lc.warn?.('Slow SQLite query', elapsed);\n manualSpan(tracer, 'db.slow-query', elapsed, attrs);\n }\n}\n\n/**\n * An error indicating that the Database failed to open. This essentially\n * wraps the TypeError thrown by the better-sqlite3 package with something\n * more specific.\n */\nexport class DatabaseInitError extends Error {}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"db.js","names":["#db","#threshold","#lc","#pageSize","#run","#bytes","#stmt","#attrs","#it","#start","#sqliteRowTimeSum","#log"],"sources":["../../../../zqlite/src/db.ts"],"sourcesContent":["import {trace, type Attributes} from '@opentelemetry/api';\nimport type {LogContext} from '@rocicorp/logger';\nimport SQLite3Database, {\n SqliteError,\n type RunResult,\n type Statement as SQLite3Statement,\n} from '@rocicorp/zero-sqlite3';\nimport {manualSpan} from '../../otel/src/span.ts';\nimport {version} from '../../otel/src/version.ts';\n\nconst tracer = trace.getTracer('view-syncer', version);\n\n// https://www.sqlite.org/pragma.html#pragma_auto_vacuum\nconst AUTO_VACUUM_INCREMENTAL = 2;\n\nconst MB = 1024 * 1024;\n\nfunction mb(bytes: number): string {\n return (bytes / MB).toFixed(2);\n}\n\nexport class Database implements Disposable {\n readonly #db: SQLite3Database.Database;\n readonly #threshold: number;\n readonly #lc: LogContext;\n readonly #pageSize: number;\n\n constructor(\n lc: LogContext,\n path: string,\n options?: SQLite3Database.Options,\n slowQueryThreshold = 100,\n ) {\n try {\n this.#lc = lc.withContext('class', 'Database').withContext('path', path);\n this.#db = new SQLite3Database(path, options);\n this.#threshold = slowQueryThreshold;\n\n const [{page_size: pageSize}] = this.pragma<{page_size: number}>(\n 'page_size',\n );\n this.#pageSize = pageSize;\n } catch (cause) {\n throw new DatabaseInitError(String(cause), {cause});\n }\n }\n\n prepare(sql: string): Statement {\n return this.#run(\n 'prepare',\n sql,\n () =>\n new Statement(\n this.#lc.withContext('sql', sql),\n {class: 'Statement', sql},\n this.#db.prepare(sql),\n this.#threshold,\n ),\n );\n }\n\n exec(sql: string): void {\n this.#run('exec', sql, () => this.#db.exec(sql));\n }\n\n pragma<T = unknown>(sql: string): T[] {\n return this.#run<T[]>('pragma', sql, () => this.#db.pragma(sql) as T[]);\n }\n\n #bytes(pages: number) {\n return pages * this.#pageSize;\n }\n\n compact(freeableBytesThreshold: number) {\n const [{freelist_count: freelistCount}] = this.pragma<{\n freelist_count: number;\n }>('freelist_count');\n\n const freeable = this.#bytes(freelistCount);\n if (freeable < freeableBytesThreshold) {\n this.#lc.debug?.(\n `Not compacting ${this.#db.name}: ${mb(freeable)} freeable MB`,\n );\n return;\n }\n const [{auto_vacuum: autoVacuumMode}] = this.pragma<{auto_vacuum: number}>(\n 'auto_vacuum',\n );\n if (autoVacuumMode !== AUTO_VACUUM_INCREMENTAL) {\n this.#lc.warn?.(\n `Cannot compact ${mb(freeable)} MB of ` +\n `${this.#db.name} because AUTO_VACUUM mode is ${autoVacuumMode}.`,\n );\n return;\n }\n const start = Date.now();\n const [{page_count: pageCountBefore}] = this.pragma<{page_count: number}>(\n 'page_count',\n );\n\n this.pragma('incremental_vacuum');\n\n const [{page_count: pageCountAfter}] = this.pragma<{page_count: number}>(\n 'page_count',\n );\n\n this.#lc.info?.(\n `Compacted ${this.#db.name} from ` +\n `${mb(this.#bytes(pageCountBefore))} MB to ` +\n `${mb(this.#bytes(pageCountAfter))} MB ` +\n `(${Date.now() - start} ms)`,\n );\n }\n\n unsafeMode(unsafe: boolean) {\n this.#db.unsafeMode(unsafe);\n }\n\n #run<T>(method: string, sql: string, fn: () => T): T {\n const start = performance.now();\n try {\n return fn();\n } catch (e) {\n if (e instanceof SqliteError) {\n e.message += `: ${sql}`;\n }\n throw e;\n } finally {\n logIfSlow(\n this.#lc.withContext('method', method),\n performance.now() - start,\n {method},\n this.#threshold,\n );\n }\n }\n\n close(): void {\n const start = Date.now();\n if (!this.#db.readonly) {\n try {\n this.#db.pragma('optimize');\n const elapsed = Date.now() - start;\n if (elapsed > 2) {\n this.#lc.debug?.(`PRAGMA optimized (${elapsed} ms)`);\n }\n } catch (e) {\n this.#lc.warn?.('error running PRAGMA optimize', e);\n }\n }\n this.#db.close();\n }\n\n transaction<T>(fn: () => T): T {\n return this.#db.transaction(fn)();\n }\n\n get name() {\n return this.#db.name;\n }\n\n get inTransaction() {\n return this.#db.inTransaction;\n }\n\n [Symbol.dispose](): void {\n this.close();\n }\n}\n\nexport class Statement {\n readonly #stmt: SQLite3Statement;\n readonly #lc: LogContext;\n readonly #threshold: number;\n readonly #attrs: Attributes;\n readonly scanStatus: SQLite3Statement['scanStatusV2'];\n readonly scanStatusReset: SQLite3Statement['scanStatusReset'];\n\n constructor(\n lc: LogContext,\n attrs: Attributes,\n stmt: SQLite3Statement,\n threshold: number,\n ) {\n this.#lc = lc.withContext('class', 'Statement');\n this.#attrs = attrs;\n this.#stmt = stmt;\n this.#threshold = threshold;\n this.scanStatus = this.#stmt.scanStatusV2.bind(this.#stmt);\n this.scanStatusReset = this.#stmt.scanStatusReset.bind(this.#stmt);\n }\n\n safeIntegers(useBigInt: boolean): this {\n this.#stmt.safeIntegers(useBigInt);\n return this;\n }\n\n run(...params: unknown[]): RunResult {\n const start = performance.now();\n const ret = this.#stmt.run(...params);\n logIfSlow(\n this.#lc.withContext('method', 'run'),\n performance.now() - start,\n {...this.#attrs, method: 'run'},\n this.#threshold,\n );\n return ret;\n }\n\n get<T>(...params: unknown[]): T {\n const start = performance.now();\n const ret = this.#stmt.get(...params);\n logIfSlow(\n this.#lc.withContext('method', 'get'),\n performance.now() - start,\n {...this.#attrs, method: 'get'},\n this.#threshold,\n );\n return ret as T;\n }\n\n all<T>(...params: unknown[]): T[] {\n const start = performance.now();\n const ret = this.#stmt.all(...params);\n logIfSlow(\n this.#lc.withContext('method', 'all'),\n performance.now() - start,\n {...this.#attrs, method: 'all'},\n this.#threshold,\n );\n return ret as T[];\n }\n\n iterate<T>(...params: unknown[]): IterableIterator<T> {\n return new LoggingIterableIterator(\n this.#lc.withContext('method', 'iterate'),\n this.#attrs,\n this.#stmt.iterate(...params),\n this.#threshold,\n ) as IterableIterator<T>;\n }\n}\n\nclass LoggingIterableIterator<T> implements IterableIterator<T> {\n readonly #lc: LogContext;\n readonly #it: IterableIterator<T>;\n readonly #threshold: number;\n readonly #attrs: Attributes;\n #start: number;\n #sqliteRowTimeSum: number;\n\n constructor(\n lc: LogContext,\n attrs: Attributes,\n it: IterableIterator<T>,\n slowQueryThreshold: number,\n ) {\n this.#lc = lc;\n this.#attrs = attrs;\n this.#it = it;\n this.#start = performance.now();\n this.#threshold = slowQueryThreshold;\n this.#sqliteRowTimeSum = 0;\n }\n\n next(): IteratorResult<T> {\n const start = performance.now();\n const ret = this.#it.next();\n const elapsed = performance.now() - start;\n this.#sqliteRowTimeSum += elapsed;\n if (ret.done) {\n this.#log();\n }\n return ret;\n }\n\n #log() {\n logIfSlow(\n this.#lc.withContext('type', 'total'),\n performance.now() - this.#start,\n {...this.#attrs, type: 'total', method: 'iterate'},\n this.#threshold,\n );\n logIfSlow(\n this.#lc.withContext('type', 'sqlite'),\n this.#sqliteRowTimeSum,\n {...this.#attrs, type: 'sqlite', method: 'iterate'},\n this.#threshold,\n );\n }\n\n [Symbol.iterator](): IterableIterator<T> {\n return this;\n }\n\n return(): IteratorResult<T> {\n this.#log();\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return this.#it.return?.() as any;\n }\n\n throw(e: unknown): IteratorResult<T> {\n this.#log();\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return this.#it.throw?.(e) as any;\n }\n}\n\nfunction logIfSlow(\n lc: LogContext,\n elapsed: number,\n attrs: Attributes,\n threshold: number,\n): void {\n if (elapsed >= threshold) {\n for (const [key, value] of Object.entries(attrs)) {\n lc = lc.withContext(key, value);\n }\n lc.warn?.('Slow SQLite query', elapsed);\n manualSpan(tracer, 'db.slow-query', elapsed, attrs);\n }\n}\n\n/**\n * An error indicating that the Database failed to open. This essentially\n * wraps the TypeError thrown by the better-sqlite3 package with something\n * more specific.\n */\nexport class DatabaseInitError extends Error {}\n"],"mappings":";;;;;AAUA,IAAM,SAAS,MAAM,UAAU,eAAe,QAAQ;AAGtD,IAAM,0BAA0B;AAEhC,IAAM,KAAK,OAAO;AAElB,SAAS,GAAG,OAAuB;AACjC,SAAQ,QAAQ,IAAI,QAAQ,EAAE;;AAGhC,IAAa,WAAb,MAA4C;CAC1C;CACA;CACA;CACA;CAEA,YACE,IACA,MACA,SACA,qBAAqB,KACrB;AACA,MAAI;AACF,SAAA,KAAW,GAAG,YAAY,SAAS,WAAW,CAAC,YAAY,QAAQ,KAAK;AACxE,SAAA,KAAW,IAAI,gBAAgB,MAAM,QAAQ;AAC7C,SAAA,YAAkB;GAElB,MAAM,CAAC,EAAC,WAAW,cAAa,KAAK,OACnC,YACD;AACD,SAAA,WAAiB;WACV,OAAO;AACd,SAAM,IAAI,kBAAkB,OAAO,MAAM,EAAE,EAAC,OAAM,CAAC;;;CAIvD,QAAQ,KAAwB;AAC9B,SAAO,MAAA,IACL,WACA,WAEE,IAAI,UACF,MAAA,GAAS,YAAY,OAAO,IAAI,EAChC;GAAC,OAAO;GAAa;GAAI,EACzB,MAAA,GAAS,QAAQ,IAAI,EACrB,MAAA,UACD,CACJ;;CAGH,KAAK,KAAmB;AACtB,QAAA,IAAU,QAAQ,WAAW,MAAA,GAAS,KAAK,IAAI,CAAC;;CAGlD,OAAoB,KAAkB;AACpC,SAAO,MAAA,IAAe,UAAU,WAAW,MAAA,GAAS,OAAO,IAAI,CAAQ;;CAGzE,OAAO,OAAe;AACpB,SAAO,QAAQ,MAAA;;CAGjB,QAAQ,wBAAgC;EACtC,MAAM,CAAC,EAAC,gBAAgB,mBAAkB,KAAK,OAE5C,iBAAiB;EAEpB,MAAM,WAAW,MAAA,MAAY,cAAc;AAC3C,MAAI,WAAW,wBAAwB;AACrC,SAAA,GAAS,QACP,kBAAkB,MAAA,GAAS,KAAK,IAAI,GAAG,SAAS,CAAC,cAClD;AACD;;EAEF,MAAM,CAAC,EAAC,aAAa,oBAAmB,KAAK,OAC3C,cACD;AACD,MAAI,mBAAmB,yBAAyB;AAC9C,SAAA,GAAS,OACP,kBAAkB,GAAG,SAAS,CAAC,SAC1B,MAAA,GAAS,KAAK,+BAA+B,eAAe,GAClE;AACD;;EAEF,MAAM,QAAQ,KAAK,KAAK;EACxB,MAAM,CAAC,EAAC,YAAY,qBAAoB,KAAK,OAC3C,aACD;AAED,OAAK,OAAO,qBAAqB;EAEjC,MAAM,CAAC,EAAC,YAAY,oBAAmB,KAAK,OAC1C,aACD;AAED,QAAA,GAAS,OACP,aAAa,MAAA,GAAS,KAAK,QACtB,GAAG,MAAA,MAAY,gBAAgB,CAAC,CAAC,SACjC,GAAG,MAAA,MAAY,eAAe,CAAC,CAAC,OAC/B,KAAK,KAAK,GAAG,MAAM,MAC1B;;CAGH,WAAW,QAAiB;AAC1B,QAAA,GAAS,WAAW,OAAO;;CAG7B,KAAQ,QAAgB,KAAa,IAAgB;EACnD,MAAM,QAAQ,YAAY,KAAK;AAC/B,MAAI;AACF,UAAO,IAAI;WACJ,GAAG;AACV,OAAI,aAAa,YACf,GAAE,WAAW,KAAK;AAEpB,SAAM;YACE;AACR,aACE,MAAA,GAAS,YAAY,UAAU,OAAO,EACtC,YAAY,KAAK,GAAG,OACpB,EAAC,QAAO,EACR,MAAA,UACD;;;CAIL,QAAc;EACZ,MAAM,QAAQ,KAAK,KAAK;AACxB,MAAI,CAAC,MAAA,GAAS,SACZ,KAAI;AACF,SAAA,GAAS,OAAO,WAAW;GAC3B,MAAM,UAAU,KAAK,KAAK,GAAG;AAC7B,OAAI,UAAU,EACZ,OAAA,GAAS,QAAQ,qBAAqB,QAAQ,MAAM;WAE/C,GAAG;AACV,SAAA,GAAS,OAAO,iCAAiC,EAAE;;AAGvD,QAAA,GAAS,OAAO;;CAGlB,YAAe,IAAgB;AAC7B,SAAO,MAAA,GAAS,YAAY,GAAG,EAAE;;CAGnC,IAAI,OAAO;AACT,SAAO,MAAA,GAAS;;CAGlB,IAAI,gBAAgB;AAClB,SAAO,MAAA,GAAS;;CAGlB,CAAC,OAAO,WAAiB;AACvB,OAAK,OAAO;;;AAIhB,IAAa,YAAb,MAAuB;CACrB;CACA;CACA;CACA;CACA;CACA;CAEA,YACE,IACA,OACA,MACA,WACA;AACA,QAAA,KAAW,GAAG,YAAY,SAAS,YAAY;AAC/C,QAAA,QAAc;AACd,QAAA,OAAa;AACb,QAAA,YAAkB;AAClB,OAAK,aAAa,MAAA,KAAW,aAAa,KAAK,MAAA,KAAW;AAC1D,OAAK,kBAAkB,MAAA,KAAW,gBAAgB,KAAK,MAAA,KAAW;;CAGpE,aAAa,WAA0B;AACrC,QAAA,KAAW,aAAa,UAAU;AAClC,SAAO;;CAGT,IAAI,GAAG,QAA8B;EACnC,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,MAAM,MAAA,KAAW,IAAI,GAAG,OAAO;AACrC,YACE,MAAA,GAAS,YAAY,UAAU,MAAM,EACrC,YAAY,KAAK,GAAG,OACpB;GAAC,GAAG,MAAA;GAAa,QAAQ;GAAM,EAC/B,MAAA,UACD;AACD,SAAO;;CAGT,IAAO,GAAG,QAAsB;EAC9B,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,MAAM,MAAA,KAAW,IAAI,GAAG,OAAO;AACrC,YACE,MAAA,GAAS,YAAY,UAAU,MAAM,EACrC,YAAY,KAAK,GAAG,OACpB;GAAC,GAAG,MAAA;GAAa,QAAQ;GAAM,EAC/B,MAAA,UACD;AACD,SAAO;;CAGT,IAAO,GAAG,QAAwB;EAChC,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,MAAM,MAAA,KAAW,IAAI,GAAG,OAAO;AACrC,YACE,MAAA,GAAS,YAAY,UAAU,MAAM,EACrC,YAAY,KAAK,GAAG,OACpB;GAAC,GAAG,MAAA;GAAa,QAAQ;GAAM,EAC/B,MAAA,UACD;AACD,SAAO;;CAGT,QAAW,GAAG,QAAwC;AACpD,SAAO,IAAI,wBACT,MAAA,GAAS,YAAY,UAAU,UAAU,EACzC,MAAA,OACA,MAAA,KAAW,QAAQ,GAAG,OAAO,EAC7B,MAAA,UACD;;;AAIL,IAAM,0BAAN,MAAgE;CAC9D;CACA;CACA;CACA;CACA;CACA;CAEA,YACE,IACA,OACA,IACA,oBACA;AACA,QAAA,KAAW;AACX,QAAA,QAAc;AACd,QAAA,KAAW;AACX,QAAA,QAAc,YAAY,KAAK;AAC/B,QAAA,YAAkB;AAClB,QAAA,mBAAyB;;CAG3B,OAA0B;EACxB,MAAM,QAAQ,YAAY,KAAK;EAC/B,MAAM,MAAM,MAAA,GAAS,MAAM;EAC3B,MAAM,UAAU,YAAY,KAAK,GAAG;AACpC,QAAA,oBAA0B;AAC1B,MAAI,IAAI,KACN,OAAA,KAAW;AAEb,SAAO;;CAGT,OAAO;AACL,YACE,MAAA,GAAS,YAAY,QAAQ,QAAQ,EACrC,YAAY,KAAK,GAAG,MAAA,OACpB;GAAC,GAAG,MAAA;GAAa,MAAM;GAAS,QAAQ;GAAU,EAClD,MAAA,UACD;AACD,YACE,MAAA,GAAS,YAAY,QAAQ,SAAS,EACtC,MAAA,kBACA;GAAC,GAAG,MAAA;GAAa,MAAM;GAAU,QAAQ;GAAU,EACnD,MAAA,UACD;;CAGH,CAAC,OAAO,YAAiC;AACvC,SAAO;;CAGT,SAA4B;AAC1B,QAAA,KAAW;AAEX,SAAO,MAAA,GAAS,UAAU;;CAG5B,MAAM,GAA+B;AACnC,QAAA,KAAW;AAEX,SAAO,MAAA,GAAS,QAAQ,EAAE;;;AAI9B,SAAS,UACP,IACA,SACA,OACA,WACM;AACN,KAAI,WAAW,WAAW;AACxB,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,MAAM,CAC9C,MAAK,GAAG,YAAY,KAAK,MAAM;AAEjC,KAAG,OAAO,qBAAqB,QAAQ;AACvC,aAAW,QAAQ,iBAAiB,SAAS,MAAM;;;;;;;;AASvD,IAAa,oBAAb,cAAuC,MAAM"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"explain-queries.js","names":[],"sources":["../../../../zqlite/src/explain-queries.ts"],"sourcesContent":["import type {RowCountsBySource} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {Database} from './db.ts';\n\nexport function explainQueries(counts: RowCountsBySource, db: Database) {\n const plans: Record<string, string[]> = {};\n for (const querySet of Object.values(counts)) {\n const queries = Object.keys(querySet);\n for (const query of queries) {\n const plan = db\n // we should be more intelligent about value replacement.\n // Different values result in different plans. E.g., picking a value at the start\n // of an index will result in `scan` vs `search`. The scan is fine in that case.\n .prepare(`EXPLAIN QUERY PLAN ${query.replaceAll('?', \"'sdfse'\")}`)\n .all<{detail: string}>()\n .map(r => r.detail);\n plans[query] = plan;\n }\n }\n\n return plans;\n}\n"],"mappings":";AAGA,SAAgB,eAAe,QAA2B,IAAc;CACtE,MAAM,QAAkC,
|
|
1
|
+
{"version":3,"file":"explain-queries.js","names":[],"sources":["../../../../zqlite/src/explain-queries.ts"],"sourcesContent":["import type {RowCountsBySource} from '../../zero-protocol/src/analyze-query-result.ts';\nimport type {Database} from './db.ts';\n\nexport function explainQueries(counts: RowCountsBySource, db: Database) {\n const plans: Record<string, string[]> = {};\n for (const querySet of Object.values(counts)) {\n const queries = Object.keys(querySet);\n for (const query of queries) {\n const plan = db\n // we should be more intelligent about value replacement.\n // Different values result in different plans. E.g., picking a value at the start\n // of an index will result in `scan` vs `search`. The scan is fine in that case.\n .prepare(`EXPLAIN QUERY PLAN ${query.replaceAll('?', \"'sdfse'\")}`)\n .all<{detail: string}>()\n .map(r => r.detail);\n plans[query] = plan;\n }\n }\n\n return plans;\n}\n"],"mappings":";AAGA,SAAgB,eAAe,QAA2B,IAAc;CACtE,MAAM,QAAkC,EAAE;AAC1C,MAAK,MAAM,YAAY,OAAO,OAAO,OAAO,EAAE;EAC5C,MAAM,UAAU,OAAO,KAAK,SAAS;AACrC,OAAK,MAAM,SAAS,QAQlB,OAAM,SAPO,GAIV,QAAQ,sBAAsB,MAAM,WAAW,KAAK,UAAU,GAAG,CACjE,KAAuB,CACvB,KAAI,MAAK,EAAE,OAAO;;AAKzB,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-inline.js","names":[],"sources":["../../../../../zqlite/src/internal/sql-inline.ts"],"sourcesContent":["import {escapeSQLiteIdentifier} from '@databases/escape-identifier';\nimport type {FormatConfig} from '@databases/sql';\nimport type {SQLQuery} from '@databases/sql';\n\n/**\n * Escapes a SQLite string value by doubling single quotes.\n * SQLite uses single quotes for string literals and doubles them for escaping.\n */\nfunction escapeSQLiteString(str: string): string {\n return `'${str.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Formats a value for inline inclusion in SQL (not as a placeholder).\n *\n * WARNING: This should ONLY be used for cost estimation in the query planner,\n * not for user-facing queries. All production queries must use parameterized\n * statements to prevent SQL injection.\n *\n * @param value The value to inline into SQL\n * @returns SQL literal representation of the value\n */\nfunction inlineValue(value: unknown): string {\n if (value === null) {\n return 'NULL';\n }\n if (typeof value === 'string') {\n return escapeSQLiteString(value);\n }\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'boolean') {\n // SQLite uses 1 and 0 for booleans\n return value ? '1' : '0';\n }\n if (Array.isArray(value)) {\n // For arrays, use JSON representation (same as query-builder.ts does for IN clauses)\n return escapeSQLiteString(JSON.stringify(value));\n }\n // For objects/other JSON types\n return escapeSQLiteString(JSON.stringify(value));\n}\n\n/**\n * Format configuration that inlines values directly into SQL instead of using placeholders.\n *\n * This is used ONLY for cost estimation in the SQLite cost model, where we want SQLite's\n * query planner to see actual values to make better decisions about index usage and query plans.\n *\n * Production code must use the standard parameterized format from sql.ts.\n */\nconst sqliteInlineFormat: FormatConfig = {\n escapeIdentifier: str => escapeSQLiteIdentifier(str),\n formatValue: value =>\n // undefined is our signal to use a placeholder\n // IMPORTANT. Changing this will break the planner as it will assume `NULL`\n // for constraints!\n value === undefined\n ? {\n placeholder: '?',\n value,\n }\n : {\n placeholder: inlineValue(value),\n value: undefined, // No binding needed since value is inlined\n },\n};\n\n/**\n * Compiles a SQL query with values inlined directly into the SQL string.\n *\n * WARNING: This should ONLY be used for cost estimation in the query planner.\n * Never use this for user-facing queries - always use the standard `compile()`\n * function from sql.ts which uses parameterized queries.\n *\n * @param sql The SQL query to compile\n * @returns SQL string with values inlined\n */\nexport function compileInline(sql: SQLQuery): string {\n return sql.format(sqliteInlineFormat).text;\n}\n"],"mappings":";;;;;;AAQA,SAAS,mBAAmB,KAAqB;
|
|
1
|
+
{"version":3,"file":"sql-inline.js","names":[],"sources":["../../../../../zqlite/src/internal/sql-inline.ts"],"sourcesContent":["import {escapeSQLiteIdentifier} from '@databases/escape-identifier';\nimport type {FormatConfig} from '@databases/sql';\nimport type {SQLQuery} from '@databases/sql';\n\n/**\n * Escapes a SQLite string value by doubling single quotes.\n * SQLite uses single quotes for string literals and doubles them for escaping.\n */\nfunction escapeSQLiteString(str: string): string {\n return `'${str.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Formats a value for inline inclusion in SQL (not as a placeholder).\n *\n * WARNING: This should ONLY be used for cost estimation in the query planner,\n * not for user-facing queries. All production queries must use parameterized\n * statements to prevent SQL injection.\n *\n * @param value The value to inline into SQL\n * @returns SQL literal representation of the value\n */\nfunction inlineValue(value: unknown): string {\n if (value === null) {\n return 'NULL';\n }\n if (typeof value === 'string') {\n return escapeSQLiteString(value);\n }\n if (typeof value === 'number') {\n return String(value);\n }\n if (typeof value === 'boolean') {\n // SQLite uses 1 and 0 for booleans\n return value ? '1' : '0';\n }\n if (Array.isArray(value)) {\n // For arrays, use JSON representation (same as query-builder.ts does for IN clauses)\n return escapeSQLiteString(JSON.stringify(value));\n }\n // For objects/other JSON types\n return escapeSQLiteString(JSON.stringify(value));\n}\n\n/**\n * Format configuration that inlines values directly into SQL instead of using placeholders.\n *\n * This is used ONLY for cost estimation in the SQLite cost model, where we want SQLite's\n * query planner to see actual values to make better decisions about index usage and query plans.\n *\n * Production code must use the standard parameterized format from sql.ts.\n */\nconst sqliteInlineFormat: FormatConfig = {\n escapeIdentifier: str => escapeSQLiteIdentifier(str),\n formatValue: value =>\n // undefined is our signal to use a placeholder\n // IMPORTANT. Changing this will break the planner as it will assume `NULL`\n // for constraints!\n value === undefined\n ? {\n placeholder: '?',\n value,\n }\n : {\n placeholder: inlineValue(value),\n value: undefined, // No binding needed since value is inlined\n },\n};\n\n/**\n * Compiles a SQL query with values inlined directly into the SQL string.\n *\n * WARNING: This should ONLY be used for cost estimation in the query planner.\n * Never use this for user-facing queries - always use the standard `compile()`\n * function from sql.ts which uses parameterized queries.\n *\n * @param sql The SQL query to compile\n * @returns SQL string with values inlined\n */\nexport function compileInline(sql: SQLQuery): string {\n return sql.format(sqliteInlineFormat).text;\n}\n"],"mappings":";;;;;;AAQA,SAAS,mBAAmB,KAAqB;AAC/C,QAAO,IAAI,IAAI,QAAQ,MAAM,KAAK,CAAC;;;;;;;;;;;;AAarC,SAAS,YAAY,OAAwB;AAC3C,KAAI,UAAU,KACZ,QAAO;AAET,KAAI,OAAO,UAAU,SACnB,QAAO,mBAAmB,MAAM;AAElC,KAAI,OAAO,UAAU,SACnB,QAAO,OAAO,MAAM;AAEtB,KAAI,OAAO,UAAU,UAEnB,QAAO,QAAQ,MAAM;AAEvB,KAAI,MAAM,QAAQ,MAAM,CAEtB,QAAO,mBAAmB,KAAK,UAAU,MAAM,CAAC;AAGlD,QAAO,mBAAmB,KAAK,UAAU,MAAM,CAAC;;;;;;;;;;AAWlD,IAAM,qBAAmC;CACvC,mBAAkB,QAAO,uBAAuB,IAAI;CACpD,cAAa,UAIX,UAAU,KAAA,IACN;EACE,aAAa;EACb;EACD,GACD;EACE,aAAa,YAAY,MAAM;EAC/B,OAAO,KAAA;EACR;CACR;;;;;;;;;;;AAYD,SAAgB,cAAc,KAAuB;AACnD,QAAO,IAAI,OAAO,mBAAmB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql.js","names":[],"sources":["../../../../../zqlite/src/internal/sql.ts"],"sourcesContent":["import {escapeSQLiteIdentifier} from '@databases/escape-identifier';\nimport type {FormatConfig, SQLQuery} from '@databases/sql';\nimport sql from '@databases/sql';\n\nconst sqliteFormat: FormatConfig = {\n escapeIdentifier: str => escapeSQLiteIdentifier(str),\n formatValue: value => ({placeholder: '?', value}),\n};\n\nexport function compile(sql: SQLQuery): string {\n return sql.format(sqliteFormat).text;\n}\n\nexport function format(sql: SQLQuery) {\n return sql.format(sqliteFormat);\n}\n\nexport {sql};\n"],"mappings":";;;AAIA,IAAM,eAA6B;CACjC,mBAAkB,QAAO,uBAAuB,
|
|
1
|
+
{"version":3,"file":"sql.js","names":[],"sources":["../../../../../zqlite/src/internal/sql.ts"],"sourcesContent":["import {escapeSQLiteIdentifier} from '@databases/escape-identifier';\nimport type {FormatConfig, SQLQuery} from '@databases/sql';\nimport sql from '@databases/sql';\n\nconst sqliteFormat: FormatConfig = {\n escapeIdentifier: str => escapeSQLiteIdentifier(str),\n formatValue: value => ({placeholder: '?', value}),\n};\n\nexport function compile(sql: SQLQuery): string {\n return sql.format(sqliteFormat).text;\n}\n\nexport function format(sql: SQLQuery) {\n return sql.format(sqliteFormat);\n}\n\nexport {sql};\n"],"mappings":";;;AAIA,IAAM,eAA6B;CACjC,mBAAkB,QAAO,uBAAuB,IAAI;CACpD,cAAa,WAAU;EAAC,aAAa;EAAK;EAAM;CACjD;AAED,SAAgB,QAAQ,KAAuB;AAC7C,QAAO,IAAI,OAAO,aAAa,CAAC;;AAGlC,SAAgB,OAAO,KAAe;AACpC,QAAO,IAAI,OAAO,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statement-cache.js","names":["#db","#size","#cache"],"sources":["../../../../../zqlite/src/internal/statement-cache.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Database, Statement} from '../db.ts';\n\nexport type CachedStatementMap = Map<string, Statement[]>;\nexport type CachedStatement = {\n sql: string;\n statement: Statement;\n};\n/**\n * SQLite statement preparation isn't cheap as it involves evaluating possible\n * query plans and picking the best one (in addition to parsing the SQL).\n *\n * This statement cache prevents the need to re-prepare the same statement\n * multiple times.\n *\n * One extra wrinkle is that a single statement cannot be used by multiple\n * callers at the same time. As in, we can't `iterate` the same statement\n * many times concurrently.\n *\n * Given that, statements are removed from the cache while in use.\n * - `get` removes the statement from the cache\n * - `return` adds it back.\n *\n * If a request for the same sql is made while a\n * statement is gotten, a new statement will be prepared.\n * Both statements can be returned to the cache even though they both\n * serve the same SQL. Having both copies returned to the cache allows\n * the cache to serve multiple callers concurrently in the future.\n *\n * It is not an error to fail to call `return` on a statement.\n * Failing to call return will only prevent the statement from being reused\n * by other callers. It will not cause a resource leak.\n */\nexport class StatementCache {\n #cache: CachedStatementMap = new Map<string, Statement[]>();\n readonly #db: Database;\n #size: number = 0;\n\n /**\n * The db connection used to prepare the statement.\n * It is an error to use a statement prepared on one connection with another connection.\n * @param db\n */\n constructor(db: Database) {\n this.#db = db;\n }\n\n // the number of statements in the cache\n get size() {\n return this.#size;\n }\n\n drop(n: number) {\n assert(n >= 0, 'Cannot drop a negative number of items');\n assert(n <= this.#size, 'Cannot drop more items than are in the cache');\n\n let remaining = n;\n for (const [sql, statements] of this.#cache.entries()) {\n if (remaining >= statements.length) {\n this.#cache.delete(sql);\n remaining -= statements.length;\n this.#size -= statements.length;\n } else {\n statements.splice(0, remaining);\n this.#size -= remaining;\n break;\n }\n }\n }\n\n /**\n * Prepares a statement for the given sql unless one is already cached.\n * If one is cached, it is removed from the cache and returned.\n *\n * Since `get` removes the item from the cache it is not an error to fail to call\n * `return`. The gotten statement will be correctly garbage collected.\n *\n * When a gotten statement is not returned, future calls to\n * `get` with the same `sql` will prepare a new statement.\n *\n * @param sql\n * @returns\n */\n get(sql: string): CachedStatement {\n sql = normalizeWhitespace(sql);\n const statements = this.#cache.get(sql);\n if (statements && statements.length > 0) {\n const statement = statements.pop()!;\n this.#size--;\n if (statements.length === 0) {\n this.#cache.delete(sql);\n }\n return {sql, statement};\n }\n const statement = this.#db.prepare(sql);\n return {sql, statement};\n }\n\n /**\n * Handles `get` and `return` for the caller by invoking them before\n * and after the callback.\n */\n use<T>(sql: string, cb: (statement: CachedStatement) => T) {\n const statement = this.get(sql);\n try {\n return cb(statement);\n } finally {\n this.return(statement);\n }\n }\n\n /**\n * Add a statement back to the cache so someone else can use it later.\n * @param statement\n */\n return(statement: CachedStatement) {\n const {sql} = statement;\n if (!this.#cache.has(sql)) {\n this.#cache.set(sql, []);\n }\n const statements = this.#cache.get(sql);\n if (statements) {\n statements.push(statement.statement);\n this.#size++;\n }\n }\n}\n\nfunction normalizeWhitespace(sql: string) {\n return sql.replaceAll(/\\s+/g, ' ');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,MAA4B;CAC1B,yBAA6B,IAAI,
|
|
1
|
+
{"version":3,"file":"statement-cache.js","names":["#db","#size","#cache"],"sources":["../../../../../zqlite/src/internal/statement-cache.ts"],"sourcesContent":["import {assert} from '../../../shared/src/asserts.ts';\nimport type {Database, Statement} from '../db.ts';\n\nexport type CachedStatementMap = Map<string, Statement[]>;\nexport type CachedStatement = {\n sql: string;\n statement: Statement;\n};\n/**\n * SQLite statement preparation isn't cheap as it involves evaluating possible\n * query plans and picking the best one (in addition to parsing the SQL).\n *\n * This statement cache prevents the need to re-prepare the same statement\n * multiple times.\n *\n * One extra wrinkle is that a single statement cannot be used by multiple\n * callers at the same time. As in, we can't `iterate` the same statement\n * many times concurrently.\n *\n * Given that, statements are removed from the cache while in use.\n * - `get` removes the statement from the cache\n * - `return` adds it back.\n *\n * If a request for the same sql is made while a\n * statement is gotten, a new statement will be prepared.\n * Both statements can be returned to the cache even though they both\n * serve the same SQL. Having both copies returned to the cache allows\n * the cache to serve multiple callers concurrently in the future.\n *\n * It is not an error to fail to call `return` on a statement.\n * Failing to call return will only prevent the statement from being reused\n * by other callers. It will not cause a resource leak.\n */\nexport class StatementCache {\n #cache: CachedStatementMap = new Map<string, Statement[]>();\n readonly #db: Database;\n #size: number = 0;\n\n /**\n * The db connection used to prepare the statement.\n * It is an error to use a statement prepared on one connection with another connection.\n * @param db\n */\n constructor(db: Database) {\n this.#db = db;\n }\n\n // the number of statements in the cache\n get size() {\n return this.#size;\n }\n\n drop(n: number) {\n assert(n >= 0, 'Cannot drop a negative number of items');\n assert(n <= this.#size, 'Cannot drop more items than are in the cache');\n\n let remaining = n;\n for (const [sql, statements] of this.#cache.entries()) {\n if (remaining >= statements.length) {\n this.#cache.delete(sql);\n remaining -= statements.length;\n this.#size -= statements.length;\n } else {\n statements.splice(0, remaining);\n this.#size -= remaining;\n break;\n }\n }\n }\n\n /**\n * Prepares a statement for the given sql unless one is already cached.\n * If one is cached, it is removed from the cache and returned.\n *\n * Since `get` removes the item from the cache it is not an error to fail to call\n * `return`. The gotten statement will be correctly garbage collected.\n *\n * When a gotten statement is not returned, future calls to\n * `get` with the same `sql` will prepare a new statement.\n *\n * @param sql\n * @returns\n */\n get(sql: string): CachedStatement {\n sql = normalizeWhitespace(sql);\n const statements = this.#cache.get(sql);\n if (statements && statements.length > 0) {\n const statement = statements.pop()!;\n this.#size--;\n if (statements.length === 0) {\n this.#cache.delete(sql);\n }\n return {sql, statement};\n }\n const statement = this.#db.prepare(sql);\n return {sql, statement};\n }\n\n /**\n * Handles `get` and `return` for the caller by invoking them before\n * and after the callback.\n */\n use<T>(sql: string, cb: (statement: CachedStatement) => T) {\n const statement = this.get(sql);\n try {\n return cb(statement);\n } finally {\n this.return(statement);\n }\n }\n\n /**\n * Add a statement back to the cache so someone else can use it later.\n * @param statement\n */\n return(statement: CachedStatement) {\n const {sql} = statement;\n if (!this.#cache.has(sql)) {\n this.#cache.set(sql, []);\n }\n const statements = this.#cache.get(sql);\n if (statements) {\n statements.push(statement.statement);\n this.#size++;\n }\n }\n}\n\nfunction normalizeWhitespace(sql: string) {\n return sql.replaceAll(/\\s+/g, ' ');\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,IAAa,iBAAb,MAA4B;CAC1B,yBAA6B,IAAI,KAA0B;CAC3D;CACA,QAAgB;;;;;;CAOhB,YAAY,IAAc;AACxB,QAAA,KAAW;;CAIb,IAAI,OAAO;AACT,SAAO,MAAA;;CAGT,KAAK,GAAW;AACd,SAAO,KAAK,GAAG,yCAAyC;AACxD,SAAO,KAAK,MAAA,MAAY,+CAA+C;EAEvE,IAAI,YAAY;AAChB,OAAK,MAAM,CAAC,KAAK,eAAe,MAAA,MAAY,SAAS,CACnD,KAAI,aAAa,WAAW,QAAQ;AAClC,SAAA,MAAY,OAAO,IAAI;AACvB,gBAAa,WAAW;AACxB,SAAA,QAAc,WAAW;SACpB;AACL,cAAW,OAAO,GAAG,UAAU;AAC/B,SAAA,QAAc;AACd;;;;;;;;;;;;;;;;CAkBN,IAAI,KAA8B;AAChC,QAAM,oBAAoB,IAAI;EAC9B,MAAM,aAAa,MAAA,MAAY,IAAI,IAAI;AACvC,MAAI,cAAc,WAAW,SAAS,GAAG;GACvC,MAAM,YAAY,WAAW,KAAK;AAClC,SAAA;AACA,OAAI,WAAW,WAAW,EACxB,OAAA,MAAY,OAAO,IAAI;AAEzB,UAAO;IAAC;IAAK;IAAU;;EAEzB,MAAM,YAAY,MAAA,GAAS,QAAQ,IAAI;AACvC,SAAO;GAAC;GAAK;GAAU;;;;;;CAOzB,IAAO,KAAa,IAAuC;EACzD,MAAM,YAAY,KAAK,IAAI,IAAI;AAC/B,MAAI;AACF,UAAO,GAAG,UAAU;YACZ;AACR,QAAK,OAAO,UAAU;;;;;;;CAQ1B,OAAO,WAA4B;EACjC,MAAM,EAAC,QAAO;AACd,MAAI,CAAC,MAAA,MAAY,IAAI,IAAI,CACvB,OAAA,MAAY,IAAI,KAAK,EAAE,CAAC;EAE1B,MAAM,aAAa,MAAA,MAAY,IAAI,IAAI;AACvC,MAAI,YAAY;AACd,cAAW,KAAK,UAAU,UAAU;AACpC,SAAA;;;;AAKN,SAAS,oBAAoB,KAAa;AACxC,QAAO,IAAI,WAAW,QAAQ,IAAI"}
|