@rocicorp/zero 1.6.0-canary.12 → 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/analyze-query/src/analyze-cli.js +3 -3
- 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.d.ts +0 -2
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +1 -9
- 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 +26 -34
- 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.d.ts.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +2 -1
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +7 -8
- 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.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.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +1 -2
- 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.map +1 -1
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/use-zero-online.js.map +1 -1
- 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.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.map +1 -1
- package/out/zero-solid/src/use-connection-state.js.map +1 -1
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero-online.js.map +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 +26 -42
- 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":"deleted-clients.js","names":[],"sources":["../../../../replicache/src/deleted-clients.ts"],"sourcesContent":["import {stringCompare} from '../../shared/src/string-compare.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport type {Read, Write} from './dag/store.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getClients, setClients} from './persist/clients.ts';\nimport {\n clientGroupIDSchema,\n clientIDSchema,\n type ClientGroupID,\n type ClientID,\n} from './sync/ids.ts';\n\n/**\n * We keep track of deleted clients in the {@linkcode DELETED_CLIENTS_HEAD_NAME}\n * head.\n */\nexport const DELETED_CLIENTS_HEAD_NAME = 'deleted-clients-v2';\n\ntype ClientIDPair = {\n clientGroupID: ClientGroupID;\n clientID: ClientID;\n};\n\nexport type DeletedClients = readonly Readonly<ClientIDPair>[];\n\nexport type WritableDeletedClients = ClientIDPair[];\n\nexport const deletedClientsSchema: v.Type<DeletedClients> = v.readonlyArray(\n v.readonlyObject({\n clientGroupID: clientGroupIDSchema,\n clientID: clientIDSchema,\n }),\n);\n\nfunction compare(a: ClientIDPair, b: ClientIDPair): number {\n const cg = stringCompare(a.clientGroupID, b.clientGroupID);\n if (cg !== 0) {\n return cg;\n }\n return stringCompare(a.clientID, b.clientID);\n}\n\nexport function normalizeDeletedClients(\n deletedClients: DeletedClients,\n): DeletedClients {\n return deletedClients\n .toSorted(compare)\n .filter((item, i, arr) => i === 0 || compare(item, arr[i - 1]) !== 0);\n}\n\nexport function mergeDeletedClients(\n a: DeletedClients,\n b: DeletedClients,\n): DeletedClients {\n const merged: WritableDeletedClients = [];\n a = normalizeDeletedClients(a);\n b = normalizeDeletedClients(b);\n for (let i = 0, j = 0; i < a.length || j < b.length; ) {\n if (i < a.length && (j >= b.length || compare(a[i], b[j]) < 0)) {\n merged.push(a[i]);\n i++;\n } else if (j < b.length && (i >= a.length || compare(b[j], a[i]) < 0)) {\n merged.push(b[j]);\n j++;\n } else {\n // equal\n merged.push(a[i]);\n i++;\n j++;\n }\n }\n return merged;\n}\n\nexport function removeFromDeletedClients(\n old: DeletedClients,\n toRemove: DeletedClients,\n): DeletedClients {\n old = normalizeDeletedClients(old);\n toRemove = normalizeDeletedClients(toRemove);\n const result: WritableDeletedClients = [];\n for (let i = 0, j = 0; i < old.length; ) {\n if (j >= toRemove.length || compare(old[i], toRemove[j]) < 0) {\n result.push(old[i]);\n i++;\n } else if (j < toRemove.length && compare(old[i], toRemove[j]) === 0) {\n // equal, skip\n i++;\n j++;\n } else {\n // old[i] > toRemove[j]\n j++;\n }\n }\n return result;\n}\n\nexport async function setDeletedClients(\n dagWrite: Write,\n deletedClients: DeletedClients,\n): Promise<DeletedClients> {\n // sort and dedupe\n\n const data = normalizeDeletedClients(deletedClients);\n\n const chunkData = deepFreeze(data);\n const chunk = dagWrite.createChunk(chunkData, []);\n await dagWrite.putChunk(chunk);\n await dagWrite.setHead(DELETED_CLIENTS_HEAD_NAME, chunk.hash);\n return data;\n}\n\nexport async function getDeletedClients(\n dagRead: Read,\n): Promise<DeletedClients> {\n const hash = await dagRead.getHead(DELETED_CLIENTS_HEAD_NAME);\n if (hash === undefined) {\n return [];\n }\n const chunk = await dagRead.mustGetChunk(hash);\n\n const res = v.test(chunk.data, deletedClientsSchema);\n if (!res.ok) {\n // If not ok then we ignore this. It might be in the old format but we do\n // not know the clientGroupID of the old clients.\n return [];\n }\n\n return res.value;\n}\n\n/**\n * Adds deleted clients to the {@linkcode DELETED_CLIENTS_HEAD_NAME} head.\n * @returns the new list of deleted clients (sorted and deduped).\n */\nexport async function addDeletedClients(\n dagWrite: Write,\n deletedClientsToAdd: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n\n return setDeletedClients(\n dagWrite,\n mergeDeletedClients(oldDeletedClients, deletedClientsToAdd),\n );\n}\n\nexport async function removeDeletedClients(\n dagWrite: Write,\n deletedClientsToRemove: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n return setDeletedClients(\n dagWrite,\n removeFromDeletedClients(oldDeletedClients, deletedClientsToRemove),\n );\n}\n\nexport async function confirmDeletedClients(\n dagWrite: Write,\n deletedClientIds: readonly ClientID[],\n deletedClientGroupIds: readonly ClientGroupID[],\n): Promise<DeletedClients> {\n const deletedClientIDSet = new Set(deletedClientIds);\n const deletedClientGroupIDSet = new Set(deletedClientGroupIds);\n const oldDeletedClients = await getDeletedClients(dagWrite);\n const clients = new Map(await getClients(dagWrite));\n for (const clientID of deletedClientIds) {\n clients.delete(clientID);\n }\n for (const clientGroupID of deletedClientGroupIds) {\n for (const [clientID, client] of clients) {\n if (client.clientGroupID === clientGroupID) {\n clients.delete(clientID);\n }\n }\n }\n\n await setClients(clients, dagWrite);\n\n return setDeletedClients(\n dagWrite,\n oldDeletedClients.filter(\n ({clientGroupID, clientID}) =>\n !deletedClientGroupIDSet.has(clientGroupID) &&\n !deletedClientIDSet.has(clientID),\n ),\n );\n}\n"],"mappings":";;;;;;;;;;AAgBA,IAAa,4BAA4B;AAWzC,IAAa,uBAA+C,cAC1D,eAAiB;CACf,eAAe;CACf,UAAU;
|
|
1
|
+
{"version":3,"file":"deleted-clients.js","names":[],"sources":["../../../../replicache/src/deleted-clients.ts"],"sourcesContent":["import {stringCompare} from '../../shared/src/string-compare.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport type {Read, Write} from './dag/store.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getClients, setClients} from './persist/clients.ts';\nimport {\n clientGroupIDSchema,\n clientIDSchema,\n type ClientGroupID,\n type ClientID,\n} from './sync/ids.ts';\n\n/**\n * We keep track of deleted clients in the {@linkcode DELETED_CLIENTS_HEAD_NAME}\n * head.\n */\nexport const DELETED_CLIENTS_HEAD_NAME = 'deleted-clients-v2';\n\ntype ClientIDPair = {\n clientGroupID: ClientGroupID;\n clientID: ClientID;\n};\n\nexport type DeletedClients = readonly Readonly<ClientIDPair>[];\n\nexport type WritableDeletedClients = ClientIDPair[];\n\nexport const deletedClientsSchema: v.Type<DeletedClients> = v.readonlyArray(\n v.readonlyObject({\n clientGroupID: clientGroupIDSchema,\n clientID: clientIDSchema,\n }),\n);\n\nfunction compare(a: ClientIDPair, b: ClientIDPair): number {\n const cg = stringCompare(a.clientGroupID, b.clientGroupID);\n if (cg !== 0) {\n return cg;\n }\n return stringCompare(a.clientID, b.clientID);\n}\n\nexport function normalizeDeletedClients(\n deletedClients: DeletedClients,\n): DeletedClients {\n return deletedClients\n .toSorted(compare)\n .filter((item, i, arr) => i === 0 || compare(item, arr[i - 1]) !== 0);\n}\n\nexport function mergeDeletedClients(\n a: DeletedClients,\n b: DeletedClients,\n): DeletedClients {\n const merged: WritableDeletedClients = [];\n a = normalizeDeletedClients(a);\n b = normalizeDeletedClients(b);\n for (let i = 0, j = 0; i < a.length || j < b.length; ) {\n if (i < a.length && (j >= b.length || compare(a[i], b[j]) < 0)) {\n merged.push(a[i]);\n i++;\n } else if (j < b.length && (i >= a.length || compare(b[j], a[i]) < 0)) {\n merged.push(b[j]);\n j++;\n } else {\n // equal\n merged.push(a[i]);\n i++;\n j++;\n }\n }\n return merged;\n}\n\nexport function removeFromDeletedClients(\n old: DeletedClients,\n toRemove: DeletedClients,\n): DeletedClients {\n old = normalizeDeletedClients(old);\n toRemove = normalizeDeletedClients(toRemove);\n const result: WritableDeletedClients = [];\n for (let i = 0, j = 0; i < old.length; ) {\n if (j >= toRemove.length || compare(old[i], toRemove[j]) < 0) {\n result.push(old[i]);\n i++;\n } else if (j < toRemove.length && compare(old[i], toRemove[j]) === 0) {\n // equal, skip\n i++;\n j++;\n } else {\n // old[i] > toRemove[j]\n j++;\n }\n }\n return result;\n}\n\nexport async function setDeletedClients(\n dagWrite: Write,\n deletedClients: DeletedClients,\n): Promise<DeletedClients> {\n // sort and dedupe\n\n const data = normalizeDeletedClients(deletedClients);\n\n const chunkData = deepFreeze(data);\n const chunk = dagWrite.createChunk(chunkData, []);\n await dagWrite.putChunk(chunk);\n await dagWrite.setHead(DELETED_CLIENTS_HEAD_NAME, chunk.hash);\n return data;\n}\n\nexport async function getDeletedClients(\n dagRead: Read,\n): Promise<DeletedClients> {\n const hash = await dagRead.getHead(DELETED_CLIENTS_HEAD_NAME);\n if (hash === undefined) {\n return [];\n }\n const chunk = await dagRead.mustGetChunk(hash);\n\n const res = v.test(chunk.data, deletedClientsSchema);\n if (!res.ok) {\n // If not ok then we ignore this. It might be in the old format but we do\n // not know the clientGroupID of the old clients.\n return [];\n }\n\n return res.value;\n}\n\n/**\n * Adds deleted clients to the {@linkcode DELETED_CLIENTS_HEAD_NAME} head.\n * @returns the new list of deleted clients (sorted and deduped).\n */\nexport async function addDeletedClients(\n dagWrite: Write,\n deletedClientsToAdd: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n\n return setDeletedClients(\n dagWrite,\n mergeDeletedClients(oldDeletedClients, deletedClientsToAdd),\n );\n}\n\nexport async function removeDeletedClients(\n dagWrite: Write,\n deletedClientsToRemove: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n return setDeletedClients(\n dagWrite,\n removeFromDeletedClients(oldDeletedClients, deletedClientsToRemove),\n );\n}\n\nexport async function confirmDeletedClients(\n dagWrite: Write,\n deletedClientIds: readonly ClientID[],\n deletedClientGroupIds: readonly ClientGroupID[],\n): Promise<DeletedClients> {\n const deletedClientIDSet = new Set(deletedClientIds);\n const deletedClientGroupIDSet = new Set(deletedClientGroupIds);\n const oldDeletedClients = await getDeletedClients(dagWrite);\n const clients = new Map(await getClients(dagWrite));\n for (const clientID of deletedClientIds) {\n clients.delete(clientID);\n }\n for (const clientGroupID of deletedClientGroupIds) {\n for (const [clientID, client] of clients) {\n if (client.clientGroupID === clientGroupID) {\n clients.delete(clientID);\n }\n }\n }\n\n await setClients(clients, dagWrite);\n\n return setDeletedClients(\n dagWrite,\n oldDeletedClients.filter(\n ({clientGroupID, clientID}) =>\n !deletedClientGroupIDSet.has(clientGroupID) &&\n !deletedClientIDSet.has(clientID),\n ),\n );\n}\n"],"mappings":";;;;;;;;;;AAgBA,IAAa,4BAA4B;AAWzC,IAAa,uBAA+C,cAC1D,eAAiB;CACf,eAAe;CACf,UAAU;CACX,CAAC,CACH;AAED,SAAS,QAAQ,GAAiB,GAAyB;CACzD,MAAM,KAAK,cAAc,EAAE,eAAe,EAAE,cAAc;AAC1D,KAAI,OAAO,EACT,QAAO;AAET,QAAO,cAAc,EAAE,UAAU,EAAE,SAAS;;AAG9C,SAAgB,wBACd,gBACgB;AAChB,QAAO,eACJ,SAAS,QAAQ,CACjB,QAAQ,MAAM,GAAG,QAAQ,MAAM,KAAK,QAAQ,MAAM,IAAI,IAAI,GAAG,KAAK,EAAE;;AAGzE,SAAgB,oBACd,GACA,GACgB;CAChB,MAAM,SAAiC,EAAE;AACzC,KAAI,wBAAwB,EAAE;AAC9B,KAAI,wBAAwB,EAAE;AAC9B,MAAK,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,QAC3C,KAAI,IAAI,EAAE,WAAW,KAAK,EAAE,UAAU,QAAQ,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;AAC9D,SAAO,KAAK,EAAE,GAAG;AACjB;YACS,IAAI,EAAE,WAAW,KAAK,EAAE,UAAU,QAAQ,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;AACrE,SAAO,KAAK,EAAE,GAAG;AACjB;QACK;AAEL,SAAO,KAAK,EAAE,GAAG;AACjB;AACA;;AAGJ,QAAO;;AA0BT,eAAsB,kBACpB,UACA,gBACyB;CAGzB,MAAM,OAAO,wBAAwB,eAAe;CAEpD,MAAM,YAAY,WAAW,KAAK;CAClC,MAAM,QAAQ,SAAS,YAAY,WAAW,EAAE,CAAC;AACjD,OAAM,SAAS,SAAS,MAAM;AAC9B,OAAM,SAAS,QAAQ,2BAA2B,MAAM,KAAK;AAC7D,QAAO;;AAGT,eAAsB,kBACpB,SACyB;CACzB,MAAM,OAAO,MAAM,QAAQ,QAAQ,0BAA0B;AAC7D,KAAI,SAAS,KAAA,EACX,QAAO,EAAE;CAIX,MAAM,MAAM,MAFE,MAAM,QAAQ,aAAa,KAAK,EAErB,MAAM,qBAAqB;AACpD,KAAI,CAAC,IAAI,GAGP,QAAO,EAAE;AAGX,QAAO,IAAI;;;;;;AAOb,eAAsB,kBACpB,UACA,qBACyB;AAGzB,QAAO,kBACL,UACA,oBAJwB,MAAM,kBAAkB,SAAS,EAIlB,oBAAoB,CAC5D;;AAcH,eAAsB,sBACpB,UACA,kBACA,uBACyB;CACzB,MAAM,qBAAqB,IAAI,IAAI,iBAAiB;CACpD,MAAM,0BAA0B,IAAI,IAAI,sBAAsB;CAC9D,MAAM,oBAAoB,MAAM,kBAAkB,SAAS;CAC3D,MAAM,UAAU,IAAI,IAAI,MAAM,WAAW,SAAS,CAAC;AACnD,MAAK,MAAM,YAAY,iBACrB,SAAQ,OAAO,SAAS;AAE1B,MAAK,MAAM,iBAAiB,sBAC1B,MAAK,MAAM,CAAC,UAAU,WAAW,QAC/B,KAAI,OAAO,kBAAkB,cAC3B,SAAQ,OAAO,SAAS;AAK9B,OAAM,WAAW,SAAS,SAAS;AAEnC,QAAO,kBACL,UACA,kBAAkB,QACf,EAAC,eAAe,eACf,CAAC,wBAAwB,IAAI,cAAc,IAC3C,CAAC,mBAAmB,IAAI,SAAS,CACpC,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error-responses.js","names":[],"sources":["../../../../replicache/src/error-responses.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\n\nfunction isError(obj: unknown, type: string): boolean {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as {error: unknown}).error === type\n );\n}\n\ntype ErrorResponse = {error: string};\n\nexport function isErrorResponse(obj: object): obj is ErrorResponse {\n return typeof (obj as {error: unknown}).error === 'string';\n}\n\n/**\n * In certain scenarios the server can signal that it does not know about the\n * client. For example, the server might have lost all of its state (this might\n * happen during the development of the server).\n */\nexport type ClientStateNotFoundResponse = {\n error: 'ClientStateNotFound';\n};\n\nexport function isClientStateNotFoundResponse(\n v: unknown,\n): v is ClientStateNotFoundResponse {\n return isError(v, 'ClientStateNotFound');\n}\n\n/**\n * The server endpoint may respond with a `VersionNotSupported` error if it does\n * not know how to handle the pull, push or schema version.\n */\nexport type VersionNotSupportedResponse = {\n error: 'VersionNotSupported';\n versionType?: 'pull' | 'push' | 'schema' | undefined;\n};\n\nexport function isVersionNotSupportedResponse(\n v: unknown,\n): v is VersionNotSupportedResponse {\n if (!isError(v, 'VersionNotSupported')) {\n return false;\n }\n\n const {versionType} = v as Record<string, unknown>;\n switch (versionType) {\n case undefined:\n case 'pull':\n case 'push':\n case 'schema':\n return true;\n }\n\n return false;\n}\n\nexport function assertVersionNotSupportedResponse(\n v: unknown,\n): asserts v is VersionNotSupportedResponse {\n assert(\n isVersionNotSupportedResponse(v),\n 'Expected a VersionNotSupportedResponse',\n );\n}\n"],"mappings":";;AAEA,SAAS,QAAQ,KAAc,MAAuB;
|
|
1
|
+
{"version":3,"file":"error-responses.js","names":[],"sources":["../../../../replicache/src/error-responses.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\n\nfunction isError(obj: unknown, type: string): boolean {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as {error: unknown}).error === type\n );\n}\n\ntype ErrorResponse = {error: string};\n\nexport function isErrorResponse(obj: object): obj is ErrorResponse {\n return typeof (obj as {error: unknown}).error === 'string';\n}\n\n/**\n * In certain scenarios the server can signal that it does not know about the\n * client. For example, the server might have lost all of its state (this might\n * happen during the development of the server).\n */\nexport type ClientStateNotFoundResponse = {\n error: 'ClientStateNotFound';\n};\n\nexport function isClientStateNotFoundResponse(\n v: unknown,\n): v is ClientStateNotFoundResponse {\n return isError(v, 'ClientStateNotFound');\n}\n\n/**\n * The server endpoint may respond with a `VersionNotSupported` error if it does\n * not know how to handle the pull, push or schema version.\n */\nexport type VersionNotSupportedResponse = {\n error: 'VersionNotSupported';\n versionType?: 'pull' | 'push' | 'schema' | undefined;\n};\n\nexport function isVersionNotSupportedResponse(\n v: unknown,\n): v is VersionNotSupportedResponse {\n if (!isError(v, 'VersionNotSupported')) {\n return false;\n }\n\n const {versionType} = v as Record<string, unknown>;\n switch (versionType) {\n case undefined:\n case 'pull':\n case 'push':\n case 'schema':\n return true;\n }\n\n return false;\n}\n\nexport function assertVersionNotSupportedResponse(\n v: unknown,\n): asserts v is VersionNotSupportedResponse {\n assert(\n isVersionNotSupportedResponse(v),\n 'Expected a VersionNotSupportedResponse',\n );\n}\n"],"mappings":";;AAEA,SAAS,QAAQ,KAAc,MAAuB;AACpD,QACE,OAAO,QAAQ,YACf,QAAQ,QACP,IAAyB,UAAU;;AAMxC,SAAgB,gBAAgB,KAAmC;AACjE,QAAO,OAAQ,IAAyB,UAAU;;AAYpD,SAAgB,8BACd,GACkC;AAClC,QAAO,QAAQ,GAAG,sBAAsB;;AAY1C,SAAgB,8BACd,GACkC;AAClC,KAAI,CAAC,QAAQ,GAAG,sBAAsB,CACpC,QAAO;CAGT,MAAM,EAAC,gBAAe;AACtB,SAAQ,aAAR;EACE,KAAK,KAAA;EACL,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;;AAGX,QAAO;;AAGT,SAAgB,kCACd,GAC0C;AAC1C,QACE,8BAA8B,EAAE,EAChC,yCACD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frozen-json.js","names":[],"sources":["../../../../replicache/src/frozen-json.ts"],"sourcesContent":["import {throwInvalidType} from '../../shared/src/asserts.ts';\nimport {skipAssertJSONValue} from '../../shared/src/config.ts';\nimport {hasOwn} from '../../shared/src/has-own.ts';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../shared/src/json.ts';\nimport {skipFreeze, skipFrozenAsserts} from './config.ts';\nimport type {Cookie, FrozenCookie} from './cookies.ts';\n\ndeclare const frozenJSONTag: unique symbol;\n\n/**\n * Used to mark a type as having been frozen.\n */\nexport type FrozenTag<T> = T & {readonly [frozenJSONTag]: true};\n\nexport type FrozenJSONValue =\n | null\n | string\n | boolean\n | number\n | FrozenJSONArray\n | FrozenJSONObject;\n\ntype FrozenJSONArray = FrozenTag<ReadonlyArray<FrozenJSONValue>>;\n\nexport type FrozenJSONObject = FrozenTag<{\n readonly [key: string]: FrozenJSONValue;\n}>;\n\n/**\n * We tag deep frozen objects in debug mode so that we do not have to deep\n * freeze an object more than once.\n */\nconst deepFrozenObjects = new WeakSet<object>();\n\n/**\n * Recursively freezes the passed in value (mutates it) and returns it.\n *\n * This is controlled by `skipFreeze` which is true in release mode.\n */\nexport function deepFreeze(v: Cookie): FrozenCookie;\nexport function deepFreeze(v: ReadonlyJSONValue): FrozenJSONValue;\nexport function deepFreeze(v: ReadonlyJSONValue): FrozenJSONValue {\n if (skipFreeze) {\n return v as FrozenJSONValue;\n }\n\n deepFreezeInternal(v, []);\n return v as FrozenJSONValue;\n}\n\nfunction deepFreezeInternal(\n v: ReadonlyJSONValue | undefined,\n seen: object[],\n): void {\n switch (typeof v) {\n case 'undefined':\n throw new TypeError('Unexpected value undefined');\n case 'boolean':\n case 'number':\n case 'string':\n return;\n case 'object': {\n if (v === null) {\n return;\n }\n\n if (deepFrozenObjects.has(v)) {\n return;\n }\n deepFrozenObjects.add(v);\n\n if (seen.includes(v)) {\n throwInvalidType(v, 'Cyclic JSON object');\n }\n\n seen.push(v);\n\n Object.freeze(v);\n if (Array.isArray(v)) {\n deepFreezeArray(v, seen);\n } else {\n deepFreezeObject(v as ReadonlyJSONObject, seen);\n }\n seen.pop();\n return;\n }\n\n default:\n throwInvalidType(v, 'JSON value');\n }\n}\n\nfunction deepFreezeArray(\n v: ReadonlyArray<ReadonlyJSONValue>,\n seen: object[],\n): void {\n for (const item of v) {\n deepFreezeInternal(item, seen);\n }\n}\n\nfunction deepFreezeObject(v: ReadonlyJSONObject, seen: object[]): void {\n for (const k in v) {\n if (hasOwn(v, k)) {\n const value = v[k];\n if (value !== undefined) {\n deepFreezeInternal(value, seen);\n }\n }\n }\n}\n\nexport function assertFrozenJSONValue(\n v: unknown,\n): asserts v is FrozenJSONValue {\n if (skipFrozenAsserts || skipAssertJSONValue) {\n return;\n }\n\n switch (typeof v) {\n case 'boolean':\n case 'number':\n case 'string':\n return;\n case 'object':\n if (v === null) {\n return;\n }\n\n if (isDeepFrozen(v, [])) {\n return;\n }\n }\n throwInvalidType(v, 'JSON value');\n}\n\nexport function assertDeepFrozen<V>(v: V): asserts v is Readonly<V> {\n if (skipFrozenAsserts) {\n return;\n }\n\n if (!isDeepFrozen(v, [])) {\n throw new Error('Expected frozen object');\n }\n}\n\n/**\n * Recursive deep frozen check.\n *\n * It adds frozen objects to the {@link deepFrozenObjects} WeakSet so that we do\n * not have to check the same object more than once.\n */\nexport function isDeepFrozen(v: unknown, seen: object[]): boolean {\n switch (typeof v) {\n case 'boolean':\n case 'number':\n case 'string':\n return true;\n case 'object':\n if (v === null) {\n return true;\n }\n\n if (deepFrozenObjects.has(v)) {\n return true;\n }\n\n if (!Object.isFrozen(v)) {\n return false;\n }\n\n if (seen.includes(v)) {\n throwInvalidType(v, 'Cyclic JSON object');\n }\n\n seen.push(v);\n\n if (Array.isArray(v)) {\n for (const item of v) {\n if (!isDeepFrozen(item, seen)) {\n seen.pop();\n return false;\n }\n }\n } else {\n for (const k in v) {\n if (hasOwn(v, k)) {\n const value = (v as Record<string, unknown>)[k];\n if (value !== undefined && !isDeepFrozen(value, seen)) {\n seen.pop();\n return false;\n }\n }\n }\n }\n\n deepFrozenObjects.add(v);\n seen.pop();\n return true;\n\n default:\n throwInvalidType(v, 'JSON value');\n }\n}\n\nexport type P = Parameters<typeof deepFreeze>[0];\nexport type R = ReturnType<typeof deepFreeze>;\nexport function deepFreezeAllowUndefined(v: P | undefined): R | undefined {\n if (v === undefined) {\n return undefined;\n }\n return deepFreeze(v) as R;\n}\n"],"mappings":";;;;;;;;;AAmCA,IAAM,oCAAoB,IAAI,
|
|
1
|
+
{"version":3,"file":"frozen-json.js","names":[],"sources":["../../../../replicache/src/frozen-json.ts"],"sourcesContent":["import {throwInvalidType} from '../../shared/src/asserts.ts';\nimport {skipAssertJSONValue} from '../../shared/src/config.ts';\nimport {hasOwn} from '../../shared/src/has-own.ts';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../shared/src/json.ts';\nimport {skipFreeze, skipFrozenAsserts} from './config.ts';\nimport type {Cookie, FrozenCookie} from './cookies.ts';\n\ndeclare const frozenJSONTag: unique symbol;\n\n/**\n * Used to mark a type as having been frozen.\n */\nexport type FrozenTag<T> = T & {readonly [frozenJSONTag]: true};\n\nexport type FrozenJSONValue =\n | null\n | string\n | boolean\n | number\n | FrozenJSONArray\n | FrozenJSONObject;\n\ntype FrozenJSONArray = FrozenTag<ReadonlyArray<FrozenJSONValue>>;\n\nexport type FrozenJSONObject = FrozenTag<{\n readonly [key: string]: FrozenJSONValue;\n}>;\n\n/**\n * We tag deep frozen objects in debug mode so that we do not have to deep\n * freeze an object more than once.\n */\nconst deepFrozenObjects = new WeakSet<object>();\n\n/**\n * Recursively freezes the passed in value (mutates it) and returns it.\n *\n * This is controlled by `skipFreeze` which is true in release mode.\n */\nexport function deepFreeze(v: Cookie): FrozenCookie;\nexport function deepFreeze(v: ReadonlyJSONValue): FrozenJSONValue;\nexport function deepFreeze(v: ReadonlyJSONValue): FrozenJSONValue {\n if (skipFreeze) {\n return v as FrozenJSONValue;\n }\n\n deepFreezeInternal(v, []);\n return v as FrozenJSONValue;\n}\n\nfunction deepFreezeInternal(\n v: ReadonlyJSONValue | undefined,\n seen: object[],\n): void {\n switch (typeof v) {\n case 'undefined':\n throw new TypeError('Unexpected value undefined');\n case 'boolean':\n case 'number':\n case 'string':\n return;\n case 'object': {\n if (v === null) {\n return;\n }\n\n if (deepFrozenObjects.has(v)) {\n return;\n }\n deepFrozenObjects.add(v);\n\n if (seen.includes(v)) {\n throwInvalidType(v, 'Cyclic JSON object');\n }\n\n seen.push(v);\n\n Object.freeze(v);\n if (Array.isArray(v)) {\n deepFreezeArray(v, seen);\n } else {\n deepFreezeObject(v as ReadonlyJSONObject, seen);\n }\n seen.pop();\n return;\n }\n\n default:\n throwInvalidType(v, 'JSON value');\n }\n}\n\nfunction deepFreezeArray(\n v: ReadonlyArray<ReadonlyJSONValue>,\n seen: object[],\n): void {\n for (const item of v) {\n deepFreezeInternal(item, seen);\n }\n}\n\nfunction deepFreezeObject(v: ReadonlyJSONObject, seen: object[]): void {\n for (const k in v) {\n if (hasOwn(v, k)) {\n const value = v[k];\n if (value !== undefined) {\n deepFreezeInternal(value, seen);\n }\n }\n }\n}\n\nexport function assertFrozenJSONValue(\n v: unknown,\n): asserts v is FrozenJSONValue {\n if (skipFrozenAsserts || skipAssertJSONValue) {\n return;\n }\n\n switch (typeof v) {\n case 'boolean':\n case 'number':\n case 'string':\n return;\n case 'object':\n if (v === null) {\n return;\n }\n\n if (isDeepFrozen(v, [])) {\n return;\n }\n }\n throwInvalidType(v, 'JSON value');\n}\n\nexport function assertDeepFrozen<V>(v: V): asserts v is Readonly<V> {\n if (skipFrozenAsserts) {\n return;\n }\n\n if (!isDeepFrozen(v, [])) {\n throw new Error('Expected frozen object');\n }\n}\n\n/**\n * Recursive deep frozen check.\n *\n * It adds frozen objects to the {@link deepFrozenObjects} WeakSet so that we do\n * not have to check the same object more than once.\n */\nexport function isDeepFrozen(v: unknown, seen: object[]): boolean {\n switch (typeof v) {\n case 'boolean':\n case 'number':\n case 'string':\n return true;\n case 'object':\n if (v === null) {\n return true;\n }\n\n if (deepFrozenObjects.has(v)) {\n return true;\n }\n\n if (!Object.isFrozen(v)) {\n return false;\n }\n\n if (seen.includes(v)) {\n throwInvalidType(v, 'Cyclic JSON object');\n }\n\n seen.push(v);\n\n if (Array.isArray(v)) {\n for (const item of v) {\n if (!isDeepFrozen(item, seen)) {\n seen.pop();\n return false;\n }\n }\n } else {\n for (const k in v) {\n if (hasOwn(v, k)) {\n const value = (v as Record<string, unknown>)[k];\n if (value !== undefined && !isDeepFrozen(value, seen)) {\n seen.pop();\n return false;\n }\n }\n }\n }\n\n deepFrozenObjects.add(v);\n seen.pop();\n return true;\n\n default:\n throwInvalidType(v, 'JSON value');\n }\n}\n\nexport type P = Parameters<typeof deepFreeze>[0];\nexport type R = ReturnType<typeof deepFreeze>;\nexport function deepFreezeAllowUndefined(v: P | undefined): R | undefined {\n if (v === undefined) {\n return undefined;\n }\n return deepFreeze(v) as R;\n}\n"],"mappings":";;;;;;;;;AAmCA,IAAM,oCAAoB,IAAI,SAAiB;AAS/C,SAAgB,WAAW,GAAuC;AAChE,KAAI,OACF,QAAO;AAGT,oBAAmB,GAAG,EAAE,CAAC;AACzB,QAAO;;AAGT,SAAS,mBACP,GACA,MACM;AACN,SAAQ,OAAO,GAAf;EACE,KAAK,YACH,OAAM,IAAI,UAAU,6BAA6B;EACnD,KAAK;EACL,KAAK;EACL,KAAK,SACH;EACF,KAAK;AACH,OAAI,MAAM,KACR;AAGF,OAAI,kBAAkB,IAAI,EAAE,CAC1B;AAEF,qBAAkB,IAAI,EAAE;AAExB,OAAI,KAAK,SAAS,EAAE,CAClB,kBAAiB,GAAG,qBAAqB;AAG3C,QAAK,KAAK,EAAE;AAEZ,UAAO,OAAO,EAAE;AAChB,OAAI,MAAM,QAAQ,EAAE,CAClB,iBAAgB,GAAG,KAAK;OAExB,kBAAiB,GAAyB,KAAK;AAEjD,QAAK,KAAK;AACV;EAGF,QACE,kBAAiB,GAAG,aAAa;;;AAIvC,SAAS,gBACP,GACA,MACM;AACN,MAAK,MAAM,QAAQ,EACjB,oBAAmB,MAAM,KAAK;;AAIlC,SAAS,iBAAiB,GAAuB,MAAsB;AACrE,MAAK,MAAM,KAAK,EACd,KAAI,OAAO,GAAG,EAAE,EAAE;EAChB,MAAM,QAAQ,EAAE;AAChB,MAAI,UAAU,KAAA,EACZ,oBAAmB,OAAO,KAAK;;;AA8BvC,SAAgB,iBAAoB,GAAgC;AAClE,KAAI,OACF;AAGF,KAAI,CAAC,aAAa,GAAG,EAAE,CAAC,CACtB,OAAM,IAAI,MAAM,yBAAyB;;;;;;;;AAU7C,SAAgB,aAAa,GAAY,MAAyB;AAChE,SAAQ,OAAO,GAAf;EACE,KAAK;EACL,KAAK;EACL,KAAK,SACH,QAAO;EACT,KAAK;AACH,OAAI,MAAM,KACR,QAAO;AAGT,OAAI,kBAAkB,IAAI,EAAE,CAC1B,QAAO;AAGT,OAAI,CAAC,OAAO,SAAS,EAAE,CACrB,QAAO;AAGT,OAAI,KAAK,SAAS,EAAE,CAClB,kBAAiB,GAAG,qBAAqB;AAG3C,QAAK,KAAK,EAAE;AAEZ,OAAI,MAAM,QAAQ,EAAE;SACb,MAAM,QAAQ,EACjB,KAAI,CAAC,aAAa,MAAM,KAAK,EAAE;AAC7B,UAAK,KAAK;AACV,YAAO;;SAIX,MAAK,MAAM,KAAK,EACd,KAAI,OAAO,GAAG,EAAE,EAAE;IAChB,MAAM,QAAS,EAA8B;AAC7C,QAAI,UAAU,KAAA,KAAa,CAAC,aAAa,OAAO,KAAK,EAAE;AACrD,UAAK,KAAK;AACV,YAAO;;;AAMf,qBAAkB,IAAI,EAAE;AACxB,QAAK,KAAK;AACV,UAAO;EAET,QACE,kBAAiB,GAAG,aAAa;;;AAMvC,SAAgB,yBAAyB,GAAiC;AACxE,KAAI,MAAM,KAAA,EACR;AAEF,QAAO,WAAW,EAAE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-default-puller.js","names":[],"sources":["../../../../replicache/src/get-default-puller.ts"],"sourcesContent":["import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\nimport {callDefaultFetch} from './call-default-fetch.ts';\nimport {assertCookie} from './cookies.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport {assertHTTPRequestInfo} from './http-request-info.ts';\nimport {assertPatchOperations} from './patch-operation.ts';\nimport type {\n PullResponseV1,\n Puller,\n PullerResult,\n PullerResultV1,\n} from './puller.ts';\nimport type {PullRequest} from './sync/pull.ts';\n\n/**\n * This creates a default puller which uses HTTP POST to send the pull request.\n */\nexport function getDefaultPuller(rep: {pullURL: string; auth: string}): Puller {\n async function puller(\n requestBody: PullRequest,\n requestID: string,\n ): Promise<PullerResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pullURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n return {\n response: await response.json(),\n httpRequestInfo,\n };\n }\n\n defaultPullers.add(puller);\n return puller;\n}\n\nconst defaultPullers = new WeakSet();\n\nexport function isDefaultPuller(puller: Puller): boolean {\n return defaultPullers.has(puller);\n}\n\nexport function assertPullResponseV1(v: unknown): asserts v is PullResponseV1 {\n assertObject(v);\n if (isClientStateNotFoundResponse(v) || isVersionNotSupportedResponse(v)) {\n return;\n }\n if (v.cookie !== undefined) {\n assertCookie(v.cookie);\n }\n assertLastMutationIDChanges(v.lastMutationIDChanges);\n assertPatchOperations(v.patch);\n}\n\nfunction assertLastMutationIDChanges(\n lastMutationIDChanges: unknown,\n): asserts lastMutationIDChanges is Record<string, number> {\n assertObject(lastMutationIDChanges);\n for (const [key, value] of Object.entries(lastMutationIDChanges)) {\n assertString(key);\n assertNumber(value);\n }\n}\n\nexport function assertPullerResultV1(v: unknown): asserts v is PullerResultV1 {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPullResponseV1(v.response);\n }\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAgB,iBAAiB,KAA8C;CAC7E,eAAe,OACb,aACA,WACuB;EACvB,MAAM,CAAC,UAAU,mBAAmB,MAAM,iBACxC,IAAI,SACJ,IAAI,MACJ,WACA,
|
|
1
|
+
{"version":3,"file":"get-default-puller.js","names":[],"sources":["../../../../replicache/src/get-default-puller.ts"],"sourcesContent":["import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\nimport {callDefaultFetch} from './call-default-fetch.ts';\nimport {assertCookie} from './cookies.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport {assertHTTPRequestInfo} from './http-request-info.ts';\nimport {assertPatchOperations} from './patch-operation.ts';\nimport type {\n PullResponseV1,\n Puller,\n PullerResult,\n PullerResultV1,\n} from './puller.ts';\nimport type {PullRequest} from './sync/pull.ts';\n\n/**\n * This creates a default puller which uses HTTP POST to send the pull request.\n */\nexport function getDefaultPuller(rep: {pullURL: string; auth: string}): Puller {\n async function puller(\n requestBody: PullRequest,\n requestID: string,\n ): Promise<PullerResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pullURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n return {\n response: await response.json(),\n httpRequestInfo,\n };\n }\n\n defaultPullers.add(puller);\n return puller;\n}\n\nconst defaultPullers = new WeakSet();\n\nexport function isDefaultPuller(puller: Puller): boolean {\n return defaultPullers.has(puller);\n}\n\nexport function assertPullResponseV1(v: unknown): asserts v is PullResponseV1 {\n assertObject(v);\n if (isClientStateNotFoundResponse(v) || isVersionNotSupportedResponse(v)) {\n return;\n }\n if (v.cookie !== undefined) {\n assertCookie(v.cookie);\n }\n assertLastMutationIDChanges(v.lastMutationIDChanges);\n assertPatchOperations(v.patch);\n}\n\nfunction assertLastMutationIDChanges(\n lastMutationIDChanges: unknown,\n): asserts lastMutationIDChanges is Record<string, number> {\n assertObject(lastMutationIDChanges);\n for (const [key, value] of Object.entries(lastMutationIDChanges)) {\n assertString(key);\n assertNumber(value);\n }\n}\n\nexport function assertPullerResultV1(v: unknown): asserts v is PullerResultV1 {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPullResponseV1(v.response);\n }\n}\n"],"mappings":";;;;;;;;;;AAwBA,SAAgB,iBAAiB,KAA8C;CAC7E,eAAe,OACb,aACA,WACuB;EACvB,MAAM,CAAC,UAAU,mBAAmB,MAAM,iBACxC,IAAI,SACJ,IAAI,MACJ,WACA,YACD;AACD,MAAI,CAAC,SACH,QAAO,EAAC,iBAAgB;AAG1B,SAAO;GACL,UAAU,MAAM,SAAS,MAAM;GAC/B;GACD;;AAGH,gBAAe,IAAI,OAAO;AAC1B,QAAO;;AAGT,IAAM,iCAAiB,IAAI,SAAS;AAEpC,SAAgB,gBAAgB,QAAyB;AACvD,QAAO,eAAe,IAAI,OAAO;;AAGnC,SAAgB,qBAAqB,GAAyC;AAC5E,cAAa,EAAE;AACf,KAAI,8BAA8B,EAAE,IAAI,8BAA8B,EAAE,CACtE;AAEF,KAAI,EAAE,WAAW,KAAA,EACf,cAAa,EAAE,OAAO;AAExB,6BAA4B,EAAE,sBAAsB;AACpD,uBAAsB,EAAE,MAAM;;AAGhC,SAAS,4BACP,uBACyD;AACzD,cAAa,sBAAsB;AACnC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,sBAAsB,EAAE;AAChE,eAAa,IAAI;AACjB,eAAa,MAAM;;;AAIvB,SAAgB,qBAAqB,GAAyC;AAC5E,cAAa,EAAE;AACf,uBAAsB,EAAE,gBAAgB;AACxC,KAAI,EAAE,aAAa,KAAA,EACjB,sBAAqB,EAAE,SAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-default-pusher.js","names":[],"sources":["../../../../replicache/src/get-default-pusher.ts"],"sourcesContent":["import {callDefaultFetch} from './call-default-fetch.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport type {Pusher, PusherResult} from './pusher.ts';\nimport type {PushRequest} from './sync/push.ts';\n\n/**\n * This creates a default pusher which uses HTTP POST to send the push request.\n */\nexport function getDefaultPusher(rep: {pushURL: string; auth: string}): Pusher {\n async function pusher(\n requestBody: PushRequest,\n requestID: string,\n ): Promise<PusherResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pushURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n const rv: PusherResult = {\n httpRequestInfo,\n };\n\n let result;\n try {\n result = await response.json();\n } catch {\n // Ignore JSON parse errors. It is valid to return a non-JSON response.\n return rv;\n }\n\n if (\n isClientStateNotFoundResponse(result) ||\n isVersionNotSupportedResponse(result)\n ) {\n rv.response = result;\n }\n\n return rv;\n }\n\n defaultPushers.add(pusher);\n return pusher;\n}\n\nconst defaultPushers = new WeakSet();\n\nexport function isDefaultPusher(pusher: Pusher): boolean {\n return defaultPushers.has(pusher);\n}\n"],"mappings":";;;;;;AAWA,SAAgB,iBAAiB,KAA8C;CAC7E,eAAe,OACb,aACA,WACuB;EACvB,MAAM,CAAC,UAAU,mBAAmB,MAAM,iBACxC,IAAI,SACJ,IAAI,MACJ,WACA,
|
|
1
|
+
{"version":3,"file":"get-default-pusher.js","names":[],"sources":["../../../../replicache/src/get-default-pusher.ts"],"sourcesContent":["import {callDefaultFetch} from './call-default-fetch.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport type {Pusher, PusherResult} from './pusher.ts';\nimport type {PushRequest} from './sync/push.ts';\n\n/**\n * This creates a default pusher which uses HTTP POST to send the push request.\n */\nexport function getDefaultPusher(rep: {pushURL: string; auth: string}): Pusher {\n async function pusher(\n requestBody: PushRequest,\n requestID: string,\n ): Promise<PusherResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pushURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n const rv: PusherResult = {\n httpRequestInfo,\n };\n\n let result;\n try {\n result = await response.json();\n } catch {\n // Ignore JSON parse errors. It is valid to return a non-JSON response.\n return rv;\n }\n\n if (\n isClientStateNotFoundResponse(result) ||\n isVersionNotSupportedResponse(result)\n ) {\n rv.response = result;\n }\n\n return rv;\n }\n\n defaultPushers.add(pusher);\n return pusher;\n}\n\nconst defaultPushers = new WeakSet();\n\nexport function isDefaultPusher(pusher: Pusher): boolean {\n return defaultPushers.has(pusher);\n}\n"],"mappings":";;;;;;AAWA,SAAgB,iBAAiB,KAA8C;CAC7E,eAAe,OACb,aACA,WACuB;EACvB,MAAM,CAAC,UAAU,mBAAmB,MAAM,iBACxC,IAAI,SACJ,IAAI,MACJ,WACA,YACD;AACD,MAAI,CAAC,SACH,QAAO,EAAC,iBAAgB;EAG1B,MAAM,KAAmB,EACvB,iBACD;EAED,IAAI;AACJ,MAAI;AACF,YAAS,MAAM,SAAS,MAAM;UACxB;AAEN,UAAO;;AAGT,MACE,8BAA8B,OAAO,IACrC,8BAA8B,OAAO,CAErC,IAAG,WAAW;AAGhB,SAAO;;AAGT,gBAAe,IAAI,OAAO;AAC1B,QAAO;;AAGT,IAAM,iCAAiB,IAAI,SAAS;AAEpC,SAAgB,gBAAgB,QAAyB;AACvD,QAAO,eAAe,IAAI,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-kv-store-provider.js","names":[],"sources":["../../../../replicache/src/get-kv-store-provider.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {\n dropIDBStoreWithMemFallback,\n newIDBStoreWithMemFallback,\n} from './kv/idb-store-with-mem-fallback.ts';\nimport {dropMemStore, MemStore} from './kv/mem-store.ts';\nimport type {StoreProvider} from './kv/store.ts';\n\nexport function getKVStoreProvider(\n lc: LogContext,\n kvStore: 'mem' | 'idb' | StoreProvider | undefined,\n): StoreProvider {\n switch (kvStore) {\n case 'idb':\n case undefined:\n return {\n create: name => newIDBStoreWithMemFallback(lc, name),\n drop: dropIDBStoreWithMemFallback,\n };\n case 'mem':\n return {\n create: name => new MemStore(name),\n drop: name => dropMemStore(name),\n };\n default:\n return kvStore;\n }\n}\n"],"mappings":";;;AAQA,SAAgB,mBACd,IACA,SACe;
|
|
1
|
+
{"version":3,"file":"get-kv-store-provider.js","names":[],"sources":["../../../../replicache/src/get-kv-store-provider.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {\n dropIDBStoreWithMemFallback,\n newIDBStoreWithMemFallback,\n} from './kv/idb-store-with-mem-fallback.ts';\nimport {dropMemStore, MemStore} from './kv/mem-store.ts';\nimport type {StoreProvider} from './kv/store.ts';\n\nexport function getKVStoreProvider(\n lc: LogContext,\n kvStore: 'mem' | 'idb' | StoreProvider | undefined,\n): StoreProvider {\n switch (kvStore) {\n case 'idb':\n case undefined:\n return {\n create: name => newIDBStoreWithMemFallback(lc, name),\n drop: dropIDBStoreWithMemFallback,\n };\n case 'mem':\n return {\n create: name => new MemStore(name),\n drop: name => dropMemStore(name),\n };\n default:\n return kvStore;\n }\n}\n"],"mappings":";;;AAQA,SAAgB,mBACd,IACA,SACe;AACf,SAAQ,SAAR;EACE,KAAK;EACL,KAAK,KAAA,EACH,QAAO;GACL,SAAQ,SAAQ,2BAA2B,IAAI,KAAK;GACpD,MAAM;GACP;EACH,KAAK,MACH,QAAO;GACL,SAAQ,SAAQ,IAAI,SAAS,KAAK;GAClC,OAAM,SAAQ,aAAa,KAAK;GACjC;EACH,QACE,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hash.js","names":[],"sources":["../../../../replicache/src/hash.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {randomUint64} from '../../shared/src/random-uint64.ts';\nimport * as valita from '../../shared/src/valita.ts';\n\nexport const STRING_LENGTH = 22;\n\n// We use an opaque type so that we can make sure that a hash is always a hash.\n// TypeScript does not have direct support but we can use a trick described\n// here:\n//\n// https://evertpot.com/opaque-ts-types/\n//\n// The basic idea is to declare a type that cannot be created. We then use\n// functions that cast a string to this type.\n//\n\n// By using declare we tell the type system that there is a unique symbol.\n// However, there is no such symbol but the type system does not care.\ndeclare const hashTag: unique symbol;\n\n/**\n * Opaque type representing a hash. The only way to create one is using `parse`\n * or `hashOf` (except for static unsafe cast of course).\n */\nexport type Hash = string & {[hashTag]: true};\n\n// We are no longer using hashes but due to legacy reason we still refer to\n// them as hashes. We use UUID and counters instead.\nconst hashRe = /^[0-9a-v-]+$/;\n\nexport function parse(s: string): Hash {\n assertHash(s);\n return s;\n}\n\nconst emptyUUID = '0'.repeat(STRING_LENGTH);\nexport const emptyHash = emptyUUID as unknown as Hash;\n\n/**\n * Creates a function that generates random hashes.\n */\nexport const newRandomHash = makeNewRandomHashFunctionInternal();\n\nconst fakeHashRe = /^[0-9a-v]{0,8}$/;\n\n/**\n * Creates a function that generates UUID hashes for tests.\n */\nexport function makeNewFakeHashFunction(hashPrefix = 'fake'): () => Hash {\n assert(fakeHashRe.test(hashPrefix), `Invalid hash prefix: ${hashPrefix}`);\n let i = 0;\n return () => {\n const count = String(i++);\n return (hashPrefix +\n '0'.repeat(STRING_LENGTH - hashPrefix.length - count.length) +\n count) as Hash;\n };\n}\n\nfunction toStringAndSlice(n: number | bigint, len: number): string {\n return n.toString(32).slice(-len).padStart(len, '0');\n}\n\n/**\n * This creates an ID that looks like `<RANDOM><COUNTER>`. The random part is\n * a random number encoded with base 32 and the length is 12 characters. The\n * is 10 characters long and encoded as base 32. The total length is 22 characters.\n *\n * Do the math: https://devina.io/collision-calculator\n */\nfunction makeNewRandomHashFunctionInternal(): () => Hash {\n let base = '';\n let i = 0;\n\n return () => {\n if (!base) {\n // This needs to be lazy because the cloudflare worker environment will\n // throw an error if crypto.getRandomValues is used statically. Specifically:\n // Error: Some functionality, such as asynchronous I/O, timeouts, and\n // generating random values, can only be performed while handling a\n // request.\n base = toStringAndSlice(randomUint64(), 12);\n }\n const tail = toStringAndSlice(i++, 10);\n return (base + tail) as Hash;\n };\n}\n\n/**\n * Generates a fake hash useful for testing.\n */\nexport function fakeHash(word: string | number): Hash {\n if (typeof word === 'number') {\n word = String(word);\n }\n return ('fake' + '0'.repeat(STRING_LENGTH - 4 - word.length) + word) as Hash;\n}\n\nexport function isHash(value: unknown): value is Hash {\n return typeof value === 'string' && hashRe.test(value);\n}\n\nexport function assertHash(value: unknown): asserts value is Hash {\n valita.assert(value, hashSchema);\n}\n\nexport const hashSchema = valita.string().assert(isHash, 'Invalid hash');\n"],"mappings":";;AA4BA,IAAM,SAAS;AAQf,IAAa,YADK,IAAI,OAAA,
|
|
1
|
+
{"version":3,"file":"hash.js","names":[],"sources":["../../../../replicache/src/hash.ts"],"sourcesContent":["import {assert} from '../../shared/src/asserts.ts';\nimport {randomUint64} from '../../shared/src/random-uint64.ts';\nimport * as valita from '../../shared/src/valita.ts';\n\nexport const STRING_LENGTH = 22;\n\n// We use an opaque type so that we can make sure that a hash is always a hash.\n// TypeScript does not have direct support but we can use a trick described\n// here:\n//\n// https://evertpot.com/opaque-ts-types/\n//\n// The basic idea is to declare a type that cannot be created. We then use\n// functions that cast a string to this type.\n//\n\n// By using declare we tell the type system that there is a unique symbol.\n// However, there is no such symbol but the type system does not care.\ndeclare const hashTag: unique symbol;\n\n/**\n * Opaque type representing a hash. The only way to create one is using `parse`\n * or `hashOf` (except for static unsafe cast of course).\n */\nexport type Hash = string & {[hashTag]: true};\n\n// We are no longer using hashes but due to legacy reason we still refer to\n// them as hashes. We use UUID and counters instead.\nconst hashRe = /^[0-9a-v-]+$/;\n\nexport function parse(s: string): Hash {\n assertHash(s);\n return s;\n}\n\nconst emptyUUID = '0'.repeat(STRING_LENGTH);\nexport const emptyHash = emptyUUID as unknown as Hash;\n\n/**\n * Creates a function that generates random hashes.\n */\nexport const newRandomHash = makeNewRandomHashFunctionInternal();\n\nconst fakeHashRe = /^[0-9a-v]{0,8}$/;\n\n/**\n * Creates a function that generates UUID hashes for tests.\n */\nexport function makeNewFakeHashFunction(hashPrefix = 'fake'): () => Hash {\n assert(fakeHashRe.test(hashPrefix), `Invalid hash prefix: ${hashPrefix}`);\n let i = 0;\n return () => {\n const count = String(i++);\n return (hashPrefix +\n '0'.repeat(STRING_LENGTH - hashPrefix.length - count.length) +\n count) as Hash;\n };\n}\n\nfunction toStringAndSlice(n: number | bigint, len: number): string {\n return n.toString(32).slice(-len).padStart(len, '0');\n}\n\n/**\n * This creates an ID that looks like `<RANDOM><COUNTER>`. The random part is\n * a random number encoded with base 32 and the length is 12 characters. The\n * is 10 characters long and encoded as base 32. The total length is 22 characters.\n *\n * Do the math: https://devina.io/collision-calculator\n */\nfunction makeNewRandomHashFunctionInternal(): () => Hash {\n let base = '';\n let i = 0;\n\n return () => {\n if (!base) {\n // This needs to be lazy because the cloudflare worker environment will\n // throw an error if crypto.getRandomValues is used statically. Specifically:\n // Error: Some functionality, such as asynchronous I/O, timeouts, and\n // generating random values, can only be performed while handling a\n // request.\n base = toStringAndSlice(randomUint64(), 12);\n }\n const tail = toStringAndSlice(i++, 10);\n return (base + tail) as Hash;\n };\n}\n\n/**\n * Generates a fake hash useful for testing.\n */\nexport function fakeHash(word: string | number): Hash {\n if (typeof word === 'number') {\n word = String(word);\n }\n return ('fake' + '0'.repeat(STRING_LENGTH - 4 - word.length) + word) as Hash;\n}\n\nexport function isHash(value: unknown): value is Hash {\n return typeof value === 'string' && hashRe.test(value);\n}\n\nexport function assertHash(value: unknown): asserts value is Hash {\n valita.assert(value, hashSchema);\n}\n\nexport const hashSchema = valita.string().assert(isHash, 'Invalid hash');\n"],"mappings":";;AA4BA,IAAM,SAAS;AAQf,IAAa,YADK,IAAI,OAAA,GAAqB;;;;AAM3C,IAAa,gBAAgB,mCAAmC;AAkBhE,SAAS,iBAAiB,GAAoB,KAAqB;AACjE,QAAO,EAAE,SAAS,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,KAAK,IAAI;;;;;;;;;AAUtD,SAAS,oCAAgD;CACvD,IAAI,OAAO;CACX,IAAI,IAAI;AAER,cAAa;AACX,MAAI,CAAC,KAMH,QAAO,iBAAiB,cAAc,EAAE,GAAG;EAE7C,MAAM,OAAO,iBAAiB,KAAK,GAAG;AACtC,SAAQ,OAAO;;;AAcnB,SAAgB,OAAO,OAA+B;AACpD,QAAO,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM;;AAGxD,SAAgB,WAAW,OAAuC;AAChE,QAAc,OAAO,WAAW;;AAGlC,IAAa,aAAa,eAAO,QAAQ,CAAC,OAAO,QAAQ,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-request-info.js","names":[],"sources":["../../../../replicache/src/http-request-info.ts"],"sourcesContent":["import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\n\nexport function assertHTTPRequestInfo(\n v: unknown,\n): asserts v is HTTPRequestInfo {\n assertObject(v);\n assertNumber(v.httpStatusCode);\n assertString(v.errorMessage);\n}\n\nexport type HTTPRequestInfo = {\n httpStatusCode: number;\n errorMessage: string;\n};\n"],"mappings":";;AAMA,SAAgB,sBACd,GAC8B;
|
|
1
|
+
{"version":3,"file":"http-request-info.js","names":[],"sources":["../../../../replicache/src/http-request-info.ts"],"sourcesContent":["import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\n\nexport function assertHTTPRequestInfo(\n v: unknown,\n): asserts v is HTTPRequestInfo {\n assertObject(v);\n assertNumber(v.httpStatusCode);\n assertString(v.errorMessage);\n}\n\nexport type HTTPRequestInfo = {\n httpStatusCode: number;\n errorMessage: string;\n};\n"],"mappings":";;AAMA,SAAgB,sBACd,GAC8B;AAC9B,cAAa,EAAE;AACf,cAAa,EAAE,eAAe;AAC9B,cAAa,EAAE,aAAa"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-defs.js","names":[],"sources":["../../../../replicache/src/index-defs.ts"],"sourcesContent":["import * as valita from '../../shared/src/valita.ts';\n\n/**\n * The definition of a single index.\n */\nexport type IndexDefinition = {\n /**\n * The prefix, if any, to limit the index over. If not provided the values of\n * all keys are indexed.\n */\n readonly prefix?: string | undefined;\n\n /**\n * A [JSON Pointer](https://tools.ietf.org/html/rfc6901) pointing at the sub\n * value inside each value to index over.\n *\n * For example, one might index over users' ages like so:\n * `{prefix: '/user/', jsonPointer: '/age'}`\n */\n readonly jsonPointer: string;\n\n /**\n * If `true`, indexing empty values will not emit a warning. Defaults to `false`.\n */\n readonly allowEmpty?: boolean | undefined;\n};\n\nexport const indexDefinitionSchema: valita.Type<IndexDefinition> =\n valita.readonlyObject({\n prefix: valita.string().optional(),\n jsonPointer: valita.string(),\n allowEmpty: valita.boolean().optional(),\n });\n\n/**\n * An object as a map defining the indexes. The keys are the index names and the\n * values are the index definitions.\n */\nexport type IndexDefinitions = {readonly [name: string]: IndexDefinition};\n\nexport const indexDefinitionsSchema = valita.readonlyRecord(\n indexDefinitionSchema,\n);\n\nexport function indexDefinitionEqual(\n a: IndexDefinition,\n b: IndexDefinition,\n): boolean {\n return (\n a.jsonPointer === b.jsonPointer &&\n (a.allowEmpty ?? false) === (b.allowEmpty ?? false) &&\n (a.prefix ?? '') === (b.prefix ?? '')\n );\n}\n\nexport function indexDefinitionsEqual(\n a: IndexDefinitions,\n b: IndexDefinitions,\n): boolean {\n if (Object.keys(a).length !== Object.keys(b).length) {\n return false;\n }\n for (const [aKey, aValue] of Object.entries(a)) {\n const bValue = b[aKey];\n if (!bValue || !indexDefinitionEqual(aValue, bValue)) {\n return false;\n }\n }\n return true;\n}\n\nexport function assertIndexDefinitions(\n value: unknown,\n): asserts value is IndexDefinitions {\n valita.assert(value, indexDefinitionsSchema);\n}\n"],"mappings":";AAwCA,IAAa,yBAAyB,eAZpC,eAAsB;CACpB,QAAQ,eAAO,
|
|
1
|
+
{"version":3,"file":"index-defs.js","names":[],"sources":["../../../../replicache/src/index-defs.ts"],"sourcesContent":["import * as valita from '../../shared/src/valita.ts';\n\n/**\n * The definition of a single index.\n */\nexport type IndexDefinition = {\n /**\n * The prefix, if any, to limit the index over. If not provided the values of\n * all keys are indexed.\n */\n readonly prefix?: string | undefined;\n\n /**\n * A [JSON Pointer](https://tools.ietf.org/html/rfc6901) pointing at the sub\n * value inside each value to index over.\n *\n * For example, one might index over users' ages like so:\n * `{prefix: '/user/', jsonPointer: '/age'}`\n */\n readonly jsonPointer: string;\n\n /**\n * If `true`, indexing empty values will not emit a warning. Defaults to `false`.\n */\n readonly allowEmpty?: boolean | undefined;\n};\n\nexport const indexDefinitionSchema: valita.Type<IndexDefinition> =\n valita.readonlyObject({\n prefix: valita.string().optional(),\n jsonPointer: valita.string(),\n allowEmpty: valita.boolean().optional(),\n });\n\n/**\n * An object as a map defining the indexes. The keys are the index names and the\n * values are the index definitions.\n */\nexport type IndexDefinitions = {readonly [name: string]: IndexDefinition};\n\nexport const indexDefinitionsSchema = valita.readonlyRecord(\n indexDefinitionSchema,\n);\n\nexport function indexDefinitionEqual(\n a: IndexDefinition,\n b: IndexDefinition,\n): boolean {\n return (\n a.jsonPointer === b.jsonPointer &&\n (a.allowEmpty ?? false) === (b.allowEmpty ?? false) &&\n (a.prefix ?? '') === (b.prefix ?? '')\n );\n}\n\nexport function indexDefinitionsEqual(\n a: IndexDefinitions,\n b: IndexDefinitions,\n): boolean {\n if (Object.keys(a).length !== Object.keys(b).length) {\n return false;\n }\n for (const [aKey, aValue] of Object.entries(a)) {\n const bValue = b[aKey];\n if (!bValue || !indexDefinitionEqual(aValue, bValue)) {\n return false;\n }\n }\n return true;\n}\n\nexport function assertIndexDefinitions(\n value: unknown,\n): asserts value is IndexDefinitions {\n valita.assert(value, indexDefinitionsSchema);\n}\n"],"mappings":";AAwCA,IAAa,yBAAyB,eAZpC,eAAsB;CACpB,QAAQ,eAAO,QAAQ,CAAC,UAAU;CAClC,aAAa,eAAO,QAAQ;CAC5B,YAAY,eAAO,SAAS,CAAC,UAAU;CACxC,CAAC,CAUH;AAED,SAAgB,qBACd,GACA,GACS;AACT,QACE,EAAE,gBAAgB,EAAE,gBACnB,EAAE,cAAc,YAAY,EAAE,cAAc,WAC5C,EAAE,UAAU,SAAS,EAAE,UAAU;;AAItC,SAAgB,sBACd,GACA,GACS;AACT,KAAI,OAAO,KAAK,EAAE,CAAC,WAAW,OAAO,KAAK,EAAE,CAAC,OAC3C,QAAO;AAET,MAAK,MAAM,CAAC,MAAM,WAAW,OAAO,QAAQ,EAAE,EAAE;EAC9C,MAAM,SAAS,EAAE;AACjB,MAAI,CAAC,UAAU,CAAC,qBAAqB,QAAQ,OAAO,CAClD,QAAO;;AAGX,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","names":["#statement","#db","#filename","#statements"],"sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"sourcesContent":["import {\n deleteDatabaseSync,\n openDatabaseSync,\n type SQLiteDatabase as DB,\n type SQLiteStatement,\n} from 'expo-sqlite';\nimport type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\n\nexport type ExpoSQLiteStoreOptions = SQLiteStoreOptions;\n\nexport function dropExpoSQLiteStore(\n name: string,\n opts?: ExpoSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(name, filename => new ExpoSQLiteDatabase(filename), opts);\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using expo-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n */\nexport function expoSQLiteStoreProvider(\n opts?: ExpoSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(name, name => new ExpoSQLiteDatabase(name), opts),\n drop: name => dropExpoSQLiteStore(name, opts),\n };\n}\n\nclass ExpoSQLitePreparedStatement implements PreparedStatement {\n readonly #statement: SQLiteStatement;\n\n constructor(statement: SQLiteStatement) {\n this.#statement = statement;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#statement.executeForRawResultAsync(params);\n }\n\n async all(params: string[]): Promise<unknown[][]> {\n const result = await this.#statement.executeForRawResultAsync(params);\n return result.getAllAsync() as Promise<unknown[][]>;\n }\n}\n\nclass ExpoSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n readonly #statements: Set<SQLiteStatement> = new Set();\n\n constructor(filename: string) {\n this.#filename = filename;\n this.#db = openDatabaseSync(filename);\n }\n\n close(): void {\n for (const stmt of this.#statements) {\n stmt.finalizeSync();\n }\n this.#db.closeSync();\n }\n\n destroy(): void {\n deleteDatabaseSync(this.#filename);\n }\n\n prepare(sql: string): PreparedStatement {\n const statement = this.#db.prepareSync(sql);\n this.#statements.add(statement);\n return new ExpoSQLitePreparedStatement(statement);\n }\n\n execSync(sql: string): void {\n this.#db.execSync(sql);\n }\n}\n"],"mappings":";;;AAgBA,SAAgB,oBACd,MACA,MACe;
|
|
1
|
+
{"version":3,"file":"store.js","names":["#statement","#db","#filename","#statements"],"sources":["../../../../../../replicache/src/kv/expo-sqlite/store.ts"],"sourcesContent":["import {\n deleteDatabaseSync,\n openDatabaseSync,\n type SQLiteDatabase as DB,\n type SQLiteStatement,\n} from 'expo-sqlite';\nimport type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\n\nexport type ExpoSQLiteStoreOptions = SQLiteStoreOptions;\n\nexport function dropExpoSQLiteStore(\n name: string,\n opts?: ExpoSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(name, filename => new ExpoSQLiteDatabase(filename), opts);\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using expo-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n */\nexport function expoSQLiteStoreProvider(\n opts?: ExpoSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(name, name => new ExpoSQLiteDatabase(name), opts),\n drop: name => dropExpoSQLiteStore(name, opts),\n };\n}\n\nclass ExpoSQLitePreparedStatement implements PreparedStatement {\n readonly #statement: SQLiteStatement;\n\n constructor(statement: SQLiteStatement) {\n this.#statement = statement;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#statement.executeForRawResultAsync(params);\n }\n\n async all(params: string[]): Promise<unknown[][]> {\n const result = await this.#statement.executeForRawResultAsync(params);\n return result.getAllAsync() as Promise<unknown[][]>;\n }\n}\n\nclass ExpoSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n readonly #statements: Set<SQLiteStatement> = new Set();\n\n constructor(filename: string) {\n this.#filename = filename;\n this.#db = openDatabaseSync(filename);\n }\n\n close(): void {\n for (const stmt of this.#statements) {\n stmt.finalizeSync();\n }\n this.#db.closeSync();\n }\n\n destroy(): void {\n deleteDatabaseSync(this.#filename);\n }\n\n prepare(sql: string): PreparedStatement {\n const statement = this.#db.prepareSync(sql);\n this.#statements.add(statement);\n return new ExpoSQLitePreparedStatement(statement);\n }\n\n execSync(sql: string): void {\n this.#db.execSync(sql);\n }\n}\n"],"mappings":";;;AAgBA,SAAgB,oBACd,MACA,MACe;AACf,QAAO,UAAU,OAAM,aAAY,IAAI,mBAAmB,SAAS,EAAE,KAAK;;;;;;;AAQ5E,SAAgB,wBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YAAY,OAAM,SAAQ,IAAI,mBAAmB,KAAK,EAAE,KAAK;EACnE,OAAM,SAAQ,oBAAoB,MAAM,KAAK;EAC9C;;AAGH,IAAM,8BAAN,MAA+D;CAC7D;CAEA,YAAY,WAA4B;AACtC,QAAA,YAAkB;;CAGpB,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,UAAgB,yBAAyB,OAAO;;CAGxD,MAAM,IAAI,QAAwC;AAEhD,UADe,MAAM,MAAA,UAAgB,yBAAyB,OAAO,EACvD,aAAa;;;AAI/B,IAAM,qBAAN,MAAmD;CACjD;CACA;CACA,8BAA6C,IAAI,KAAK;CAEtD,YAAY,UAAkB;AAC5B,QAAA,WAAiB;AACjB,QAAA,KAAW,iBAAiB,SAAS;;CAGvC,QAAc;AACZ,OAAK,MAAM,QAAQ,MAAA,WACjB,MAAK,cAAc;AAErB,QAAA,GAAS,WAAW;;CAGtB,UAAgB;AACd,qBAAmB,MAAA,SAAe;;CAGpC,QAAQ,KAAgC;EACtC,MAAM,YAAY,MAAA,GAAS,YAAY,IAAI;AAC3C,QAAA,WAAiB,IAAI,UAAU;AAC/B,SAAO,IAAI,4BAA4B,UAAU;;CAGnD,SAAS,KAAmB;AAC1B,QAAA,GAAS,SAAS,IAAI"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idb-store-with-mem-fallback.js","names":["#lc","#name","#store","#withBrainTransplant"],"sources":["../../../../../replicache/src/kv/idb-store-with-mem-fallback.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {navigator} from '../../../shared/src/navigator.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {IDBStore} from './idb-store.ts';\nimport {MemStore, dropMemStore} from './mem-store.ts';\nimport type {Read, Store, Write} from './store.ts';\n\n/**\n * This store uses an {@link IDBStore} by default. If the {@link IDBStore} fails\n * to open the DB with an exception that matches\n * {@link isFirefoxPrivateBrowsingError} we switch out the implementation to use\n * a {@link MemStore} instead.\n *\n * The reason this is relatively complicated is that when {@link IDBStore} is\n * created, it calls `openDatabase` synchronously, but that returns a `Promise`\n * that will reject in the case of Firefox private browsing. We don't await this\n * promise until we call `read` or `write` so we cannot do the switch until\n * then.\n */\n\nexport class IDBStoreWithMemFallback implements Store {\n readonly #lc: LogContext;\n readonly #name: string;\n #store: Store;\n constructor(lc: LogContext, name: string) {\n this.#lc = lc;\n this.#name = name;\n this.#store = new IDBStore(name);\n }\n\n read(): Promise<Read> {\n return this.#withBrainTransplant(s => s.read());\n }\n\n write(): Promise<Write> {\n return this.#withBrainTransplant(s => s.write());\n }\n\n async #withBrainTransplant<T extends Read>(\n f: (store: Store) => Promise<T>,\n ): Promise<T> {\n try {\n return await f(this.#store);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n // It is possible that we end up with multiple pending read/write and\n // they all reject. Make sure we only replace the implementation once.\n if (this.#store instanceof IDBStore) {\n this.#lc.info?.(\n 'Switching to MemStore because of Firefox private browsing error',\n );\n this.#store = new MemStore(this.#name);\n }\n return f(this.#store);\n }\n throw e;\n }\n }\n\n close(): Promise<void> {\n return this.#store.close();\n }\n\n get closed(): boolean {\n return this.#store.closed;\n }\n}\n\nfunction isFirefoxPrivateBrowsingError(e: unknown): e is DOMException {\n return (\n isFirefox() &&\n e instanceof DOMException &&\n e.name === 'InvalidStateError' &&\n e.message ===\n 'A mutation operation was attempted on a database that did not allow mutations.'\n );\n}\n\nfunction isFirefox(): boolean {\n return navigator?.userAgent?.includes('Firefox') ?? false;\n}\n\nexport function newIDBStoreWithMemFallback(\n lc: LogContext,\n name: string,\n): Store {\n if (isFirefox()) {\n return new IDBStoreWithMemFallback(lc, name);\n }\n return new IDBStore(name);\n}\n\nexport function dropIDBStoreWithMemFallback(name: string): Promise<void> {\n if (!isFirefox()) {\n return dropIDBStore(name);\n }\n try {\n return dropIDBStore(name);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n return dropMemStore(name);\n }\n }\n return promiseVoid;\n}\n\nfunction dropIDBStore(name: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,IAAa,0BAAb,MAAsD;CACpD;CACA;CACA;CACA,YAAY,IAAgB,MAAc;
|
|
1
|
+
{"version":3,"file":"idb-store-with-mem-fallback.js","names":["#lc","#name","#store","#withBrainTransplant"],"sources":["../../../../../replicache/src/kv/idb-store-with-mem-fallback.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport {navigator} from '../../../shared/src/navigator.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {IDBStore} from './idb-store.ts';\nimport {MemStore, dropMemStore} from './mem-store.ts';\nimport type {Read, Store, Write} from './store.ts';\n\n/**\n * This store uses an {@link IDBStore} by default. If the {@link IDBStore} fails\n * to open the DB with an exception that matches\n * {@link isFirefoxPrivateBrowsingError} we switch out the implementation to use\n * a {@link MemStore} instead.\n *\n * The reason this is relatively complicated is that when {@link IDBStore} is\n * created, it calls `openDatabase` synchronously, but that returns a `Promise`\n * that will reject in the case of Firefox private browsing. We don't await this\n * promise until we call `read` or `write` so we cannot do the switch until\n * then.\n */\n\nexport class IDBStoreWithMemFallback implements Store {\n readonly #lc: LogContext;\n readonly #name: string;\n #store: Store;\n constructor(lc: LogContext, name: string) {\n this.#lc = lc;\n this.#name = name;\n this.#store = new IDBStore(name);\n }\n\n read(): Promise<Read> {\n return this.#withBrainTransplant(s => s.read());\n }\n\n write(): Promise<Write> {\n return this.#withBrainTransplant(s => s.write());\n }\n\n async #withBrainTransplant<T extends Read>(\n f: (store: Store) => Promise<T>,\n ): Promise<T> {\n try {\n return await f(this.#store);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n // It is possible that we end up with multiple pending read/write and\n // they all reject. Make sure we only replace the implementation once.\n if (this.#store instanceof IDBStore) {\n this.#lc.info?.(\n 'Switching to MemStore because of Firefox private browsing error',\n );\n this.#store = new MemStore(this.#name);\n }\n return f(this.#store);\n }\n throw e;\n }\n }\n\n close(): Promise<void> {\n return this.#store.close();\n }\n\n get closed(): boolean {\n return this.#store.closed;\n }\n}\n\nfunction isFirefoxPrivateBrowsingError(e: unknown): e is DOMException {\n return (\n isFirefox() &&\n e instanceof DOMException &&\n e.name === 'InvalidStateError' &&\n e.message ===\n 'A mutation operation was attempted on a database that did not allow mutations.'\n );\n}\n\nfunction isFirefox(): boolean {\n return navigator?.userAgent?.includes('Firefox') ?? false;\n}\n\nexport function newIDBStoreWithMemFallback(\n lc: LogContext,\n name: string,\n): Store {\n if (isFirefox()) {\n return new IDBStoreWithMemFallback(lc, name);\n }\n return new IDBStore(name);\n}\n\nexport function dropIDBStoreWithMemFallback(name: string): Promise<void> {\n if (!isFirefox()) {\n return dropIDBStore(name);\n }\n try {\n return dropIDBStore(name);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n return dropMemStore(name);\n }\n }\n return promiseVoid;\n}\n\nfunction dropIDBStore(name: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAoBA,IAAa,0BAAb,MAAsD;CACpD;CACA;CACA;CACA,YAAY,IAAgB,MAAc;AACxC,QAAA,KAAW;AACX,QAAA,OAAa;AACb,QAAA,QAAc,IAAI,SAAS,KAAK;;CAGlC,OAAsB;AACpB,SAAO,MAAA,qBAA0B,MAAK,EAAE,MAAM,CAAC;;CAGjD,QAAwB;AACtB,SAAO,MAAA,qBAA0B,MAAK,EAAE,OAAO,CAAC;;CAGlD,OAAA,oBACE,GACY;AACZ,MAAI;AACF,UAAO,MAAM,EAAE,MAAA,MAAY;WACpB,GAAG;AACV,OAAI,8BAA8B,EAAE,EAAE;AAGpC,QAAI,MAAA,iBAAuB,UAAU;AACnC,WAAA,GAAS,OACP,kEACD;AACD,WAAA,QAAc,IAAI,SAAS,MAAA,KAAW;;AAExC,WAAO,EAAE,MAAA,MAAY;;AAEvB,SAAM;;;CAIV,QAAuB;AACrB,SAAO,MAAA,MAAY,OAAO;;CAG5B,IAAI,SAAkB;AACpB,SAAO,MAAA,MAAY;;;AAIvB,SAAS,8BAA8B,GAA+B;AACpE,QACE,WAAW,IACX,aAAa,gBACb,EAAE,SAAS,uBACX,EAAE,YACA;;AAIN,SAAS,YAAqB;AAC5B,QAAO,gBAAW,WAAW,SAAS,UAAU,IAAI;;AAGtD,SAAgB,2BACd,IACA,MACO;AACP,KAAI,WAAW,CACb,QAAO,IAAI,wBAAwB,IAAI,KAAK;AAE9C,QAAO,IAAI,SAAS,KAAK;;AAG3B,SAAgB,4BAA4B,MAA6B;AACvE,KAAI,CAAC,WAAW,CACd,QAAO,aAAa,KAAK;AAE3B,KAAI;AACF,SAAO,aAAa,KAAK;UAClB,GAAG;AACV,MAAI,8BAA8B,EAAE,CAClC,QAAO,aAAa,KAAK;;AAG7B,QAAO;;AAGT,SAAS,aAAa,MAA6B;AACjD,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,MAAM,UAAU,eAAe,KAAK;AAC1C,MAAI,kBAAkB,SAAS;AAC/B,MAAI,gBAAgB,OAAO,IAAI,MAAM;GACrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"idb-store.js","names":["#db","#closed","#withReopen","#idbDeleted","#tx"],"sources":["../../../../../replicache/src/kv/idb-store.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport {assertNotNull} from '../../../shared/src/asserts.ts';\nimport {mustGetBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n storeIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\nimport {WriteImplBase, deleteSentinel} from './write-impl-base.ts';\n\nconst RELAXED = {durability: 'relaxed'} as const;\nconst OBJECT_STORE = 'chunks';\n\nexport class IDBStore implements Store {\n #db: Promise<IDBDatabase>;\n #closed = false;\n #idbDeleted = false;\n\n constructor(name: string) {\n this.#db = openDatabase(name);\n }\n\n read(): Promise<Read> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(readImpl);\n }\n\n write(): Promise<Write> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(writeImpl);\n }\n\n async close(): Promise<void> {\n if (!this.#idbDeleted) {\n const db = await this.#db;\n db.close();\n }\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n async #withReopen<R>(fn: (db: IDBDatabase) => R): Promise<R> {\n // Tries to reopen an IndexedDB, and rejects if the database needs\n // upgrading (is missing for whatever reason).\n const reopenExistingDB = async (name: string): Promise<IDBDatabase> => {\n const {promise, resolve, reject} = resolver<IDBDatabase>();\n const req = indexedDB.open(name);\n\n req.onupgradeneeded = () => {\n const tx = req.transaction;\n assertNotNull(tx);\n tx.abort();\n this.#idbDeleted = true;\n reject(\n new IDBNotFoundError(\n `Expected IndexedDB not found: ${name}. This likely means that the user deleted IndexedDB instances while the app was running. This is non-fatal. The app will continue running in memory until reload.`,\n ),\n );\n };\n\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n\n const db = await promise;\n db.onversionchange = () => db.close();\n return db;\n };\n\n // We abstract on `readImpl` to work around an issue in Safari. Safari does\n // not allow any microtask between a transaction is created until it is\n // first used. We used to use `await read()` here instead of `await\n // this._db` but then there is a microtask between the creation of the\n // transaction and the return of this function. By doing `await this._db`\n // here we only await the db and no await is involved with the transaction.\n // See https://github.com/jakearchibald/idb-keyval/commit/1af0a00b1a70a678d2f9cf5e74c55a22e57324c5#r55989916\n const db = await this.#db;\n\n try {\n return fn(db);\n } catch (e: unknown) {\n if (!this.#closed && e instanceof DOMException) {\n if (e.name === 'InvalidStateError') {\n this.#db = reopenExistingDB(db.name);\n const reopened = await this.#db;\n return fn(reopened);\n } else if (e.name === 'NotFoundError') {\n // This edge-case can happen if the db has been deleted and the\n // user/developer has DevTools open in certain browsers.\n // See discussion at https://github.com/rocicorp/replicache-internal/pull/216\n this.#idbDeleted = true;\n mustGetBrowserGlobal('indexedDB').deleteDatabase(db.name);\n throw new IDBNotFoundError(\n `Expected IndexedDB ${db.name} missing object store. Deleting db. This is non-fatal, the app will continue working in memory until it is reloaded.`,\n );\n }\n }\n throw e;\n }\n }\n}\n\nclass ReadImpl implements Read {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n this.#tx = tx;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).count(key);\n req.onsuccess = () => resolve(req.result > 0);\n req.onerror = () => reject(req.error);\n });\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).get(key);\n req.onsuccess = () => resolve(deepFreezeAllowUndefined(req.result));\n req.onerror = () => reject(req.error);\n });\n }\n\n release(): void {\n this.#closed = true;\n // Do nothing. We rely on IDB locking.\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nclass WriteImpl extends WriteImplBase {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n super(new ReadImpl(tx));\n this.#tx = tx;\n }\n\n commit(): Promise<void> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n if (this._pending.size === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n const tx = this.#tx;\n const store = objectStore(tx);\n for (const [key, val] of this._pending) {\n if (val === deleteSentinel) {\n store.delete(key);\n } else {\n store.put(val, key);\n }\n }\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n release(): void {\n // We rely on IDB locking so no need to do anything here.\n this.#closed = true;\n super.release();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nfunction writeImpl(db: IDBDatabase): Write {\n const tx = db.transaction(OBJECT_STORE, 'readwrite', RELAXED);\n return new WriteImpl(tx);\n}\n\nfunction readImpl(db: IDBDatabase): Read {\n const tx = db.transaction(OBJECT_STORE, 'readonly');\n return new ReadImpl(tx);\n}\n\nfunction objectStore(tx: IDBTransaction): IDBObjectStore {\n return tx.objectStore(OBJECT_STORE);\n}\n\nfunction openDatabase(name: string): Promise<IDBDatabase> {\n const idb = mustGetBrowserGlobal('indexedDB');\n return new Promise((resolve, reject) => {\n const req = idb.open(name);\n req.onupgradeneeded = () => {\n req.result.createObjectStore(OBJECT_STORE);\n };\n req.onsuccess = () => {\n const db = req.result;\n // Another tab/process wants to modify the db, so release it.\n db.onversionchange = () => db.close();\n resolve(db);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\n/**\n * This error is thrown when we detect that the IndexedDB has been removed. This\n * does not normally happen but can happen during development if the user has\n * DevTools open and deletes the IndexedDB from there.\n */\nexport class IDBNotFoundError extends Error {\n name = 'IDBNotFoundError';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"idb-store.js","names":["#db","#closed","#withReopen","#idbDeleted","#tx"],"sources":["../../../../../replicache/src/kv/idb-store.ts"],"sourcesContent":["import {resolver} from '@rocicorp/resolver';\nimport {assertNotNull} from '../../../shared/src/asserts.ts';\nimport {mustGetBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n storeIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\nimport {WriteImplBase, deleteSentinel} from './write-impl-base.ts';\n\nconst RELAXED = {durability: 'relaxed'} as const;\nconst OBJECT_STORE = 'chunks';\n\nexport class IDBStore implements Store {\n #db: Promise<IDBDatabase>;\n #closed = false;\n #idbDeleted = false;\n\n constructor(name: string) {\n this.#db = openDatabase(name);\n }\n\n read(): Promise<Read> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(readImpl);\n }\n\n write(): Promise<Write> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(writeImpl);\n }\n\n async close(): Promise<void> {\n if (!this.#idbDeleted) {\n const db = await this.#db;\n db.close();\n }\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n async #withReopen<R>(fn: (db: IDBDatabase) => R): Promise<R> {\n // Tries to reopen an IndexedDB, and rejects if the database needs\n // upgrading (is missing for whatever reason).\n const reopenExistingDB = async (name: string): Promise<IDBDatabase> => {\n const {promise, resolve, reject} = resolver<IDBDatabase>();\n const req = indexedDB.open(name);\n\n req.onupgradeneeded = () => {\n const tx = req.transaction;\n assertNotNull(tx);\n tx.abort();\n this.#idbDeleted = true;\n reject(\n new IDBNotFoundError(\n `Expected IndexedDB not found: ${name}. This likely means that the user deleted IndexedDB instances while the app was running. This is non-fatal. The app will continue running in memory until reload.`,\n ),\n );\n };\n\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n\n const db = await promise;\n db.onversionchange = () => db.close();\n return db;\n };\n\n // We abstract on `readImpl` to work around an issue in Safari. Safari does\n // not allow any microtask between a transaction is created until it is\n // first used. We used to use `await read()` here instead of `await\n // this._db` but then there is a microtask between the creation of the\n // transaction and the return of this function. By doing `await this._db`\n // here we only await the db and no await is involved with the transaction.\n // See https://github.com/jakearchibald/idb-keyval/commit/1af0a00b1a70a678d2f9cf5e74c55a22e57324c5#r55989916\n const db = await this.#db;\n\n try {\n return fn(db);\n } catch (e: unknown) {\n if (!this.#closed && e instanceof DOMException) {\n if (e.name === 'InvalidStateError') {\n this.#db = reopenExistingDB(db.name);\n const reopened = await this.#db;\n return fn(reopened);\n } else if (e.name === 'NotFoundError') {\n // This edge-case can happen if the db has been deleted and the\n // user/developer has DevTools open in certain browsers.\n // See discussion at https://github.com/rocicorp/replicache-internal/pull/216\n this.#idbDeleted = true;\n mustGetBrowserGlobal('indexedDB').deleteDatabase(db.name);\n throw new IDBNotFoundError(\n `Expected IndexedDB ${db.name} missing object store. Deleting db. This is non-fatal, the app will continue working in memory until it is reloaded.`,\n );\n }\n }\n throw e;\n }\n }\n}\n\nclass ReadImpl implements Read {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n this.#tx = tx;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).count(key);\n req.onsuccess = () => resolve(req.result > 0);\n req.onerror = () => reject(req.error);\n });\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).get(key);\n req.onsuccess = () => resolve(deepFreezeAllowUndefined(req.result));\n req.onerror = () => reject(req.error);\n });\n }\n\n release(): void {\n this.#closed = true;\n // Do nothing. We rely on IDB locking.\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nclass WriteImpl extends WriteImplBase {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n super(new ReadImpl(tx));\n this.#tx = tx;\n }\n\n commit(): Promise<void> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n if (this._pending.size === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n const tx = this.#tx;\n const store = objectStore(tx);\n for (const [key, val] of this._pending) {\n if (val === deleteSentinel) {\n store.delete(key);\n } else {\n store.put(val, key);\n }\n }\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n release(): void {\n // We rely on IDB locking so no need to do anything here.\n this.#closed = true;\n super.release();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nfunction writeImpl(db: IDBDatabase): Write {\n const tx = db.transaction(OBJECT_STORE, 'readwrite', RELAXED);\n return new WriteImpl(tx);\n}\n\nfunction readImpl(db: IDBDatabase): Read {\n const tx = db.transaction(OBJECT_STORE, 'readonly');\n return new ReadImpl(tx);\n}\n\nfunction objectStore(tx: IDBTransaction): IDBObjectStore {\n return tx.objectStore(OBJECT_STORE);\n}\n\nfunction openDatabase(name: string): Promise<IDBDatabase> {\n const idb = mustGetBrowserGlobal('indexedDB');\n return new Promise((resolve, reject) => {\n const req = idb.open(name);\n req.onupgradeneeded = () => {\n req.result.createObjectStore(OBJECT_STORE);\n };\n req.onsuccess = () => {\n const db = req.result;\n // Another tab/process wants to modify the db, so release it.\n db.onversionchange = () => db.close();\n resolve(db);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\n/**\n * This error is thrown when we detect that the IndexedDB has been removed. This\n * does not normally happen but can happen during development if the user has\n * DevTools open and deletes the IndexedDB from there.\n */\nexport class IDBNotFoundError extends Error {\n name = 'IDBNotFoundError';\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mem-store.js","names":["#map","#rwLock","#closed"],"sources":["../../../../../replicache/src/kv/mem-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {throwIfStoreClosed} from './throw-if-closed.ts';\nimport {WriteImpl} from './write-impl.ts';\n\ntype StorageMap = Map<string, FrozenJSONValue>;\n\ntype Value = {readonly lock: RWLock; readonly map: StorageMap};\n\nconst stores = new Map<string, Value>();\n\nexport function clearAllNamedMemStoresForTesting(): void {\n stores.clear();\n}\n\nexport function dropMemStore(name: string): Promise<void> {\n stores.delete(name);\n return promiseVoid;\n}\n\nexport function hasMemStore(name: string): boolean {\n return stores.has(name);\n}\n\n/**\n * A named in-memory Store implementation.\n *\n * Two (or more) named memory stores with the same name will share the same\n * underlying storage. They will also share the same read/write locks, so that\n * only one write transaction can be running at the same time.\n *\n * @experimental This class is experimental and might be removed or changed\n * in the future without following semver versioning. Please be cautious.\n */\nexport class MemStore implements Store {\n readonly #map: StorageMap;\n readonly #rwLock: RWLock;\n #closed = false;\n\n constructor(name: string) {\n const entry = stores.get(name);\n let lock: RWLock;\n let map: StorageMap;\n if (entry) {\n ({lock, map} = entry);\n } else {\n lock = new RWLock();\n map = new Map();\n stores.set(name, {lock, map});\n }\n this.#rwLock = lock;\n this.#map = map;\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.read();\n return new ReadImpl(this.#map, release);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.write();\n return new WriteImpl(this.#map, release);\n }\n\n close(): Promise<void> {\n this.#closed = true;\n return promiseVoid;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n"],"mappings":";;;;;;AAYA,IAAM,yBAAS,IAAI,
|
|
1
|
+
{"version":3,"file":"mem-store.js","names":["#map","#rwLock","#closed"],"sources":["../../../../../replicache/src/kv/mem-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {throwIfStoreClosed} from './throw-if-closed.ts';\nimport {WriteImpl} from './write-impl.ts';\n\ntype StorageMap = Map<string, FrozenJSONValue>;\n\ntype Value = {readonly lock: RWLock; readonly map: StorageMap};\n\nconst stores = new Map<string, Value>();\n\nexport function clearAllNamedMemStoresForTesting(): void {\n stores.clear();\n}\n\nexport function dropMemStore(name: string): Promise<void> {\n stores.delete(name);\n return promiseVoid;\n}\n\nexport function hasMemStore(name: string): boolean {\n return stores.has(name);\n}\n\n/**\n * A named in-memory Store implementation.\n *\n * Two (or more) named memory stores with the same name will share the same\n * underlying storage. They will also share the same read/write locks, so that\n * only one write transaction can be running at the same time.\n *\n * @experimental This class is experimental and might be removed or changed\n * in the future without following semver versioning. Please be cautious.\n */\nexport class MemStore implements Store {\n readonly #map: StorageMap;\n readonly #rwLock: RWLock;\n #closed = false;\n\n constructor(name: string) {\n const entry = stores.get(name);\n let lock: RWLock;\n let map: StorageMap;\n if (entry) {\n ({lock, map} = entry);\n } else {\n lock = new RWLock();\n map = new Map();\n stores.set(name, {lock, map});\n }\n this.#rwLock = lock;\n this.#map = map;\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.read();\n return new ReadImpl(this.#map, release);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.write();\n return new WriteImpl(this.#map, release);\n }\n\n close(): Promise<void> {\n this.#closed = true;\n return promiseVoid;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n"],"mappings":";;;;;;AAYA,IAAM,yBAAS,IAAI,KAAoB;AAMvC,SAAgB,aAAa,MAA6B;AACxD,QAAO,OAAO,KAAK;AACnB,QAAO;;;;;;;;;;;;AAiBT,IAAa,WAAb,MAAuC;CACrC;CACA;CACA,UAAU;CAEV,YAAY,MAAc;EACxB,MAAM,QAAQ,OAAO,IAAI,KAAK;EAC9B,IAAI;EACJ,IAAI;AACJ,MAAI,MACF,EAAC,CAAC,MAAM,OAAO;OACV;AACL,UAAO,IAAI,QAAQ;AACnB,yBAAM,IAAI,KAAK;AACf,UAAO,IAAI,MAAM;IAAC;IAAM;IAAI,CAAC;;AAE/B,QAAA,SAAe;AACf,QAAA,MAAY;;CAGd,MAAM,OAAsB;AAC1B,qBAAmB,KAAK;EACxB,MAAM,UAAU,MAAM,MAAA,OAAa,MAAM;AACzC,SAAO,IAAI,SAAS,MAAA,KAAW,QAAQ;;CAGzC,MAAM,QAAwB;AAC5B,qBAAmB,KAAK;EACxB,MAAM,UAAU,MAAM,MAAA,OAAa,OAAO;AAC1C,SAAO,IAAI,UAAU,MAAA,KAAW,QAAQ;;CAG1C,QAAuB;AACrB,QAAA,SAAe;AACf,SAAO;;CAGT,IAAI,SAAkB;AACpB,SAAO,MAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","names":["#db","#sql","#filename"],"sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"sourcesContent":["import type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\nimport {open, type DB} from './types.ts';\n\nexport type OpSQLiteStoreOptions = SQLiteStoreOptions & {\n // OpSQLite-specific options\n location?: 'default' | 'Library' | 'Documents' | 'Temporary';\n encryptionKey?: string;\n};\n\nfunction dropOpSQLiteStore(\n name: string,\n opts?: OpSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(\n name,\n (filename, options) => new OpSQLiteDatabase(filename, options),\n opts,\n );\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using @op-engineering/op-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport function opSQLiteStoreProvider(\n opts?: OpSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(\n name,\n (name, options) => new OpSQLiteDatabase(name, options),\n opts,\n ),\n drop: name => dropOpSQLiteStore(name, opts),\n };\n}\n\nclass OpSQLitePreparedStatement implements PreparedStatement {\n readonly #db: DB;\n readonly #sql: string;\n\n constructor(db: DB, sql: string) {\n this.#db = db;\n this.#sql = sql;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#db.executeRaw(this.#sql, params);\n }\n\n all(params: string[]): Promise<unknown[][]> {\n return this.#db.executeRaw(this.#sql, params);\n }\n}\n\nclass OpSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n\n constructor(filename: string, opts?: OpSQLiteStoreOptions) {\n this.#filename = filename;\n const openOpts: {\n name: string;\n location?: string;\n encryptionKey?: string;\n } = {name: filename};\n\n if (opts?.location) {\n openOpts.location = opts.location;\n }\n if (opts?.encryptionKey) {\n openOpts.encryptionKey = opts.encryptionKey;\n }\n\n this.#db = open(openOpts);\n }\n\n close(): void {\n this.#db.close();\n }\n\n destroy(): void {\n // OpSQLite uses delete method on the database instance\n // We need to create a temporary connection to delete the database\n try {\n const tempDb = open({name: this.#filename});\n tempDb.delete();\n tempDb.close();\n } catch (_error) {\n // Database might not exist, which is fine\n }\n }\n\n prepare(sql: string): PreparedStatement {\n return new OpSQLitePreparedStatement(this.#db, sql);\n }\n\n execSync(sql: string): void {\n this.#db.executeRawSync(sql, []);\n }\n}\n"],"mappings":";;;AAeA,SAAS,kBACP,MACA,MACe;
|
|
1
|
+
{"version":3,"file":"store.js","names":["#db","#sql","#filename"],"sources":["../../../../../../replicache/src/kv/op-sqlite/store.ts"],"sourcesContent":["import type {\n PreparedStatement,\n SQLiteDatabase,\n SQLiteStoreOptions,\n} from '../sqlite-store.ts';\nimport {dropStore, SQLiteStore} from '../sqlite-store.ts';\nimport type {StoreProvider} from '../store.ts';\nimport {open, type DB} from './types.ts';\n\nexport type OpSQLiteStoreOptions = SQLiteStoreOptions & {\n // OpSQLite-specific options\n location?: 'default' | 'Library' | 'Documents' | 'Temporary';\n encryptionKey?: string;\n};\n\nfunction dropOpSQLiteStore(\n name: string,\n opts?: OpSQLiteStoreOptions,\n): Promise<void> {\n return dropStore(\n name,\n (filename, options) => new OpSQLiteDatabase(filename, options),\n opts,\n );\n}\n\n/**\n * Creates a StoreProvider for SQLite-based stores using @op-engineering/op-sqlite.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport function opSQLiteStoreProvider(\n opts?: OpSQLiteStoreOptions,\n): StoreProvider {\n return {\n create: name =>\n new SQLiteStore(\n name,\n (name, options) => new OpSQLiteDatabase(name, options),\n opts,\n ),\n drop: name => dropOpSQLiteStore(name, opts),\n };\n}\n\nclass OpSQLitePreparedStatement implements PreparedStatement {\n readonly #db: DB;\n readonly #sql: string;\n\n constructor(db: DB, sql: string) {\n this.#db = db;\n this.#sql = sql;\n }\n\n async exec(params: string[]): Promise<void> {\n await this.#db.executeRaw(this.#sql, params);\n }\n\n all(params: string[]): Promise<unknown[][]> {\n return this.#db.executeRaw(this.#sql, params);\n }\n}\n\nclass OpSQLiteDatabase implements SQLiteDatabase {\n readonly #db: DB;\n readonly #filename: string;\n\n constructor(filename: string, opts?: OpSQLiteStoreOptions) {\n this.#filename = filename;\n const openOpts: {\n name: string;\n location?: string;\n encryptionKey?: string;\n } = {name: filename};\n\n if (opts?.location) {\n openOpts.location = opts.location;\n }\n if (opts?.encryptionKey) {\n openOpts.encryptionKey = opts.encryptionKey;\n }\n\n this.#db = open(openOpts);\n }\n\n close(): void {\n this.#db.close();\n }\n\n destroy(): void {\n // OpSQLite uses delete method on the database instance\n // We need to create a temporary connection to delete the database\n try {\n const tempDb = open({name: this.#filename});\n tempDb.delete();\n tempDb.close();\n } catch (_error) {\n // Database might not exist, which is fine\n }\n }\n\n prepare(sql: string): PreparedStatement {\n return new OpSQLitePreparedStatement(this.#db, sql);\n }\n\n execSync(sql: string): void {\n this.#db.executeRawSync(sql, []);\n }\n}\n"],"mappings":";;;AAeA,SAAS,kBACP,MACA,MACe;AACf,QAAO,UACL,OACC,UAAU,YAAY,IAAI,iBAAiB,UAAU,QAAQ,EAC9D,KACD;;;;;;;;AASH,SAAgB,sBACd,MACe;AACf,QAAO;EACL,SAAQ,SACN,IAAI,YACF,OACC,MAAM,YAAY,IAAI,iBAAiB,MAAM,QAAQ,EACtD,KACD;EACH,OAAM,SAAQ,kBAAkB,MAAM,KAAK;EAC5C;;AAGH,IAAM,4BAAN,MAA6D;CAC3D;CACA;CAEA,YAAY,IAAQ,KAAa;AAC/B,QAAA,KAAW;AACX,QAAA,MAAY;;CAGd,MAAM,KAAK,QAAiC;AAC1C,QAAM,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO;;CAG9C,IAAI,QAAwC;AAC1C,SAAO,MAAA,GAAS,WAAW,MAAA,KAAW,OAAO;;;AAIjD,IAAM,mBAAN,MAAiD;CAC/C;CACA;CAEA,YAAY,UAAkB,MAA6B;AACzD,QAAA,WAAiB;EACjB,MAAM,WAIF,EAAC,MAAM,UAAS;AAEpB,MAAI,MAAM,SACR,UAAS,WAAW,KAAK;AAE3B,MAAI,MAAM,cACR,UAAS,gBAAgB,KAAK;AAGhC,QAAA,KAAW,KAAK,SAAS;;CAG3B,QAAc;AACZ,QAAA,GAAS,OAAO;;CAGlB,UAAgB;AAGd,MAAI;GACF,MAAM,SAAS,KAAK,EAAC,MAAM,MAAA,UAAe,CAAC;AAC3C,UAAO,QAAQ;AACf,UAAO,OAAO;WACP,QAAQ;;CAKnB,QAAQ,KAAgC;AACtC,SAAO,IAAI,0BAA0B,MAAA,IAAU,IAAI;;CAGrD,SAAS,KAAmB;AAC1B,QAAA,GAAS,eAAe,KAAK,EAAE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-impl.js","names":["#map","#release","#closed"],"sources":["../../../../../replicache/src/kv/read-impl.ts"],"sourcesContent":["import type {FrozenJSONValue} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {maybeTransactionIsClosedRejection} from './throw-if-closed.ts';\n\nexport class ReadImpl implements Read {\n readonly #map: Map<string, FrozenJSONValue>;\n readonly #release: () => void;\n #closed = false;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n this.#map = map;\n this.#release = release;\n }\n\n release() {\n this.#release();\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.has(key))\n );\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.get(key))\n );\n }\n}\n"],"mappings":";;AAIA,IAAa,WAAb,MAAsC;CACpC;CACA;CACA,UAAU;CAEV,YAAY,KAAmC,SAAqB;
|
|
1
|
+
{"version":3,"file":"read-impl.js","names":["#map","#release","#closed"],"sources":["../../../../../replicache/src/kv/read-impl.ts"],"sourcesContent":["import type {FrozenJSONValue} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {maybeTransactionIsClosedRejection} from './throw-if-closed.ts';\n\nexport class ReadImpl implements Read {\n readonly #map: Map<string, FrozenJSONValue>;\n readonly #release: () => void;\n #closed = false;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n this.#map = map;\n this.#release = release;\n }\n\n release() {\n this.#release();\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.has(key))\n );\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.get(key))\n );\n }\n}\n"],"mappings":";;AAIA,IAAa,WAAb,MAAsC;CACpC;CACA;CACA,UAAU;CAEV,YAAY,KAAmC,SAAqB;AAClE,QAAA,MAAY;AACZ,QAAA,UAAgB;;CAGlB,UAAU;AACR,QAAA,SAAe;AACf,QAAA,SAAe;;CAGjB,IAAI,SAAkB;AACpB,SAAO,MAAA;;CAGT,IAAI,KAA+B;AACjC,SACE,kCAAkC,KAAK,IACvC,QAAQ,QAAQ,MAAA,IAAU,IAAI,IAAI,CAAC;;CAIvC,IAAI,KAAmD;AACrD,SACE,kCAAkC,KAAK,IACvC,QAAQ,QAAQ,MAAA,IAAU,IAAI,IAAI,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAC,MAAM,YAAY,CAAC;AAMnD,OAAO,EAAiB,aAAa,EAAC,MAAM,sBAAsB,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;OAEG;IACH,OAAO,IAAI,IAAI,CAAC;IAEhB;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC;IAGxC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,MAAM,oBAAoB,GAAG,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,kBAAkB,KACtB,cAAc,CAAC;AAEpB;;;;;GAKG;AACH,qBAAa,WAAY,YAAW,KAAK;;gBAOrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,oBAAoB,EAC5B,IAAI,CAAC,EAAE,kBAAkB;IAMrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBrB,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAcvB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5B,IAAI,MAAM,IAAI,OAAO,CAEpB;CACF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAQD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,GAAG,EAAE,iBAAiB,CAAC;IACvB,GAAG,EAAE,iBAAiB,CAAC;CACxB,CAAC;AAEF,MAAM,WAAW,kBAAkB;IAEjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC/B,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED;;;GAGG;AAEH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,cAAc,EACxB,IAAI,CAAC,EAAE,kBAAkB,GACxB,kBAAkB,CAmCpB;
|
|
1
|
+
{"version":3,"file":"sqlite-store.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -88,12 +88,9 @@ var CB_REJECT = 1;
|
|
|
88
88
|
function rejectAll(callbacks, e) {
|
|
89
89
|
for (let i = CB_REJECT; i < callbacks.length; i += CB_STRIDE) callbacks[i](e);
|
|
90
90
|
}
|
|
91
|
-
function parseRawValue(raw) {
|
|
92
|
-
return raw === void 0 ? void 0 : deepFreeze(JSON.parse(raw));
|
|
93
|
-
}
|
|
94
91
|
function resolveGet(resolve, reject, raw) {
|
|
95
92
|
try {
|
|
96
|
-
resolve(
|
|
93
|
+
resolve(raw === void 0 ? void 0 : deepFreeze(JSON.parse(raw)));
|
|
97
94
|
} catch (e) {
|
|
98
95
|
reject(e);
|
|
99
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-store.js","names":["#filename","#entry","#closed","#release","#preparedStatements","#pendingHasKeys","#pendingHasCallbacks","#scheduleLookup","#pendingGetKeys","#pendingGetCallbacks","#scheduled","#dbDelegate","#committed"],"sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {deepFreeze} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n throwIfStoreClosed,\n transactionError,\n} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\n/**\n * A SQLite prepared statement.\n */\nexport interface PreparedStatement {\n exec(params: string[]): Promise<void>;\n all(params: string[]): Promise<unknown[][]>;\n}\n\nexport interface SQLiteDatabase {\n /**\n * Close the database connection.\n */\n close(): void;\n\n /**\n * Destroy or delete the database (e.g. delete file).\n */\n destroy(): void;\n\n /**\n * Prepare a SQL string, returning a statement you can execute.\n * E.g. `const stmt = db.prepare(\"SELECT * FROM todos WHERE id=?\");`\n */\n prepare(sql: string): PreparedStatement;\n\n // for PRAGMA statements, schema creation and transaction control.\n execSync(sql: string): void;\n}\n\nexport type CreateSQLiteDatabase = (\n filename: string,\n opts?: SQLiteStoreOptions,\n) => SQLiteDatabase;\n\n/**\n * SQLite-based implementation of the Store interface using a configurable delegate.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport class SQLiteStore implements Store {\n readonly #filename: string;\n readonly #entry: StoreEntry;\n\n #closed = false;\n\n constructor(\n name: string,\n create: CreateSQLiteDatabase,\n opts?: SQLiteStoreOptions,\n ) {\n this.#filename = resolveFilename(name, opts);\n this.#entry = getOrCreateEntry(this.#filename, create, opts);\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n\n const entry = this.#entry;\n const {db, lock, preparedStatements} = entry;\n const release = await lock.read();\n\n // Start shared read transaction if this is the first reader\n // This ensures consistent reads across all concurrent readers\n if (entry.activeReaders === 0) {\n db.execSync('BEGIN');\n }\n entry.activeReaders++;\n\n return new SQLiteStoreRead(() => {\n entry.activeReaders--;\n // Commit shared read transaction when last reader finishes\n if (entry.activeReaders === 0) {\n db.execSync('COMMIT');\n }\n release();\n }, preparedStatements);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n\n const {lock, db, preparedStatements} = this.#entry;\n const release = await lock.write();\n\n // At this point, RWLock guarantees no active readers\n // The last reader would have already committed the shared transaction\n\n db.execSync('BEGIN IMMEDIATE');\n\n return new SQLiteWrite(release, db, preparedStatements);\n }\n\n async close(): Promise<void> {\n if (this.#closed) {\n return;\n }\n\n const {lock, db} = this.#entry;\n // Wait for all readers and writers to finish.\n const writeRelease = await lock.write();\n\n // Handle reference counting for shared stores - only close database\n // when this is the last store instance using it\n decrementStoreRefCount(this.#filename, db);\n\n this.#closed = true;\n writeRelease();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport function safeFilename(name: string): string {\n return name.replace(/[^a-zA-Z0-9]/g, '_');\n}\n\nfunction resolveFilename(name: string, opts?: SQLiteStoreOptions): string {\n const safe = safeFilename(name);\n const dir = opts?.directory;\n return dir ? `${dir}/${safe}` : safe;\n}\n\nexport type PreparedStatements = {\n has: PreparedStatement;\n get: PreparedStatement;\n hasMany: PreparedStatement;\n getMany: PreparedStatement;\n put: PreparedStatement;\n del: PreparedStatement;\n};\n\nexport interface SQLiteStoreOptions {\n // Common options\n busyTimeout?: number;\n journalMode?: 'WAL' | 'DELETE';\n synchronous?: 'NORMAL' | 'FULL';\n readUncommitted?: boolean;\n /** Directory in which to create the SQLite file. Defaults to the process CWD. */\n directory?: string | undefined;\n}\n\n/**\n * Common database setup logic shared between expo-sqlite and op-sqlite implementations.\n * Configures SQLite pragmas, creates the entry table, and prepares common statements.\n */\n\nexport function setupDatabase(\n delegate: SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): PreparedStatements {\n // Configure SQLite pragmas for optimal performance\n delegate.execSync(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 200}`);\n delegate.execSync(`PRAGMA journal_mode = '${opts?.journalMode ?? 'WAL'}'`);\n delegate.execSync(`PRAGMA synchronous = '${opts?.synchronous ?? 'NORMAL'}'`);\n delegate.execSync(\n `PRAGMA read_uncommitted = ${Boolean(opts?.readUncommitted)}`,\n );\n\n // Create the entry table\n delegate.execSync(`\n CREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n ) WITHOUT ROWID\n `);\n\n // Prepare common statements\n return {\n has: delegate.prepare(`SELECT 1 FROM entry WHERE key = ? LIMIT 1`),\n get: delegate.prepare('SELECT value FROM entry WHERE key = ?'),\n hasMany: delegate.prepare(\n `SELECT key FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n getMany: delegate.prepare(\n `SELECT key, value FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n put: delegate.prepare(\n `INSERT OR REPLACE INTO entry (key, value)\n SELECT e.value->>0, e.value->1 FROM json_each(?) e`,\n ),\n del: delegate.prepare(\n `DELETE FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n };\n}\n\n// Callbacks are stored as striped pairs: [resolve, reject, resolve, reject, ...]\nconst CB_STRIDE = 2;\nconst CB_RESOLVE = 0;\nconst CB_REJECT = 1;\n\ntype GetResolve = (v: ReadonlyJSONValue | undefined) => void;\ntype HasResolve = (v: boolean) => void;\ntype Reject = (e: unknown) => void;\n\nfunction rejectAll(callbacks: unknown[], e: unknown): void {\n for (let i = CB_REJECT; i < callbacks.length; i += CB_STRIDE) {\n (callbacks[i] as Reject)(e);\n }\n}\n\nfunction parseRawValue(raw: string | undefined): ReadonlyJSONValue | undefined {\n return raw === undefined\n ? undefined\n : deepFreeze(JSON.parse(raw) as ReadonlyJSONValue);\n}\n\nfunction resolveGet(\n resolve: GetResolve,\n reject: Reject,\n raw: string | undefined,\n): void {\n try {\n resolve(parseRawValue(raw));\n } catch (e) {\n reject(e);\n }\n}\n\nasync function flushGets(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.get.all([keys[0]])\n : await ps.getMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n resolveGet(\n callbacks[CB_RESOLVE] as GetResolve,\n callbacks[CB_REJECT] as Reject,\n rows[0]?.[0] as string | undefined,\n );\n return;\n }\n const resultMap = new Map(rows as [string, string][]);\n for (let i = 0; i < keys.length; i++) {\n resolveGet(\n callbacks[i * CB_STRIDE + CB_RESOLVE] as GetResolve,\n callbacks[i * CB_STRIDE + CB_REJECT] as Reject,\n resultMap.get(keys[i]),\n );\n }\n}\n\nasync function flushHas(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.has.all([keys[0]])\n : await ps.hasMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n (callbacks[CB_RESOLVE] as HasResolve)(rows.length > 0);\n return;\n }\n const existingKeys = new Set(rows.map(row => row[0] as string));\n for (let i = 0; i < keys.length; i++) {\n (callbacks[i * CB_STRIDE + CB_RESOLVE] as HasResolve)(\n existingKeys.has(keys[i]),\n );\n }\n}\n\nexport class SQLiteStoreRead implements Read {\n readonly #release: () => void;\n readonly #preparedStatements: PreparedStatements;\n #closed = false;\n #pendingGetKeys: string[] = [];\n #pendingGetCallbacks: unknown[] = [];\n #pendingHasKeys: string[] = [];\n #pendingHasCallbacks: unknown[] = [];\n #scheduled = false;\n\n constructor(release: () => void, preparedStatements: PreparedStatements) {\n this.#release = release;\n this.#preparedStatements = preparedStatements;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingHasKeys.push(key);\n this.#pendingHasCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingGetKeys.push(key);\n this.#pendingGetCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n #scheduleLookup(): void {\n if (!this.#scheduled) {\n this.#scheduled = true;\n queueMicrotask(() => {\n this.#scheduled = false;\n\n const ps = this.#preparedStatements;\n const getKeys = this.#pendingGetKeys;\n this.#pendingGetKeys = [];\n const getCallbacks = this.#pendingGetCallbacks;\n this.#pendingGetCallbacks = [];\n const hasKeys = this.#pendingHasKeys;\n this.#pendingHasKeys = [];\n const hasCallbacks = this.#pendingHasCallbacks;\n this.#pendingHasCallbacks = [];\n\n if (this.#closed) {\n const e = transactionError();\n rejectAll(getCallbacks, e);\n rejectAll(hasCallbacks, e);\n return;\n }\n\n if (getKeys.length > 0) {\n void flushGets(getKeys, getCallbacks, ps);\n }\n if (hasKeys.length > 0) {\n void flushHas(hasKeys, hasCallbacks, ps);\n }\n });\n }\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n this.#release();\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport class SQLiteWrite extends WriteImplBase implements Write {\n readonly #release: () => void;\n readonly #dbDelegate: SQLiteDatabase;\n readonly #preparedStatements: PreparedStatements;\n #committed = false;\n #closed = false;\n\n constructor(\n release: () => void,\n dbDelegate: SQLiteDatabase,\n preparedStatements: PreparedStatements,\n ) {\n super(new SQLiteStoreRead(() => undefined, preparedStatements));\n this.#release = release;\n this.#dbDelegate = dbDelegate;\n this.#preparedStatements = preparedStatements;\n }\n\n async commit(): Promise<void> {\n if (this.#closed) {\n throw transactionError();\n }\n\n const deleteKeys: string[] = [];\n for (const entry of this._pending) {\n if (entry[1] === deleteSentinel) {\n deleteKeys.push(entry[0]);\n this._pending.delete(entry[0]);\n }\n }\n\n const delP =\n deleteKeys.length > 0\n ? this.#preparedStatements.del.exec([JSON.stringify(deleteKeys)])\n : undefined;\n const putP =\n this._pending.size > 0\n ? this.#preparedStatements.put.exec([\n JSON.stringify([...this._pending]),\n ])\n : undefined;\n\n if (putP) await putP;\n if (delP) await delP;\n\n this.#dbDelegate.execSync('COMMIT');\n this._pending.clear();\n this.#committed = true;\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n super.release();\n let rollbackError: unknown;\n if (!this.#committed) {\n try {\n this.#dbDelegate.execSync('ROLLBACK');\n } catch (e) {\n rollbackError = e;\n }\n }\n this.#release();\n if (rollbackError !== undefined) {\n throw rollbackError;\n }\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\ntype StoreEntry = {\n readonly lock: RWLock;\n readonly db: SQLiteDatabase;\n refCount: number;\n activeReaders: number;\n preparedStatements: PreparedStatements;\n};\n\n// Global map to share database connections between multiple store instances with the same name\nconst stores = new Map<string, StoreEntry>();\n\n/**\n * Gets an existing store entry or creates a new one if it doesn't exist.\n * This implements the shared connection pattern where multiple stores with the same\n * name share the same database connection, lock, and delegate.\n */\nfunction getOrCreateEntry(\n filename: string,\n create: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): StoreEntry {\n const entry = stores.get(filename);\n\n if (entry) {\n entry.refCount++;\n return entry;\n }\n\n const dbDelegate = create(filename, opts);\n const preparedStatements = setupDatabase(dbDelegate, opts);\n\n const lock = new RWLock();\n\n const newEntry: StoreEntry = {\n lock,\n db: dbDelegate,\n refCount: 1,\n activeReaders: 0,\n preparedStatements,\n };\n stores.set(filename, newEntry);\n return newEntry;\n}\n\n/**\n * Decrements the reference count for a shared store and cleans up resources\n * when the last reference is released.\n */\n\nfunction decrementStoreRefCount(\n filename: string,\n dbDelegate: SQLiteDatabase,\n): void {\n const entry = stores.get(filename);\n if (entry) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n dbDelegate.close();\n stores.delete(filename);\n }\n }\n}\nexport function clearAllNamedStoresForTesting(): void {\n for (const entry of stores.values()) {\n entry.db.close();\n }\n stores.clear();\n}\n\nexport function dropStore(\n name: string,\n createDelegate: (\n filename: string,\n opts?: SQLiteStoreOptions,\n ) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): Promise<void> {\n const filename = resolveFilename(name, opts);\n const entry = stores.get(filename);\n if (entry) {\n try {\n entry.db.close();\n } catch {\n // Ignore close errors\n }\n stores.delete(filename);\n }\n\n // Create a temporary delegate to handle database deletion\n const tempDelegate = createDelegate(filename, opts);\n try {\n // we close the db before destroying it - this\n // caused an issue with expo-sqlite since it requires this\n tempDelegate.close();\n } catch {\n // Ignore close errors\n }\n try {\n tempDelegate.destroy();\n } catch {\n // Destroy errors shouldn't be fatal; the file may already be gone or locked\n }\n\n return Promise.resolve();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sqlite-store.js","names":["#filename","#entry","#closed","#release","#preparedStatements","#pendingHasKeys","#pendingHasCallbacks","#scheduleLookup","#pendingGetKeys","#pendingGetCallbacks","#scheduled","#dbDelegate","#committed"],"sources":["../../../../../replicache/src/kv/sqlite-store.ts"],"sourcesContent":["import {RWLock} from '@rocicorp/lock';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {deepFreeze} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n throwIfStoreClosed,\n transactionError,\n} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\n/**\n * A SQLite prepared statement.\n */\nexport interface PreparedStatement {\n exec(params: string[]): Promise<void>;\n all(params: string[]): Promise<unknown[][]>;\n}\n\nexport interface SQLiteDatabase {\n /**\n * Close the database connection.\n */\n close(): void;\n\n /**\n * Destroy or delete the database (e.g. delete file).\n */\n destroy(): void;\n\n /**\n * Prepare a SQL string, returning a statement you can execute.\n * E.g. `const stmt = db.prepare(\"SELECT * FROM todos WHERE id=?\");`\n */\n prepare(sql: string): PreparedStatement;\n\n // for PRAGMA statements, schema creation and transaction control.\n execSync(sql: string): void;\n}\n\nexport type CreateSQLiteDatabase = (\n filename: string,\n opts?: SQLiteStoreOptions,\n) => SQLiteDatabase;\n\n/**\n * SQLite-based implementation of the Store interface using a configurable delegate.\n * Supports shared connections between multiple store instances with the same name,\n * providing efficient resource utilization and proper transaction isolation.\n * Uses parameterized queries for safety and performance.\n */\nexport class SQLiteStore implements Store {\n readonly #filename: string;\n readonly #entry: StoreEntry;\n\n #closed = false;\n\n constructor(\n name: string,\n create: CreateSQLiteDatabase,\n opts?: SQLiteStoreOptions,\n ) {\n this.#filename = resolveFilename(name, opts);\n this.#entry = getOrCreateEntry(this.#filename, create, opts);\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n\n const entry = this.#entry;\n const {db, lock, preparedStatements} = entry;\n const release = await lock.read();\n\n // Start shared read transaction if this is the first reader\n // This ensures consistent reads across all concurrent readers\n if (entry.activeReaders === 0) {\n db.execSync('BEGIN');\n }\n entry.activeReaders++;\n\n return new SQLiteStoreRead(() => {\n entry.activeReaders--;\n // Commit shared read transaction when last reader finishes\n if (entry.activeReaders === 0) {\n db.execSync('COMMIT');\n }\n release();\n }, preparedStatements);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n\n const {lock, db, preparedStatements} = this.#entry;\n const release = await lock.write();\n\n // At this point, RWLock guarantees no active readers\n // The last reader would have already committed the shared transaction\n\n db.execSync('BEGIN IMMEDIATE');\n\n return new SQLiteWrite(release, db, preparedStatements);\n }\n\n async close(): Promise<void> {\n if (this.#closed) {\n return;\n }\n\n const {lock, db} = this.#entry;\n // Wait for all readers and writers to finish.\n const writeRelease = await lock.write();\n\n // Handle reference counting for shared stores - only close database\n // when this is the last store instance using it\n decrementStoreRefCount(this.#filename, db);\n\n this.#closed = true;\n writeRelease();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport function safeFilename(name: string): string {\n return name.replace(/[^a-zA-Z0-9]/g, '_');\n}\n\nfunction resolveFilename(name: string, opts?: SQLiteStoreOptions): string {\n const safe = safeFilename(name);\n const dir = opts?.directory;\n return dir ? `${dir}/${safe}` : safe;\n}\n\nexport type PreparedStatements = {\n has: PreparedStatement;\n get: PreparedStatement;\n hasMany: PreparedStatement;\n getMany: PreparedStatement;\n put: PreparedStatement;\n del: PreparedStatement;\n};\n\nexport interface SQLiteStoreOptions {\n // Common options\n busyTimeout?: number;\n journalMode?: 'WAL' | 'DELETE';\n synchronous?: 'NORMAL' | 'FULL';\n readUncommitted?: boolean;\n /** Directory in which to create the SQLite file. Defaults to the process CWD. */\n directory?: string | undefined;\n}\n\n/**\n * Common database setup logic shared between expo-sqlite and op-sqlite implementations.\n * Configures SQLite pragmas, creates the entry table, and prepares common statements.\n */\n\nexport function setupDatabase(\n delegate: SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): PreparedStatements {\n // Configure SQLite pragmas for optimal performance\n delegate.execSync(`PRAGMA busy_timeout = ${opts?.busyTimeout ?? 200}`);\n delegate.execSync(`PRAGMA journal_mode = '${opts?.journalMode ?? 'WAL'}'`);\n delegate.execSync(`PRAGMA synchronous = '${opts?.synchronous ?? 'NORMAL'}'`);\n delegate.execSync(\n `PRAGMA read_uncommitted = ${Boolean(opts?.readUncommitted)}`,\n );\n\n // Create the entry table\n delegate.execSync(`\n CREATE TABLE IF NOT EXISTS entry (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n ) WITHOUT ROWID\n `);\n\n // Prepare common statements\n return {\n has: delegate.prepare(`SELECT 1 FROM entry WHERE key = ? LIMIT 1`),\n get: delegate.prepare('SELECT value FROM entry WHERE key = ?'),\n hasMany: delegate.prepare(\n `SELECT key FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n getMany: delegate.prepare(\n `SELECT key, value FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n put: delegate.prepare(\n `INSERT OR REPLACE INTO entry (key, value)\n SELECT e.value->>0, e.value->1 FROM json_each(?) e`,\n ),\n del: delegate.prepare(\n `DELETE FROM entry WHERE key IN (SELECT value FROM json_each(?))`,\n ),\n };\n}\n\n// Callbacks are stored as striped pairs: [resolve, reject, resolve, reject, ...]\nconst CB_STRIDE = 2;\nconst CB_RESOLVE = 0;\nconst CB_REJECT = 1;\n\ntype GetResolve = (v: ReadonlyJSONValue | undefined) => void;\ntype HasResolve = (v: boolean) => void;\ntype Reject = (e: unknown) => void;\n\nfunction rejectAll(callbacks: unknown[], e: unknown): void {\n for (let i = CB_REJECT; i < callbacks.length; i += CB_STRIDE) {\n (callbacks[i] as Reject)(e);\n }\n}\n\nfunction resolveGet(\n resolve: GetResolve,\n reject: Reject,\n raw: string | undefined,\n): void {\n try {\n resolve(\n raw === undefined\n ? undefined\n : deepFreeze(JSON.parse(raw) as ReadonlyJSONValue),\n );\n } catch (e) {\n reject(e);\n }\n}\n\nasync function flushGets(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.get.all([keys[0]])\n : await ps.getMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n resolveGet(\n callbacks[CB_RESOLVE] as GetResolve,\n callbacks[CB_REJECT] as Reject,\n rows[0]?.[0] as string | undefined,\n );\n return;\n }\n const resultMap = new Map(rows as [string, string][]);\n for (let i = 0; i < keys.length; i++) {\n resolveGet(\n callbacks[i * CB_STRIDE + CB_RESOLVE] as GetResolve,\n callbacks[i * CB_STRIDE + CB_REJECT] as Reject,\n resultMap.get(keys[i]),\n );\n }\n}\n\nasync function flushHas(\n keys: string[],\n callbacks: unknown[],\n ps: PreparedStatements,\n): Promise<void> {\n let rows: unknown[][];\n try {\n rows =\n keys.length === 1\n ? await ps.has.all([keys[0]])\n : await ps.hasMany.all([JSON.stringify(keys)]);\n } catch (e) {\n rejectAll(callbacks, e);\n return;\n }\n if (keys.length === 1) {\n (callbacks[CB_RESOLVE] as HasResolve)(rows.length > 0);\n return;\n }\n const existingKeys = new Set(rows.map(row => row[0] as string));\n for (let i = 0; i < keys.length; i++) {\n (callbacks[i * CB_STRIDE + CB_RESOLVE] as HasResolve)(\n existingKeys.has(keys[i]),\n );\n }\n}\n\nexport class SQLiteStoreRead implements Read {\n readonly #release: () => void;\n readonly #preparedStatements: PreparedStatements;\n #closed = false;\n #pendingGetKeys: string[] = [];\n #pendingGetCallbacks: unknown[] = [];\n #pendingHasKeys: string[] = [];\n #pendingHasCallbacks: unknown[] = [];\n #scheduled = false;\n\n constructor(release: () => void, preparedStatements: PreparedStatements) {\n this.#release = release;\n this.#preparedStatements = preparedStatements;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingHasKeys.push(key);\n this.#pendingHasCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n new Promise((resolve, reject) => {\n this.#pendingGetKeys.push(key);\n this.#pendingGetCallbacks.push(resolve, reject);\n this.#scheduleLookup();\n })\n );\n }\n\n #scheduleLookup(): void {\n if (!this.#scheduled) {\n this.#scheduled = true;\n queueMicrotask(() => {\n this.#scheduled = false;\n\n const ps = this.#preparedStatements;\n const getKeys = this.#pendingGetKeys;\n this.#pendingGetKeys = [];\n const getCallbacks = this.#pendingGetCallbacks;\n this.#pendingGetCallbacks = [];\n const hasKeys = this.#pendingHasKeys;\n this.#pendingHasKeys = [];\n const hasCallbacks = this.#pendingHasCallbacks;\n this.#pendingHasCallbacks = [];\n\n if (this.#closed) {\n const e = transactionError();\n rejectAll(getCallbacks, e);\n rejectAll(hasCallbacks, e);\n return;\n }\n\n if (getKeys.length > 0) {\n void flushGets(getKeys, getCallbacks, ps);\n }\n if (hasKeys.length > 0) {\n void flushHas(hasKeys, hasCallbacks, ps);\n }\n });\n }\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n this.#release();\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nexport class SQLiteWrite extends WriteImplBase implements Write {\n readonly #release: () => void;\n readonly #dbDelegate: SQLiteDatabase;\n readonly #preparedStatements: PreparedStatements;\n #committed = false;\n #closed = false;\n\n constructor(\n release: () => void,\n dbDelegate: SQLiteDatabase,\n preparedStatements: PreparedStatements,\n ) {\n super(new SQLiteStoreRead(() => undefined, preparedStatements));\n this.#release = release;\n this.#dbDelegate = dbDelegate;\n this.#preparedStatements = preparedStatements;\n }\n\n async commit(): Promise<void> {\n if (this.#closed) {\n throw transactionError();\n }\n\n const deleteKeys: string[] = [];\n for (const entry of this._pending) {\n if (entry[1] === deleteSentinel) {\n deleteKeys.push(entry[0]);\n this._pending.delete(entry[0]);\n }\n }\n\n const delP =\n deleteKeys.length > 0\n ? this.#preparedStatements.del.exec([JSON.stringify(deleteKeys)])\n : undefined;\n const putP =\n this._pending.size > 0\n ? this.#preparedStatements.put.exec([\n JSON.stringify([...this._pending]),\n ])\n : undefined;\n\n if (putP) await putP;\n if (delP) await delP;\n\n this.#dbDelegate.execSync('COMMIT');\n this._pending.clear();\n this.#committed = true;\n }\n\n release(): void {\n if (!this.#closed) {\n this.#closed = true;\n super.release();\n let rollbackError: unknown;\n if (!this.#committed) {\n try {\n this.#dbDelegate.execSync('ROLLBACK');\n } catch (e) {\n rollbackError = e;\n }\n }\n this.#release();\n if (rollbackError !== undefined) {\n throw rollbackError;\n }\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\ntype StoreEntry = {\n readonly lock: RWLock;\n readonly db: SQLiteDatabase;\n refCount: number;\n activeReaders: number;\n preparedStatements: PreparedStatements;\n};\n\n// Global map to share database connections between multiple store instances with the same name\nconst stores = new Map<string, StoreEntry>();\n\n/**\n * Gets an existing store entry or creates a new one if it doesn't exist.\n * This implements the shared connection pattern where multiple stores with the same\n * name share the same database connection, lock, and delegate.\n */\nfunction getOrCreateEntry(\n filename: string,\n create: (filename: string, opts?: SQLiteStoreOptions) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): StoreEntry {\n const entry = stores.get(filename);\n\n if (entry) {\n entry.refCount++;\n return entry;\n }\n\n const dbDelegate = create(filename, opts);\n const preparedStatements = setupDatabase(dbDelegate, opts);\n\n const lock = new RWLock();\n\n const newEntry: StoreEntry = {\n lock,\n db: dbDelegate,\n refCount: 1,\n activeReaders: 0,\n preparedStatements,\n };\n stores.set(filename, newEntry);\n return newEntry;\n}\n\n/**\n * Decrements the reference count for a shared store and cleans up resources\n * when the last reference is released.\n */\n\nfunction decrementStoreRefCount(\n filename: string,\n dbDelegate: SQLiteDatabase,\n): void {\n const entry = stores.get(filename);\n if (entry) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n dbDelegate.close();\n stores.delete(filename);\n }\n }\n}\nexport function clearAllNamedStoresForTesting(): void {\n for (const entry of stores.values()) {\n entry.db.close();\n }\n stores.clear();\n}\n\nexport function dropStore(\n name: string,\n createDelegate: (\n filename: string,\n opts?: SQLiteStoreOptions,\n ) => SQLiteDatabase,\n opts?: SQLiteStoreOptions,\n): Promise<void> {\n const filename = resolveFilename(name, opts);\n const entry = stores.get(filename);\n if (entry) {\n try {\n entry.db.close();\n } catch {\n // Ignore close errors\n }\n stores.delete(filename);\n }\n\n // Create a temporary delegate to handle database deletion\n const tempDelegate = createDelegate(filename, opts);\n try {\n // we close the db before destroying it - this\n // caused an issue with expo-sqlite since it requires this\n tempDelegate.close();\n } catch {\n // Ignore close errors\n }\n try {\n tempDelegate.destroy();\n } catch {\n // Destroy errors shouldn't be fatal; the file may already be gone or locked\n }\n\n return Promise.resolve();\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"throw-if-closed.js","names":[],"sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"sourcesContent":["function storeError(): Error {\n return new Error('Store is closed');\n}\n\nexport function transactionError(): Error {\n return new Error('Transaction is closed');\n}\n\nexport function throwIfStoreClosed(store: {readonly closed: boolean}): void {\n if (store.closed) {\n throw storeError();\n }\n}\n\nexport function throwIfTransactionClosed(transaction: {\n readonly closed: boolean;\n}): void {\n if (transaction.closed) {\n throw transactionError();\n }\n}\n\nexport function transactionIsClosedRejection() {\n return Promise.reject(transactionError());\n}\n\nexport function maybeTransactionIsClosedRejection(transaction: {\n readonly closed: boolean;\n}): Promise<never> | undefined {\n return transaction.closed ? transactionIsClosedRejection() : undefined;\n}\n\nexport function storeIsClosedRejection() {\n return Promise.reject(storeError());\n}\n"],"mappings":";AAAA,SAAS,aAAoB;
|
|
1
|
+
{"version":3,"file":"throw-if-closed.js","names":[],"sources":["../../../../../replicache/src/kv/throw-if-closed.ts"],"sourcesContent":["function storeError(): Error {\n return new Error('Store is closed');\n}\n\nexport function transactionError(): Error {\n return new Error('Transaction is closed');\n}\n\nexport function throwIfStoreClosed(store: {readonly closed: boolean}): void {\n if (store.closed) {\n throw storeError();\n }\n}\n\nexport function throwIfTransactionClosed(transaction: {\n readonly closed: boolean;\n}): void {\n if (transaction.closed) {\n throw transactionError();\n }\n}\n\nexport function transactionIsClosedRejection() {\n return Promise.reject(transactionError());\n}\n\nexport function maybeTransactionIsClosedRejection(transaction: {\n readonly closed: boolean;\n}): Promise<never> | undefined {\n return transaction.closed ? transactionIsClosedRejection() : undefined;\n}\n\nexport function storeIsClosedRejection() {\n return Promise.reject(storeError());\n}\n"],"mappings":";AAAA,SAAS,aAAoB;AAC3B,wBAAO,IAAI,MAAM,kBAAkB;;AAGrC,SAAgB,mBAA0B;AACxC,wBAAO,IAAI,MAAM,wBAAwB;;AAG3C,SAAgB,mBAAmB,OAAyC;AAC1E,KAAI,MAAM,OACR,OAAM,YAAY;;AAYtB,SAAgB,+BAA+B;AAC7C,QAAO,QAAQ,OAAO,kBAAkB,CAAC;;AAG3C,SAAgB,kCAAkC,aAEnB;AAC7B,QAAO,YAAY,SAAS,8BAA8B,GAAG,KAAA;;AAG/D,SAAgB,yBAAyB;AACvC,QAAO,QAAQ,OAAO,YAAY,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-impl-base.js","names":["#read"],"sources":["../../../../../replicache/src/kv/write-impl-base.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n promiseFalse,\n promiseTrue,\n promiseVoid,\n} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreeze,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\n\nexport const deleteSentinel = Symbol();\ntype DeleteSentinel = typeof deleteSentinel;\n\nexport class WriteImplBase {\n protected readonly _pending: Map<string, FrozenJSONValue | DeleteSentinel> =\n new Map();\n readonly #read: Read;\n\n constructor(read: Read) {\n this.#read = read;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n switch (this._pending.get(key)) {\n case undefined:\n return this.#read.has(key);\n case deleteSentinel:\n return promiseFalse;\n default:\n return promiseTrue;\n }\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n const v = this._pending.get(key);\n switch (v) {\n case deleteSentinel:\n return undefined;\n case undefined: {\n const v = await this.#read.get(key);\n return deepFreezeAllowUndefined(v);\n }\n default:\n return v;\n }\n }\n\n put(key: string, value: ReadonlyJSONValue) {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deepFreeze(value)), promiseVoid)\n );\n }\n\n del(key: string): Promise<void> {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deleteSentinel), promiseVoid)\n );\n }\n\n release(): void {\n this.#read.release();\n }\n\n get closed(): boolean {\n return this.#read.closed;\n }\n}\n"],"mappings":";;;;AAiBA,IAAa,iBAAiB,
|
|
1
|
+
{"version":3,"file":"write-impl-base.js","names":["#read"],"sources":["../../../../../replicache/src/kv/write-impl-base.ts"],"sourcesContent":["import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n promiseFalse,\n promiseTrue,\n promiseVoid,\n} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreeze,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\n\nexport const deleteSentinel = Symbol();\ntype DeleteSentinel = typeof deleteSentinel;\n\nexport class WriteImplBase {\n protected readonly _pending: Map<string, FrozenJSONValue | DeleteSentinel> =\n new Map();\n readonly #read: Read;\n\n constructor(read: Read) {\n this.#read = read;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n switch (this._pending.get(key)) {\n case undefined:\n return this.#read.has(key);\n case deleteSentinel:\n return promiseFalse;\n default:\n return promiseTrue;\n }\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n const v = this._pending.get(key);\n switch (v) {\n case deleteSentinel:\n return undefined;\n case undefined: {\n const v = await this.#read.get(key);\n return deepFreezeAllowUndefined(v);\n }\n default:\n return v;\n }\n }\n\n put(key: string, value: ReadonlyJSONValue) {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deepFreeze(value)), promiseVoid)\n );\n }\n\n del(key: string): Promise<void> {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deleteSentinel), promiseVoid)\n );\n }\n\n release(): void {\n this.#read.release();\n }\n\n get closed(): boolean {\n return this.#read.closed;\n }\n}\n"],"mappings":";;;;AAiBA,IAAa,iBAAiB,QAAQ;AAGtC,IAAa,gBAAb,MAA2B;CACzB,2BACE,IAAI,KAAK;CACX;CAEA,YAAY,MAAY;AACtB,QAAA,OAAa;;CAGf,IAAI,KAA+B;AACjC,MAAI,MAAA,KAAW,OACb,QAAO,8BAA8B;AAEvC,UAAQ,KAAK,SAAS,IAAI,IAAI,EAA9B;GACE,KAAK,KAAA,EACH,QAAO,MAAA,KAAW,IAAI,IAAI;GAC5B,KAAK,eACH,QAAO;GACT,QACE,QAAO;;;CAIb,MAAM,IAAI,KAAmD;AAC3D,MAAI,MAAA,KAAW,OACb,QAAO,8BAA8B;EAEvC,MAAM,IAAI,KAAK,SAAS,IAAI,IAAI;AAChC,UAAQ,GAAR;GACE,KAAK,eACH;GACF,KAAK,KAAA,EAEH,QAAO,yBADG,MAAM,MAAA,KAAW,IAAI,IAAI,CACD;GAEpC,QACE,QAAO;;;CAIb,IAAI,KAAa,OAA0B;AACzC,SACE,kCAAkC,MAAA,KAAW,KAC5C,KAAK,SAAS,IAAI,KAAK,WAAW,MAAM,CAAC,EAAE;;CAIhD,IAAI,KAA4B;AAC9B,SACE,kCAAkC,MAAA,KAAW,KAC5C,KAAK,SAAS,IAAI,KAAK,eAAe,EAAE;;CAI7C,UAAgB;AACd,QAAA,KAAW,SAAS;;CAGtB,IAAI,SAAkB;AACpB,SAAO,MAAA,KAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-impl.js","names":["#map"],"sources":["../../../../../replicache/src/kv/write-impl.ts"],"sourcesContent":["import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Write} from './store.ts';\nimport {transactionIsClosedRejection} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\nexport class WriteImpl extends WriteImplBase implements Write {\n readonly #map: Map<string, FrozenJSONValue>;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n super(new ReadImpl(map, release));\n this.#map = map;\n }\n\n commit(): Promise<void> {\n if (this.closed) {\n return transactionIsClosedRejection();\n }\n\n // HOT. Do not allocate entry tuple and destructure.\n this._pending.forEach((value, key) => {\n if (value === deleteSentinel) {\n this.#map.delete(key);\n } else {\n this.#map.set(key, value);\n }\n });\n this._pending.clear();\n this.release();\n return promiseVoid;\n }\n}\n"],"mappings":";;;;;AAOA,IAAa,YAAb,cAA+B,cAA+B;CAC5D;CAEA,YAAY,KAAmC,SAAqB;
|
|
1
|
+
{"version":3,"file":"write-impl.js","names":["#map"],"sources":["../../../../../replicache/src/kv/write-impl.ts"],"sourcesContent":["import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Write} from './store.ts';\nimport {transactionIsClosedRejection} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\nexport class WriteImpl extends WriteImplBase implements Write {\n readonly #map: Map<string, FrozenJSONValue>;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n super(new ReadImpl(map, release));\n this.#map = map;\n }\n\n commit(): Promise<void> {\n if (this.closed) {\n return transactionIsClosedRejection();\n }\n\n // HOT. Do not allocate entry tuple and destructure.\n this._pending.forEach((value, key) => {\n if (value === deleteSentinel) {\n this.#map.delete(key);\n } else {\n this.#map.set(key, value);\n }\n });\n this._pending.clear();\n this.release();\n return promiseVoid;\n }\n}\n"],"mappings":";;;;;AAOA,IAAa,YAAb,cAA+B,cAA+B;CAC5D;CAEA,YAAY,KAAmC,SAAqB;AAClE,QAAM,IAAI,SAAS,KAAK,QAAQ,CAAC;AACjC,QAAA,MAAY;;CAGd,SAAwB;AACtB,MAAI,KAAK,OACP,QAAO,8BAA8B;AAIvC,OAAK,SAAS,SAAS,OAAO,QAAQ;AACpC,OAAI,UAAU,eACZ,OAAA,IAAU,OAAO,IAAI;OAErB,OAAA,IAAU,IAAI,KAAK,MAAM;IAE3B;AACF,OAAK,SAAS,OAAO;AACrB,OAAK,SAAS;AACd,SAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lazy.js","names":[],"sources":["../../../../replicache/src/lazy.ts"],"sourcesContent":["export function lazy<T>(factory: () => T): () => T {\n let value: T | undefined;\n return () => {\n if (value === undefined) {\n value = factory();\n }\n return value;\n };\n}\n"],"mappings":";AAAA,SAAgB,KAAQ,SAA2B;CACjD,IAAI;
|
|
1
|
+
{"version":3,"file":"lazy.js","names":[],"sources":["../../../../replicache/src/lazy.ts"],"sourcesContent":["export function lazy<T>(factory: () => T): () => T {\n let value: T | undefined;\n return () => {\n if (value === undefined) {\n value = factory();\n }\n return value;\n };\n}\n"],"mappings":";AAAA,SAAgB,KAAQ,SAA2B;CACjD,IAAI;AACJ,cAAa;AACX,MAAI,UAAU,KAAA,EACZ,SAAQ,SAAS;AAEnB,SAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-options.js","names":[],"sources":["../../../../replicache/src/log-options.ts"],"sourcesContent":["import {\n consoleLogSink,\n LogContext,\n TeeLogSink,\n type Context,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\n\n/**\n * Creates a LogContext\n * @param logLevel The log level to use. Default is `'info'`.\n * @param logSinks Destination for logs. Default is `[consoleLogSink]`.\n * @param context Optional: Additional information that can be associated with logs.\n * @returns A LogContext instance configured with the provided options.\n */\nexport function createLogContext(\n logLevel: LogLevel = 'info',\n logSinks: LogSink[] = [consoleLogSink],\n context?: Context,\n): LogContext {\n const logSink =\n logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);\n return new LogContext(logLevel, context, logSink);\n}\n"],"mappings":";;;;;;;;;AAgBA,SAAgB,iBACd,WAAqB,QACrB,WAAsB,CAAC,
|
|
1
|
+
{"version":3,"file":"log-options.js","names":[],"sources":["../../../../replicache/src/log-options.ts"],"sourcesContent":["import {\n consoleLogSink,\n LogContext,\n TeeLogSink,\n type Context,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\n\n/**\n * Creates a LogContext\n * @param logLevel The log level to use. Default is `'info'`.\n * @param logSinks Destination for logs. Default is `[consoleLogSink]`.\n * @param context Optional: Additional information that can be associated with logs.\n * @returns A LogContext instance configured with the provided options.\n */\nexport function createLogContext(\n logLevel: LogLevel = 'info',\n logSinks: LogSink[] = [consoleLogSink],\n context?: Context,\n): LogContext {\n const logSink =\n logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);\n return new LogContext(logLevel, context, logSink);\n}\n"],"mappings":";;;;;;;;;AAgBA,SAAgB,iBACd,WAAqB,QACrB,WAAsB,CAAC,eAAe,EACtC,SACY;AAGZ,QAAO,IAAI,WAAW,UAAU,SAD9B,SAAS,WAAW,IAAI,SAAS,KAAK,IAAI,WAAW,SAAS,CACf"}
|