@rocicorp/zero 0.3.2024102800 → 0.5.2024103100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/chunk-TBA526RR.js +16475 -0
- package/out/chunk-TBA526RR.js.map +7 -0
- package/out/chunk-ULOTOBTC.js +1 -0
- package/out/internal.js +1 -1
- package/out/react.js.map +2 -2
- package/out/shared/src/arrays.d.ts +6 -0
- package/out/shared/src/arrays.d.ts.map +1 -0
- package/out/shared/src/arrays.js +20 -0
- package/out/shared/src/arrays.js.map +1 -0
- package/out/shared/src/iterables.d.ts +1 -0
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +33 -0
- package/out/shared/src/iterables.js.map +1 -1
- package/out/solid.js +16 -1
- package/out/solid.js.map +3 -3
- package/out/zero/src/advanced.d.ts +2 -0
- package/out/zero/src/advanced.d.ts.map +1 -0
- package/out/{zero-internal → zero-advanced}/src/mod.d.ts +2 -1
- package/out/{zero-internal → zero-advanced}/src/mod.d.ts.map +1 -1
- package/out/zero-cache/src/config/config-query.d.ts +1 -0
- package/out/zero-cache/src/config/config-query.d.ts.map +1 -1
- package/out/zero-cache/src/config/config-query.js +3 -0
- package/out/zero-cache/src/config/config-query.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +114 -114
- package/out/zero-cache/src/db/statements.d.ts +1 -1
- package/out/zero-cache/src/server/life-cycle.d.ts +19 -4
- package/out/zero-cache/src/server/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/server/life-cycle.js +105 -54
- package/out/zero-cache/src/server/life-cycle.js.map +1 -1
- package/out/zero-cache/src/server/logging.js +2 -2
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.js +9 -9
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +3 -9
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +12 -32
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.js +4 -4
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js +2 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/shard.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/pg/schema/shard.js +4 -3
- package/out/zero-cache/src/services/change-streamer/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/dispatcher/connect-params.d.ts +2 -1
- package/out/zero-cache/src/services/dispatcher/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/services/dispatcher/connect-params.js +4 -4
- package/out/zero-cache/src/services/dispatcher/connect-params.js.map +1 -1
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts +3 -8
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/services/dispatcher/dispatcher.js +8 -24
- package/out/zero-cache/src/services/dispatcher/dispatcher.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +16 -0
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -0
- package/out/zero-cache/src/services/http-service.js +39 -0
- package/out/zero-cache/src/services/http-service.js.map +1 -0
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +2 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +6 -8
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +6 -0
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +15 -15
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +6 -6
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +2 -2
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +5 -0
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +1 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +3 -2
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts +2 -2
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +5 -1
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +3 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/context.d.ts +2 -1
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +53 -39
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +37 -0
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +28 -10
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.d.ts +1 -0
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-client/src/mod.js +1 -0
- package/out/zero-client/src/mod.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +18 -10
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +80 -12
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.d.ts +6 -6
- package/out/zero-protocol/src/connect.d.ts +11 -13
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +6 -16
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/data.d.ts +2 -2
- package/out/zero-protocol/src/data.d.ts.map +1 -1
- package/out/zero-protocol/src/data.js +2 -1
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +7 -7
- package/out/zero-protocol/src/poke.d.ts +14 -14
- package/out/zero-protocol/src/push.d.ts +21 -21
- package/out/zero-protocol/src/queries-patch.d.ts +9 -9
- package/out/zero-protocol/src/row-patch.d.ts +2 -2
- package/out/zero-protocol/src/up.d.ts +9 -9
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/create-zero.d.ts +3 -0
- package/out/zero-solid/src/create-zero.d.ts.map +1 -0
- package/out/zero-solid/src/mod.d.ts +1 -0
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +1 -1
- package/out/zero-solid/src/use-query.d.ts +1 -1
- package/out/zero.js +24 -16033
- package/out/zero.js.map +4 -4
- package/out/zql/src/zql/builder/builder.d.ts.map +1 -1
- package/out/zql/src/zql/builder/builder.js +49 -8
- package/out/zql/src/zql/builder/builder.js.map +1 -1
- package/out/zql/src/zql/builder/filter.d.ts +2 -2
- package/out/zql/src/zql/builder/filter.d.ts.map +1 -1
- package/out/zql/src/zql/builder/filter.js.map +1 -1
- package/out/zql/src/zql/builder/like.js +1 -1
- package/out/zql/src/zql/builder/like.js.map +1 -1
- package/out/zql/src/zql/ivm/fan-in.d.ts +31 -0
- package/out/zql/src/zql/ivm/fan-in.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/fan-in.js +61 -0
- package/out/zql/src/zql/ivm/fan-in.js.map +1 -0
- package/out/zql/src/zql/ivm/fan-out.d.ts +19 -0
- package/out/zql/src/zql/ivm/fan-out.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/fan-out.js +54 -0
- package/out/zql/src/zql/ivm/fan-out.js.map +1 -0
- package/out/zql/src/zql/ivm/filter.d.ts +1 -2
- package/out/zql/src/zql/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/filter.js +8 -5
- package/out/zql/src/zql/ivm/filter.js.map +1 -1
- package/out/zql/src/zql/ivm/memory-source.d.ts +22 -4
- package/out/zql/src/zql/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/memory-source.js +48 -1
- package/out/zql/src/zql/ivm/memory-source.js.map +1 -1
- package/out/zql/src/zql/ivm/schema.d.ts +1 -1
- package/out/zql/src/zql/ivm/schema.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/source.d.ts +1 -1
- package/out/zql/src/zql/ivm/source.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/take.d.ts.map +1 -1
- package/out/zql/src/zql/ivm/take.js.map +1 -1
- package/out/zql/src/zql/query/expression.d.ts +25 -0
- package/out/zql/src/zql/query/expression.d.ts.map +1 -0
- package/out/zql/src/zql/query/expression.js +115 -0
- package/out/zql/src/zql/query/expression.js.map +1 -0
- package/out/zql/src/zql/query/query-impl.d.ts +7 -3
- package/out/zql/src/zql/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/zql/query/query-impl.js +19 -16
- package/out/zql/src/zql/query/query-impl.js.map +1 -1
- package/out/zql/src/zql/query/query-internal.d.ts +1 -1
- package/out/zql/src/zql/query/query.d.ts +15 -4
- package/out/zql/src/zql/query/query.d.ts.map +1 -1
- package/out/zqlite/src/db.d.ts +1 -1
- package/out/zqlite/src/db.js +1 -1
- package/out/zqlite/src/table-source.d.ts +2 -2
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +48 -26
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +5 -5
- package/out/chunk-NKGIR6IA.js +0 -1
- package/out/zero/src/internal.d.ts +0 -2
- package/out/zero/src/internal.d.ts.map +0 -1
- /package/out/{chunk-NKGIR6IA.js.map → chunk-ULOTOBTC.js.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../shared/src/config.ts", "../../shared/src/json.ts", "../../replicache/src/call-default-fetch.ts", "../../shared/src/string-compare.ts", "../../replicache/src/cookies.ts", "../../replicache/src/error-responses.ts", "../../replicache/src/http-request-info.ts", "../../replicache/src/patch-operation.ts", "../../replicache/src/get-default-puller.ts", "../../replicache/src/kv/idb-store.ts", "../../shared/src/resolved-promises.ts", "../../replicache/src/frozen-json.ts", "../../replicache/src/kv/write-impl-base.ts", "../../shared/src/browser-env.ts", "../../replicache/src/transaction-closed-error.ts", "../../replicache/src/format-version-enum.ts", "../../shared/src/navigator.ts", "../../replicache/src/kv/mem-store.ts", "../../replicache/src/kv/read-impl.ts", "../../replicache/src/kv/write-impl.ts", "../../replicache/src/kv/idb-store-with-mem-fallback.ts", "../../replicache/src/replicache-impl.ts", "../../shared/src/abort-error.ts", "../../shared/src/document-visible.ts", "../../replicache/src/connection-loop-delegates.ts", "../../replicache/src/connection-loop.ts", "../../shared/src/sleep.ts", "../../replicache/src/dag/lazy-store.ts", "../../shared/src/iterables.ts", "../../replicache/src/size-of-value.ts", "../../replicache/src/dag/chunk.ts", "../../shared/src/random-uint64.ts", "../../shared/src/valita.ts", "../../replicache/src/hash.ts", "../../replicache/src/dag/gc.ts", "../../replicache/src/dag/store.ts", "../../replicache/src/dag/key.ts", "../../replicache/src/dag/store-impl.ts", "../../replicache/src/db/meta-type-enum.ts", "../../replicache/src/db/commit.ts", "../../replicache/src/btree/node.ts", "../../replicache/src/binary-search.ts", "../../replicache/src/btree/splice.ts", "../../replicache/src/btree/read.ts", "../../replicache/src/db/index-operation-enum.ts", "../../replicache/src/db/index.ts", "../../replicache/src/db/read.ts", "../../replicache/src/transactions.ts", "../../replicache/src/scan-iterator.ts", "../../replicache/src/async-iterable-to-array.ts", "../../replicache/src/scan-options.ts", "../../replicache/src/btree/diff.ts", "../../replicache/src/btree/write.ts", "../../replicache/src/lazy.ts", "../../replicache/src/sync/diff.ts", "../../replicache/src/db/write.ts", "../../replicache/src/db/rebase.ts", "../../replicache/src/get-default-pusher.ts", "../../replicache/src/log-options.ts", "../../replicache/src/format-version.ts", "../../replicache/src/index-defs.ts", "../../replicache/src/persist/client-groups.ts", "../../replicache/src/sync/ids.ts", "../../replicache/src/with-transactions.ts", "../../replicache/src/persist/make-client-id.ts", "../../replicache/src/persist/clients.ts", "../../replicache/src/to-error.ts", "../../replicache/src/sync/handle-pull-response-result-type-enum.ts", "../../replicache/src/sync/patch.ts", "../../replicache/src/sync/pull-error.ts", "../../replicache/src/sync/sync-head-name.ts", "../../replicache/src/sync/pull.ts", "../../shared/src/json-schema.ts", "../../replicache/src/pusher.ts", "../../replicache/src/sync/push.ts", "../../replicache/src/mutation-recovery.ts", "../../replicache/src/broadcast-channel.ts", "../../replicache/src/new-client-channel.ts", "../../replicache/src/on-persist-channel.ts", "../../replicache/src/pending-mutations.ts", "../../replicache/src/bg-interval.ts", "../../replicache/src/persist/client-gc.ts", "../../replicache/src/persist/client-group-gc.ts", "../../replicache/src/persist/idb-databases-store-db-name.ts", "../../replicache/src/persist/idb-databases-store.ts", "../../replicache/src/persist/collect-idb-databases.ts", "../../replicache/src/persist/heartbeat.ts", "../../replicache/src/dag/visitor.ts", "../../replicache/src/persist/gather-mem-only-visitor.ts", "../../replicache/src/persist/persist.ts", "../../replicache/src/persist/gather-not-cached-visitor.ts", "../../replicache/src/persist/refresh.ts", "../../replicache/src/process-scheduler.ts", "../../replicache/src/request-idle.ts", "../../replicache/src/set-interval-with-signal.ts", "../../replicache/src/subscriptions.ts", "../../replicache/src/invoke-kind-enum.ts", "../../shared/src/random-values.ts", "../../replicache/src/sync/request-id.ts", "../../replicache/src/version.ts", "../../replicache/src/replicache.ts", "../../replicache/src/mod.ts", "../../zql/src/zql/query/schema.ts", "../../zql/src/zql/query/expression.ts", "../../zql/src/zql/query/query-impl.ts", "../../shared/src/xxhash.ts", "../../zero-protocol/src/ast.ts", "../../shared/src/arrays.ts", "../../zero-protocol/src/data.ts", "../../zero-protocol/src/ast-hash.ts", "../../zql/src/zql/ivm/fan-in.ts", "../../zql/src/zql/ivm/fan-out.ts", "../../zql/src/zql/ivm/maybe-split-and-push-edit-change.ts", "../../zql/src/zql/ivm/filter.ts", "../../zql/src/zql/ivm/data.ts", "../../zql/src/zql/ivm/stream.ts", "../../zql/src/zql/ivm/join.ts", "../../zql/src/zql/ivm/skip.ts", "../../zql/src/zql/ivm/take.ts", "../../zql/src/zql/builder/error.ts", "../../zql/src/zql/builder/like.ts", "../../zql/src/zql/builder/filter.ts", "../../zql/src/zql/builder/builder.ts", "../../zql/src/zql/ivm/array-view.ts", "../../shared/src/sorted-entries.ts", "../../zql/src/zql/query/normalize-table-schema.ts", "../../zql/src/zql/query/escape-like.ts", "../../zero-client/src/client/zero.ts", "../../zero-protocol/src/queries-patch.ts", "../../zero-protocol/src/change-desired-queries.ts", "../../zero-protocol/src/clients-patch.ts", "../../zero-protocol/src/connect.ts", "../../zero-protocol/src/error.ts", "../../zero-protocol/src/primary-key.ts", "../../zero-protocol/src/row-patch.ts", "../../zero-protocol/src/version.ts", "../../zero-protocol/src/poke.ts", "../../zero-protocol/src/pong.ts", "../../zero-protocol/src/pull.ts", "../../zero-protocol/src/warm.ts", "../../zero-protocol/src/down.ts", "../../zero-protocol/src/ping.ts", "../../zero-protocol/src/push.ts", "../../zero-protocol/src/delete-clients.ts", "../../zero-protocol/src/up.ts", "../../zero-client/src/util/nanoid.ts", "../../zero-client/src/util/socket.ts", "../../btree/b+tree.ts", "../../zql/src/zql/ivm/lookahead-iterator.ts", "../../zql/src/zql/ivm/memory-source.ts", "../../zql/src/zql/ivm/memory-storage.ts", "../../shared/src/reverse-string.ts", "../../shared/src/h64-with-reverse.ts", "../../zero-client/src/client/keys.ts", "../../zero-client/src/client/context.ts", "../../zero-client/src/client/crud.ts", "../../zero-client/src/client/enable-analytics.ts", "../../zero-client/src/client/http-string.ts", "../../zero-client/src/client/log-options.ts", "../../datadog/src/datadog-log-sink.ts", "../../zero-client/src/client/version.ts", "../../zero-client/src/client/metrics.ts", "../../zero-client/src/client/normalized-schema.ts", "../../zero-client/src/client/query-manager.ts", "../../zero-client/src/client/reload-error-handler.ts", "../../zero-client/src/client/server-error.ts", "../../zero-client/src/client/server-option.ts", "../../zero-client/src/client/zero-poke-handler.ts"],
|
|
4
|
+
"sourcesContent": ["declare const process: {\n env: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n NODE_ENV?: string;\n };\n};\n\nexport const isProd = process.env.NODE_ENV === 'production';\n\nexport {isProd as skipAssertJSONValue};\n", "import {assertObject, throwInvalidType} from './asserts.js';\nimport {skipAssertJSONValue} from './config.js';\nimport {hasOwn} from './has-own.js';\n\n/** The values that can be represented in JSON */\nexport type JSONValue =\n | null\n | string\n | boolean\n | number\n | Array<JSONValue>\n | JSONObject;\n\n/**\n * A JSON object. This is a map from strings to JSON values or `undefined`. We\n * allow `undefined` values as a convenience... but beware that the `undefined`\n * values do not round trip to the server. For example:\n *\n * ```\n * // Time t1\n * await tx.set('a', {a: undefined});\n *\n * // time passes, in a new transaction\n * const v = await tx.get('a');\n * console.log(v); // either {a: undefined} or {}\n * ```\n */\nexport type JSONObject = {[key: string]: JSONValue | undefined};\n\n/** Like {@link JSONValue} but deeply readonly */\nexport type ReadonlyJSONValue =\n | null\n | string\n | boolean\n | number\n | ReadonlyArray<ReadonlyJSONValue>\n | ReadonlyJSONObject;\n\n/** Like {@link JSONObject} but deeply readonly */\nexport type ReadonlyJSONObject = {\n readonly [key: string]: ReadonlyJSONValue | undefined;\n};\n\n/**\n * Checks deep equality of two JSON value with (almost) same semantics as\n * `JSON.stringify`. The only difference is that with `JSON.stringify` the\n * ordering of the properties in an object/map/dictionary matters. In\n * {@link deepEqual} the following two values are consider equal, even though the\n * strings JSON.stringify would produce is different:\n *\n * ```js\n * assert(deepEqual(t({a: 1, b: 2}, {b: 2, a: 1}))\n * ```\n */\nexport function deepEqual(\n a: ReadonlyJSONValue | undefined,\n b: ReadonlyJSONValue | undefined,\n): boolean {\n if (a === b) {\n return true;\n }\n\n if (typeof a !== typeof b) {\n return false;\n }\n\n switch (typeof a) {\n case 'boolean':\n case 'number':\n case 'string':\n return false;\n }\n\n // a cannot be undefined here because either a and b are undefined or their\n // types are different.\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n a = a!;\n\n // 'object'\n if (Array.isArray(a)) {\n if (!Array.isArray(b)) {\n return false;\n }\n if (a.length !== b.length) {\n return false;\n }\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) {\n return false;\n }\n }\n return true;\n }\n\n if (a === null || b === null) {\n return false;\n }\n\n if (Array.isArray(b)) {\n return false;\n }\n\n // We know a and b are objects here but type inference is not smart enough.\n a = a as ReadonlyJSONObject;\n b = b as ReadonlyJSONObject;\n\n // We use for-in loops instead of for of Object.keys() to make sure deepEquals\n // does not allocate any objects.\n\n let aSize = 0;\n for (const key in a) {\n if (hasOwn(a, key)) {\n if (!deepEqual(a[key], b[key])) {\n return false;\n }\n aSize++;\n }\n }\n\n let bSize = 0;\n for (const key in b) {\n if (hasOwn(b, key)) {\n bSize++;\n }\n }\n\n return aSize === bSize;\n}\n\nexport function assertJSONValue(v: unknown): asserts v is JSONValue {\n if (skipAssertJSONValue) {\n return;\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 if (Array.isArray(v)) {\n return assertJSONArray(v);\n }\n return assertObjectIsJSONObject(v as Record<string, unknown>);\n }\n throwInvalidType(v, 'JSON value');\n}\n\nexport function assertJSONObject(v: unknown): asserts v is JSONObject {\n assertObject(v);\n assertObjectIsJSONObject(v);\n}\n\nfunction assertObjectIsJSONObject(\n v: Record<string, unknown>,\n): asserts v is JSONObject {\n for (const k in v) {\n if (hasOwn(v, k)) {\n const value = v[k];\n if (value !== undefined) {\n assertJSONValue(value);\n }\n }\n }\n}\n\nfunction assertJSONArray(v: unknown[]): asserts v is JSONValue[] {\n for (const item of v) {\n assertJSONValue(item);\n }\n}\n\ninterface Path {\n push(key: string | number): void;\n pop(): void;\n}\n\n/**\n * Checks if a value is a JSON value. If there is a value that is not a JSON\n * value, the path parameter is updated to the path of the invalid value.\n */\nexport function isJSONValue(v: unknown, path: Path): v is JSONValue {\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 if (Array.isArray(v)) {\n return isJSONArray(v, path);\n }\n return objectIsJSONObject(v as Record<string, unknown>, path);\n }\n return false;\n}\n\nexport function isJSONObject(v: unknown, path: Path): v is JSONObject {\n if (typeof v !== 'object' || v === null) {\n return false;\n }\n return objectIsJSONObject(v as Record<string, unknown>, path);\n}\n\nfunction objectIsJSONObject(\n v: Record<string, unknown>,\n path: Path,\n): v is JSONObject {\n for (const k in v) {\n if (hasOwn(v, k)) {\n path.push(k);\n const value = v[k];\n if (value !== undefined && !isJSONValue(value, path)) {\n return false;\n }\n path.pop();\n }\n }\n return true;\n}\n\nfunction isJSONArray(v: unknown[], path: Path): v is JSONValue[] {\n for (let i = 0; i < v.length; i++) {\n path.push(i);\n if (!isJSONValue(v[i], path)) {\n return false;\n }\n path.pop();\n }\n return true;\n}\n\n/** Basic deep readonly type. It works for {@link JSONValue} types. */\nexport type DeepReadonly<T> = T extends\n | null\n | boolean\n | string\n | number\n | undefined\n ? T\n : {readonly [K in keyof T]: DeepReadonly<T[K]>};\n", "import type {HTTPRequestInfo} from './http-request-info.js';\n\n/**\n * Helper function for {@link getDefaultPuller} and {@link getDefaultPusher}.\n */\nexport async function callDefaultFetch<Body>(\n url: string,\n auth: string,\n requestID: string,\n requestBody: Body,\n): Promise<readonly [Response | undefined, HTTPRequestInfo]> {\n const init = {\n headers: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'Content-type': 'application/json',\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'Authorization': auth,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'X-Replicache-RequestID': requestID,\n },\n body: JSON.stringify(requestBody),\n method: 'POST',\n };\n const request = new Request(url, init);\n const response = await fetch(request);\n const httpStatusCode = response.status;\n if (httpStatusCode !== 200) {\n return [\n undefined,\n {\n httpStatusCode,\n errorMessage: await response.text(),\n },\n ];\n }\n return [\n response,\n {\n httpStatusCode,\n errorMessage: '',\n },\n ];\n}\n", "export function stringCompare(a: string, b: string): number {\n if (a === b) {\n return 0;\n }\n if (a < b) {\n return -1;\n }\n return 1;\n}\n", "import {\n assertJSONObject,\n type ReadonlyJSONValue,\n} from '../../shared/src/json.js';\nimport {stringCompare} from '../../shared/src/string-compare.js';\nimport type {FrozenJSONValue} from './frozen-json.js';\n\n/**\n * A cookie is a value that is used to determine the order of snapshots. It\n * needs to be comparable. This can be a `string`, `number` or if you want to\n * use a more complex value, you can use an object with an `order` property. The\n * value `null` is considered to be less than any other cookie and it is used\n * for the first pull when no cookie has been set.\n *\n * The order is the natural order of numbers and strings. If one of the cookies\n * is an object then the value of the `order` property is treated as the cookie\n * when doing comparison.\n *\n * If one of the cookies is a string and the other is a number, the number is\n * fist converted to a string (using `toString()`).\n */\nexport type Cookie =\n | null\n | string\n | number\n | (ReadonlyJSONValue & {readonly order: number | string});\n\nexport type FrozenCookie =\n | null\n | string\n | number\n | (FrozenJSONValue & {readonly order: number | string});\n\n/**\n * Compare two cookies.\n * `null` is considered to be less than any other cookie.\n */\nexport function compareCookies(a: Cookie, b: Cookie): number {\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n\n const cva = getCompareValue(a);\n const cvb = getCompareValue(b);\n\n // If either a or b is a string. Compare by string.\n if (typeof cva === 'string' || typeof cvb === 'string') {\n return stringCompare(String(cva), String(cvb));\n }\n\n return cva - cvb;\n}\n\ntype NonNull<T> = T extends null ? never : T;\n\nfunction getCompareValue(cookie: NonNull<Cookie>): string | number {\n if (typeof cookie === 'string' || typeof cookie === 'number') {\n return cookie;\n }\n return cookie.order;\n}\n\nexport function assertCookie(v: unknown): asserts v is Cookie {\n if (v === null || typeof v === 'string' || typeof v === 'number') {\n return;\n }\n\n assertJSONObject(v);\n if (typeof v.order === 'string' || typeof v.order === 'number') {\n return;\n }\n\n throw new Error('Invalid cookie');\n}\n", "import {assert} from '../../shared/src/asserts.js';\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 {@link pullVersion}, {@link pushVersion} or the\n * {@link schemaVersion}.\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(isVersionNotSupportedResponse(v));\n}\n", "import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.js';\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", "import {\n assertArray,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.js';\nimport {\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n assertJSONObject,\n assertJSONValue,\n} from '../../shared/src/json.js';\n\nexport type PatchOperationInternal =\n | {\n readonly op: 'put';\n readonly key: string;\n readonly value: ReadonlyJSONValue;\n }\n | {\n readonly op: 'update';\n readonly key: string;\n readonly merge?: ReadonlyJSONObject | undefined;\n readonly constrain?: string[] | undefined;\n }\n | {\n readonly op: 'del';\n readonly key: string;\n }\n | {\n readonly op: 'clear';\n };\n\n/**\n * This type describes the patch field in a {@link PullResponse} and it is used\n * to describe how to update the Replicache key-value store.\n */\nexport type PatchOperation =\n | {\n readonly op: 'put';\n readonly key: string;\n readonly value: ReadonlyJSONValue;\n }\n | {\n readonly op: 'del';\n readonly key: string;\n }\n | {\n readonly op: 'clear';\n };\n\nexport function assertPatchOperations(\n p: unknown,\n): asserts p is PatchOperationInternal[] {\n assertArray(p);\n for (const item of p) {\n assertPatchOperation(item);\n }\n}\n\nfunction assertPatchOperation(p: unknown): asserts p is PatchOperationInternal {\n assertObject(p);\n switch (p.op) {\n case 'put':\n assertString(p.key);\n assertJSONValue(p.value);\n break;\n case 'update':\n assertString(p.key);\n if (p.merge !== undefined) {\n assertJSONObject(p.merge);\n }\n if (p.constrain !== undefined) {\n assertArray(p.constrain);\n for (const key of p.constrain) {\n assertString(key);\n }\n }\n break;\n case 'del':\n assertString(p.key);\n break;\n case 'clear':\n break;\n default:\n throw new Error(\n `unknown patch op \\`${p.op}\\`, expected one of \\`put\\`, \\`del\\`, \\`clear\\``,\n );\n }\n}\n", "import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.js';\nimport {assertJSONValue} from '../../shared/src/json.js';\nimport {callDefaultFetch} from './call-default-fetch.js';\nimport {assertCookie} from './cookies.js';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.js';\nimport {assertHTTPRequestInfo} from './http-request-info.js';\nimport {assertPatchOperations} from './patch-operation.js';\nimport type {\n PullResponseOKV0,\n PullResponseV0,\n PullResponseV1,\n Puller,\n PullerResult,\n PullerResultV0,\n PullerResultV1,\n} from './puller.js';\nimport type {PullRequest} from './sync/pull.js';\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 assertPullResponseV0(v: unknown): asserts v is PullResponseV0 {\n assertObject(v);\n if (isClientStateNotFoundResponse(v) || isVersionNotSupportedResponse(v)) {\n return;\n }\n const v2 = v as Partial<PullResponseOKV0>;\n if (v2.cookie !== undefined) {\n assertJSONValue(v2.cookie);\n }\n assertNumber(v2.lastMutationID);\n assertPatchOperations(v2.patch);\n}\n\nexport function assertPullResponseV1(v: unknown): asserts v is PullResponseV1 {\n assertObject(v);\n if (isClientStateNotFoundResponse(v) || isVersionNotSupportedResponse(v)) {\n return;\n }\n const v2 = v as Record<string, unknown>;\n if (v2.cookie !== undefined) {\n assertCookie(v2.cookie);\n }\n assertLastMutationIDChanges(v2.lastMutationIDChanges);\n assertPatchOperations(v2.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\nexport function assertPullerResultV0(v: unknown): asserts v is PullerResultV0 {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPullResponseV0(v.response);\n }\n}\n", "import {resolver} from '@rocicorp/resolver';\nimport {assertNotNull} from '../../../shared/src/asserts.js';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport {\n type FrozenJSONValue,\n deepFreezeAllowUndefined,\n} from '../frozen-json.js';\nimport type {Read, Store, Write} from './store.js';\nimport {WriteImplBase, deleteSentinel} from './write-impl-base.js';\nimport {mustGetBrowserGlobal} from '../../../shared/src/browser-env.js';\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 return this.#withReopen(readImpl);\n }\n\n write(): Promise<Write> {\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(new IDBNotFoundError(`Replicache IndexedDB not found: ${name}`));\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 `Replicache IndexedDB ${db.name} missing object store. Deleting db.`,\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 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 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._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 }\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 {@link Error} is thrown when we detect that the IndexedDB has been\n * removed. This does not normally happen but can happen during development if\n * the user has DevTools open and deletes the IndexedDB from there.\n */\nexport class IDBNotFoundError extends Error {\n name = 'IDBNotFoundError';\n}\n", "export const promiseTrue = Promise.resolve(true);\nexport const promiseFalse = Promise.resolve(false);\nexport const promiseUndefined = Promise.resolve(undefined);\nexport const promiseVoid = Promise.resolve();\n", "import {throwInvalidType} from '../../shared/src/asserts.js';\nimport {skipAssertJSONValue} from '../../shared/src/config.js';\nimport {hasOwn} from '../../shared/src/has-own.js';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../shared/src/json.js';\nimport {skipFreeze, skipFrozenAsserts} from './config.js';\nimport type {Cookie, FrozenCookie} from './cookies.js';\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", "import type {ReadonlyJSONValue} from '../../../shared/src/json.js';\nimport {\n promiseFalse,\n promiseTrue,\n promiseVoid,\n} from '../../../shared/src/resolved-promises.js';\nimport {\n type FrozenJSONValue,\n deepFreeze,\n deepFreezeAllowUndefined,\n} from '../frozen-json.js';\nimport type {Read} from './store.js';\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 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 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): Promise<void> {\n this._pending.set(key, deepFreeze(value));\n return promiseVoid;\n }\n\n del(key: string): Promise<void> {\n this._pending.set(key, deleteSentinel);\n return promiseVoid;\n }\n\n release(): void {\n this.#read.release();\n }\n\n get closed(): boolean {\n return this.#read.closed;\n }\n}\n", "// Helpers for some objects from the browser environment. These are wrapped in\n// functions because Replicache runs in environments that do not have these\n// objects (such as Web Workers, Deno etc).\n\ntype GlobalThis = typeof globalThis;\n\nexport function getBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n return (globalThis as unknown as GlobalThis)[name] as GlobalThis[T];\n}\n\nexport function mustGetBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] {\n const r = getBrowserGlobal(name);\n if (r === undefined) {\n throw new Error(\n `Unsupported JavaScript environment: Could not find ${name}.`,\n );\n }\n return r;\n}\n", "/**\n * This error is thrown when you try to call methods on a closed transaction.\n */\nexport class TransactionClosedError extends Error {\n constructor() {\n super('Transaction is closed');\n }\n}\n\nexport type Closed = {closed: boolean};\n\nexport function throwIfClosed(tx: Closed): void {\n if (tx.closed) {\n throw new TransactionClosedError();\n }\n}\n\nexport function rejectIfClosed(tx: Closed): undefined | Promise<never> {\n return tx.closed ? Promise.reject(new TransactionClosedError()) : undefined;\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const SDD = 4;\nexport const DD31 = 5;\n// V6 added refreshHashes and persistHash to Client to fix ChunkNotFound errors\nexport const V6 = 6;\n// V7 added sizeOfEntry to the BTree chunk data.\nexport const V7 = 7;\nexport const Latest = V7;\n\nexport type SDD = typeof SDD;\nexport type DD31 = typeof DD31;\nexport type V6 = typeof V6;\nexport type V7 = typeof V7;\nexport type Latest = typeof Latest;\n\nexport type Type = SDD | DD31 | V6 | V7 | Latest;\nexport type {Type as FormatVersion};\n", "type Navigator = {\n onLine: boolean;\n userAgent: string;\n // add more as needed\n};\n\nconst localNavigator: Navigator | undefined =\n typeof navigator !== 'undefined' ? navigator : undefined;\n\nexport {localNavigator as navigator};\n", "import {RWLock} from '@rocicorp/lock';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {ReadImpl} from './read-impl.js';\nimport type {Read, Store, Write} from './store.js';\nimport {WriteImpl} from './write-impl.js';\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 const release = await this.#rwLock.read();\n return new ReadImpl(this.#map, release);\n }\n\n async write(): Promise<Write> {\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", "import type {FrozenJSONValue} from '../frozen-json.js';\nimport type {Read} from './store.js';\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 Promise.resolve(this.#map.has(key));\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return Promise.resolve(this.#map.get(key));\n }\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {ReadImpl} from './read-impl.js';\nimport type {Write} from './store.js';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.js';\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 // 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", "import type {LogContext} from '@rocicorp/logger';\nimport {navigator} from '../../../shared/src/navigator.js';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport {IDBStore} from './idb-store.js';\nimport {MemStore, dropMemStore} from './mem-store.js';\nimport type {Read, Store, Write} from './store.js';\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", "import {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.js';\nimport {assert} from '../../shared/src/asserts.js';\nimport {getBrowserGlobal} from '../../shared/src/browser-env.js';\nimport {getDocumentVisibilityWatcher} from '../../shared/src/document-visible.js';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.js';\nimport type {MaybePromise} from '../../shared/src/types.js';\nimport {PullDelegate, PushDelegate} from './connection-loop-delegates.js';\nimport {ConnectionLoop, MAX_DELAY_MS, MIN_DELAY_MS} from './connection-loop.js';\nimport {assertCookie, type Cookie} from './cookies.js';\nimport {LazyStore} from './dag/lazy-store.js';\nimport {StoreImpl} from './dag/store-impl.js';\nimport {ChunkNotFoundError, mustGetHeadHash, type Store} from './dag/store.js';\nimport {\n baseSnapshotFromHash,\n DEFAULT_HEAD_NAME,\n isLocalMetaDD31,\n type LocalMeta,\n} from './db/commit.js';\nimport {readFromDefaultHead} from './db/read.js';\nimport {rebaseMutationAndCommit} from './db/rebase.js';\nimport {newWriteLocal} from './db/write.js';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.js';\nimport * as FormatVersion from './format-version-enum.js';\nimport {deepFreeze} from './frozen-json.js';\nimport {getDefaultPuller, isDefaultPuller} from './get-default-puller.js';\nimport {getDefaultPusher, isDefaultPusher} from './get-default-pusher.js';\nimport {assertHash, emptyHash, type Hash, newRandomHash} from './hash.js';\nimport type {HTTPRequestInfo} from './http-request-info.js';\nimport type {IndexDefinitions} from './index-defs.js';\nimport type {StoreProvider} from './kv/store.js';\nimport {createLogContext} from './log-options.js';\nimport {MutationRecovery} from './mutation-recovery.js';\nimport {initNewClientChannel} from './new-client-channel.js';\nimport {\n initOnPersistChannel,\n type OnPersist,\n type PersistInfo,\n} from './on-persist-channel.js';\nimport {\n type PendingMutation,\n pendingMutationsForAPI,\n} from './pending-mutations.js';\nimport {\n CLIENT_MAX_INACTIVE_TIME,\n GC_INTERVAL,\n initClientGC,\n} from './persist/client-gc.js';\nimport {initClientGroupGC} from './persist/client-group-gc.js';\nimport {disableClientGroup} from './persist/client-groups.js';\nimport {\n type ClientMap,\n ClientStateNotFoundError,\n initClientV6,\n hasClientState as persistHasClientState,\n} from './persist/clients.js';\nimport {\n COLLECT_IDB_INTERVAL,\n initCollectIDBDatabases,\n INITIAL_COLLECT_IDB_DELAY,\n SDD_IDB_MAX_AGE,\n} from './persist/collect-idb-databases.js';\nimport {HEARTBEAT_INTERVAL, startHeartbeats} from './persist/heartbeat.js';\nimport {\n IDBDatabasesStore,\n type IndexedDBDatabase,\n} from './persist/idb-databases-store.js';\nimport {makeClientID} from './persist/make-client-id.js';\nimport {persistDD31} from './persist/persist.js';\nimport {refresh} from './persist/refresh.js';\nimport {ProcessScheduler} from './process-scheduler.js';\nimport type {Puller} from './puller.js';\nimport {type Pusher, PushError} from './pusher.js';\nimport type {ReplicacheOptions} from './replicache-options.js';\nimport {\n getKVStoreProvider,\n httpStatusUnauthorized,\n makeIDBName,\n ReportError,\n} from './replicache.js';\nimport {setIntervalWithSignal} from './set-interval-with-signal.js';\nimport {\n type SubscribeOptions,\n SubscriptionImpl,\n type SubscriptionsManager,\n SubscriptionsManagerImpl,\n type WatchCallback,\n type WatchCallbackForOptions,\n type WatchNoIndexCallback,\n type WatchOptions,\n WatchSubscription,\n} from './subscriptions.js';\nimport * as HandlePullResponseResultEnum from './sync/handle-pull-response-result-type-enum.js';\nimport type {ClientGroupID, ClientID} from './sync/ids.js';\nimport {PullError} from './sync/pull-error.js';\nimport {beginPullV1, handlePullResponseV1, maybeEndPull} from './sync/pull.js';\nimport {push, PUSH_VERSION_DD31} from './sync/push.js';\nimport {newRequestID} from './sync/request-id.js';\nimport {SYNC_HEAD_NAME} from './sync/sync-head-name.js';\nimport {throwIfClosed} from './transaction-closed-error.js';\nimport type {ReadTransaction, WriteTransaction} from './transactions.js';\nimport {ReadTransactionImpl, WriteTransactionImpl} from './transactions.js';\nimport type {\n BeginPullResult,\n MakeMutator,\n MakeMutators,\n MutatorDefs,\n MutatorReturn,\n PokeInternal,\n QueryInternal,\n RequestOptions,\n UpdateNeededReason,\n} from './types.js';\nimport {version} from './version.js';\nimport {\n withRead,\n withWrite,\n withWriteNoImplicitCommit,\n} from './with-transactions.js';\n\ndeclare const TESTING: boolean;\n\n/**\n * The maximum number of time to call out to getAuth before giving up\n * and throwing an error.\n */\nconst MAX_REAUTH_TRIES = 8;\n\nconst PERSIST_IDLE_TIMEOUT_MS = 1000;\nconst REFRESH_IDLE_TIMEOUT_MS = 1000;\n\nconst PERSIST_THROTTLE_MS = 500;\nconst REFRESH_THROTTLE_MS = 500;\n\nconst LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 100 * 2 ** 20; // 100 MB\n\nconst RECOVER_MUTATIONS_INTERVAL_MS = 5 * 60 * 1000; // 5 mins\n\nconst noop = () => {\n // noop\n};\n\nconst updateNeededReasonNewClientGroup: UpdateNeededReason = {\n type: 'NewClientGroup',\n} as const;\n\n/** @deprecated Not used any more */\nexport interface MakeSubscriptionsManager {\n (queryInternal: QueryInternal, lc: LogContext): SubscriptionsManager;\n}\n\nexport interface ReplicacheImplOptions {\n /**\n * Defaults to true.\n */\n enableMutationRecovery?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledPersist?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledRefresh?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enablePullAndPushInOpen?: boolean | undefined;\n\n /**\n * @deprecated Not used anymore.\n */\n makeSubscriptionsManager?: unknown;\n\n /**\n * Default is `true`. If `false` if an exact match client group\n * is not found, a new client group is always made instead of forking\n * from an existing client group.\n */\n enableClientGroupForking?: boolean | undefined;\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport class ReplicacheImpl<MD extends MutatorDefs = {}> {\n /** The URL to use when doing a pull request. */\n pullURL: string;\n\n /** The URL to use when doing a push request. */\n pushURL: string;\n\n /** The authorization token used when doing a push request. */\n auth: string;\n\n /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */\n readonly name: string;\n\n readonly #subscriptions: SubscriptionsManager;\n readonly #mutationRecovery: MutationRecovery;\n\n /**\n * Client groups gets disabled when the server does not know about it.\n * A disabled client group prevents the client from pushing and pulling.\n */\n isClientGroupDisabled = false;\n\n readonly #kvStoreProvider: StoreProvider;\n\n lastMutationID: number = 0;\n\n /**\n * This is the name Replicache uses for the IndexedDB database where data is\n * stored.\n */\n get idbName(): string {\n return makeIDBName(this.name, this.schemaVersion);\n }\n\n /** The schema version of the data understood by this application. */\n readonly schemaVersion: string;\n\n get #idbDatabase(): IndexedDBDatabase {\n return {\n name: this.idbName,\n replicacheName: this.name,\n replicacheFormatVersion: FormatVersion.Latest,\n schemaVersion: this.schemaVersion,\n };\n }\n #closed = false;\n #online = true;\n readonly #clientID = makeClientID();\n readonly #ready: Promise<void>;\n readonly #profileIDPromise: Promise<string>;\n readonly #clientGroupIDPromise: Promise<string>;\n readonly #mutatorRegistry: MutatorDefs = {};\n\n /**\n * The mutators that was registered in the constructor.\n */\n readonly mutate: MakeMutators<MD>;\n\n // Number of pushes/pulls at the moment.\n #pushCounter = 0;\n #pullCounter = 0;\n\n #pullConnectionLoop: ConnectionLoop;\n #pushConnectionLoop: ConnectionLoop;\n\n /**\n * The duration between each periodic {@link pull}. Setting this to `null`\n * disables periodic pull completely. Pull will still happen if you call\n * {@link pull} manually.\n */\n pullInterval: number | null;\n\n /**\n * The delay between when a change is made to Replicache and when Replicache\n * attempts to push that change.\n */\n pushDelay: number;\n\n readonly #requestOptions: Required<RequestOptions>;\n\n /**\n * The function to use to pull data from the server.\n */\n puller: Puller;\n\n /**\n * The function to use to push data to the server.\n */\n pusher: Pusher;\n\n readonly memdag: LazyStore;\n readonly perdag: Store;\n readonly #idbDatabases: IDBDatabasesStore;\n readonly #lc: LogContext;\n\n readonly #closeAbortController = new AbortController();\n\n #persistIsRunning = false;\n readonly #enableScheduledPersist: boolean;\n readonly #enableScheduledRefresh: boolean;\n readonly #enablePullAndPushInOpen: boolean;\n #persistScheduler = new ProcessScheduler(\n () => this.persist(),\n PERSIST_IDLE_TIMEOUT_MS,\n PERSIST_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n readonly #onPersist: OnPersist;\n #refreshScheduler = new ProcessScheduler(\n () => this.refresh(),\n REFRESH_IDLE_TIMEOUT_MS,\n REFRESH_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n\n /**\n * The options used to control the {@link pull} and push request behavior. This\n * object is live so changes to it will affect the next pull or push call.\n */\n get requestOptions(): Required<RequestOptions> {\n return this.#requestOptions;\n }\n\n /**\n * `onSync(true)` is called when Replicache transitions from no push or pull\n * happening to at least one happening. `onSync(false)` is called in the\n * opposite case: when Replicache transitions from at least one push or pull\n * happening to none happening.\n *\n * This can be used in a React like app by doing something like the following:\n *\n * ```js\n * const [syncing, setSyncing] = useState(false);\n * useEffect(() => {\n * rep.onSync = setSyncing;\n * }, [rep]);\n * ```\n */\n onSync: ((syncing: boolean) => void) | null = null;\n\n /**\n * `onClientStateNotFound` is called when the persistent client has been\n * garbage collected. This can happen if the client has no pending mutations\n * and has not been used for a while.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n onClientStateNotFound: (() => void) | null = reload;\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the {@link pushVersion},\n * {@link pullVersion} or {@link schemaVersion} of the current code.\n * - a new Replicache client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Replicache client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Replicache client (i.e. to sync while offline, the clients can still\n * sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n onUpdateNeeded: ((reason: UpdateNeededReason) => void) | null = reload;\n\n /**\n * This gets called when we get an HTTP unauthorized (401) response from the\n * push or pull endpoint. Set this to a function that will ask your user to\n * reauthenticate.\n */\n getAuth: (() => MaybePromise<string | null | undefined>) | null | undefined =\n null;\n\n // These three are used for testing\n onPushInvoked = () => undefined;\n onBeginPull = () => undefined;\n onRecoverMutations = (r: Promise<boolean>) => r;\n\n constructor(\n options: ReplicacheOptions<MD>,\n implOptions: ReplicacheImplOptions = {},\n ) {\n validateOptions(options);\n const {\n name,\n logLevel = 'info',\n logSinks = [consoleLogSink],\n pullURL = '',\n auth,\n pushDelay = 10,\n pushURL = '',\n schemaVersion = '',\n pullInterval = 60000,\n mutators = {} as MD,\n requestOptions = {},\n puller,\n pusher,\n indexes = {},\n clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME,\n } = options;\n const {\n enableMutationRecovery = true,\n enableScheduledPersist = true,\n enableScheduledRefresh = true,\n enablePullAndPushInOpen = true,\n enableClientGroupForking = true,\n } = implOptions;\n this.auth = auth ?? '';\n this.pullURL = pullURL;\n this.pushURL = pushURL;\n this.name = name;\n this.schemaVersion = schemaVersion;\n this.pullInterval = pullInterval;\n this.pushDelay = pushDelay;\n this.puller = puller ?? getDefaultPuller(this);\n this.pusher = pusher ?? getDefaultPusher(this);\n\n this.#enableScheduledPersist = enableScheduledPersist;\n this.#enableScheduledRefresh = enableScheduledRefresh;\n this.#enablePullAndPushInOpen = enablePullAndPushInOpen;\n\n this.#lc = createLogContext(logLevel, logSinks, {name});\n this.#lc.debug?.('Constructing Replicache', {\n name,\n 'replicache version': version,\n });\n\n this.#subscriptions = new SubscriptionsManagerImpl(\n this.#queryInternal,\n this.#lc,\n this.#closeAbortController.signal,\n );\n\n const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);\n this.#kvStoreProvider = kvStoreProvider;\n\n const perKVStore = kvStoreProvider.create(this.idbName);\n\n this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);\n this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);\n this.memdag = new LazyStore(\n this.perdag,\n LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n newRandomHash,\n assertHash,\n );\n\n // Use a promise-resolve pair so that we have a promise to use even before\n // we call the Open RPC.\n const readyResolver = resolver<void>();\n this.#ready = readyResolver.promise;\n\n const {minDelayMs = MIN_DELAY_MS, maxDelayMs = MAX_DELAY_MS} =\n requestOptions;\n this.#requestOptions = {maxDelayMs, minDelayMs};\n\n const visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n 0,\n this.#closeAbortController.signal,\n );\n\n this.#pullConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PULL'),\n new PullDelegate(this, () => this.#invokePull()),\n visibilityWatcher,\n );\n\n this.#pushConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PUSH'),\n new PushDelegate(this, () => this.#invokePush()),\n );\n\n this.mutate = this.#registerMutators(mutators);\n\n const profileIDResolver = resolver<string>();\n this.#profileIDPromise = profileIDResolver.promise;\n const clientGroupIDResolver = resolver<string>();\n this.#clientGroupIDPromise = clientGroupIDResolver.promise;\n\n this.#mutationRecovery = new MutationRecovery({\n delegate: this,\n lc: this.#lc,\n enableMutationRecovery,\n wrapInOnlineCheck: this.#wrapInOnlineCheck.bind(this),\n wrapInReauthRetries: this.#wrapInReauthRetries.bind(this),\n isPullDisabled: this.#isPullDisabled.bind(this),\n isPushDisabled: this.#isPushDisabled.bind(this),\n clientGroupIDPromise: this.#clientGroupIDPromise,\n });\n\n this.#onPersist = initOnPersistChannel(\n this.name,\n this.#closeAbortController.signal,\n persistInfo => {\n void this.#handlePersist(persistInfo);\n },\n );\n\n void this.#open(\n indexes,\n enableClientGroupForking,\n clientMaxAgeMs,\n profileIDResolver.resolve,\n clientGroupIDResolver.resolve,\n readyResolver.resolve,\n );\n }\n\n async #open(\n indexes: IndexDefinitions,\n enableClientGroupForking: boolean,\n clientMaxAgeMs: number,\n profileIDResolver: (profileID: string) => void,\n resolveClientGroupID: (clientGroupID: ClientGroupID) => void,\n resolveReady: () => void,\n ): Promise<void> {\n const {clientID} = this;\n // If we are currently closing a Replicache instance with the same name,\n // wait for it to finish closing.\n await closingInstances.get(this.name);\n await this.#idbDatabases.getProfileID().then(profileIDResolver);\n await this.#idbDatabases.putDatabase(this.#idbDatabase);\n const [client, headHash, clients, isNewClientGroup] = await initClientV6(\n clientID,\n this.#lc,\n this.perdag,\n Object.keys(this.#mutatorRegistry),\n indexes,\n FormatVersion.Latest,\n enableClientGroupForking,\n );\n\n resolveClientGroupID(client.clientGroupID);\n await withWrite(this.memdag, write =>\n write.setHead(DEFAULT_HEAD_NAME, headHash),\n );\n\n // Now we have a profileID, a clientID, a clientGroupID and DB!\n resolveReady();\n\n if (this.#enablePullAndPushInOpen) {\n this.pull().catch(noop);\n this.push().catch(noop);\n }\n\n const {signal} = this.#closeAbortController;\n\n startHeartbeats(\n clientID,\n this.perdag,\n () => {\n this.#clientStateNotFoundOnClient(clientID);\n },\n HEARTBEAT_INTERVAL,\n this.#lc,\n signal,\n );\n initClientGC(\n clientID,\n this.perdag,\n clientMaxAgeMs,\n GC_INTERVAL,\n this.#lc,\n signal,\n );\n initCollectIDBDatabases(\n this.#idbDatabases,\n this.#kvStoreProvider.drop,\n COLLECT_IDB_INTERVAL,\n INITIAL_COLLECT_IDB_DELAY,\n SDD_IDB_MAX_AGE,\n 2 * clientMaxAgeMs,\n this.#lc,\n signal,\n );\n initClientGroupGC(this.perdag, this.#lc, signal);\n initNewClientChannel(\n this.name,\n this.idbName,\n signal,\n client.clientGroupID,\n isNewClientGroup,\n () => {\n this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);\n },\n this.perdag,\n );\n\n setIntervalWithSignal(\n () => this.recoverMutations(),\n RECOVER_MUTATIONS_INTERVAL_MS,\n signal,\n );\n void this.recoverMutations(clients);\n\n getBrowserGlobal('document')?.addEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n }\n\n #onVisibilityChange = async () => {\n if (this.#closed) {\n return;\n }\n\n // In case of running in a worker, we don't have a document.\n if (getBrowserGlobal('document')?.visibilityState !== 'visible') {\n return;\n }\n\n await this.#checkForClientStateNotFoundAndCallHandler();\n };\n\n async #checkForClientStateNotFoundAndCallHandler(): Promise<boolean> {\n const {clientID} = this;\n const hasClientState = await withRead(this.perdag, read =>\n persistHasClientState(clientID, read),\n );\n if (!hasClientState) {\n this.#clientStateNotFoundOnClient(clientID);\n }\n return !hasClientState;\n }\n\n /**\n * The browser profile ID for this browser profile. Every instance of Replicache\n * browser-profile-wide shares the same profile ID.\n */\n get profileID(): Promise<string> {\n return this.#profileIDPromise;\n }\n\n /**\n * The client ID for this instance of Replicache. Each instance of Replicache\n * gets a unique client ID.\n */\n get clientID(): string {\n return this.#clientID;\n }\n\n /**\n * The client group ID for this instance of Replicache. Instances of\n * Replicache will have the same client group ID if and only if they have\n * the same name, mutators, indexes, schema version, format version, and\n * browser profile.\n */\n get clientGroupID(): Promise<string> {\n return this.#clientGroupIDPromise;\n }\n\n /**\n * `onOnlineChange` is called when the {@link online} property changes. See\n * {@link online} for more details.\n */\n onOnlineChange: ((online: boolean) => void) | null = null;\n\n /**\n * A rough heuristic for whether the client is currently online. Note that\n * there is no way to know for certain whether a client is online - the next\n * request can always fail. This property returns true if the last sync attempt succeeded,\n * and false otherwise.\n */\n get online(): boolean {\n return this.#online;\n }\n\n /**\n * Whether the Replicache database has been closed. Once Replicache has been\n * closed it no longer syncs and you can no longer read or write data out of\n * it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Closes this Replicache instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n async close(): Promise<void> {\n this.#closed = true;\n const {promise, resolve} = resolver();\n closingInstances.set(this.name, promise);\n\n this.#closeAbortController.abort();\n\n getBrowserGlobal('document')?.removeEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n\n await this.#ready;\n const closingPromises = [\n this.memdag.close(),\n this.perdag.close(),\n this.#idbDatabases.close(),\n ];\n\n this.#pullConnectionLoop.close();\n this.#pushConnectionLoop.close();\n\n this.#subscriptions.clear();\n\n await Promise.all(closingPromises);\n closingInstances.delete(this.name);\n resolve();\n }\n\n async maybeEndPull(syncHead: Hash, requestID: string): Promise<void> {\n for (;;) {\n if (this.#closed) {\n return;\n }\n\n await this.#ready;\n const {clientID} = this;\n const lc = this.#lc\n .withContext('maybeEndPull')\n .withContext('requestID', requestID);\n const {replayMutations, diffs} = await maybeEndPull<LocalMeta>(\n this.memdag,\n lc,\n syncHead,\n clientID,\n this.#subscriptions,\n FormatVersion.Latest,\n );\n\n if (!replayMutations || replayMutations.length === 0) {\n // All done.\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return;\n }\n\n // Replay.\n for (const mutation of replayMutations) {\n // TODO(greg): I'm not sure why this was in Replicache#_mutate...\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n const {meta} = mutation;\n syncHead = await withWriteNoImplicitCommit(this.memdag, dagWrite =>\n rebaseMutationAndCommit(\n mutation,\n dagWrite,\n syncHead,\n SYNC_HEAD_NAME,\n this.#mutatorRegistry,\n lc,\n isLocalMetaDD31(meta) ? meta.clientID : clientID,\n FormatVersion.Latest,\n ),\n );\n }\n }\n }\n\n #invokePull(): Promise<boolean> {\n if (this.#isPullDisabled()) {\n return Promise.resolve(true);\n }\n\n return this.#wrapInOnlineCheck(async () => {\n try {\n this.#changeSyncCounters(0, 1);\n const {syncHead, requestID, ok} = await this.beginPull();\n if (!ok) {\n return false;\n }\n if (syncHead !== emptyHash) {\n await this.maybeEndPull(syncHead, requestID);\n }\n } catch (e) {\n throw await this.#convertToClientStateNotFoundError(e);\n } finally {\n this.#changeSyncCounters(0, -1);\n }\n return true;\n }, 'Pull');\n }\n\n #isPullDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pullURL === '' && isDefaultPuller(this.puller))\n );\n }\n\n async #wrapInOnlineCheck(\n f: () => Promise<boolean>,\n name: string,\n ): Promise<boolean> {\n let online = true;\n\n try {\n return await f();\n } catch (e) {\n // The error paths of beginPull and maybeEndPull need to be reworked.\n //\n // We want to distinguish between:\n // a) network requests failed -- we're offline basically\n // b) sync was aborted because one's already in progress\n // c) oh noes - something unexpected happened\n //\n // Right now, all of these come out as errors. We distinguish (b) with a\n // hacky string search. (a) and (c) are not distinguishable currently\n // because repc doesn't provide sufficient information, so we treat all\n // errors that aren't (b) as (a).\n if (e instanceof PushError || e instanceof PullError) {\n online = false;\n this.#lc.debug?.(`${name} threw:\\n`, e, '\\nwith cause:\\n', e.causedBy);\n } else if (e instanceof ReportError) {\n this.#lc.error?.(e);\n } else {\n this.#lc.info?.(`${name} threw:\\n`, e);\n }\n return false;\n } finally {\n if (this.#online !== online) {\n this.#online = online;\n this.onOnlineChange?.(online);\n if (online) {\n void this.recoverMutations();\n }\n }\n }\n }\n\n async #wrapInReauthRetries<R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth: () => MaybePromise<void> = noop,\n postAuth: () => MaybePromise<void> = noop,\n ): Promise<{\n result: R;\n authFailure: boolean;\n }> {\n const {clientID} = this;\n let reauthAttempts = 0;\n let lastResult;\n lc = lc.withContext(verb);\n do {\n const requestID = newRequestID(clientID);\n const requestLc = lc.withContext('requestID', requestID);\n const {httpRequestInfo, result} = await f(requestID, requestLc);\n lastResult = result;\n if (!httpRequestInfo) {\n return {\n result,\n authFailure: false,\n };\n }\n const {errorMessage, httpStatusCode} = httpRequestInfo;\n\n if (errorMessage || httpStatusCode !== 200) {\n // TODO(arv): Maybe we should not log the server URL when the error comes\n // from a Pusher/Puller?\n requestLc.error?.(\n `Got a non 200 response doing ${verb}: ${httpStatusCode}` +\n (errorMessage ? `: ${errorMessage}` : ''),\n );\n }\n if (httpStatusCode !== httpStatusUnauthorized) {\n return {\n result,\n authFailure: false,\n };\n }\n if (!this.getAuth) {\n return {\n result,\n authFailure: true,\n };\n }\n let auth;\n try {\n await preAuth();\n auth = await this.getAuth();\n } finally {\n await postAuth();\n }\n if (auth === null || auth === undefined) {\n return {\n result,\n authFailure: true,\n };\n }\n this.auth = auth;\n reauthAttempts++;\n } while (reauthAttempts < MAX_REAUTH_TRIES);\n lc.info?.('Tried to reauthenticate too many times');\n return {\n result: lastResult,\n authFailure: true,\n };\n }\n\n #isPushDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pushURL === '' && isDefaultPusher(this.pusher))\n );\n }\n\n async #invokePush(): Promise<boolean> {\n if (TESTING) {\n this.onPushInvoked();\n }\n if (this.#isPushDisabled()) {\n return true;\n }\n\n await this.#ready;\n const profileID = await this.#profileIDPromise;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n return this.#wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n try {\n this.#changeSyncCounters(1, 0);\n const pusherResult = await push(\n requestID,\n this.memdag,\n requestLc,\n profileID,\n clientGroupID,\n clientID,\n this.pusher,\n this.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n } finally {\n this.#changeSyncCounters(-1, 0);\n }\n },\n 'push',\n this.#lc,\n );\n\n if (pusherResult === undefined) {\n // No pending mutations.\n return true;\n }\n\n const {response, httpRequestInfo} = pusherResult;\n\n if (isVersionNotSupportedResponse(response)) {\n this.#handleVersionNotSupportedResponse(response);\n } else if (isClientStateNotFoundResponse(response)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n // No pushResponse means we didn't do a push because there were no\n // pending mutations.\n return httpRequestInfo.httpStatusCode === 200;\n }, 'Push');\n }\n\n #handleVersionNotSupportedResponse(response: VersionNotSupportedResponse) {\n const reason: UpdateNeededReason = {\n type: response.error,\n };\n if (response.versionType) {\n reason.versionType = response.versionType;\n }\n this.#fireOnUpdateNeeded(reason);\n }\n\n /**\n * Push pushes pending changes to the {@link pushURL}.\n *\n * You do not usually need to manually call push. If {@link pushDelay} is\n * non-zero (which it is by default) pushes happen automatically shortly after\n * mutations.\n *\n * If the server endpoint fails push will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, push will happen immediately and ignore\n * {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the\n * exponential backoff in case of errors.\n * @returns A promise that resolves when the next push completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n push({now = false} = {}): Promise<void> {\n return throwIfError(this.#pushConnectionLoop.send(now));\n }\n\n /**\n * Pull pulls changes from the {@link pullURL}. If there are any changes local\n * changes will get replayed on top of the new server state.\n *\n * If the server endpoint fails pull will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, pull will happen immediately and ignore\n * {@link RequestOptions.minDelayMs} as well as the exponential backoff in\n * case of errors.\n * @returns A promise that resolves when the next pull completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n pull({now = false} = {}): Promise<void> {\n return throwIfError(this.#pullConnectionLoop.send(now));\n }\n\n /**\n * Applies an update from the server to Replicache.\n * Throws an error if cookie does not match. In that case the server thinks\n * this client has a different cookie than it does; the caller should disconnect\n * from the server and re-register, which transmits the cookie the client actually\n * has.\n *\n * @experimental This method is under development and its semantics will change.\n */\n async poke(poke: PokeInternal): Promise<void> {\n await this.#ready;\n // TODO(MP) Previously we created a request ID here and included it with the\n // PullRequest to the server so we could tie events across client and server\n // together. Since the direction is now reversed, creating and adding a request ID\n // here is kind of silly. We should consider creating the request ID\n // on the *server* and passing it down in the poke for inclusion here in the log\n // context\n const {clientID} = this;\n const requestID = newRequestID(clientID);\n const lc = this.#lc\n .withContext('handlePullResponse')\n .withContext('requestID', requestID);\n\n const {pullResponse} = poke;\n\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n return;\n }\n\n if (isClientStateNotFoundResponse(pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n return;\n }\n\n const result = await handlePullResponseV1(\n lc,\n this.memdag,\n deepFreeze(poke.baseCookie),\n pullResponse,\n clientID,\n FormatVersion.Latest,\n );\n\n switch (result.type) {\n case HandlePullResponseResultEnum.Applied:\n await this.maybeEndPull(result.syncHead, requestID);\n break;\n case HandlePullResponseResultEnum.CookieMismatch:\n throw new Error(\n 'unexpected base cookie for poke: ' + JSON.stringify(poke),\n );\n case HandlePullResponseResultEnum.NoOp:\n break;\n }\n }\n\n async beginPull(): Promise<BeginPullResult> {\n if (TESTING) {\n this.onBeginPull();\n }\n await this.#ready;\n const profileID = await this.profileID;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n const {\n result: {beginPullResponse, requestID},\n } = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n const beginPullResponse = await beginPullV1(\n profileID,\n clientID,\n clientGroupID,\n this.schemaVersion,\n this.puller,\n requestID,\n this.memdag,\n FormatVersion.Latest,\n requestLc,\n );\n return {\n result: {beginPullResponse, requestID},\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n 'pull',\n this.#lc,\n () => this.#changeSyncCounters(0, -1),\n () => this.#changeSyncCounters(0, 1),\n );\n\n const {pullResponse} = beginPullResponse;\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n } else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n const {syncHead, httpRequestInfo} = beginPullResponse;\n return {requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200};\n }\n\n async persist(): Promise<void> {\n assert(!this.#persistIsRunning);\n this.#persistIsRunning = true;\n try {\n const {clientID} = this;\n await this.#ready;\n if (this.#closed) {\n return;\n }\n try {\n await persistDD31(\n this.#lc,\n clientID,\n this.memdag,\n this.perdag,\n this.#mutatorRegistry,\n () => this.closed,\n FormatVersion.Latest,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception persisting during close', e);\n } else {\n throw e;\n }\n }\n } finally {\n this.#persistIsRunning = false;\n }\n\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID);\n this.#onPersist({clientID, clientGroupID});\n }\n\n async refresh(): Promise<void> {\n await this.#ready;\n const {clientID} = this;\n if (this.#closed) {\n return;\n }\n let diffs;\n try {\n diffs = await refresh(\n this.#lc,\n this.memdag,\n this.perdag,\n clientID,\n this.#mutatorRegistry,\n this.#subscriptions,\n () => this.closed,\n FormatVersion.Latest,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception refreshing during close', e);\n } else {\n throw e;\n }\n }\n if (diffs !== undefined) {\n await this.#subscriptions.fire(diffs);\n }\n }\n\n #fireOnClientStateNotFound() {\n this.onClientStateNotFound?.();\n }\n\n #clientStateNotFoundOnClient(clientID: ClientID) {\n this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);\n this.#fireOnClientStateNotFound();\n }\n\n async #clientStateNotFoundOnServer() {\n const clientGroupID = await this.#clientGroupIDPromise;\n this.#lc.error?.(\n `Client state not found on server, clientGroupID: ${clientGroupID}`,\n );\n await this.disableClientGroup();\n this.#fireOnClientStateNotFound();\n }\n\n async disableClientGroup(): Promise<void> {\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID);\n this.isClientGroupDisabled = true;\n await withWrite(this.perdag, dagWrite =>\n disableClientGroup(clientGroupID, dagWrite),\n );\n }\n\n #fireOnUpdateNeeded(reason: UpdateNeededReason) {\n this.#lc.debug?.(`Update needed, reason: ${reason}`);\n this.onUpdateNeeded?.(reason);\n }\n\n async #schedulePersist(): Promise<void> {\n if (!this.#enableScheduledPersist) {\n return;\n }\n await this.#schedule('persist', this.#persistScheduler);\n }\n\n async #handlePersist(persistInfo: PersistInfo): Promise<void> {\n this.#lc.debug?.('Handling persist', persistInfo);\n const clientGroupID = await this.#clientGroupIDPromise;\n if (persistInfo.clientGroupID === clientGroupID) {\n void this.#scheduleRefresh();\n }\n }\n\n async #scheduleRefresh(): Promise<void> {\n if (!this.#enableScheduledRefresh) {\n return;\n }\n await this.#schedule('refresh from storage', this.#refreshScheduler);\n }\n\n async #schedule(name: string, scheduler: ProcessScheduler): Promise<void> {\n try {\n await scheduler.schedule();\n } catch (e) {\n if (e instanceof AbortError) {\n this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);\n } else {\n this.#lc.error?.(`Error during ${name}`, e);\n }\n }\n }\n\n #changeSyncCounters(pushDelta: 0, pullDelta: 1 | -1): void;\n #changeSyncCounters(pushDelta: 1 | -1, pullDelta: 0): void;\n #changeSyncCounters(pushDelta: number, pullDelta: number): void {\n this.#pushCounter += pushDelta;\n this.#pullCounter += pullDelta;\n const delta = pushDelta + pullDelta;\n const counter = this.#pushCounter + this.#pullCounter;\n if ((delta === 1 && counter === 1) || counter === 0) {\n const syncing = counter > 0;\n // Run in a new microtask.\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n Promise.resolve().then(() => this.onSync?.(syncing));\n }\n }\n\n /**\n * Subscribe to the result of a {@link query}. The `body` function is\n * evaluated once and its results are returned via `onData`.\n *\n * Thereafter, each time the the result of `body` changes, `onData` is fired\n * again with the new result.\n *\n * `subscribe()` goes to significant effort to avoid extraneous work\n * re-evaluating subscriptions:\n *\n * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`\n * is only re-evaluated when those keys change.\n * 2. subscribe only re-fires `onData` in the case that a result changes by\n * way of the `isEqual` option which defaults to doing a deep JSON value\n * equality check.\n *\n * Because of (1), `body` must be a pure function of the data in Replicache.\n * `body` must not access anything other than the `tx` parameter passed to it.\n *\n * Although subscribe is as efficient as it can be, it is somewhat constrained\n * by the goal of returning an arbitrary computation of the cache. For even\n * better performance (but worse dx), see {@link experimentalWatch}.\n *\n * If an error occurs in the `body` the `onError` function is called if\n * present. Otherwise, the error is logged at log level 'error'.\n *\n * To cancel the subscription, call the returned function.\n *\n * @param body The function to evaluate to get the value to pass into\n * `onData`.\n * @param options Options is either a function or an object. If it is a\n * function it is equivalent to passing it as the `onData` property of an\n * object.\n */\n subscribe<R>(\n body: (tx: ReadTransaction) => Promise<R>,\n options: SubscribeOptions<R> | ((result: R) => void),\n ): () => void {\n if (typeof options === 'function') {\n options = {onData: options};\n }\n\n const {onData, onError, onDone, isEqual} = options;\n return this.#subscriptions.add(\n new SubscriptionImpl(body, onData, onError, onDone, isEqual),\n );\n }\n\n /**\n * Watches Replicache for changes.\n *\n * The `callback` gets called whenever the underlying data changes and the\n * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or\n * {@link ExperimentalWatchNoIndexOptions} if present. If a change\n * occurs to the data but the change does not impact the key space the\n * callback is not called. In other words, the callback is never called with\n * an empty diff.\n *\n * This gets called after commit (a mutation or a rebase).\n *\n * @experimental This method is under development and its semantics will\n * change.\n */\n experimentalWatch(callback: WatchNoIndexCallback): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void {\n return this.#subscriptions.add(\n new WatchSubscription(callback as WatchCallback, options),\n );\n }\n\n /**\n * Query is used for read transactions. It is recommended to use transactions\n * to ensure you get a consistent view across multiple calls to `get`, `has`\n * and `scan`.\n */\n query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R> {\n return this.#queryInternal(body);\n }\n\n get cookie(): Promise<Cookie> {\n return this.#ready.then(() =>\n withRead(this.memdag, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n const cookie = baseSnapshotMeta.cookieJSON;\n assertCookie(cookie);\n return cookie;\n }),\n );\n }\n\n #queryInternal: QueryInternal = async body => {\n await this.#ready;\n const {clientID} = this;\n return withRead(this.memdag, async dagRead => {\n try {\n const dbRead = await readFromDefaultHead(dagRead, FormatVersion.Latest);\n const tx = new ReadTransactionImpl(clientID, dbRead, this.#lc);\n return await body(tx);\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n };\n\n #register<Return extends ReadonlyJSONValue | void, Args extends JSONValue>(\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: Args) => MaybePromise<Return>,\n ): (args?: Args) => Promise<Return> {\n this.#mutatorRegistry[name] = mutatorImpl as (\n tx: WriteTransaction,\n args: JSONValue | undefined,\n ) => Promise<void | JSONValue>;\n\n return (args?: Args): Promise<Return> =>\n this.#mutate(name, mutatorImpl, args, performance.now());\n }\n\n #registerMutators<\n M extends {\n [key: string]: (\n tx: WriteTransaction,\n args?: ReadonlyJSONValue,\n ) => MutatorReturn;\n },\n >(regs: M): MakeMutators<M> {\n type Mut = MakeMutators<M>;\n const rv: Partial<Mut> = Object.create(null);\n for (const k in regs) {\n rv[k] = this.#register(k, regs[k]) as MakeMutator<M[typeof k]>;\n }\n return rv as Mut;\n }\n\n async #mutate<\n R extends ReadonlyJSONValue | void,\n A extends ReadonlyJSONValue,\n >(\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: A) => MaybePromise<R>,\n args: A | undefined,\n timestamp: number,\n ): Promise<R> {\n const frozenArgs = deepFreeze(args ?? null);\n\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n\n await this.#ready;\n const {clientID} = this;\n return withWriteNoImplicitCommit(this.memdag, async dagWrite => {\n try {\n const headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);\n const originalHash = null;\n\n const dbWrite = await newWriteLocal(\n headHash,\n name,\n frozenArgs,\n originalHash,\n dagWrite,\n timestamp,\n clientID,\n FormatVersion.Latest,\n );\n\n const tx = new WriteTransactionImpl(\n clientID,\n await dbWrite.getMutationID(),\n 'initial',\n dbWrite,\n this.#lc,\n );\n const result: R = await mutatorImpl(tx, args);\n throwIfClosed(dbWrite);\n const lastMutationID = await dbWrite.getMutationID();\n const diffs = await dbWrite.commitWithDiffs(\n DEFAULT_HEAD_NAME,\n this.#subscriptions,\n );\n\n // Update this after the commit in case the commit fails.\n this.lastMutationID = lastMutationID;\n\n // Send is not supposed to reject\n this.#pushConnectionLoop.send(false).catch(() => void 0);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return result;\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n }\n\n /**\n * In the case we get a ChunkNotFoundError we check if the client got garbage\n * collected and if so change the error to a ClientStateNotFoundError instead\n */\n async #convertToClientStateNotFoundError(ex: unknown): Promise<unknown> {\n if (\n ex instanceof ChunkNotFoundError &&\n (await this.#checkForClientStateNotFoundAndCallHandler())\n ) {\n return new ClientStateNotFoundError(this.clientID);\n }\n\n return ex;\n }\n\n recoverMutations(preReadClientMap?: ClientMap): Promise<boolean> {\n const result = this.#mutationRecovery.recoverMutations(\n preReadClientMap,\n this.#ready,\n this.perdag,\n this.#idbDatabase,\n this.#idbDatabases,\n this.#kvStoreProvider.create,\n );\n if (TESTING) {\n void this.onRecoverMutations(result);\n }\n return result;\n }\n\n /**\n * List of pending mutations. The order of this is from oldest to newest.\n *\n * Gives a list of local mutations that have `mutationID` >\n * `syncHead.mutationID` that exists on the main client group.\n *\n * @experimental This method is experimental and may change in the future.\n */\n experimentalPendingMutations(): Promise<readonly PendingMutation[]> {\n return withRead(this.memdag, pendingMutationsForAPI);\n }\n}\n\n// This map is used to keep track of closing instances of Replicache. When an\n// instance is opening we wait for any currently closing instances.\nconst closingInstances: Map<string, Promise<unknown>> = new Map();\n\nasync function throwIfError(p: Promise<undefined | {error: unknown}>) {\n const res = await p;\n if (res) {\n throw res.error;\n }\n}\n\nfunction reload(): void {\n if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\nfunction validateOptions<MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n): void {\n const {name, clientMaxAgeMs} = options;\n if (typeof name !== 'string' || !name) {\n throw new TypeError('name is required and must be non-empty');\n }\n\n if (clientMaxAgeMs !== undefined) {\n const min = Math.max(GC_INTERVAL, HEARTBEAT_INTERVAL);\n if (typeof clientMaxAgeMs !== 'number' || clientMaxAgeMs <= min) {\n throw new TypeError(\n `clientAgeMaxMs must be a number larger than ${min}ms`,\n );\n }\n }\n}\n", "export class AbortError extends Error {\n name = 'AbortError';\n}\n", "import {resolver} from '@rocicorp/resolver';\n\ntype PartialDocument = Pick<\n Document,\n 'visibilityState' | 'addEventListener' | 'removeEventListener'\n>;\n\nexport function getDocumentVisibilityWatcher(\n doc: PartialDocument | undefined,\n hiddenIntervalMS: number,\n signal: AbortSignal,\n): DocumentVisibilityWatcher {\n return doc\n ? new DocumentVisibilityWatcherImpl(doc, hiddenIntervalMS, signal)\n : new DocumentVisibilityWatcherNoDoc();\n}\n\nexport interface DocumentVisibilityWatcher {\n readonly visibilityState: DocumentVisibilityState;\n waitForVisible(): Promise<unknown>;\n waitForHidden(): Promise<unknown>;\n}\n\nclass DocumentVisibilityWatcherImpl implements DocumentVisibilityWatcher {\n readonly #doc: PartialDocument;\n readonly #hiddenIntervalMS: number;\n #timeoutID: ReturnType<typeof setTimeout> | 0 = 0;\n\n // This trails doc.visibilityState by hiddenIntervalMS when being hidden. This\n // is because we want to wait for the tab to be hidden for a while before\n // considering as hidden.\n visibilityState: DocumentVisibilityState;\n\n readonly #promises = new Set<{\n resolve: () => void;\n state: DocumentVisibilityState;\n }>();\n\n constructor(\n doc: PartialDocument,\n hiddenIntervalMS: number,\n signal: AbortSignal,\n ) {\n this.#doc = doc;\n this.#hiddenIntervalMS = hiddenIntervalMS;\n this.visibilityState = doc.visibilityState;\n // Safari got support for abort signal in addEventListener in version\n // 15 (Released 2021-09-20)\n this.#doc.addEventListener('visibilitychange', this.#onVisibilityChange, {\n signal,\n });\n }\n\n #onVisibilityChange = () => {\n if (this.#doc.visibilityState === 'visible') {\n clearTimeout(this.#timeoutID);\n this.#setVisibilityState('visible');\n } else {\n this.#timeoutID = setTimeout(() => {\n this.#setVisibilityState('hidden');\n }, this.#hiddenIntervalMS);\n }\n };\n\n #setVisibilityState(visibilityState: DocumentVisibilityState) {\n if (visibilityState === this.visibilityState) {\n return;\n }\n this.visibilityState = visibilityState;\n for (const entry of this.#promises) {\n const {resolve, state} = entry;\n if (state === visibilityState) {\n resolve();\n this.#promises.delete(entry);\n }\n }\n }\n\n waitForVisible(): Promise<unknown> {\n return this.#waitFor('visible');\n }\n\n waitForHidden(): Promise<unknown> {\n return this.#waitFor('hidden');\n }\n\n #waitFor(state: DocumentVisibilityState): Promise<unknown> {\n if (this.visibilityState === state) {\n return Promise.resolve();\n }\n\n const {promise, resolve} = resolver();\n this.#promises.add({resolve, state});\n return promise;\n }\n}\n\nconst resolvedPromise = Promise.resolve();\nconst promiseThatNeverResolves = new Promise(() => undefined);\n\nclass DocumentVisibilityWatcherNoDoc implements DocumentVisibilityWatcher {\n readonly visibilityState: DocumentVisibilityState = 'visible';\n waitForVisible(): Promise<unknown> {\n return resolvedPromise;\n }\n\n waitForHidden(): Promise<unknown> {\n return promiseThatNeverResolves;\n }\n}\n", "import type {ConnectionLoopDelegate} from './connection-loop.js';\nimport type {ReplicacheImpl} from './replicache-impl.js';\n\nclass ConnectionLoopDelegateImpl {\n readonly rep: ReplicacheImpl;\n readonly invokeSend: () => Promise<boolean>;\n\n // TODO: Remove the ability to have more than one concurrent connection and update tests.\n // Bug: https://github.com/rocicorp/replicache-internal/issues/303\n readonly maxConnections = 1;\n\n constructor(rep: ReplicacheImpl, invokeSend: () => Promise<boolean>) {\n this.rep = rep;\n this.invokeSend = invokeSend;\n }\n\n get maxDelayMs(): number {\n return this.rep.requestOptions.maxDelayMs;\n }\n\n get minDelayMs(): number {\n return this.rep.requestOptions.minDelayMs;\n }\n}\n\nexport class PullDelegate\n extends ConnectionLoopDelegateImpl\n implements ConnectionLoopDelegate\n{\n readonly debounceDelay = 0;\n\n get watchdogTimer(): number | null {\n return this.rep.pullInterval;\n }\n}\n\nexport class PushDelegate\n extends ConnectionLoopDelegateImpl\n implements ConnectionLoopDelegate\n{\n get debounceDelay(): number {\n return this.rep.pushDelay;\n }\n\n watchdogTimer = null;\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport type {DocumentVisibilityWatcher} from '../../shared/src/document-visible.js';\nimport {sleep} from '../../shared/src/sleep.js';\n\nexport const DEBOUNCE_DELAY_MS = 10;\n\nexport const MIN_DELAY_MS = 30;\nexport const MAX_DELAY_MS = 60_000;\n\ntype SendRecord = {duration: number; ok: boolean};\n\nexport interface ConnectionLoopDelegate {\n invokeSend(): Promise<boolean>;\n debounceDelay: number;\n // If null, no watchdog timer is used.\n watchdogTimer: number | null;\n maxConnections: number;\n maxDelayMs: number;\n minDelayMs: number;\n}\n\nexport class ConnectionLoop {\n // ConnectionLoop runs a loop sending network requests (either pushes or\n // pulls) to the server. Our goal, generally, is to send requests as fast as\n // we can, but to adjust in case of slowness, network errors, etc. We will\n // send requests in parallel if the server supports it. We also debounce\n // pushes since they frequently happen in series very near to one another\n // (e.g., during drag'n drops).\n //\n // The loop flows through the following states forever, until it is closed:\n //\n // Pending: Wait for event or watchdog\n // |\n // v\n // Debounce: Wait for more events (we debounce pushes)\n // |\n // v\n // Wait for available connection (we limit number of parallel requests\n // allowed)\n // |\n // v\n // Wait to send (if requests are taking too long, we will slow down)\n // |\n // v\n // Send (asynchronously, wrt the loop)\n // |\n // v\n // Back to the pending!\n\n // Controls whether the next iteration of the loop will wait at the pending\n // state.\n #pendingResolver = resolver<void>();\n\n /**\n * This resolver is used to allow us to skip sleeps when we do send(true)\n */\n #skipSleepsResolver = resolver<void>();\n\n /**\n * Resolver for the next send. Never rejects. Returns an error instead since\n * this resolver is used in cases where they might not be someone waiting,\n * and we don't want an unhandled promise rejection in that case.\n */\n #sendResolver = resolver<undefined | {error: unknown}>();\n\n readonly #delegate: ConnectionLoopDelegate;\n #closed = false;\n\n /**\n * Number of pending send calls.\n *\n * We keep track of this because if close happens while we are waiting for the\n * send to resolve we should reject the send promise.\n */\n #sendCounter = 0;\n readonly #lc: LogContext;\n readonly #visibilityWatcher: DocumentVisibilityWatcher | undefined;\n\n constructor(\n lc: LogContext,\n delegate: ConnectionLoopDelegate,\n visibilityWatcher?: DocumentVisibilityWatcher,\n ) {\n this.#lc = lc;\n this.#delegate = delegate;\n this.#visibilityWatcher = visibilityWatcher;\n void this.run();\n }\n\n close(): void {\n this.#closed = true;\n if (this.#sendCounter > 0) {\n this.#sendResolver.resolve({error: closeError()});\n }\n }\n\n /**\n *\n * @returns Returns undefined if ok, otherwise it return the error that caused\n * the send to fail.\n */\n async send(now: boolean): Promise<undefined | {error: unknown}> {\n if (this.#closed) {\n return {error: closeError()};\n }\n this.#sendCounter++;\n this.#lc.debug?.('send', now);\n if (now) {\n this.#skipSleepsResolver.resolve();\n } else {\n await this.#visibilityWatcher?.waitForVisible();\n }\n\n this.#pendingResolver.resolve();\n\n const result = await this.#sendResolver.promise;\n this.#sendCounter--;\n return result;\n }\n\n async run(): Promise<void> {\n const sendRecords: SendRecord[] = [];\n\n let recoverResolver = resolver();\n let lastSendTime;\n\n // The number of active connections.\n let counter = 0;\n const delegate = this.#delegate;\n const {debug} = this.#lc;\n let delay = 0;\n\n debug?.('Starting connection loop');\n\n const sleepMaybeSkip: typeof sleep = ms =>\n Promise.race([this.#skipSleepsResolver.promise, sleep(ms)]);\n\n while (!this.#closed) {\n debug?.(\n didLastSendRequestFail(sendRecords)\n ? 'Last request failed. Trying again'\n : 'Waiting for a send',\n );\n\n // Wait until send is called or until the watchdog timer fires.\n const races = [this.#pendingResolver.promise];\n const t = delegate.watchdogTimer;\n if (t !== null) {\n races.push(sleep(t));\n }\n await Promise.race(races);\n if (this.#closed) break;\n\n debug?.('Waiting for debounce');\n await sleepMaybeSkip(delegate.debounceDelay);\n if (this.#closed) break;\n debug?.('debounced');\n\n // This resolver is used to wait for incoming push calls.\n this.#pendingResolver = resolver();\n\n if (counter >= delegate.maxConnections) {\n debug?.('Too many request in flight. Waiting until one finishes...');\n await this.#waitUntilAvailableConnection();\n if (this.#closed) break;\n debug?.('...finished');\n }\n\n // We need to delay the next request even if there are no active requests\n // in case of error.\n if (counter > 0 || didLastSendRequestFail(sendRecords)) {\n delay = computeDelayAndUpdateDurations(delay, delegate, sendRecords);\n debug?.(\n didLastSendRequestFail(sendRecords)\n ? 'Last connection errored. Sleeping for'\n : 'More than one outstanding connection (' +\n counter +\n '). Sleeping for',\n delay,\n 'ms',\n );\n } else {\n // We set this to 0 here in case minDelayMs is mutated to a lower value\n // than the old delay so that we still get minDelayMs. This can happen\n // if we get an error during a run where minDelayMs is larger than the\n // current value of minDelayMs.\n delay = 0;\n }\n\n const clampedDelay = Math.min(\n delegate.maxDelayMs,\n Math.max(delegate.minDelayMs, delay),\n );\n if (lastSendTime !== undefined) {\n const timeSinceLastSend = Date.now() - lastSendTime;\n if (clampedDelay > timeSinceLastSend) {\n await Promise.race([\n sleepMaybeSkip(clampedDelay - timeSinceLastSend),\n recoverResolver.promise,\n ]);\n if (this.#closed) break;\n }\n }\n\n counter++;\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n (async () => {\n const start = Date.now();\n let ok: boolean;\n let error: unknown;\n try {\n lastSendTime = start;\n debug?.('Sending request');\n this.#skipSleepsResolver = resolver();\n ok = await delegate.invokeSend();\n debug?.('Send returned', ok);\n } catch (e) {\n debug?.('Send failed', e);\n error = e;\n ok = false;\n }\n if (this.#closed) {\n debug?.('Closed after invokeSend');\n return;\n }\n debug?.('Request done', {duration: Date.now() - start, ok});\n sendRecords.push({duration: Date.now() - start, ok});\n if (recovered(sendRecords)) {\n recoverResolver.resolve();\n recoverResolver = resolver();\n }\n counter--;\n this.#connectionAvailable();\n const sendResolver = this.#sendResolver;\n this.#sendResolver = resolver();\n if (error) {\n sendResolver.resolve({error});\n } else {\n sendResolver.resolve(undefined);\n }\n if (!ok) {\n // Keep trying\n this.#pendingResolver.resolve();\n }\n })();\n }\n }\n\n #waitingConnectionResolve: (() => void) | undefined = undefined;\n\n #connectionAvailable() {\n if (this.#waitingConnectionResolve) {\n const resolve = this.#waitingConnectionResolve;\n this.#waitingConnectionResolve = undefined;\n resolve();\n }\n }\n\n #waitUntilAvailableConnection() {\n const {promise, resolve} = resolver();\n this.#waitingConnectionResolve = resolve;\n return promise;\n }\n}\n\n// Number of connections to remember when computing the new delay.\nconst CONNECTION_MEMORY_COUNT = 9;\n\nfunction closeError() {\n return new Error('Closed');\n}\n\n// Computes a new delay based on the previous requests. We use the median of the\n// previous successful request divided by `maxConnections`. When we get errors\n// we do exponential backoff. As soon as we recover from an error we reset back\n// to delegate.minDelayMs.\nfunction computeDelayAndUpdateDurations(\n delay: number,\n delegate: ConnectionLoopDelegate,\n sendRecords: SendRecord[],\n): number {\n const {length} = sendRecords;\n if (length === 0) {\n return delay;\n }\n\n const {ok} = sendRecords[sendRecords.length - 1];\n const {maxConnections, minDelayMs} = delegate;\n\n if (!ok) {\n return delay === 0 ? minDelayMs : delay * 2;\n }\n\n if (length > 1) {\n // length > 1\n const previous: SendRecord = sendRecords[sendRecords.length - 2];\n\n // Prune\n while (sendRecords.length > CONNECTION_MEMORY_COUNT) {\n sendRecords.shift();\n }\n\n if (ok && !previous.ok) {\n // Recovered\n return minDelayMs;\n }\n }\n\n const med = median(\n sendRecords.filter(({ok}) => ok).map(({duration}) => duration),\n );\n\n return (med / maxConnections) | 0;\n}\n\nfunction median(values: number[]) {\n values.sort();\n const {length} = values;\n const half = length >> 1;\n if (length % 2 === 1) {\n return values[half];\n }\n return (values[half - 1] + values[half]) / 2;\n}\n\nfunction didLastSendRequestFail(sendRecords: SendRecord[]) {\n return sendRecords.length > 0 && !sendRecords[sendRecords.length - 1].ok;\n}\n\nfunction recovered(sendRecords: SendRecord[]) {\n return (\n sendRecords.length > 1 &&\n !sendRecords[sendRecords.length - 2].ok &&\n sendRecords[sendRecords.length - 1].ok\n );\n}\n", "import {resolver} from '@rocicorp/resolver';\nimport {AbortError} from './abort-error.js';\n\nconst promiseVoid = Promise.resolve();\nconst promiseNever = new Promise<void>(() => undefined);\n\n/**\n * Creates a promise that resolves after `ms` milliseconds. Note that if you\n * pass in `0` no `setTimeout` is used and the promise resolves immediately. In\n * other words no macro task is used in that case.\n *\n * Pass in an AbortSignal to clear the timeout.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (ms === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n let handleAbort: () => void;\n if (signal) {\n handleAbort = () => {\n clearTimeout(id);\n reject(new AbortError('Aborted'));\n };\n signal.addEventListener('abort', handleAbort, {once: true});\n }\n\n const id = setTimeout(() => {\n resolve();\n signal?.removeEventListener('abort', handleAbort);\n }, ms);\n });\n}\n\n/**\n * Returns a pair of promises. The first promise resolves after `ms` milliseconds\n * unless the AbortSignal is aborted. The second promise resolves when the AbortSignal\n * is aborted.\n */\nexport function sleepWithAbort(\n ms: number,\n signal: AbortSignal,\n): [ok: Promise<void>, aborted: Promise<void>] {\n if (ms === 0) {\n return [promiseVoid, promiseNever];\n }\n\n const {promise: abortedPromise, resolve: abortedResolve} = resolver<void>();\n\n const sleepPromise = new Promise<void>(resolve => {\n const handleAbort = () => {\n clearTimeout(id);\n abortedResolve();\n };\n\n const id = setTimeout(() => {\n resolve();\n signal.removeEventListener('abort', handleAbort);\n }, ms);\n\n signal.addEventListener('abort', handleAbort, {once: true});\n });\n\n return [sleepPromise, abortedPromise];\n}\n", "import {RWLock} from '@rocicorp/lock';\nimport {joinIterables} from '../../../shared/src/iterables.js';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {MaybePromise} from '../../../shared/src/types.js';\nimport type {Hash} from '../hash.js';\nimport {getSizeOfValue} from '../size-of-value.js';\nimport {Chunk, type ChunkHasher, type Refs, createChunk} from './chunk.js';\nimport {\n type HeadChange,\n type RefCountUpdatesDelegate,\n computeRefCountUpdates,\n} from './gc.js';\nimport {type Read, type Store, type Write, mustGetChunk} from './store.js';\n\n/**\n * Dag Store which lazily loads values from a source store and then caches\n * them in an LRU cache. The memory cache for chunks from the source store\n * size is limited to `sourceCacheSizeLimit` bytes, and values are evicted in an\n * LRU fashion. The purpose of this store is to avoid holding the entire client\n * view (i.e. the source store's content) in each tab's JavaScript heap.\n *\n * This store's heads are independent from the heads of source store, and are\n * only stored in memory.\n *\n * Chunks which are created via this store's {@link Write} transaction's\n * {@link createChunk} method are assumed to not be persisted to the source\n * store and thus are cached separately from the source store chunks. These\n * memory-only chunks will not be evicted, and their sizes are not counted\n * towards the source chunk cache size. A memory-only chunk will be deleted if\n * it is no longer reachable from one of this store's heads.\n *\n * Writes only manipulate the in memory state of this store and do not alter the\n * source store. Thus values must be written to the source store through a\n * separate process (see {@link persist}).\n *\n * Intended use:\n * 1. source store is the 'perdag', a slower persistent store (i.e.\n * dag.StoreImpl using a kv.IDBStore)\n * 2. this store's 'main' head is initialized to the hash of a chunk containing\n * a commit in the source store\n * 3. reads lazily read chunks from the source store and cache them\n * 3. writes are initially made to this store with memory-only chunks\n * 4. writes are asynchronously persisted to the source store through a separate\n * process (see {@link persist}}. This process gathers memory-only chunks\n * from this store and then writes them to the source store. It then informs\n * this store that these chunks are no longer memory-only by calling\n * {@link chunksPersisted}, which move these chunks\n * to this store's LRU cache of source chunks (making them eligible for\n * eviction).\n *\n * @param sourceStore Store to lazy load and cache values from.\n * @param sourceCacheSizeLimit Size limit in bytes for cache of chunks loaded\n * from `sourceStore`. This size of a value is determined using\n * `getSizeOfValue`. Keys do not count towards cache size. Memory-only chunks\n * do not count towards cache size.\n * @param getSizeOfValue Function for measuring the size in bytes of a value.\n */\nexport class LazyStore implements Store {\n /**\n * This lock is used to ensure correct isolation of Reads and Writes.\n * Multiple Reads are allowed in parallel but only a single Write. Reads and\n * Writes see an isolated view of the store (corresponding to the Serializable\n * level of transaction isolation defined in the SQL standard).\n *\n * To ensure these semantics the read lock must be acquired when a Read is\n * created and held til it is closed, and a Write lock must be acquired when a\n * Write is created and held til it is committed or closed.\n *\n * Code must have a read or write lock to\n * - read `_heads`\n * - read `_memOnlyChunks`\n * - read `_sourceStore`\n * - read and write `_sourceChunksCache`\n * - read and write `_refCounts`\n * - read and write `_refs`\n * and must have a write lock to\n * - write `_heads`\n * - write `_memOnlyChunks`\n */\n readonly #rwLock = new RWLock();\n readonly #heads = new Map<string, Hash>();\n readonly #sourceStore: Store;\n readonly #chunkHasher: ChunkHasher;\n readonly #assertValidHash: (hash: Hash) => void;\n\n /** The following are protected so testing subclass can access. */\n protected readonly _memOnlyChunks = new Map<Hash, Chunk>();\n protected readonly _sourceChunksCache: ChunksCache;\n /**\n * Ref counts are maintained so that chunks which are unreachable\n * from this stores heads can be eagerly and deterministically deleted from\n * `this._memOnlyChunks` and `this._sourceChunksCache`.\n *\n * These ref counts are independent from `this._sourceStore`'s ref counts.\n * These ref counts are based on reachability from `this._heads`.\n * A chunk is deleted from `this._memOnlyChunks` or\n * `this._sourceChunksCache` (which ever it is in) when its ref count becomes\n * zero.\n * These ref counts count the refs in `this._heads` and `this._refs`.\n *\n * Not all reachable chunk's refs are included in `this._refs`, because this\n * would require loading all chunks reachable in the source store in a\n * non-lazy manner. `this._refs` contains the refs of all currently reachable\n * chunks that were ever in `this._memOnlyChunks` or\n * `this._sourceChunksCache` (even if they have been evicted). A\n * chunk's ref information is lazily discovered and stored in `this._refs` and\n * counted in `this._refCounts`. A chunk's entries in `this._refs` and\n * `this._refCounts` are only deleted when a chunk is deleted due to it\n * becoming unreachable (it is not deleted if the chunk is evicted from the\n * source-store cache).\n *\n * The major implication of this lazy discovery of source store refs, is that\n * a reachable source store chunk may not be cached when loaded, because it is\n * not known to be reachable because some of the pertinent refs have not been\n * discovered. However, in practice chunks are read by traversing the graph\n * starting from a head, and all pertinent refs are discovered as part of the\n * traversal.\n *\n * These ref counts can be changed in two ways:\n * 1. A LazyRead has a cache miss and loads a chunk from the source store that\n * is reachable from this._heads. If this chunk's refs are not currently\n * counted, it will not have an entry in `this._refs`. In this case, the\n * chunks refs will be put in `this._refs` and `this._refCounts` will be\n * updated to count them.\n * 2. A LazyWrite commit updates a head (which can result in increasing or\n * decreasing ref count) or puts a reachable chunk (either a `memory-only` or\n * `source` chunk) that references this hash (increasing ref count). The\n * computation of these ref count changes is delegated to the\n * `computeRefCountUpdates` shared with dag.StoreImpl. In order to\n * delegate determining reachability to `computeRefCountUpdates` and defer\n * this determination until commit time, LazyWrite treats cache misses\n * as a 'put' of the lazily-loaded chunk.\n *\n * A chunk's hash may have an entry in `this._refCounts` without that\n * chunk have ever been in `this._memOnlyChunks` or `this._sourceChunksCache`.\n * This is the case when a head or a reachable chunk that was ever in\n * `this._memOnlyChunks` or `this._sourceChunksCache` references a chunk\n * which is not currently cached (either because it has not been read, or\n * because it has been evicted).\n */\n protected readonly _refCounts = new Map<Hash, number>();\n protected readonly _refs = new Map<Hash, readonly Hash[]>();\n\n constructor(\n sourceStore: Store,\n sourceCacheSizeLimit: number,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n getSizeOfChunk: (chunk: Chunk) => number = getSizeOfValue,\n ) {\n this._sourceChunksCache = new ChunksCache(\n sourceCacheSizeLimit,\n getSizeOfChunk,\n this._refCounts,\n this._refs,\n );\n this.#sourceStore = sourceStore;\n this.#chunkHasher = chunkHasher;\n this.#assertValidHash = assertValidHash;\n }\n\n async read(): Promise<LazyRead> {\n const release = await this.#rwLock.read();\n return new LazyRead(\n this.#heads,\n this._memOnlyChunks,\n this._sourceChunksCache,\n this.#sourceStore,\n release,\n this.#assertValidHash,\n );\n }\n\n async write(): Promise<LazyWrite> {\n const release = await this.#rwLock.write();\n return new LazyWrite(\n this.#heads,\n this._memOnlyChunks,\n this._sourceChunksCache,\n this.#sourceStore,\n this._refCounts,\n this._refs,\n release,\n this.#chunkHasher,\n this.#assertValidHash,\n );\n }\n\n close(): Promise<void> {\n return promiseVoid;\n }\n\n /**\n * Does not acquire any lock on the store.\n */\n isCached(chunkHash: Hash): boolean {\n return (\n this._sourceChunksCache.getWithoutUpdatingLRU(chunkHash) !== undefined\n );\n }\n\n withSuspendedSourceCacheEvictsAndDeletes<T>(\n fn: () => MaybePromise<T>,\n ): Promise<T> {\n return this._sourceChunksCache.withSuspendedEvictsAndDeletes(fn);\n }\n}\n\nexport class LazyRead implements Read {\n protected readonly _heads: Map<string, Hash>;\n protected readonly _memOnlyChunks: Map<Hash, Chunk>;\n protected readonly _sourceChunksCache: ChunksCache;\n protected readonly _sourceStore: Store;\n #sourceRead: Promise<Read> | undefined = undefined;\n readonly #release: () => void;\n #closed = false;\n readonly assertValidHash: (hash: Hash) => void;\n\n constructor(\n heads: Map<string, Hash>,\n memOnlyChunks: Map<Hash, Chunk>,\n sourceChunksCache: ChunksCache,\n sourceStore: Store,\n release: () => void,\n assertValidHash: (hash: Hash) => void,\n ) {\n this._heads = heads;\n this._memOnlyChunks = memOnlyChunks;\n this._sourceChunksCache = sourceChunksCache;\n this._sourceStore = sourceStore;\n this.#release = release;\n this.assertValidHash = assertValidHash;\n }\n\n isMemOnlyChunkHash(hash: Hash): boolean {\n return this._memOnlyChunks.has(hash);\n }\n\n async hasChunk(hash: Hash): Promise<boolean> {\n return (await this.getChunk(hash)) !== undefined;\n }\n\n async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk !== undefined) {\n return memOnlyChunk;\n }\n let chunk = this._sourceChunksCache.get(hash);\n if (chunk === undefined) {\n chunk = await (await this._getSourceRead()).getChunk(hash);\n if (chunk !== undefined) {\n this._sourceChunksCache.put(chunk);\n }\n }\n return chunk;\n }\n\n mustGetChunk(hash: Hash): Promise<Chunk> {\n return mustGetChunk(this, hash);\n }\n\n getHead(name: string): Promise<Hash | undefined> {\n return Promise.resolve(this._heads.get(name));\n }\n\n release(): void {\n if (!this.#closed) {\n this.#release();\n this.#sourceRead\n ?.then(read => read.release())\n // If creation of the read failed there is nothing to release.\n // Catch to avoid `Uncaught (in promise)` errors being reported.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n .catch(_ => {});\n this.#closed = true;\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n protected _getSourceRead(): Promise<Read> {\n if (!this.#sourceRead) {\n this.#sourceRead = this._sourceStore.read();\n }\n return this.#sourceRead;\n }\n}\n\nexport class LazyWrite\n extends LazyRead\n implements Write, RefCountUpdatesDelegate\n{\n readonly #refCounts: Map<Hash, number>;\n readonly #refs: Map<Hash, readonly Hash[]>;\n readonly #chunkHasher: ChunkHasher;\n protected readonly _pendingHeadChanges = new Map<string, HeadChange>();\n protected readonly _pendingMemOnlyChunks = new Map<Hash, Chunk>();\n protected readonly _pendingCachedChunks = new Map<\n Hash,\n {chunk: Chunk; size: number}\n >();\n readonly #createdChunks = new Set<Hash>();\n\n constructor(\n heads: Map<string, Hash>,\n memOnlyChunks: Map<Hash, Chunk>,\n sourceChunksCache: ChunksCache,\n sourceStore: Store,\n refCounts: Map<Hash, number>,\n refs: Map<Hash, readonly Hash[]>,\n release: () => void,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n super(\n heads,\n memOnlyChunks,\n sourceChunksCache,\n sourceStore,\n release,\n assertValidHash,\n );\n this.#refCounts = refCounts;\n this.#refs = refs;\n this.#chunkHasher = chunkHasher;\n }\n\n createChunk = <V>(data: V, refs: Refs): Chunk<V> => {\n const chunk = createChunk(data, refs, this.#chunkHasher);\n this.#createdChunks.add(chunk.hash);\n return chunk;\n };\n\n putChunk<V>(c: Chunk<V>, size?: number): Promise<void> {\n const {hash, meta} = c;\n this.assertValidHash(hash);\n if (meta.length > 0) {\n for (const h of meta) {\n this.assertValidHash(h);\n }\n }\n if (this.#createdChunks.has(hash) || this.isMemOnlyChunkHash(hash)) {\n this._pendingMemOnlyChunks.set(hash, c);\n } else {\n this._pendingCachedChunks.set(hash, {chunk: c, size: size ?? -1});\n }\n return promiseVoid;\n }\n\n async setHead(name: string, hash: Hash): Promise<void> {\n await this.#setHead(name, hash);\n }\n\n async removeHead(name: string): Promise<void> {\n await this.#setHead(name, undefined);\n }\n\n async #setHead(name: string, hash: Hash | undefined): Promise<void> {\n const oldHash = await this.getHead(name);\n const v = this._pendingHeadChanges.get(name);\n if (v === undefined) {\n this._pendingHeadChanges.set(name, {new: hash, old: oldHash});\n } else {\n // Keep old if existing\n v.new = hash;\n }\n }\n\n override isMemOnlyChunkHash(hash: Hash): boolean {\n return (\n this._pendingMemOnlyChunks.has(hash) || super.isMemOnlyChunkHash(hash)\n );\n }\n\n override async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const pendingMemOnlyChunk = this._pendingMemOnlyChunks.get(hash);\n if (pendingMemOnlyChunk !== undefined) {\n return pendingMemOnlyChunk;\n }\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk !== undefined) {\n return memOnlyChunk;\n }\n // In order to delegate determining reachability to `computeRefCountUpdates`\n // and defer this determination until commit time, treat cache misses\n // as a 'put' of the lazily-loaded chunk.\n const pendingCachedChunk = this._pendingCachedChunks.get(hash);\n if (pendingCachedChunk !== undefined) {\n return pendingCachedChunk.chunk;\n }\n let chunk = this._sourceChunksCache.get(hash);\n if (chunk === undefined) {\n chunk = await (await this._getSourceRead()).getChunk(hash);\n if (chunk !== undefined) {\n this._pendingCachedChunks.set(chunk.hash, {chunk, size: -1});\n }\n }\n return chunk;\n }\n\n override getHead(name: string): Promise<Hash | undefined> {\n const headChange = this._pendingHeadChanges.get(name);\n if (headChange) {\n return Promise.resolve(headChange.new);\n }\n return super.getHead(name);\n }\n\n async commit(): Promise<void> {\n const pendingChunks = new Set(\n joinIterables(\n this._pendingMemOnlyChunks.keys(),\n this._pendingCachedChunks.keys(),\n ),\n );\n const refCountUpdates = await computeRefCountUpdates(\n this._pendingHeadChanges.values(),\n pendingChunks,\n this,\n );\n\n for (const [hash, count] of refCountUpdates) {\n if (this.isMemOnlyChunkHash(hash)) {\n if (count === 0) {\n this.#refCounts.delete(hash);\n this._memOnlyChunks.delete(hash);\n this.#refs.delete(hash);\n } else {\n this.#refCounts.set(hash, count);\n const chunk = this._pendingMemOnlyChunks.get(hash);\n if (chunk) {\n this.#refs.set(hash, chunk.meta);\n this._memOnlyChunks.set(hash, chunk);\n }\n }\n refCountUpdates.delete(hash);\n }\n }\n\n this._sourceChunksCache.updateForCommit(\n this._pendingCachedChunks,\n refCountUpdates,\n );\n\n for (const [name, headChange] of this._pendingHeadChanges) {\n if (headChange.new) {\n this._heads.set(name, headChange.new);\n } else {\n this._heads.delete(name);\n }\n }\n\n this._pendingMemOnlyChunks.clear();\n this._pendingCachedChunks.clear();\n this._pendingHeadChanges.clear();\n this.release();\n }\n\n getRefCount(hash: Hash): number | undefined {\n return this.#refCounts.get(hash);\n }\n\n getRefs(hash: Hash): readonly Hash[] | undefined {\n const pendingMemOnlyChunk = this._pendingMemOnlyChunks.get(hash);\n if (pendingMemOnlyChunk) {\n return pendingMemOnlyChunk.meta;\n }\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk) {\n return memOnlyChunk.meta;\n }\n const pendingCachedChunk = this._pendingCachedChunks.get(hash);\n if (pendingCachedChunk !== undefined) {\n return pendingCachedChunk.chunk.meta;\n }\n return this.#refs.get(hash);\n }\n\n areRefsCounted(hash: Hash): boolean {\n return this.#refs.has(hash);\n }\n\n chunksPersisted(chunkHashes: readonly Hash[]): void {\n const chunksToCache = [];\n for (const chunkHash of chunkHashes) {\n const chunk = this._memOnlyChunks.get(chunkHash);\n if (chunk) {\n this._memOnlyChunks.delete(chunkHash);\n chunksToCache.push(chunk);\n }\n }\n this._sourceChunksCache.persisted(chunksToCache);\n }\n}\n\ntype CacheEntry = {\n chunk: Chunk;\n size: number;\n};\n\nclass ChunksCache {\n readonly #cacheSizeLimit: number;\n readonly #getSizeOfChunk: (chunk: Chunk) => number;\n readonly #refCounts: Map<Hash, number>;\n readonly #refs: Map<Hash, readonly Hash[]>;\n #size = 0;\n #evictsAndDeletesSuspended = false;\n readonly #suspendedDeletes: Hash[] = [];\n\n /**\n * Iteration order is from least to most recently used.\n *\n * Public so that testing subclass can access.\n */\n readonly cacheEntries = new Map<Hash, CacheEntry>();\n\n constructor(\n cacheSizeLimit: number,\n getSizeOfChunk: (v: Chunk) => number,\n refCounts: Map<Hash, number>,\n refs: Map<Hash, readonly Hash[]>,\n ) {\n this.#cacheSizeLimit = cacheSizeLimit;\n this.#getSizeOfChunk = getSizeOfChunk;\n this.#refCounts = refCounts;\n this.#refs = refs;\n }\n\n get(hash: Hash): Chunk | undefined {\n const cacheEntry = this.cacheEntries.get(hash);\n if (cacheEntry) {\n // Update order in map for LRU tracking.\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, cacheEntry);\n }\n return cacheEntry?.chunk;\n }\n\n getWithoutUpdatingLRU(hash: Hash): Chunk | undefined {\n return this.cacheEntries.get(hash)?.chunk;\n }\n\n put(chunk: Chunk): void {\n const {hash} = chunk;\n // If there is an existing cache entry then the cached value must be\n // equivalent. Update order in map for LRU tracking and early return.\n const oldCacheEntry = this.cacheEntries.get(hash);\n if (oldCacheEntry) {\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, oldCacheEntry);\n return;\n }\n\n // Only cache if there is a ref from a head to this chunk\n const refCount = this.#refCounts.get(hash);\n if (refCount === undefined || refCount < 1) {\n return;\n }\n if (!this.#cacheChunk(chunk)) {\n return;\n }\n if (!this.#refs.has(hash)) {\n for (const refHash of chunk.meta) {\n this.#refCounts.set(refHash, (this.#refCounts.get(refHash) || 0) + 1);\n }\n this.#refs.set(hash, chunk.meta);\n }\n\n this.#ensureCacheSizeLimit();\n }\n\n #ensureCacheSizeLimit() {\n if (this.#evictsAndDeletesSuspended) {\n return;\n }\n for (const entry of this.cacheEntries.values()) {\n if (this.#size <= this.#cacheSizeLimit) {\n break;\n }\n this.#evict(entry);\n }\n }\n\n #cacheChunk(chunk: Chunk, size?: number): boolean {\n const chunkSize = size ?? this.#getSizeOfChunk(chunk);\n if (chunkSize > this.#cacheSizeLimit) {\n // This value cannot be cached due to its size exceeding the\n // cache size limit, don't evict other entries to try to make\n // room for it.\n return false;\n }\n this.#size += chunkSize;\n this.cacheEntries.set(chunk.hash, {chunk, size: chunkSize});\n return true;\n }\n\n #evict(cacheEntry: CacheEntry): void {\n const {hash} = cacheEntry.chunk;\n this.#size -= cacheEntry.size;\n this.cacheEntries.delete(hash);\n }\n\n #deleteEntryByHash(hash: Hash): void {\n this.#refCounts.delete(hash);\n this.#refs.delete(hash);\n const cacheEntry = this.cacheEntries.get(hash);\n if (cacheEntry) {\n this.#size -= cacheEntry.size;\n this.cacheEntries.delete(hash);\n }\n }\n\n updateForCommit(\n chunksToPut: Map<Hash, {chunk: Chunk; size: number}>,\n refCountUpdates: Map<Hash, number>,\n ): void {\n for (const [hash, count] of refCountUpdates) {\n if (count === 0) {\n if (!this.#evictsAndDeletesSuspended) {\n this.#deleteEntryByHash(hash);\n } else {\n this.#refCounts.set(hash, 0);\n this.#suspendedDeletes.push(hash);\n }\n } else {\n this.#refCounts.set(hash, count);\n const chunkAndSize = chunksToPut.get(hash);\n if (chunkAndSize) {\n const {chunk, size} = chunkAndSize;\n const oldCacheEntry = this.cacheEntries.get(hash);\n if (oldCacheEntry) {\n // If there is an existing cache entry then the cached value must be\n // equivalent. Update order in map for LRU tracking but avoid\n // recomputing size and creating a new cache entry.\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, oldCacheEntry);\n } else {\n this.#cacheChunk(chunk, size !== -1 ? size : undefined);\n this.#refs.set(hash, chunk.meta);\n }\n }\n }\n }\n this.#ensureCacheSizeLimit();\n }\n\n persisted(chunks: Iterable<Chunk>) {\n for (const chunk of chunks) {\n this.#cacheChunk(chunk);\n }\n this.#ensureCacheSizeLimit();\n }\n\n async withSuspendedEvictsAndDeletes<T>(\n fn: () => MaybePromise<T>,\n ): Promise<T> {\n this.#evictsAndDeletesSuspended = true;\n try {\n return await fn();\n } finally {\n this.#evictsAndDeletesSuspended = false;\n for (const hash of this.#suspendedDeletes) {\n if (this.#refCounts.get(hash) === 0) {\n this.#deleteEntryByHash(hash);\n }\n }\n this.#ensureCacheSizeLimit();\n }\n }\n}\n", "import {assert} from './asserts.js';\n\nexport function* joinIterables<T>(...iters: Iterable<T>[]) {\n for (const iter of iters) {\n yield* iter;\n }\n}\n\nfunction* filterIter<T>(\n iter: Iterable<T>,\n p: (t: T, index: number) => boolean,\n): Iterable<T> {\n let index = 0;\n for (const t of iter) {\n if (p(t, index++)) {\n yield t;\n }\n }\n}\n\nfunction* mapIter<T, U>(\n iter: Iterable<T>,\n f: (t: T, index: number) => U,\n): Iterable<U> {\n let index = 0;\n for (const t of iter) {\n yield f(t, index++);\n }\n}\n\n// TODO(arv): Use ES2024 Iterable.from when available\n// https://github.com/tc39/proposal-iterator-helpers\n\nclass IterWrapper<T> implements Iterable<T> {\n iter: Iterable<T>;\n constructor(iter: Iterable<T>) {\n this.iter = iter;\n }\n\n [Symbol.iterator]() {\n return this.iter[Symbol.iterator]();\n }\n\n map<U>(f: (t: T, index: number) => U): IterWrapper<U> {\n return new IterWrapper(mapIter(this.iter, f));\n }\n\n filter(p: (t: T, index: number) => boolean): IterWrapper<T> {\n return new IterWrapper(filterIter(this.iter, p));\n }\n}\n\nexport function wrapIterable<T>(iter: Iterable<T>): IterWrapper<T> {\n return new IterWrapper(iter);\n}\n\nexport function* mergeIterables<T>(\n iterables: Iterable<T>[],\n comparator: (l: T, r: T) => number,\n distinct = false,\n): IterableIterator<T> {\n const iterators = iterables.map(i => i[Symbol.iterator]());\n try {\n const current = iterators.map(i => i.next());\n let lastYielded: T | undefined;\n while (current.some(c => !c.done)) {\n const min = current.reduce(\n (acc: [T, number] | undefined, c, i): [T, number] | undefined => {\n if (c.done) {\n return acc;\n }\n if (acc === undefined || comparator(c.value, acc[0]) < 0) {\n return [c.value, i];\n }\n return acc;\n },\n undefined,\n );\n\n assert(min !== undefined, 'min is undefined');\n current[min[1]] = iterators[min[1]].next();\n if (\n lastYielded !== undefined &&\n distinct &&\n comparator(lastYielded, min[0]) === 0\n ) {\n continue;\n }\n lastYielded = min[0];\n yield min[0];\n }\n } finally {\n for (const it of iterators) {\n it.return?.();\n }\n }\n}\n", "import {hasOwn} from '../../shared/src/has-own.js';\nimport type {ReadonlyJSONObject} from '../../shared/src/json.js';\n\nconst SIZE_TAG = 1;\nconst SIZE_INT32 = 4;\nconst SIZE_SMI = 5;\nconst SIZE_DOUBLE = 8;\n\n/**\n * Gives a size of a value. The size is modelled after the size used by\n * Chromium/V8's structuredClone algorithm. It does not match exactly so the\n * size is just an approximation.\n * https://source.chromium.org/chromium/chromium/src/+/main:v8/src/objects/value-serializer.cc;l=102;drc=f0b6f7d12ea47ad7c08fb554f678c1e73801ca36;bpv=1;bpt=1\n * For example we follow JSC/Mozilla for ints and skip the varint encoding.\n *\n * Mozilla does things similarly. Main difference is that there is no varint\n * encoding and every value uses multiples of 64bits\n * https://searchfox.org/mozilla-central/source/js/src/vm/StructuredClone.cpp#94\n *\n * And JSC:\n * https://github.com/WebKit/WebKit/blob/main/Source/WebCore/bindings/js/SerializedScriptValue.cpp#L356\n * - Use 1 byte tag\n * - Numbers are either stored as Int32 or Float64\n */\nexport function getSizeOfValue(value: unknown): number {\n switch (typeof value) {\n case 'string':\n // Assumes all strings are one byte strings. V8 writes OneByteString and\n // TwoByteString. We could check the string but it would require iterating\n // over all the characters.\n return SIZE_TAG + SIZE_INT32 + value.length;\n case 'number':\n if (isSmi(value)) {\n if (value <= -(2 ** 30) || value >= 2 ** 30 - 1) {\n return SIZE_TAG + SIZE_SMI;\n }\n return SIZE_TAG + SIZE_INT32;\n }\n return SIZE_TAG + SIZE_DOUBLE;\n case 'boolean':\n return SIZE_TAG;\n case 'object':\n if (value === null) {\n return SIZE_TAG;\n }\n\n if (Array.isArray(value)) {\n let sum = 2 * SIZE_TAG + SIZE_INT32;\n for (const element of value) {\n sum += getSizeOfValue(element);\n }\n return sum;\n }\n\n {\n const val = value as ReadonlyJSONObject;\n let sum: number = 2 * SIZE_TAG + SIZE_INT32;\n for (const k in val) {\n if (hasOwn(val, k)) {\n // Skip undefined values. undefined values in an object gets\n // stripped if we round trip through JSON.stringif which is what we\n // use when syncing.\n const propertyValue = val[k];\n if (propertyValue !== undefined) {\n sum += getSizeOfValue(k) + getSizeOfValue(propertyValue);\n }\n }\n }\n return sum;\n }\n }\n\n throw new Error(`Invalid value. type: ${typeof value}, value: ${value}`);\n}\n\nfunction isSmi(value: number): boolean {\n return value === (value | 0);\n}\n\nconst entryFixed = 2 * SIZE_TAG + SIZE_INT32 + SIZE_TAG + SIZE_INT32;\n\nexport function getSizeOfEntry<K, V>(key: K, value: V): number {\n // Entries are stored as [key, value, sizeOfEntry]\n return entryFixed + getSizeOfValue(key) + getSizeOfValue(value);\n}\n", "import {assert, assertString} from '../../../shared/src/asserts.js';\nimport {assertDeepFrozen} from '../frozen-json.js';\nimport type {Hash} from '../hash.js';\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 refsTag: unique symbol;\n\n/**\n * Opaque type representing a Refs. The reason to use an opaque type here is to\n * make sure that Refs are always sorted and have no duplicates.\n */\nexport type Refs = [] | readonly [Hash] | (readonly Hash[] & {[refsTag]: true});\n\n/**\n * Convert to a Refs when we already know it is sorted and has no duplicates.\n */\nexport function asRefs(sortedRefs: Hash[]): Refs {\n return sortedRefs as unknown as Refs;\n}\n\n/**\n * Sorts and tags as Refs. If an Array is passed in the array is sorted in\n * place, otherwise a copy of the iterable is created. This checks for duplicates.\n */\nexport function toRefs(refs: Hash[] | Set<Hash>): Refs {\n if (Array.isArray(refs)) {\n refs.sort();\n for (let i = 1; i < refs.length; i++) {\n assert(refs[i - 1] !== refs[i], 'Refs must not have duplicates');\n }\n return asRefs(refs);\n }\n\n const refsArray = [...refs];\n refsArray.sort();\n // no need to check for duplicates as Set cannot have duplicates.\n return asRefs(refsArray);\n}\n\nexport class Chunk<V = unknown> {\n readonly hash: Hash;\n readonly data: V;\n\n /**\n * Meta is an array of refs. If there are no refs we do not write a meta\n * chunk.\n */\n readonly meta: Refs;\n\n constructor(hash: Hash, data: V, refs: Refs) {\n assert(\n !(refs as unknown[]).includes(hash),\n 'Chunk cannot reference itself',\n );\n assertDeepFrozen(data);\n this.hash = hash;\n this.data = data;\n this.meta = refs;\n }\n}\n\nexport function assertRefs(v: unknown): asserts v is Refs {\n if (!Array.isArray(v)) {\n throw new Error('Refs must be an array');\n }\n if (v.length > 0) {\n assertString(v[0]);\n for (let i = 1; i < v.length; i++) {\n assertString(v[i]);\n }\n }\n}\n\nexport function createChunk<V>(\n data: V,\n refs: Refs,\n chunkHasher: ChunkHasher,\n): Chunk<V> {\n const hash = chunkHasher();\n return new Chunk(hash, data, refs);\n}\n\nexport type CreateChunk = <V>(data: V, refs: Refs) => Chunk<V>;\n\nexport type ChunkHasher = () => Hash;\n\nexport function throwChunkHasher(): Hash {\n throw new Error('unexpected call to compute chunk hash');\n}\n", "export function randomUint64(): bigint {\n // Generate two random 32-bit unsigned integers using Math.random()\n const high = Math.floor(Math.random() * 0xffffffff); // High 32 bits\n const low = Math.floor(Math.random() * 0xffffffff); // Low 32 bits\n\n // Combine the high and low parts to form a 64-bit unsigned integer\n return (BigInt(high) << 32n) | BigInt(low);\n}\n", "import * as v from '@badrap/valita';\n\nexport * from '@badrap/valita';\n\nfunction toDisplay(value: unknown): string {\n switch (typeof value) {\n case 'string':\n case 'number':\n case 'boolean':\n return JSON.stringify(value);\n case 'undefined':\n return 'undefined';\n case 'bigint':\n return value.toString() + 'n';\n default:\n if (value === null) {\n return 'null';\n }\n if (Array.isArray(value)) {\n return 'array';\n }\n return typeof value;\n }\n}\n\ntype Key = string | number;\n\nfunction toDisplayAtPath(v: unknown, path: Key[] | undefined): string {\n if (!path?.length) {\n return toDisplay(v);\n }\n\n let cur = v;\n for (const p of path) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n cur = (cur as any)[p];\n }\n return toDisplay(cur);\n}\n\nfunction displayList<T>(\n word: string,\n expected: T[],\n toDisplay: (x: T) => string | number = x => String(x),\n): string | number {\n if (expected.length === 1) {\n return toDisplay(expected[0]);\n }\n\n const suffix = `${toDisplay(\n expected[expected.length - 2],\n )} ${word} ${toDisplay(expected[expected.length - 1])}`;\n if (expected.length === 2) {\n return suffix;\n }\n return `${expected.slice(0, -2).map(toDisplay).join(', ')}, ${suffix}`;\n}\n\nfunction getMessage(err: v.Err, v: unknown): string {\n const firstIssue = err.issues[0];\n const {path} = firstIssue;\n const atPath = path?.length ? ` at ${path.join('.')}` : '';\n\n switch (firstIssue.code) {\n case 'invalid_type':\n return `Expected ${displayList(\n 'or',\n firstIssue.expected,\n )}${atPath}. Got ${toDisplayAtPath(v, path)}`;\n case 'missing_value': {\n const atPath =\n path && path.length > 1 ? ` at ${path.slice(0, -1).join('.')}` : '';\n\n if (firstIssue.path?.length) {\n return `Missing property ${firstIssue.path.at(-1)}${atPath}`;\n }\n return `TODO Unknown missing property${atPath}`;\n }\n\n case 'invalid_literal':\n return `Expected literal value ${displayList(\n 'or',\n firstIssue.expected,\n toDisplay,\n )}${atPath} Got ${toDisplayAtPath(v, path)}`;\n\n case 'invalid_length': {\n return `Expected array with length ${\n firstIssue.minLength === firstIssue.maxLength\n ? firstIssue.minLength\n : `between ${firstIssue.minLength} and ${firstIssue.maxLength}`\n }${atPath}. Got array with length ${(v as {length: number}).length}`;\n }\n\n case 'unrecognized_keys':\n if (firstIssue.keys.length === 1) {\n return `Unexpected property ${firstIssue.keys[0]}${atPath}`;\n }\n return `Unexpected properties ${displayList(\n 'and',\n firstIssue.keys,\n )}${atPath}`;\n\n case 'invalid_union':\n return `Invalid union value${atPath}`;\n\n case 'custom_error': {\n const {error} = firstIssue;\n const message = !error\n ? 'unknown'\n : typeof error === 'string'\n ? error\n : error.message ?? 'unknown';\n return `${message}${atPath}. Got ${toDisplayAtPath(v, path)}`;\n }\n }\n}\n\n/**\n * 'strip' allows unknown properties and removes unknown properties.\n * 'strict' errors if there are unknown properties.\n * 'passthrough' allows unknown properties.\n */\nexport type ParseOptionsMode = 'passthrough' | 'strict' | 'strip';\n\nexport function parse<T>(\n value: unknown,\n schema: v.Type<T>,\n mode?: ParseOptionsMode,\n): T {\n const res = test(value, schema, mode);\n if (!res.ok) {\n throw new TypeError(res.error);\n }\n return res.value;\n}\n\nexport function is<T>(\n value: unknown,\n schema: v.Type<T>,\n mode?: ParseOptionsMode,\n): value is T {\n return test(value, schema, mode).ok;\n}\n\nexport function assert<T>(\n value: unknown,\n schema: v.Type<T>,\n mode?: ParseOptionsMode,\n): asserts value is T {\n parse(value, schema, mode);\n}\n\ntype Result<T> = {ok: true; value: T} | {ok: false; error: string};\n\nexport function test<T>(\n value: unknown,\n schema: v.Type<T>,\n mode?: ParseOptionsMode,\n): Result<T> {\n const res = (schema as v.Type<T>).try(value, mode ? {mode} : undefined);\n if (!res.ok) {\n return {ok: false, error: getMessage(res, value)};\n }\n return res;\n}\n\n/**\n * Shallowly marks the schema as readonly.\n */\nexport function readonly<T extends v.Type>(t: T): v.Type<Readonly<v.Infer<T>>> {\n return t as v.Type<Readonly<v.Infer<T>>>;\n}\n\nexport function readonlyObject<T extends Record<string, v.Type | v.Optional>>(\n t: T,\n): v.ObjectType<Readonly<T>, undefined> {\n return v.object(t);\n}\n\nexport function readonlyArray<T extends v.Type>(\n t: T,\n): v.Type<readonly v.Infer<T>[]> {\n return v.array(t);\n}\n\nexport function readonlyRecord<T extends v.Type>(\n t: T,\n): v.Type<Readonly<Record<string, v.Infer<T>>>> {\n return v.record(t);\n}\n", "import {assert} from '../../shared/src/asserts.js';\nimport {randomUint64} from '../../shared/src/random-uint64.js';\nimport * as valita from '../../shared/src/valita.js';\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\n/**\n * Creates a function that generates UUID hashes for tests.\n */\nexport function makeNewFakeHashFunction(hashPrefix = 'fake'): () => Hash {\n assert(\n /^[0-9a-v]{0,8}$/.test(hashPrefix),\n `Invalid hash prefix: ${hashPrefix}`,\n );\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", "import {assert, assertNumber} from '../../../shared/src/asserts.js';\nimport type {MaybePromise} from '../../../shared/src/types.js';\nimport {skipGCAsserts} from '../config.js';\nimport {type Hash, emptyHash} from '../hash.js';\n\nexport type HeadChange = {\n new: Hash | undefined;\n old: Hash | undefined;\n};\n\ntype LoadedRefCountPromises = Map<Hash, Promise<number>>;\n\nexport interface RefCountUpdatesDelegate {\n getRefCount: (hash: Hash) => MaybePromise<number | undefined>;\n getRefs: (hash: Hash) => MaybePromise<readonly Hash[] | undefined>;\n /**\n * Should be implemented if the store lazily loads refs, returning whether\n * or not the chunks refs have already been counted (i.e. are reflected\n * in `getRefCount`).\n *\n * If defined then:\n * - `getRefs` should return undefined for refs that have not been loaded,\n * but should never return undefined for hashes in `putChunks`.\n * - it is assumed that chunks in `putChunks` may have been reachable before\n * the write, but may not have been counted. This method is used to\n * determine if they have been counted or not. If they have not been\n * counted, and are reachable with the write applied, the returned\n * ref count updates will include updates for counting them.\n *\n * If undefined then:\n * - `getRefs` should never return undefined\n * - it is assumed that the refs of any chunks which were reachable before\n * the write are already counted\n */\n areRefsCounted?: (hash: Hash) => boolean;\n}\n\n/**\n * Computes how ref counts should be updated when a dag write is committed.\n * Does not modify the dag store.\n * @param headChanges Heads that were changed by the dag write.\n * @param putChunks Chunks that were put by the dag write.\n * @param delegate Delegate used for getting ref information from the dag store.\n * @returns Map from chunk Hash to changed ref counts. Chunks with a new ref\n * count of 0 should be deleted. All hashes in `putChunks` will have an entry\n * (which will be zero if the newly put chunk is not reachable from any head).\n */\nexport function computeRefCountUpdates(\n headChanges: Iterable<HeadChange>,\n putChunks: ReadonlySet<Hash>,\n delegate: RefCountUpdatesDelegate,\n): Promise<Map<Hash, number>> {\n return new RefCountUpdates(headChanges, putChunks, delegate).compute();\n}\n\nclass RefCountUpdates {\n readonly #newHeads: Hash[];\n readonly #oldHeads: Hash[];\n readonly #putChunks: ReadonlySet<Hash>;\n readonly #delegate: RefCountUpdatesDelegate;\n readonly #refsCounted: Set<Hash> | null;\n readonly #refCountUpdates: Map<Hash, number>;\n readonly #loadedRefCountPromises: LoadedRefCountPromises;\n readonly #isLazyDelegate: boolean;\n\n constructor(\n headChanges: Iterable<HeadChange>,\n putChunks: ReadonlySet<Hash>,\n delegate: RefCountUpdatesDelegate,\n ) {\n const newHeads: Hash[] = [];\n const oldHeads: Hash[] = [];\n for (const changedHead of headChanges) {\n if (changedHead.old !== changedHead.new) {\n changedHead.old && oldHeads.push(changedHead.old);\n changedHead.new && newHeads.push(changedHead.new);\n }\n }\n this.#newHeads = newHeads;\n this.#oldHeads = oldHeads;\n this.#putChunks = putChunks;\n this.#delegate = delegate;\n this.#refCountUpdates = new Map();\n // This map is used to ensure we do not load the ref count key more than once.\n // Once it is loaded we only operate on a cache of the ref counts.\n this.#loadedRefCountPromises = new Map();\n this.#isLazyDelegate = delegate.areRefsCounted !== undefined;\n this.#refsCounted = this.#isLazyDelegate ? new Set() : null;\n }\n\n async compute(): Promise<Map<Hash, number>> {\n for (const n of this.#newHeads) {\n await this.#changeRefCount(n, 1);\n }\n\n // Now go through the put chunks to ensure each has an entry in\n // refCountUpdates (zero for new chunks which are not reachable from\n // newHeads).\n await Promise.all(\n Array.from(this.#putChunks.values(), hash =>\n this.#ensureRefCountLoaded(hash),\n ),\n );\n\n if (this.#isLazyDelegate) {\n assert(this.#delegate.areRefsCounted);\n assert(this.#refsCounted);\n let refCountsUpdated;\n do {\n refCountsUpdated = false;\n for (const hash of this.#putChunks.values()) {\n if (\n !this.#delegate.areRefsCounted(hash) &&\n !this.#refsCounted.has(hash) &&\n this.#refCountUpdates.get(hash) !== 0\n ) {\n await this.#updateRefsCounts(hash, 1);\n refCountsUpdated = true;\n break;\n }\n }\n } while (refCountsUpdated);\n }\n\n for (const o of this.#oldHeads) {\n await this.#changeRefCount(o, -1);\n }\n\n if (!skipGCAsserts) {\n for (const [hash, update] of this.#refCountUpdates) {\n assert(\n update >= 0,\n `ref count update must be non-negative. ${hash}:${update}`,\n );\n }\n }\n\n return this.#refCountUpdates;\n }\n\n async #changeRefCount(hash: Hash, delta: number): Promise<void> {\n // First make sure that we have the ref count in the cache. This is async\n // because it might need to load the ref count from the store (via the delegate).\n //\n // Once we have loaded the ref count all the updates to it are sync to\n // prevent race conditions.\n await this.#ensureRefCountLoaded(hash);\n if (this.#updateRefCount(hash, delta)) {\n await this.#updateRefsCounts(hash, delta);\n }\n }\n\n async #updateRefsCounts(hash: Hash, delta: number) {\n if (hash === emptyHash) {\n return;\n }\n const refs = await this.#delegate.getRefs(hash);\n if (!skipGCAsserts) {\n assert(\n refs || (this.#isLazyDelegate && !this.#putChunks.has(hash)),\n 'refs must be defined',\n );\n }\n\n if (refs !== undefined) {\n this.#refsCounted?.add(hash);\n const ps = refs.map(ref => this.#changeRefCount(ref, delta));\n await Promise.all(ps);\n }\n }\n\n #ensureRefCountLoaded(hash: Hash): Promise<number> {\n // Only get the ref count once.\n let p = this.#loadedRefCountPromises.get(hash);\n if (p === undefined) {\n p = (async () => {\n const value = (await this.#delegate.getRefCount(hash)) || 0;\n this.#refCountUpdates.set(hash, value);\n return value;\n })();\n this.#loadedRefCountPromises.set(hash, p);\n }\n return p;\n }\n\n #updateRefCount(hash: Hash, delta: number): boolean {\n const oldCount = this.#refCountUpdates.get(hash);\n assertNumber(oldCount);\n this.#refCountUpdates.set(hash, oldCount + delta);\n return (oldCount === 0 && delta === 1) || (oldCount === 1 && delta === -1);\n }\n}\n", "import {assert} from '../../../shared/src/asserts.js';\nimport type {Hash} from '../hash.js';\nimport type {Release} from '../with-transactions.js';\nimport type {Chunk, Refs} from './chunk.js';\n\nexport interface Store {\n read(): Promise<Read>;\n write(): Promise<Write>;\n close(): Promise<void>;\n}\n\ninterface GetChunk {\n getChunk(hash: Hash): Promise<Chunk | undefined>;\n}\n\nexport interface MustGetChunk {\n mustGetChunk(hash: Hash): Promise<Chunk>;\n}\n\nexport interface Read extends GetChunk, MustGetChunk, Release {\n hasChunk(hash: Hash): Promise<boolean>;\n getHead(name: string): Promise<Hash | undefined>;\n get closed(): boolean;\n}\n\nexport interface Write extends Read {\n createChunk<V>(data: V, refs: Refs): Chunk<V>;\n putChunk<V>(c: Chunk<V>): Promise<void>;\n setHead(name: string, hash: Hash): Promise<void>;\n removeHead(name: string): Promise<void>;\n assertValidHash(hash: Hash): void;\n commit(): Promise<void>;\n}\n\nexport class ChunkNotFoundError extends Error {\n name = 'ChunkNotFoundError';\n readonly hash: Hash;\n constructor(hash: Hash) {\n super(`Chunk not found ${hash}`);\n this.hash = hash;\n }\n}\n\nexport async function mustGetChunk(\n store: GetChunk,\n hash: Hash,\n): Promise<Chunk> {\n const chunk = await store.getChunk(hash);\n if (chunk) {\n return chunk;\n }\n throw new ChunkNotFoundError(hash);\n}\n\nexport async function mustGetHeadHash(\n name: string,\n store: Read,\n): Promise<Hash> {\n const hash = await store.getHead(name);\n assert(hash, `Missing head ${name}`);\n return hash;\n}\n", "import {type Hash, parse as parseHash} from '../hash.js';\nimport * as KeyType from './key-type-enum.js';\n\nexport function chunkDataKey(hash: Hash): string {\n return `c/${hash}/d`;\n}\n\nexport function chunkMetaKey(hash: Hash): string {\n return `c/${hash}/m`;\n}\n\nexport function chunkRefCountKey(hash: Hash): string {\n return `c/${hash}/r`;\n}\n\nexport function headKey(name: string): string {\n return `h/${name}`;\n}\n\nexport type Key =\n | {\n type: KeyType.ChunkData;\n hash: Hash;\n }\n | {\n type: KeyType.ChunkMeta;\n hash: Hash;\n }\n | {\n type: KeyType.ChunkRefCount;\n hash: Hash;\n }\n | {\n type: KeyType.Head;\n name: string;\n };\n\nexport function parse(key: string): Key {\n const invalidKey = () => new Error(`Invalid key. Got \"${key}\"`);\n const hash = () => parseHash(key.substring(2, key.length - 2));\n\n // '/'\n if (key.charCodeAt(1) === 47) {\n switch (key.charCodeAt(0)) {\n // c\n case 99: {\n if (key.length < 4 || key.charCodeAt(key.length - 2) !== 47) {\n throw invalidKey();\n }\n switch (key.charCodeAt(key.length - 1)) {\n case 100: // d\n return {\n type: KeyType.ChunkData,\n hash: hash(),\n };\n case 109: // m\n return {\n type: KeyType.ChunkMeta,\n hash: hash(),\n };\n case 114: // r\n return {\n type: KeyType.ChunkRefCount,\n hash: hash(),\n };\n }\n break;\n }\n case 104: // h\n return {\n type: KeyType.Head,\n name: key.substring(2),\n };\n }\n }\n throw invalidKey();\n}\n", "import {assertNumber} from '../../../shared/src/asserts.js';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.js';\nimport {type Hash, assertHash} from '../hash.js';\nimport type {\n Read as KVRead,\n Store as KVStore,\n Write as KVWrite,\n} from '../kv/store.js';\nimport {\n Chunk,\n type ChunkHasher,\n type Refs,\n assertRefs,\n createChunk,\n} from './chunk.js';\nimport {type RefCountUpdatesDelegate, computeRefCountUpdates} from './gc.js';\nimport {chunkDataKey, chunkMetaKey, chunkRefCountKey, headKey} from './key.js';\nimport {type Read, type Store, type Write, mustGetChunk} from './store.js';\n\nexport class StoreImpl implements Store {\n readonly #kv: KVStore;\n readonly #chunkHasher: ChunkHasher;\n readonly #assertValidHash: (hash: Hash) => void;\n\n constructor(\n kv: KVStore,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n this.#kv = kv;\n this.#chunkHasher = chunkHasher;\n this.#assertValidHash = assertValidHash;\n }\n\n async read(): Promise<Read> {\n return new ReadImpl(await this.#kv.read(), this.#assertValidHash);\n }\n\n async write(): Promise<Write> {\n return new WriteImpl(\n await this.#kv.write(),\n this.#chunkHasher,\n this.#assertValidHash,\n );\n }\n\n close(): Promise<void> {\n return this.#kv.close();\n }\n}\n\nexport class ReadImpl implements Read {\n protected readonly _tx: KVRead;\n readonly assertValidHash: (hash: Hash) => void;\n\n constructor(kv: KVRead, assertValidHash: (hash: Hash) => void) {\n this._tx = kv;\n this.assertValidHash = assertValidHash;\n }\n\n hasChunk(hash: Hash): Promise<boolean> {\n return this._tx.has(chunkDataKey(hash));\n }\n\n async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const data = await this._tx.get(chunkDataKey(hash));\n if (data === undefined) {\n return undefined;\n }\n\n const refsVal = await this._tx.get(chunkMetaKey(hash));\n let refs: Refs;\n if (refsVal !== undefined) {\n assertRefs(refsVal);\n refs = refsVal;\n } else {\n refs = [];\n }\n return new Chunk(hash, data, refs);\n }\n\n mustGetChunk(hash: Hash): Promise<Chunk> {\n return mustGetChunk(this, hash);\n }\n\n async getHead(name: string): Promise<Hash | undefined> {\n const data = await this._tx.get(headKey(name));\n if (data === undefined) {\n return undefined;\n }\n assertHash(data);\n return data;\n }\n\n release(): void {\n this._tx.release();\n }\n\n get closed(): boolean {\n return this._tx.closed;\n }\n}\n\ntype HeadChange = {\n new: Hash | undefined;\n old: Hash | undefined;\n};\n\nexport class WriteImpl\n extends ReadImpl\n implements Write, RefCountUpdatesDelegate\n{\n protected declare readonly _tx: KVWrite;\n readonly #chunkHasher: ChunkHasher;\n\n readonly #putChunks = new Set<Hash>();\n readonly #changedHeads = new Map<string, HeadChange>();\n\n constructor(\n kvw: KVWrite,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n super(kvw, assertValidHash);\n this.#chunkHasher = chunkHasher;\n }\n\n createChunk = <V>(data: V, refs: Refs): Chunk<V> =>\n createChunk(data, refs, this.#chunkHasher);\n\n get kvWrite(): KVWrite {\n return this._tx;\n }\n\n async putChunk(c: Chunk): Promise<void> {\n const {hash, data, meta} = c;\n // We never want to write temp hashes to the underlying store.\n this.assertValidHash(hash);\n const key = chunkDataKey(hash);\n // Commit contains InternalValue and Hash which are opaque types.\n const p1 = this._tx.put(key, data as ReadonlyJSONValue);\n let p2;\n if (meta.length > 0) {\n for (const h of meta) {\n this.assertValidHash(h);\n }\n p2 = this._tx.put(chunkMetaKey(hash), meta);\n }\n this.#putChunks.add(hash);\n await p1;\n await p2;\n }\n\n setHead(name: string, hash: Hash): Promise<void> {\n return this.#setHead(name, hash);\n }\n\n removeHead(name: string): Promise<void> {\n return this.#setHead(name, undefined);\n }\n\n async #setHead(name: string, hash: Hash | undefined): Promise<void> {\n const oldHash = await this.getHead(name);\n const hk = headKey(name);\n\n let p1: Promise<void>;\n if (hash === undefined) {\n p1 = this._tx.del(hk);\n } else {\n p1 = this._tx.put(hk, hash);\n }\n\n const v = this.#changedHeads.get(name);\n if (v === undefined) {\n this.#changedHeads.set(name, {new: hash, old: oldHash});\n } else {\n // Keep old if existing\n v.new = hash;\n }\n\n await p1;\n }\n\n async commit(): Promise<void> {\n const refCountUpdates = await computeRefCountUpdates(\n this.#changedHeads.values(),\n this.#putChunks,\n this,\n );\n await this.#applyRefCountUpdates(refCountUpdates);\n await this._tx.commit();\n }\n\n async getRefCount(hash: Hash): Promise<number | undefined> {\n const value = await this._tx.get(chunkRefCountKey(hash));\n if (value === undefined) {\n return undefined;\n }\n assertNumber(value);\n if (value < 0 || value > 0xffff || value !== (value | 0)) {\n throw new Error(\n `Invalid ref count ${value}. We expect the value to be a Uint16`,\n );\n }\n return value;\n }\n\n async getRefs(hash: Hash): Promise<readonly Hash[]> {\n const meta = await this._tx.get(chunkMetaKey(hash));\n if (meta === undefined) {\n return [];\n }\n assertRefs(meta);\n return meta;\n }\n\n async #applyRefCountUpdates(refCountCache: Map<Hash, number>): Promise<void> {\n const ps: Promise<void>[] = [];\n for (const [hash, count] of refCountCache) {\n if (count === 0) {\n ps.push(this.#removeAllRelatedKeys(hash));\n } else {\n const refCountKey = chunkRefCountKey(hash);\n ps.push(this._tx.put(refCountKey, count));\n }\n }\n await Promise.all(ps);\n }\n\n async #removeAllRelatedKeys(hash: Hash): Promise<void> {\n await Promise.all([\n this._tx.del(chunkDataKey(hash)),\n this._tx.del(chunkMetaKey(hash)),\n this._tx.del(chunkRefCountKey(hash)),\n ]);\n\n this.#putChunks.delete(hash);\n }\n\n release(): void {\n this._tx.release();\n }\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const IndexChangeSDD = 1;\nexport const LocalSDD = 2;\nexport const SnapshotSDD = 3;\nexport const LocalDD31 = 4;\nexport const SnapshotDD31 = 5;\n\nexport type IndexChangeSDD = typeof IndexChangeSDD;\nexport type LocalSDD = typeof LocalSDD;\nexport type SnapshotSDD = typeof SnapshotSDD;\nexport type LocalDD31 = typeof LocalDD31;\nexport type SnapshotDD31 = typeof SnapshotDD31;\n\nexport type Type =\n | IndexChangeSDD\n | LocalSDD\n | SnapshotSDD\n | LocalDD31\n | SnapshotDD31;\n", "import {\n assert,\n assertArray,\n assertBoolean,\n assertNumber,\n assertObject,\n assertString,\n unreachable,\n} from '../../../shared/src/asserts.js';\nimport {assertJSONValue} from '../../../shared/src/json.js';\nimport {skipCommitDataAsserts} from '../config.js';\nimport {type FrozenCookie, compareCookies} from '../cookies.js';\nimport {type Chunk, type CreateChunk, type Refs, toRefs} from '../dag/chunk.js';\nimport {type MustGetChunk, type Read, mustGetHeadHash} from '../dag/store.js';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.js';\nimport {type Hash, assertHash} from '../hash.js';\nimport type {IndexDefinition} from '../index-defs.js';\nimport type {ClientID} from '../sync/ids.js';\nimport * as MetaType from './meta-type-enum.js';\n\nexport const DEFAULT_HEAD_NAME = 'main';\n\nexport function commitIsLocalSDD(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaSDD> {\n return isLocalMetaSDD(commit.meta);\n}\n\nexport function commitIsLocalDD31(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31> {\n return isLocalMetaDD31(commit.meta);\n}\n\nexport function commitIsLocal(\n commit: Commit<Meta>,\n): commit is Commit<LocalMetaDD31 | LocalMetaSDD> {\n return commitIsLocalDD31(commit) || commitIsLocalSDD(commit);\n}\n\nfunction commitIsSnapshotDD31(\n commit: Commit<Meta>,\n): commit is Commit<SnapshotMetaDD31> {\n return isSnapshotMetaDD31(commit.meta);\n}\n\nfunction commitIsSnapshotSDD(\n commit: Commit<Meta>,\n): commit is Commit<SnapshotMetaSDD> {\n return isSnapshotMetaSDD(commit.meta);\n}\n\nexport function commitIsSnapshot(\n commit: Commit<Meta>,\n): commit is Commit<SnapshotMetaDD31 | SnapshotMetaSDD> {\n return commitIsSnapshotDD31(commit) || commitIsSnapshotSDD(commit);\n}\n\nexport class Commit<M extends Meta> {\n readonly chunk: Chunk<CommitData<M>>;\n\n constructor(chunk: Chunk<CommitData<M>>) {\n this.chunk = chunk;\n }\n\n get meta(): M {\n return this.chunk.data.meta;\n }\n\n get valueHash(): Hash {\n // Already validated!\n return this.chunk.data.valueHash;\n }\n\n getMutationID(clientID: ClientID, dagRead: MustGetChunk): Promise<number> {\n return getMutationID(clientID, dagRead, this.meta);\n }\n\n async getNextMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n ): Promise<number> {\n return (await this.getMutationID(clientID, dagRead)) + 1;\n }\n\n get indexes(): readonly IndexRecord[] {\n // Already validated!\n return this.chunk.data.indexes;\n }\n}\n\nexport async function getMutationID(\n clientID: ClientID,\n dagRead: MustGetChunk,\n meta: Meta,\n): Promise<number> {\n switch (meta.type) {\n case MetaType.IndexChangeSDD:\n return meta.lastMutationID;\n\n case MetaType.SnapshotSDD:\n return meta.lastMutationID;\n\n case MetaType.SnapshotDD31:\n return meta.lastMutationIDs[clientID] ?? 0;\n\n case MetaType.LocalSDD:\n return meta.mutationID;\n\n case MetaType.LocalDD31: {\n if (meta.clientID === clientID) {\n return meta.mutationID;\n }\n const {basisHash} = meta;\n const basisCommit = await commitFromHash(basisHash, dagRead);\n return getMutationID(clientID, dagRead, basisCommit.meta);\n }\n\n default:\n unreachable(meta);\n }\n}\n\n/**\n * Returns the set of local commits from the given `fromCommitHash` back to but not\n * including its base snapshot. If `fromCommitHash` is a snapshot, the returned vector\n * will be empty. When, as typical, `fromCommitHash` is the head of the default chain\n * then the returned commits are the set of pending commits, ie the set of local commits\n * that have not yet been pushed to the data layer.\n *\n * The vector of commits is returned in reverse chain order, that is, starting\n * with the commit with hash `fromCommitHash` and walking backwards.\n */\nexport async function localMutations(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaSDD | LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocal(c)) as Commit<\n LocalMetaSDD | LocalMetaDD31\n >[];\n}\n\nexport async function localMutationsDD31(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits = await commitChain(fromCommitHash, dagRead);\n // Filter does not deal with type narrowing.\n return commits.filter(c => commitIsLocalDD31(c)) as Commit<LocalMetaDD31>[];\n}\n\nexport async function localMutationsGreaterThan(\n commit: Commit<Meta>,\n mutationIDLimits: Record<ClientID, number>,\n dagRead: Read,\n): Promise<Commit<LocalMetaDD31>[]> {\n const commits: Commit<LocalMetaDD31>[] = [];\n const remainingMutationIDLimits = new Map(Object.entries(mutationIDLimits));\n while (!commitIsSnapshot(commit) && remainingMutationIDLimits.size > 0) {\n if (commitIsLocalDD31(commit)) {\n const {meta} = commit;\n const mutationIDLowerLimit = remainingMutationIDLimits.get(meta.clientID);\n if (mutationIDLowerLimit !== undefined) {\n if (meta.mutationID <= mutationIDLowerLimit) {\n remainingMutationIDLimits.delete(meta.clientID);\n } else {\n commits.push(commit as Commit<LocalMetaDD31>);\n }\n }\n }\n const {basisHash} = commit.meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n return commits;\n}\n\nexport async function baseSnapshotFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaSDD | SnapshotMetaDD31>> {\n const hash = await dagRead.getHead(name);\n assert(hash, `Missing head ${name}`);\n return baseSnapshotFromHash(hash, dagRead);\n}\n\nexport async function baseSnapshotHashFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Hash> {\n return (await baseSnapshotFromHash(hash, dagRead)).chunk.hash;\n}\n\nexport async function baseSnapshotFromHash(\n hash: Hash,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaSDD | SnapshotMetaDD31>> {\n const commit = await commitFromHash(hash, dagRead);\n return baseSnapshotFromCommit(commit, dagRead);\n}\n\nexport async function baseSnapshotFromCommit(\n commit: Commit<Meta>,\n dagRead: Read,\n): Promise<Commit<SnapshotMetaSDD | SnapshotMetaDD31>> {\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n if (isLocalMetaDD31(meta)) {\n commit = await commitFromHash(meta.baseSnapshotHash, dagRead);\n } else {\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commit = await commitFromHash(basisHash, dagRead);\n }\n }\n return commit;\n}\n\nexport function snapshotMetaParts(\n c: Commit<SnapshotMetaSDD | SnapshotMetaDD31>,\n clientID: ClientID,\n): [lastMutationID: number, cookie: FrozenCookie | FrozenJSONValue] {\n const m = c.meta;\n if (isSnapshotMetaDD31(m)) {\n const lmid = m.lastMutationIDs[clientID] ?? 0;\n return [lmid, m.cookieJSON];\n }\n return [m.lastMutationID, m.cookieJSON];\n}\n\nexport function compareCookiesForSnapshots(\n a: Commit<SnapshotMetaDD31>,\n b: Commit<SnapshotMetaDD31>,\n): number {\n return compareCookies(a.meta.cookieJSON, b.meta.cookieJSON);\n}\n\n/**\n * Returns all commits from the commit with fromCommitHash to its base snapshot,\n * inclusive of both. Resulting vector is in chain-head-first order (so snapshot\n * comes last).\n */\nexport async function commitChain(\n fromCommitHash: Hash,\n dagRead: Read,\n): Promise<Commit<Meta>[]> {\n let commit = await commitFromHash(fromCommitHash, dagRead);\n const commits = [];\n while (!commitIsSnapshot(commit)) {\n const {meta} = commit;\n const {basisHash} = meta;\n if (basisHash === null) {\n throw new Error(`Commit ${commit.chunk.hash} has no basis`);\n }\n commits.push(commit);\n commit = await commitFromHash(basisHash, dagRead);\n }\n commits.push(commit);\n return commits;\n}\n\nexport async function commitFromHash(\n hash: Hash,\n dagRead: MustGetChunk,\n): Promise<Commit<Meta>> {\n const chunk = await dagRead.mustGetChunk(hash);\n return fromChunk(chunk);\n}\n\nexport async function commitFromHead(\n name: string,\n dagRead: Read,\n): Promise<Commit<Meta>> {\n const hash = await mustGetHeadHash(name, dagRead);\n return commitFromHash(hash, dagRead);\n}\n\nexport type IndexChangeMetaSDD = {\n readonly type: MetaType.IndexChangeSDD;\n readonly basisHash: Hash;\n readonly lastMutationID: number;\n};\n\nfunction assertIndexChangeMeta(\n v: Record<string, unknown>,\n): asserts v is IndexChangeMetaSDD {\n // type already asserted\n assertNumber(v.lastMutationID);\n\n // Note: indexes are already validated for all commit types. Only additional\n // things to validate are:\n // - lastMutationID is equal to the basis\n // - valueHash has not been changed\n // However we don't have a write transaction this deep, so these validated at\n // commit time.\n}\n\nexport function assertIndexChangeCommit(\n c: Commit<Meta>,\n): asserts c is Commit<IndexChangeMetaSDD> {\n assertIndexChangeMeta(c.meta);\n}\n\nexport type LocalMetaSDD = {\n readonly type: MetaType.LocalSDD;\n readonly basisHash: Hash;\n readonly mutationID: number;\n readonly mutatorName: string;\n readonly mutatorArgsJSON: FrozenJSONValue;\n readonly originalHash: Hash | null;\n readonly timestamp: number;\n};\n\nexport type LocalMetaDD31 = Omit<LocalMetaSDD, 'type'> & {\n readonly type: MetaType.LocalDD31;\n readonly clientID: ClientID;\n readonly baseSnapshotHash: Hash;\n};\n\nexport type LocalMeta = LocalMetaSDD | LocalMetaDD31;\n\nfunction assertLocalMetaSDD(\n v: Record<string, unknown>,\n): asserts v is LocalMetaSDD {\n // type already asserted\n assertNumber(v.mutationID);\n assertString(v.mutatorName);\n if (!v.mutatorName) {\n throw new Error('Missing mutator name');\n }\n assertJSONValue(v.mutatorArgsJSON);\n if (v.originalHash !== null) {\n assertHash(v.originalHash);\n }\n assertNumber(v.timestamp);\n}\n\nexport function assertLocalMetaDD31(\n v: Record<string, unknown>,\n): asserts v is LocalMetaDD31 {\n // type already asserted\n assertString(v.clientID);\n assertLocalMetaSDD(v);\n}\n\nexport function isLocalMetaDD31(meta: Meta): meta is LocalMetaDD31 {\n return meta.type === MetaType.LocalDD31;\n}\n\nfunction isLocalMetaSDD(meta: Meta): meta is LocalMetaSDD {\n return meta.type === MetaType.LocalSDD;\n}\n\nexport function assertLocalCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<LocalMetaDD31> {\n assertLocalMetaDD31(c.meta);\n}\n\nexport function assertLocalCommitSDD(\n c: Commit<Meta>,\n): asserts c is Commit<LocalMetaSDD> {\n assertLocalMetaSDD(c.meta);\n}\n\nexport type SnapshotMetaSDD = {\n readonly type: MetaType.SnapshotSDD;\n readonly basisHash: Hash | null;\n readonly lastMutationID: number;\n readonly cookieJSON: FrozenJSONValue;\n};\n\nexport type SnapshotMetaDD31 = {\n readonly type: MetaType.SnapshotDD31;\n readonly basisHash: Hash | null;\n readonly lastMutationIDs: Record<ClientID, number>;\n readonly cookieJSON: FrozenCookie;\n};\n\nexport type SnapshotMeta = SnapshotMetaSDD | SnapshotMetaDD31;\n\nfunction assertSnapshotMetaBase(v: Record<string, unknown>) {\n // type already asserted\n if (v.basisHash !== null) {\n assertHash(v.basisHash);\n }\n assertJSONValue(v.cookieJSON);\n}\n\nexport function assertSnapshotMetaSDD(\n v: Record<string, unknown>,\n): asserts v is SnapshotMetaSDD {\n assertSnapshotMetaBase(v);\n assertNumber(v.lastMutationID);\n}\n\nexport function assertSnapshotMetaDD31(\n v: Record<string, unknown>,\n): asserts v is SnapshotMetaDD31 {\n assertSnapshotMetaBase(v);\n assertLastMutationIDs(v.lastMutationIDs);\n}\n\nfunction assertLastMutationIDs(\n v: unknown,\n): asserts v is Record<ClientID, number> {\n assertObject(v);\n for (const e of Object.values(v)) {\n assertNumber(e);\n }\n}\n\nexport function assertSnapshotCommitSDD(\n c: Commit<Meta>,\n): asserts c is Commit<SnapshotMetaSDD> {\n assertSnapshotMetaSDD(c.meta);\n}\n\nexport type Meta =\n | IndexChangeMetaSDD\n | LocalMetaSDD\n | LocalMetaDD31\n | SnapshotMetaSDD\n | SnapshotMetaDD31;\n\nexport function assertSnapshotCommitDD31(\n c: Commit<Meta>,\n): asserts c is Commit<SnapshotMetaDD31> {\n assertSnapshotMetaDD31(c.meta);\n}\n\nfunction isSnapshotMetaDD31(meta: Meta): meta is SnapshotMetaDD31 {\n return meta.type === MetaType.SnapshotDD31;\n}\n\nfunction isSnapshotMetaSDD(meta: Meta): meta is SnapshotMetaSDD {\n return meta.type === MetaType.SnapshotSDD;\n}\n\nfunction assertMeta(v: unknown): asserts v is Meta {\n assertObject(v);\n assertDeepFrozen(v);\n if (v.basisHash !== null) {\n assertString(v.basisHash);\n }\n\n assertNumber(v.type);\n switch (v.type) {\n case MetaType.IndexChangeSDD:\n assertIndexChangeMeta(v);\n break;\n case MetaType.LocalSDD:\n assertLocalMetaSDD(v);\n break;\n case MetaType.LocalDD31:\n assertLocalMetaDD31(v);\n break;\n case MetaType.SnapshotSDD:\n assertSnapshotMetaSDD(v);\n break;\n case MetaType.SnapshotDD31:\n assertSnapshotMetaDD31(v);\n break;\n default:\n throw new Error(`Invalid enum value ${v.type}`);\n }\n}\n\n/**\n * This is the type used for index definitions as defined in the Commit chunk data.\n *\n * Changing this requires a REPLICACHE_FORMAT_VERSION bump.\n */\nexport type ChunkIndexDefinition = {\n readonly name: string;\n readonly keyPrefix: string;\n readonly jsonPointer: string;\n // Used to not exist\n readonly allowEmpty?: boolean;\n};\n\nexport function chunkIndexDefinitionEqualIgnoreName(\n a: ChunkIndexDefinition,\n b: ChunkIndexDefinition,\n): boolean {\n return (\n a.jsonPointer === b.jsonPointer &&\n (a.allowEmpty ?? false) === (b.allowEmpty ?? false) &&\n a.keyPrefix === b.keyPrefix\n );\n}\n\nfunction assertChunkIndexDefinition(\n v: unknown,\n): asserts v is ChunkIndexDefinition {\n assertObject(v);\n assertDeepFrozen(v);\n assertString(v.name);\n assertString(v.keyPrefix);\n assertString(v.jsonPointer);\n if (v.allowEmpty !== undefined) {\n assertBoolean(v.allowEmpty);\n }\n}\n\nexport function toChunkIndexDefinition(\n name: string,\n indexDefinition: IndexDefinition,\n): Required<ChunkIndexDefinition> {\n return {\n name,\n keyPrefix: indexDefinition.prefix ?? '',\n jsonPointer: indexDefinition.jsonPointer,\n allowEmpty: indexDefinition.allowEmpty ?? false,\n };\n}\n\nexport type IndexRecord = {\n readonly definition: ChunkIndexDefinition;\n readonly valueHash: Hash;\n};\n\nfunction assertIndexRecord(v: unknown): asserts v is IndexRecord {\n assertObject(v);\n assertDeepFrozen(v);\n assertChunkIndexDefinition(v.definition);\n assertString(v.valueHash);\n}\n\nfunction assertIndexRecords(v: unknown): asserts v is IndexRecord[] {\n assertArray(v);\n assertDeepFrozen(v);\n for (const ir of v) {\n assertIndexRecord(ir);\n }\n}\n\nexport function newLocalSDD(\n createChunk: CreateChunk,\n basisHash: Hash,\n mutationID: number,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n timestamp: number,\n): Commit<LocalMetaSDD | LocalMetaDD31> {\n const meta: LocalMetaSDD = {\n type: MetaType.LocalSDD,\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n };\n return commitFromCommitData(\n createChunk,\n makeCommitData(meta, valueHash, indexes),\n );\n}\n\nexport function newLocalDD31(\n createChunk: CreateChunk,\n basisHash: Hash,\n baseSnapshotHash: Hash,\n mutationID: number,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n timestamp: number,\n clientID: ClientID,\n): Commit<LocalMetaDD31> {\n const meta: LocalMetaDD31 = {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n clientID,\n };\n return commitFromCommitData(\n createChunk,\n makeCommitData(meta, valueHash, indexes),\n );\n}\n\nexport function newSnapshotSDD(\n createChunk: CreateChunk,\n basisHash: Hash | null,\n lastMutationID: number,\n cookieJSON: FrozenJSONValue,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): Commit<SnapshotMetaSDD> {\n return commitFromCommitData(\n createChunk,\n newSnapshotCommitDataSDD(\n basisHash,\n lastMutationID,\n cookieJSON,\n valueHash,\n indexes,\n ),\n );\n}\n\nexport function newSnapshotDD31(\n createChunk: CreateChunk,\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): Commit<SnapshotMetaDD31> {\n return commitFromCommitData(\n createChunk,\n newSnapshotCommitDataDD31(\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexes,\n ),\n );\n}\n\nexport function newSnapshotCommitDataSDD(\n basisHash: Hash | null,\n lastMutationID: number,\n cookieJSON: FrozenJSONValue,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<SnapshotMetaSDD> {\n const meta: SnapshotMetaSDD = {\n type: MetaType.SnapshotSDD,\n basisHash,\n lastMutationID,\n cookieJSON,\n };\n return makeCommitData(meta, valueHash, indexes);\n}\n\nexport function newSnapshotCommitDataDD31(\n basisHash: Hash | null,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<SnapshotMetaDD31> {\n const meta: SnapshotMetaDD31 = {\n type: MetaType.SnapshotDD31,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n };\n return makeCommitData(meta, valueHash, indexes);\n}\n\nexport function newIndexChange(\n createChunk: CreateChunk,\n basisHash: Hash,\n lastMutationID: number,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): Commit<IndexChangeMetaSDD> {\n const meta: IndexChangeMetaSDD = {\n type: MetaType.IndexChangeSDD,\n basisHash,\n lastMutationID,\n };\n return commitFromCommitData(\n createChunk,\n makeCommitData(meta, valueHash, indexes),\n );\n}\n\nexport function fromChunk(chunk: Chunk): Commit<Meta> {\n validateChunk(chunk);\n return new Commit(chunk);\n}\n\nfunction commitFromCommitData<M extends Meta>(\n createChunk: CreateChunk,\n data: CommitData<M>,\n): Commit<M> {\n return new Commit(createChunk(data, getRefs(data)));\n}\n\nexport function getRefs(data: CommitData<Meta>): Refs {\n const refs: Set<Hash> = new Set();\n refs.add(data.valueHash);\n const {meta} = data;\n switch (meta.type) {\n case MetaType.IndexChangeSDD:\n meta.basisHash && refs.add(meta.basisHash);\n break;\n case MetaType.LocalSDD:\n case MetaType.LocalDD31:\n meta.basisHash && refs.add(meta.basisHash);\n // Local has weak originalHash\n break;\n case MetaType.SnapshotSDD:\n case MetaType.SnapshotDD31:\n // Snapshot has weak basisHash\n break;\n default:\n unreachable(meta);\n }\n\n for (const index of data.indexes) {\n refs.add(index.valueHash);\n }\n\n return toRefs(refs);\n}\n\nexport type CommitData<M extends Meta> = FrozenTag<{\n readonly meta: M;\n readonly valueHash: Hash;\n readonly indexes: readonly IndexRecord[];\n}>;\n\nexport function makeCommitData<M extends Meta>(\n meta: M,\n valueHash: Hash,\n indexes: readonly IndexRecord[],\n): CommitData<M> {\n return deepFreeze({\n meta,\n valueHash,\n indexes,\n }) as unknown as CommitData<M>;\n}\n\nexport function assertCommitData(v: unknown): asserts v is CommitData<Meta> {\n if (skipCommitDataAsserts) {\n return;\n }\n\n assertObject(v);\n assertDeepFrozen(v);\n assertMeta(v.meta);\n assertString(v.valueHash);\n assertIndexRecords(v.indexes);\n}\n\nfunction validateChunk(chunk: Chunk): asserts chunk is Chunk<CommitData<Meta>> {\n const {data} = chunk;\n assertCommitData(data);\n\n const seen = new Set();\n for (const index of data.indexes) {\n const {name} = index.definition;\n if (seen.has(name)) {\n throw new Error(`Duplicate index ${name}`);\n }\n seen.add(name);\n }\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {\n assert,\n assertArray,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.js';\nimport {joinIterables} from '../../../shared/src/iterables.js';\nimport {\n type JSONValue,\n type ReadonlyJSONValue,\n assertJSONValue,\n} from '../../../shared/src/json.js';\nimport {binarySearch as binarySearchWithFunc} from '../binary-search.js';\nimport {skipBTreeNodeAsserts} from '../config.js';\nimport type {IndexKey} from '../db/index.js';\nimport * as FormatVersion from '../format-version-enum.js';\nimport {\n type FrozenJSONValue,\n type FrozenTag,\n assertDeepFrozen,\n deepFreeze,\n} from '../frozen-json.js';\nimport {type Hash, emptyHash, newRandomHash} from '../hash.js';\nimport type {BTreeRead} from './read.js';\nimport type {BTreeWrite} from './write.js';\n\nexport type Entry<V> = readonly [key: string, value: V, sizeOfEntry: number];\n\nexport const NODE_LEVEL = 0;\nexport const NODE_ENTRIES = 1;\n\n/**\n * The type of B+Tree node chunk data\n */\ntype BaseNode<V> = FrozenTag<\n readonly [level: number, entries: ReadonlyArray<Entry<V>>]\n>;\nexport type InternalNode = BaseNode<Hash>;\n\nexport type DataNode = BaseNode<FrozenJSONValue>;\n\nexport function makeNodeChunkData<V>(\n level: number,\n entries: ReadonlyArray<Entry<V>>,\n formatVersion: FormatVersion.Type,\n): BaseNode<V> {\n return deepFreeze([\n level,\n (formatVersion >= FormatVersion.V7\n ? entries\n : entries.map(e => e.slice(0, 2))) as readonly ReadonlyJSONValue[],\n ]) as BaseNode<V>;\n}\n\nexport type Node = DataNode | InternalNode;\n\n/**\n * Describes the changes that happened to Replicache after a\n * {@link WriteTransaction} was committed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type Diff = IndexDiff | NoIndexDiff;\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type IndexDiff = readonly DiffOperation<IndexKey>[];\n\n/**\n * @experimental This type is experimental and may change in the future.\n */\nexport type NoIndexDiff = readonly DiffOperation<string>[];\n\n/**\n * InternalDiff uses string keys even for the secondary index maps.\n */\nexport type InternalDiff = readonly InternalDiffOperation[];\n\nexport type DiffOperationAdd<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'add';\n readonly key: Key;\n readonly newValue: Value;\n};\n\nexport type DiffOperationDel<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'del';\n readonly key: Key;\n readonly oldValue: Value;\n};\n\nexport type DiffOperationChange<Key, Value = ReadonlyJSONValue> = {\n readonly op: 'change';\n readonly key: Key;\n readonly oldValue: Value;\n readonly newValue: Value;\n};\n\n/**\n * The individual parts describing the changes that happened to the Replicache\n * data. There are three different kinds of operations:\n * - `add`: A new entry was added.\n * - `del`: An entry was deleted.\n * - `change`: An entry was changed.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type DiffOperation<Key> =\n | DiffOperationAdd<Key>\n | DiffOperationDel<Key>\n | DiffOperationChange<Key>;\n\n// Duplicated with DiffOperation to make the docs less confusing.\nexport type InternalDiffOperation<Key = string, Value = FrozenJSONValue> =\n | DiffOperationAdd<Key, Value>\n | DiffOperationDel<Key, Value>\n | DiffOperationChange<Key, Value>;\n\n/**\n * Finds the leaf where a key is (if present) or where it should go if not\n * present.\n */\nexport async function findLeaf(\n key: string,\n hash: Hash,\n source: BTreeRead,\n expectedRootHash: Hash,\n): Promise<DataNodeImpl> {\n const node = await source.getNode(hash);\n // The root changed. Try again\n if (expectedRootHash !== source.rootHash) {\n return findLeaf(key, source.rootHash, source, source.rootHash);\n }\n if (isDataNodeImpl(node)) {\n return node;\n }\n const {entries} = node;\n let i = binarySearch(key, entries);\n if (i === entries.length) {\n i--;\n }\n const entry = entries[i];\n return findLeaf(key, entry[1], source, expectedRootHash);\n}\n\ntype BinarySearchEntries = readonly Entry<unknown>[];\n\n/**\n * Does a binary search over entries\n *\n * If the key found then the return value is the index it was found at.\n *\n * If the key was *not* found then the return value is the index where it should\n * be inserted at\n */\nexport function binarySearch(\n key: string,\n entries: BinarySearchEntries,\n): number {\n return binarySearchWithFunc(entries.length, i =>\n compareUTF8(key, entries[i][0]),\n );\n}\n\nexport function binarySearchFound(\n i: number,\n entries: BinarySearchEntries,\n key: string,\n): boolean {\n return i !== entries.length && entries[i][0] === key;\n}\n\nexport function parseBTreeNode(\n v: unknown,\n formatVersion: FormatVersion.Type,\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): InternalNode | DataNode {\n if (skipBTreeNodeAsserts && formatVersion >= FormatVersion.V7) {\n return v as InternalNode | DataNode;\n }\n\n assertArray(v);\n assertDeepFrozen(v);\n // Be relaxed about what we accept.\n assert(v.length >= 2);\n const [level, entries] = v;\n assertNumber(level);\n assertArray(entries);\n\n const f = level > 0 ? assertString : assertJSONValue;\n\n // For V7 we do not need to change the entries. Just assert that they are correct.\n if (formatVersion >= FormatVersion.V7) {\n for (const e of entries) {\n assertEntry(e, f);\n }\n return v as unknown as InternalNode | DataNode;\n }\n\n const newEntries = entries.map(e => convertNonV7Entry(e, f, getSizeOfEntry));\n return [level, newEntries] as unknown as InternalNode | DataNode;\n}\n\nfunction assertEntry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n): asserts entry is Entry<Hash | JSONValue> {\n assertArray(entry);\n // Be relaxed about what we accept.\n assert(entry.length >= 3);\n assertString(entry[0]);\n f(entry[1]);\n assertNumber(entry[2]);\n}\n\n/**\n * Converts an entry that was from a format version before V7 to the format\n * wanted by V7.\n */\nfunction convertNonV7Entry(\n entry: unknown,\n f:\n | ((v: unknown) => asserts v is Hash)\n | ((v: unknown) => asserts v is JSONValue),\n getSizeOfEntry: <K, V>(key: K, value: V) => number,\n): Entry<Hash | JSONValue> {\n assertArray(entry);\n assert(entry.length >= 2);\n assertString(entry[0]);\n f(entry[1]);\n const entrySize = getSizeOfEntry(entry[0], entry[1]);\n return [entry[0], entry[1], entrySize] as Entry<Hash | JSONValue>;\n}\n\nexport function isInternalNode(node: Node): node is InternalNode {\n return node[NODE_LEVEL] > 0;\n}\n\nabstract class NodeImpl<Value> {\n entries: Array<Entry<Value>>;\n hash: Hash;\n abstract readonly level: number;\n readonly isMutable: boolean;\n\n #childNodeSize = -1;\n\n constructor(entries: Array<Entry<Value>>, hash: Hash, isMutable: boolean) {\n this.entries = entries;\n this.hash = hash;\n this.isMutable = isMutable;\n }\n\n abstract set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value>>;\n\n abstract del(\n key: string,\n tree: BTreeWrite,\n ): Promise<NodeImpl<Value> | DataNodeImpl>;\n\n maxKey(): string {\n return this.entries[this.entries.length - 1][0];\n }\n\n getChildNodeSize(tree: BTreeRead): number {\n if (this.#childNodeSize !== -1) {\n return this.#childNodeSize;\n }\n\n let sum = tree.chunkHeaderSize;\n for (const entry of this.entries) {\n sum += entry[2];\n }\n return (this.#childNodeSize = sum);\n }\n\n protected _updateNode(tree: BTreeWrite) {\n this.#childNodeSize = -1;\n tree.updateNode(\n this as NodeImpl<unknown> as DataNodeImpl | InternalNodeImpl,\n );\n }\n}\n\nexport function toChunkData<V>(\n node: NodeImpl<V>,\n formatVersion: FormatVersion.Type,\n): BaseNode<V> {\n return makeNodeChunkData(node.level, node.entries, formatVersion);\n}\n\nexport class DataNodeImpl extends NodeImpl<FrozenJSONValue> {\n readonly level = 0;\n\n set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<DataNodeImpl> {\n let deleteCount: number;\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found, insert.\n deleteCount = 0;\n } else {\n deleteCount = 1;\n }\n\n return Promise.resolve(\n this.#splice(tree, i, deleteCount, [key, value, entrySize]),\n );\n }\n\n #splice(\n tree: BTreeWrite,\n start: number,\n deleteCount: number,\n ...items: Entry<FrozenJSONValue>[]\n ): DataNodeImpl {\n if (this.isMutable) {\n this.entries.splice(start, deleteCount, ...items);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(this.entries, start, deleteCount, ...items);\n return tree.newDataNodeImpl(entries);\n }\n\n del(key: string, tree: BTreeWrite): Promise<DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (!binarySearchFound(i, this.entries, key)) {\n // Not found. Return this without changes.\n return Promise.resolve(this);\n }\n\n // Found. Create new node or mutate existing one.\n return Promise.resolve(this.#splice(tree, i, 1));\n }\n\n async *keys(_tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n yield entry[0];\n }\n }\n\n async *entriesIter(\n _tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n yield entry;\n }\n }\n}\n\nfunction readonlySplice<T>(\n array: ReadonlyArray<T>,\n start: number,\n deleteCount: number,\n ...items: T[]\n): T[] {\n const arr = array.slice(0, start);\n for (let i = 0; i < items.length; i++) {\n arr.push(items[i]);\n }\n for (let i = start + deleteCount; i < array.length; i++) {\n arr.push(array[i]);\n }\n return arr;\n}\n\nexport class InternalNodeImpl extends NodeImpl<Hash> {\n readonly level: number;\n\n constructor(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n ) {\n super(entries, hash, isMutable);\n this.level = level;\n }\n\n async set(\n key: string,\n value: FrozenJSONValue,\n entrySize: number,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl> {\n let i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // We are going to insert into last (right most) leaf.\n i--;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n\n const childNode = await oldChildNode.set(key, value, entrySize, tree);\n\n const childNodeSize = childNode.getChildNodeSize(tree);\n if (childNodeSize > tree.maxSize || childNodeSize < tree.minSize) {\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n const newEntry = createNewInternalEntryForNode(\n childNode,\n tree.getEntrySize,\n );\n return this.#replaceChild(tree, i, newEntry);\n }\n\n /**\n * This merges the child node entries with previous or next sibling and then\n * partitions the merged entries.\n */\n async #mergeAndPartition(\n tree: BTreeWrite,\n i: number,\n childNode: DataNodeImpl | InternalNodeImpl,\n ): Promise<InternalNodeImpl> {\n const level = this.level - 1;\n const thisEntries = this.entries;\n\n type IterableHashEntries = Iterable<Entry<Hash>>;\n\n let values: IterableHashEntries;\n let startIndex: number;\n let removeCount: number;\n if (i > 0) {\n const hash = thisEntries[i - 1][1];\n const previousSibling = await tree.getNode(hash);\n values = joinIterables(\n previousSibling.entries as IterableHashEntries,\n childNode.entries as IterableHashEntries,\n );\n startIndex = i - 1;\n removeCount = 2;\n } else if (i < thisEntries.length - 1) {\n const hash = thisEntries[i + 1][1];\n const nextSibling = await tree.getNode(hash);\n values = joinIterables(\n childNode.entries as IterableHashEntries,\n nextSibling.entries as IterableHashEntries,\n );\n startIndex = i;\n removeCount = 2;\n } else {\n values = childNode.entries as IterableHashEntries;\n startIndex = i;\n removeCount = 1;\n }\n\n const partitions = partition(\n values,\n value => value[2],\n tree.minSize - tree.chunkHeaderSize,\n tree.maxSize - tree.chunkHeaderSize,\n );\n\n // TODO: There are cases where we can reuse the old nodes. Creating new ones\n // means more memory churn but also more writes to the underlying KV store.\n const newEntries: Entry<Hash>[] = [];\n for (const entries of partitions) {\n const node = tree.newNodeImpl(entries, level);\n const newHashEntry = createNewInternalEntryForNode(\n node,\n tree.getEntrySize,\n );\n newEntries.push(newHashEntry);\n }\n\n if (this.isMutable) {\n this.entries.splice(startIndex, removeCount, ...newEntries);\n this._updateNode(tree);\n return this;\n }\n\n const entries = readonlySplice(\n thisEntries,\n startIndex,\n removeCount,\n ...newEntries,\n );\n\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n #replaceChild(\n tree: BTreeWrite,\n index: number,\n newEntry: Entry<Hash>,\n ): InternalNodeImpl {\n if (this.isMutable) {\n this.entries.splice(index, 1, newEntry);\n this._updateNode(tree);\n return this;\n }\n const entries = readonlySplice(this.entries, index, 1, newEntry);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n async del(\n key: string,\n tree: BTreeWrite,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const i = binarySearch(key, this.entries);\n if (i === this.entries.length) {\n // Key is larger than maxKey of rightmost entry so it is not present.\n return this;\n }\n\n const childHash = this.entries[i][1];\n const oldChildNode = await tree.getNode(childHash);\n const oldHash = oldChildNode.hash;\n\n const childNode = await oldChildNode.del(key, tree);\n if (childNode.hash === oldHash) {\n // Not changed so not found.\n return this;\n }\n\n if (childNode.entries.length === 0) {\n // Subtree is now empty. Remove internal node.\n const entries = readonlySplice(this.entries, i, 1);\n return tree.newInternalNodeImpl(entries, this.level);\n }\n\n if (i === 0 && this.entries.length === 1) {\n // There was only one node at this level and it was removed. We can return\n // the modified subtree.\n return childNode;\n }\n\n // The child node is still a good size.\n if (childNode.getChildNodeSize(tree) > tree.minSize) {\n // No merging needed.\n const entry = createNewInternalEntryForNode(childNode, tree.getEntrySize);\n return this.#replaceChild(tree, i, entry);\n }\n\n // Child node size is too small.\n return this.#mergeAndPartition(tree, i, childNode);\n }\n\n async *keys(tree: BTreeRead): AsyncGenerator<string, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.keys(tree);\n }\n }\n\n async *entriesIter(\n tree: BTreeRead,\n ): AsyncGenerator<Entry<FrozenJSONValue>, void> {\n for (const entry of this.entries) {\n const childNode = await tree.getNode(entry[1]);\n yield* childNode.entriesIter(tree);\n }\n }\n\n getChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<Array<InternalNodeImpl | DataNodeImpl>> {\n const ps: Promise<DataNodeImpl | InternalNodeImpl>[] = [];\n for (let i = start; i < length && i < this.entries.length; i++) {\n ps.push(tree.getNode(this.entries[i][1]));\n }\n return Promise.all(ps);\n }\n\n async getCompositeChildren(\n start: number,\n length: number,\n tree: BTreeRead,\n ): Promise<InternalNodeImpl | DataNodeImpl> {\n const {level} = this;\n\n if (length === 0) {\n return new InternalNodeImpl([], newRandomHash(), level - 1, true);\n }\n\n const output = await this.getChildren(start, start + length, tree);\n\n if (level > 1) {\n const entries: Entry<Hash>[] = [];\n for (const child of output as InternalNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new InternalNodeImpl(entries, newRandomHash(), level - 1, true);\n }\n\n assert(level === 1);\n const entries: Entry<FrozenJSONValue>[] = [];\n for (const child of output as DataNodeImpl[]) {\n entries.push(...child.entries);\n }\n return new DataNodeImpl(entries, newRandomHash(), true);\n }\n}\n\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl;\nexport function newNodeImpl(\n entries: Array<Entry<FrozenJSONValue>> | Array<Entry<Hash>>,\n hash: Hash,\n level: number,\n isMutable: boolean,\n): DataNodeImpl | InternalNodeImpl {\n if (level === 0) {\n return new DataNodeImpl(\n entries as Entry<FrozenJSONValue>[],\n hash,\n isMutable,\n );\n }\n return new InternalNodeImpl(entries as Entry<Hash>[], hash, level, isMutable);\n}\n\nexport function isDataNodeImpl(\n node: DataNodeImpl | InternalNodeImpl,\n): node is DataNodeImpl {\n return node.level === 0;\n}\n\nexport function partition<T>(\n values: Iterable<T>,\n // This is the size of each Entry\n getSizeOfEntry: (v: T) => number,\n min: number,\n max: number,\n): T[][] {\n const partitions: T[][] = [];\n const sizes: number[] = [];\n let sum = 0;\n let accum: T[] = [];\n for (const value of values) {\n const size = getSizeOfEntry(value);\n if (size >= max) {\n if (accum.length > 0) {\n partitions.push(accum);\n sizes.push(sum);\n }\n partitions.push([value]);\n sizes.push(size);\n sum = 0;\n accum = [];\n } else if (sum + size >= min) {\n accum.push(value);\n partitions.push(accum);\n sizes.push(sum + size);\n sum = 0;\n accum = [];\n } else {\n sum += size;\n accum.push(value);\n }\n }\n\n if (sum > 0) {\n if (sizes.length > 0 && sum + sizes[sizes.length - 1] <= max) {\n partitions[partitions.length - 1].push(...accum);\n } else {\n partitions.push(accum);\n }\n }\n\n return partitions;\n}\n\nexport const emptyDataNode = makeNodeChunkData<ReadonlyJSONValue>(\n 0,\n [],\n FormatVersion.Latest,\n);\nexport const emptyDataNodeImpl = new DataNodeImpl([], emptyHash, false);\n\nexport function createNewInternalEntryForNode(\n node: NodeImpl<unknown>,\n getSizeOfEntry: <K, V>(k: K, v: V) => number,\n): [string, Hash, number] {\n const key = node.maxKey();\n const value = node.hash;\n const size = getSizeOfEntry(key, value);\n return [key, value, size];\n}\n", "/**\n * This is a binary search that returns the index of the first element in the\n * array that is greater than or equal to the given value.\n *\n * Typical usage:\n *\n * ```\n * const haystack = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];\n * const needle = 3;\n * const index = binarySearch(haystack.length, i => needle - haystack[i]);\n * const found = index < haystack.length && haystack[index] === needle;\n * ```\n */\nexport function binarySearch(high: number, compare: (i: number) => number) {\n let low = 0;\n while (low < high) {\n const mid = low + ((high - low) >> 1);\n const i = compare(mid);\n if (i === 0) {\n return mid;\n }\n if (i > 0) {\n low = mid + 1;\n } else {\n high = mid;\n }\n }\n return low;\n}\n", "import {deepEqual, type ReadonlyJSONValue} from '../../../shared/src/json.js';\n\nexport type Splice = [at: number, removed: number, added: number, from: number];\n\nconst SPLICE_UNASSIGNED = -1;\nexport const SPLICE_AT = 0;\nexport const SPLICE_REMOVED = 1;\nexport const SPLICE_ADDED = 2;\nexport const SPLICE_FROM = 3;\n\nconst KEY = 0;\nconst VALUE = 1;\n\ntype Entry<V> = readonly [key: string, value: V, ...rest: unknown[]];\n\nexport function* computeSplices<T>(\n previous: readonly Entry<T>[],\n current: readonly Entry<T>[],\n): Generator<Splice, void> {\n let previousIndex = 0;\n let currentIndex = 0;\n let splice: Splice | undefined;\n\n function ensureAssigned(splice: Splice, index: number): void {\n if (splice[SPLICE_FROM] === SPLICE_UNASSIGNED) {\n splice[SPLICE_FROM] = index;\n }\n }\n\n function newSplice(): Splice {\n return [previousIndex, 0, 0, SPLICE_UNASSIGNED];\n }\n\n while (previousIndex < previous.length && currentIndex < current.length) {\n if (previous[previousIndex][KEY] === current[currentIndex][KEY]) {\n if (\n deepEqual(\n // These are really Hash | InternalValue\n previous[previousIndex][VALUE] as ReadonlyJSONValue,\n current[currentIndex][VALUE] as ReadonlyJSONValue,\n )\n ) {\n if (splice) {\n ensureAssigned(splice, 0);\n yield splice;\n splice = undefined;\n }\n } else {\n if (!splice) {\n splice = newSplice();\n }\n splice[SPLICE_ADDED]++;\n splice[SPLICE_REMOVED]++;\n ensureAssigned(splice, currentIndex);\n }\n previousIndex++;\n currentIndex++;\n } else if (previous[previousIndex][KEY] < current[currentIndex][KEY]) {\n // previous was removed\n if (!splice) {\n splice = newSplice();\n }\n splice[SPLICE_REMOVED]++;\n\n previousIndex++;\n } else {\n // current was added\n if (!splice) {\n splice = newSplice();\n }\n splice[SPLICE_ADDED]++;\n ensureAssigned(splice, currentIndex);\n\n currentIndex++;\n }\n }\n\n if (currentIndex < current.length) {\n if (!splice) {\n splice = newSplice();\n }\n splice[SPLICE_ADDED] += current.length - currentIndex;\n ensureAssigned(splice, currentIndex);\n }\n\n if (previousIndex < previous.length) {\n if (!splice) {\n splice = newSplice();\n }\n splice[SPLICE_REMOVED] += previous.length - previousIndex;\n }\n\n if (splice) {\n ensureAssigned(splice, 0);\n yield splice;\n }\n}\n", "import {deepEqual} from '../../../shared/src/json.js';\nimport type {Read} from '../dag/store.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {type Hash, emptyHash} from '../hash.js';\nimport {getSizeOfEntry} from '../size-of-value.js';\nimport {\n DataNodeImpl,\n type Entry,\n type InternalDiff,\n type InternalDiffOperation,\n InternalNodeImpl,\n NODE_ENTRIES,\n NODE_LEVEL,\n binarySearch,\n binarySearchFound,\n emptyDataNodeImpl,\n findLeaf,\n isDataNodeImpl,\n newNodeImpl,\n parseBTreeNode,\n} from './node.js';\nimport {\n SPLICE_ADDED,\n SPLICE_AT,\n SPLICE_FROM,\n SPLICE_REMOVED,\n computeSplices,\n} from './splice.js';\n\n/**\n * The size of the header of a node. (If we had compile time\n * constants we would have used that).\n *\n * There is a test ensuring this is correct.\n */\nexport const NODE_HEADER_SIZE = 11;\n\nexport class BTreeRead implements AsyncIterable<Entry<FrozenJSONValue>> {\n protected readonly _cache: Map<Hash, DataNodeImpl | InternalNodeImpl> =\n new Map();\n\n protected readonly _dagRead: Read;\n protected readonly _formatVersion: FormatVersion;\n rootHash: Hash;\n readonly getEntrySize: <K, V>(k: K, v: V) => number;\n readonly chunkHeaderSize: number;\n\n constructor(\n dagRead: Read,\n formatVersion: FormatVersion,\n root: Hash = emptyHash,\n getEntrySize: <K, V>(k: K, v: V) => number = getSizeOfEntry,\n chunkHeaderSize = NODE_HEADER_SIZE,\n ) {\n this._dagRead = dagRead;\n this._formatVersion = formatVersion;\n this.rootHash = root;\n this.getEntrySize = getEntrySize;\n this.chunkHeaderSize = chunkHeaderSize;\n }\n\n async getNode(hash: Hash): Promise<DataNodeImpl | InternalNodeImpl> {\n if (hash === emptyHash) {\n return emptyDataNodeImpl;\n }\n\n const cached = this._cache.get(hash);\n if (cached) {\n return cached;\n }\n\n const chunk = await this._dagRead.mustGetChunk(hash);\n const data = parseBTreeNode(\n chunk.data,\n this._formatVersion,\n this.getEntrySize,\n );\n const impl = newNodeImpl(\n data[NODE_ENTRIES] as Entry<FrozenJSONValue>[],\n hash,\n data[NODE_LEVEL],\n false,\n );\n this._cache.set(hash, impl);\n return impl;\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n if (!binarySearchFound(index, leaf.entries, key)) {\n return undefined;\n }\n return leaf.entries[index][1];\n }\n\n async has(key: string): Promise<boolean> {\n const leaf = await findLeaf(key, this.rootHash, this, this.rootHash);\n const index = binarySearch(key, leaf.entries);\n return binarySearchFound(index, leaf.entries, key);\n }\n\n async isEmpty(): Promise<boolean> {\n const {rootHash} = this;\n const node = await this.getNode(this.rootHash);\n // The root hash has changed, so the tree has been modified.\n if (this.rootHash !== rootHash) {\n return this.isEmpty();\n }\n return node.entries.length === 0;\n }\n\n // We don't do any encoding of the key in the map, so we have no way of\n // determining from an entry.key alone whether it is a regular key or an\n // encoded IndexKey in an index map. Without encoding regular map keys the\n // caller has to deal with encoding and decoding the keys for the index map.\n scan(fromKey: string): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return scanForHash(\n this.rootHash,\n () => this.rootHash,\n this.rootHash,\n fromKey,\n async hash => {\n const cached = await this.getNode(hash);\n if (cached) {\n return [\n cached.level,\n cached.isMutable ? cached.entries.slice() : cached.entries,\n ];\n }\n const chunk = await this._dagRead.mustGetChunk(hash);\n return parseBTreeNode(\n chunk.data,\n this._formatVersion,\n this.getEntrySize,\n );\n },\n );\n }\n\n async *keys(): AsyncIterableIterator<string> {\n const node = await this.getNode(this.rootHash);\n yield* node.keys(this);\n }\n\n async *entries(): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n const node = await this.getNode(this.rootHash);\n yield* node.entriesIter(this);\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n return this.entries();\n }\n\n async *diff(last: BTreeRead): AsyncIterableIterator<InternalDiffOperation> {\n const [currentNode, lastNode] = await Promise.all([\n this.getNode(this.rootHash),\n last.getNode(last.rootHash),\n ]);\n yield* diffNodes(lastNode, currentNode, last, this);\n }\n}\n\nasync function* diffNodes(\n last: InternalNodeImpl | DataNodeImpl,\n current: InternalNodeImpl | DataNodeImpl,\n lastTree: BTreeRead,\n currentTree: BTreeRead,\n): AsyncIterableIterator<InternalDiffOperation> {\n if (last.level > current.level) {\n // merge all of last's children into a new node\n // We know last is an internal node because level > 0.\n const lastChild = (await (last as InternalNodeImpl).getCompositeChildren(\n 0,\n last.entries.length,\n lastTree,\n )) as InternalNodeImpl;\n yield* diffNodes(lastChild, current, lastTree, currentTree);\n return;\n }\n\n if (current.level > last.level) {\n // We know current is an internal node because level > 0.\n const currentChild = (await (\n current as InternalNodeImpl\n ).getCompositeChildren(\n 0,\n current.entries.length,\n currentTree,\n )) as InternalNodeImpl;\n yield* diffNodes(last, currentChild, lastTree, currentTree);\n return;\n }\n\n if (isDataNodeImpl(last) && isDataNodeImpl(current)) {\n yield* diffEntries(\n (last as DataNodeImpl).entries,\n (current as DataNodeImpl).entries,\n );\n return;\n }\n\n // Now we have two internal nodes with the same level. We compute the diff as\n // splices for the internal node entries. We then flatten these and call diff\n // recursively.\n const initialSplices = computeSplices(\n (last as InternalNodeImpl).entries,\n (current as InternalNodeImpl).entries,\n );\n for (const splice of initialSplices) {\n const [lastChild, currentChild] = await Promise.all([\n (last as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_AT],\n splice[SPLICE_REMOVED],\n lastTree,\n ),\n (current as InternalNodeImpl).getCompositeChildren(\n splice[SPLICE_FROM],\n splice[SPLICE_ADDED],\n currentTree,\n ),\n ]);\n yield* diffNodes(lastChild, currentChild, lastTree, currentTree);\n }\n}\n\nfunction* diffEntries(\n lastEntries: readonly Entry<FrozenJSONValue>[],\n currentEntries: readonly Entry<FrozenJSONValue>[],\n): IterableIterator<InternalDiffOperation> {\n const lastLength = lastEntries.length;\n const currentLength = currentEntries.length;\n let i = 0;\n let j = 0;\n while (i < lastLength && j < currentLength) {\n const lastKey = lastEntries[i][0];\n const currentKey = currentEntries[j][0];\n if (lastKey === currentKey) {\n if (!deepEqual(lastEntries[i][1], currentEntries[j][1])) {\n yield {\n op: 'change',\n key: lastKey,\n oldValue: lastEntries[i][1],\n newValue: currentEntries[j][1],\n };\n }\n i++;\n j++;\n } else if (lastKey < currentKey) {\n yield {\n op: 'del',\n key: lastKey,\n oldValue: lastEntries[i][1],\n };\n i++;\n } else {\n yield {\n op: 'add',\n key: currentKey,\n newValue: currentEntries[j][1],\n };\n j++;\n }\n }\n for (; i < lastLength; i++) {\n yield {\n op: 'del',\n key: lastEntries[i][0],\n oldValue: lastEntries[i][1],\n };\n }\n for (; j < currentLength; j++) {\n yield {\n op: 'add',\n key: currentEntries[j][0],\n newValue: currentEntries[j][1],\n };\n }\n}\n\n// Redefine the type here to allow the optional size in the tuple.\ntype ReadNodeResult = readonly [\n level: number,\n data: readonly Entry<FrozenJSONValue>[] | readonly Entry<Hash>[],\n];\n\ntype ReadNode = (hash: Hash) => Promise<ReadNodeResult>;\n\nasync function* scanForHash(\n expectedRootHash: Hash,\n getRootHash: () => Hash,\n hash: Hash,\n fromKey: string,\n readNode: ReadNode,\n): AsyncIterableIterator<Entry<FrozenJSONValue>> {\n if (hash === emptyHash) {\n return;\n }\n\n const data = await readNode(hash);\n const entries = data[NODE_ENTRIES];\n let i = 0;\n if (fromKey) {\n i = binarySearch(fromKey, entries);\n }\n if (data[NODE_LEVEL] > 0) {\n for (; i < entries.length; i++) {\n yield* scanForHash(\n expectedRootHash,\n getRootHash,\n (entries[i] as Entry<Hash>)[1],\n fromKey,\n readNode,\n );\n fromKey = '';\n }\n } else {\n for (; i < entries.length; i++) {\n const rootHash = getRootHash();\n // If rootHash changed then we start a new iterator from the key.\n if (expectedRootHash !== rootHash) {\n yield* scanForHash(\n rootHash,\n getRootHash,\n rootHash,\n entries[i][0],\n readNode,\n );\n return;\n }\n yield entries[i] as Entry<FrozenJSONValue>;\n }\n }\n}\n\nexport async function allEntriesAsDiff(\n map: BTreeRead,\n op: 'add' | 'del',\n): Promise<InternalDiff> {\n const diff: InternalDiffOperation[] = [];\n const make: (entry: Entry<FrozenJSONValue>) => InternalDiffOperation =\n op === 'add'\n ? entry => ({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n })\n : entry => ({\n op: 'del',\n key: entry[0],\n oldValue: entry[1],\n });\n\n for await (const entry of map.entries()) {\n diff.push(make(entry));\n }\n return diff;\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const Add = 0;\nexport const Remove = 1;\n\nexport type Add = typeof Add;\nexport type Remove = typeof Remove;\n\nexport type Type = Add | Remove;\n", "import type {LogContext} from '@rocicorp/logger';\nimport type {BTreeRead} from '../btree/read.js';\nimport type {BTreeWrite} from '../btree/write.js';\nimport type {FrozenJSONObject, FrozenJSONValue} from '../frozen-json.js';\nimport type {Hash} from '../hash.js';\nimport type {IndexRecord} from './commit.js';\nimport * as IndexOperation from './index-operation-enum.js';\n\nexport class IndexRead<BTree = BTreeRead> {\n readonly meta: IndexRecord;\n readonly map: BTree;\n\n constructor(meta: IndexRecord, map: BTree) {\n this.meta = meta;\n this.map = map;\n }\n}\n\nexport class IndexWrite extends IndexRead<BTreeWrite> {\n // Note: does not update self.meta.valueHash (doesn't need to at this point as flush\n // is only called during commit.)\n flush(): Promise<Hash> {\n return this.map.flush();\n }\n\n clear(): Promise<void> {\n return this.map.clear();\n }\n}\n\n// Index or de-index a single primary entry.\nexport async function indexValue(\n lc: LogContext,\n index: BTreeWrite,\n op: IndexOperation.Type,\n key: string,\n val: FrozenJSONValue,\n jsonPointer: string,\n allowEmpty: boolean,\n): Promise<void> {\n try {\n for (const entry of getIndexKeys(key, val, jsonPointer, allowEmpty)) {\n switch (op) {\n case IndexOperation.Add:\n await index.put(entry, val);\n break;\n case IndexOperation.Remove:\n await index.del(entry);\n break;\n }\n }\n } catch (e) {\n // Right now all the errors that index_value() returns are customers dev\n // problems: either the value is not json, the pointer is into nowhere, etc.\n // So we ignore them.\n lc.info?.('Not indexing value', val, ':', e);\n }\n}\n\n// Gets the set of index keys for a given primary key and value.\nexport function getIndexKeys(\n primary: string,\n value: FrozenJSONValue,\n jsonPointer: string,\n allowEmpty: boolean,\n): string[] {\n const target = evaluateJSONPointer(value, jsonPointer);\n if (target === undefined) {\n if (allowEmpty) {\n return [];\n }\n throw new Error(`No value at path: ${jsonPointer}`);\n }\n\n const values = Array.isArray(target) ? target : [target];\n\n const indexKeys: string[] = [];\n for (const value of values) {\n if (typeof value === 'string') {\n indexKeys.push(encodeIndexKey([value, primary]));\n } else {\n throw new Error('Unsupported target type');\n }\n }\n\n return indexKeys;\n}\n\nexport const KEY_VERSION_0 = '\\u0000';\nexport const KEY_SEPARATOR = '\\u0000';\n\n/**\n * When using indexes the key is a tuple of the secondary key and the primary\n * key.\n */\nexport type IndexKey = readonly [secondary: string, primary: string];\n\n// An index key is encoded to vec of bytes in the following order:\n// - key version byte(s), followed by\n// - the secondary key bytes (which for now is a UTF8 encoded string), followed by\n// - the key separator, a null byte, followed by\n// - the primary key bytes\n//\n// The null separator byte ensures that if a secondary key A is longer than B then\n// A always sorts after B. Appending the primary key ensures index keys with\n// identical secondary keys sort in primary key order. Secondary keys must not\n// contain a zero (null) byte.\nexport function encodeIndexKey(indexKey: IndexKey): string {\n const secondary = indexKey[0];\n const primary = indexKey[1];\n\n if (secondary.includes('\\u0000')) {\n throw new Error('Secondary key cannot contain null byte');\n }\n return KEY_VERSION_0 + secondary + KEY_SEPARATOR + primary;\n}\n\n// Returns bytes that can be used to scan for the given secondary index value.\n//\n// Consider a scan for start_secondary_key=\"a\" (97). We want to scan with scan\n// key [0, 97]. We could also scan with [0, 97, 0], but then we couldn't use\n// this function for prefix scans, so we lop off the null byte. If we want\n// the scan to be exclusive, we scan with the next greater value, [0, 97, 1]\n// (we disallow zero bytes in secondary keys).\n//\n// Now it gets a little tricky. We also want to be able to scan using the\n// primary key, start_key. When we do this we have to encode the scan key\n// a little differently We essentially have to fix the value of the\n// secondary key so we can vary the start_key. That is, the match on\n// start_secondary_key becomes an exact match.\n//\n// Consider the scan for start_secondary_key=\"a\" and start_key=[2]. We want\n// to scan with [0, 97, 0, 2]. If we want exclusive we want to scan with\n// the next highest value, [0, 97, 0, 2, 0] (zero bytes are allowed in primary\n// keys). So far so good. It is important to notice that we need to\n// be able to distinguish between not wanting use start_key and wanting to\n// use start_key=[]. In the former case we want to scan with the secondary\n// key value, possibly followed by a 1 with no trailing zero byte ([0, 97]\n// or [0, 97, 1]). In the latter case we want to scan by the secondary\n// key value, followed by the zero byte, followed by the primary key value\n// and another zero if it is exclusive ([0, 97, 0] or [0, 97, 0, 0]).\n// This explains why we need the Option around start_key.\nexport function encodeIndexScanKey(\n secondary: string,\n primary: string | undefined,\n): string {\n const k = encodeIndexKey([secondary, primary || '']);\n if (primary === undefined) {\n return k.slice(0, k.length - 1);\n }\n return k;\n}\n\n// Decodes an IndexKey encoded by encode_index_key.\nexport function decodeIndexKey(encodedIndexKey: string): IndexKey {\n if (encodedIndexKey[0] !== KEY_VERSION_0) {\n throw new Error('Invalid version');\n }\n\n const versionLen = KEY_VERSION_0.length;\n const separatorLen = KEY_SEPARATOR.length;\n const separatorOffset = encodedIndexKey.indexOf(KEY_SEPARATOR, versionLen);\n if (separatorOffset === -1) {\n throw new Error('Invalid formatting');\n }\n\n const secondary = encodedIndexKey.slice(versionLen, separatorOffset);\n const primary = encodedIndexKey.slice(separatorOffset + separatorLen);\n return [secondary, primary];\n}\n\nexport function evaluateJSONPointer(\n value: FrozenJSONValue,\n pointer: string,\n): FrozenJSONValue | undefined {\n function parseIndex(s: string): number | undefined {\n if (s.startsWith('+') || (s.startsWith('0') && s.length !== 1)) {\n return undefined;\n }\n return parseInt(s, 10);\n }\n\n if (pointer === '') {\n return value;\n }\n if (!pointer.startsWith('/')) {\n throw new Error(`Invalid JSON pointer: ${pointer}`);\n }\n\n const tokens = pointer\n .split('/')\n .slice(1)\n .map(x => x.replace(/~1/g, '/').replace(/~0/g, '~'));\n\n let target = value;\n for (const token of tokens) {\n let targetOpt;\n if (Array.isArray(target)) {\n const i = parseIndex(token);\n if (i === undefined) {\n return undefined;\n }\n targetOpt = target[i];\n } else if (target === null) {\n return undefined;\n } else if (typeof target === 'object') {\n target = target as FrozenJSONObject;\n targetOpt = target[token];\n }\n if (targetOpt === undefined) {\n return undefined;\n }\n target = targetOpt;\n }\n return target;\n}\n", "import {BTreeRead} from '../btree/read.js';\nimport type {Read as DagRead} from '../dag/store.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport type {Hash} from '../hash.js';\nimport {\n Commit,\n DEFAULT_HEAD_NAME,\n type Meta,\n commitFromHash,\n commitFromHead,\n} from './commit.js';\nimport {IndexRead} from './index.js';\n\nexport class Read {\n readonly #dagRead: DagRead;\n map: BTreeRead;\n readonly indexes: Map<string, IndexRead>;\n\n constructor(\n dagRead: DagRead,\n map: BTreeRead,\n indexes: Map<string, IndexRead>,\n ) {\n this.#dagRead = dagRead;\n this.map = map;\n this.indexes = indexes;\n }\n\n has(key: string): Promise<boolean> {\n return this.map.has(key);\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return this.map.get(key);\n }\n\n isEmpty(): Promise<boolean> {\n return this.map.isEmpty();\n }\n\n getMapForIndex(indexName: string): BTreeRead {\n const idx = this.indexes.get(indexName);\n if (idx === undefined) {\n throw new Error(`Unknown index name: ${indexName}`);\n }\n return idx.map;\n }\n\n get closed(): boolean {\n return this.#dagRead.closed;\n }\n\n close(): void {\n this.#dagRead.release();\n }\n}\n\nexport function readFromDefaultHead(\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n return readFromHead(DEFAULT_HEAD_NAME, dagRead, formatVersion);\n}\n\nexport async function readFromHead(\n name: string,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHead(name, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nexport async function readFromHash(\n hash: Hash,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Promise<Read> {\n const commit = await commitFromHash(hash, dagRead);\n return readFromCommit(commit, dagRead, formatVersion);\n}\n\nfunction readFromCommit(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Read {\n const indexes = readIndexesForRead(commit, dagRead, formatVersion);\n const map = new BTreeRead(dagRead, formatVersion, commit.valueHash);\n return new Read(dagRead, map, indexes);\n}\n\nexport function readIndexesForRead(\n commit: Commit<Meta>,\n dagRead: DagRead,\n formatVersion: FormatVersion,\n): Map<string, IndexRead> {\n const m = new Map();\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexRead(\n index,\n new BTreeRead(dagRead, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {greaterThan} from 'compare-utf8';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.js';\nimport {type IndexKey, decodeIndexKey} from './db/index.js';\nimport type {Read} from './db/read.js';\nimport type {Write} from './db/write.js';\nimport {deepFreeze} from './frozen-json.js';\nimport type {IndexDefinition} from './index-defs.js';\nimport type {ScanResult} from './scan-iterator.js';\nimport {ScanResultImpl, fromKeyForIndexScanInternal} from './scan-iterator.js';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanNoIndexOptions,\n type ScanOptions,\n isScanIndexOptions,\n toDbScanOptions,\n} from './scan-options.js';\nimport type {ScanSubscriptionInfo} from './subscriptions.js';\nimport type {ClientID} from './sync/ids.js';\nimport {rejectIfClosed, throwIfClosed} from './transaction-closed-error.js';\n\nexport type TransactionEnvironment = 'client' | 'server';\nexport type TransactionLocation = TransactionEnvironment;\nexport type TransactionReason = 'initial' | 'rebase' | 'authoritative';\n\n/**\n * Basic deep readonly type. It works for {@link JSONValue}.\n */\nexport type DeepReadonly<T> = T extends\n | null\n | boolean\n | string\n | number\n | undefined\n ? T\n : DeepReadonlyObject<T>;\n\nexport type DeepReadonlyObject<T> = {\n readonly [K in keyof T]: DeepReadonly<T[K]>;\n};\n\n/**\n * ReadTransactions are used with {@link Replicache.query} and\n * {@link Replicache.subscribe} and allows read operations on the\n * database.\n */\nexport interface ReadTransaction {\n readonly clientID: ClientID;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n readonly location: TransactionLocation;\n\n /**\n * Get a single value from the database. If the `key` is not present this\n * returns `undefined`.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined>;\n\n /** Determines if a single `key` is present in the database. */\n has(key: string): Promise<boolean>;\n\n /** Whether the database is empty. */\n isEmpty(): Promise<boolean>;\n\n /**\n * Gets many values from the database. This returns a {@link ScanResult} which\n * implements `AsyncIterable`. It also has methods to iterate over the\n * {@link ScanResult.keys | keys} and {@link ScanResult.entries | entries}.\n *\n * If `options` has an `indexName`, then this does a scan over an index with\n * that name. A scan over an index uses a tuple for the key consisting of\n * `[secondary: string, primary: string]`.\n *\n * If the {@link ScanResult} is used after the `ReadTransaction` has been closed\n * it will throw a {@link TransactionClosedError}.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n}\n\nlet transactionIDCounter = 0;\n\nexport class ReadTransactionImpl implements ReadTransaction {\n readonly clientID: ClientID;\n readonly dbtx: Read;\n protected readonly _lc: LogContext;\n\n /**\n * The location in which this transaction is being used. This is either `client` or `server`.\n */\n readonly location: TransactionLocation;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n\n constructor(\n clientID: ClientID,\n dbRead: Read,\n lc: LogContext,\n rpcName = 'openReadTransaction',\n ) {\n this.clientID = clientID;\n this.dbtx = dbRead;\n this._lc = lc\n .withContext(rpcName)\n .withContext('txid', transactionIDCounter++);\n this.environment = 'client';\n this.location = 'client';\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<V extends JSONValue>(key: string): Promise<DeepReadonly<V> | undefined> {\n return (\n rejectIfClosed(this.dbtx) ||\n (this.dbtx.get(key) as Promise<DeepReadonly<V> | undefined>)\n );\n }\n\n // eslint-disable-next-line require-await\n async has(key: string): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.has(key);\n }\n\n // eslint-disable-next-line require-await\n async isEmpty(): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.isEmpty();\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n return scan(options, this.dbtx, noop);\n }\n}\n\nfunction noop(_: unknown): void {\n // empty\n}\n\nfunction scan<Options extends ScanOptions, V extends JSONValue>(\n options: Options | undefined,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n const iter = getScanIterator<Options, V>(dbRead, options);\n return makeScanResultFromScanIteratorInternal(\n iter,\n options ?? ({} as Options),\n dbRead,\n onLimitKey,\n );\n}\n\n// An implementation of ReadTransaction that keeps track of `keys` and `scans`\n// for use with Subscriptions.\nexport class SubscriptionTransactionWrapper implements ReadTransaction {\n readonly #keys: Set<string> = new Set();\n readonly #scans: ScanSubscriptionInfo[] = [];\n readonly #tx: ReadTransactionImpl;\n\n constructor(tx: ReadTransactionImpl) {\n this.#tx = tx;\n }\n\n get environment(): TransactionLocation {\n return this.#tx.location;\n }\n\n get location(): TransactionLocation {\n return this.#tx.location;\n }\n\n get clientID(): string {\n return this.#tx.clientID;\n }\n\n isEmpty(): Promise<boolean> {\n // Any change to the subscription requires rerunning it.\n this.#scans.push({options: {}});\n return this.#tx.isEmpty();\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined> {\n this.#keys.add(key);\n return this.#tx.get(key) as Promise<DeepReadonly<T> | undefined>;\n }\n\n has(key: string): Promise<boolean> {\n this.#keys.add(key);\n return this.#tx.has(key);\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n const scanInfo: ScanSubscriptionInfo = {\n options: toDbScanOptions(options),\n inclusiveLimitKey: undefined,\n };\n this.#scans.push(scanInfo);\n return scan(options, this.#tx.dbtx, inclusiveLimitKey => {\n scanInfo.inclusiveLimitKey = inclusiveLimitKey;\n });\n }\n\n get keys(): ReadonlySet<string> {\n return this.#keys;\n }\n\n get scans(): ScanSubscriptionInfo[] {\n return this.#scans;\n }\n}\n\n/**\n * WriteTransactions are used with *mutators* which are registered using\n * {@link ReplicacheOptions.mutators} and allows read and write operations on the\n * database.\n */\nexport interface WriteTransaction extends ReadTransaction {\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction. This can be `initial`, `rebase` or `authoriative`.\n */\n readonly reason: TransactionReason;\n\n /**\n * Sets a single `value` in the database. The value will be frozen (using\n * `Object.freeze`) in debug mode.\n */\n set(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * @deprecated Use {@link WriteTransaction.set} instead.\n */\n put(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * Removes a `key` and its value from the database. Returns `true` if there was a\n * `key` to remove.\n */\n del(key: string): Promise<boolean>;\n}\n\nexport class WriteTransactionImpl\n extends ReadTransactionImpl\n implements WriteTransaction\n{\n // use `declare` to specialize the type.\n declare readonly dbtx: Write;\n readonly reason: TransactionReason;\n readonly mutationID: number;\n\n constructor(\n clientID: ClientID,\n mutationID: number,\n reason: TransactionReason,\n dbWrite: Write,\n lc: LogContext,\n rpcName = 'openWriteTransaction',\n ) {\n super(clientID, dbWrite, lc, rpcName);\n this.mutationID = mutationID;\n this.reason = reason;\n }\n\n put(key: string, value: ReadonlyJSONValue): Promise<void> {\n return this.set(key, value);\n }\n\n async set(key: string, value: ReadonlyJSONValue): Promise<void> {\n throwIfClosed(this.dbtx);\n await this.dbtx.put(this._lc, key, deepFreeze(value));\n }\n\n del(key: string): Promise<boolean> {\n return rejectIfClosed(this.dbtx) ?? this.dbtx.del(this._lc, key);\n }\n}\n\nexport type CreateIndexDefinition = IndexDefinition & {name: string};\n\ntype Entry<Key, Value> = readonly [key: Key, value: Value];\n\ntype IndexKeyEntry<Value> = Entry<IndexKey, Value>;\n\ntype StringKeyEntry<Value> = Entry<string, Value>;\n\nexport type EntryForOptions<\n Options extends ScanOptions,\n V,\n> = Options extends ScanIndexOptions ? IndexKeyEntry<V> : StringKeyEntry<V>;\n\nfunction getScanIterator<Options extends ScanOptions, V>(\n dbRead: Read,\n options: Options | undefined,\n): AsyncIterable<EntryForOptions<Options, V>> {\n if (options && isScanIndexOptions(options)) {\n return getScanIteratorForIndexMap(dbRead, options) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n }\n\n return dbRead.map.scan(fromKeyForNonIndexScan(options)) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n}\n\nexport function fromKeyForNonIndexScan(\n options: ScanNoIndexOptions | undefined,\n): string {\n if (!options) {\n return '';\n }\n\n const {prefix = '', start} = options;\n if (start && greaterThan(start.key, prefix)) {\n return start.key;\n }\n return prefix;\n}\n\nfunction makeScanResultFromScanIteratorInternal<\n Options extends ScanOptions,\n V extends JSONValue,\n>(\n iter: AsyncIterable<EntryForOptions<Options, V>>,\n options: Options,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n return new ScanResultImpl(iter, options, dbRead, onLimitKey);\n}\n\nasync function* getScanIteratorForIndexMap(\n dbRead: Read,\n options: ScanIndexOptions,\n): AsyncIterable<IndexKeyEntry<ReadonlyJSONValue>> {\n const map = dbRead.getMapForIndex(options.indexName);\n for await (const entry of map.scan(fromKeyForIndexScanInternal(options))) {\n yield [decodeIndexKey(entry[0]), entry[1]];\n }\n}\n", "import {greaterThan} from 'compare-utf8';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.js';\nimport {asyncIterableToArray} from './async-iterable-to-array.js';\nimport {type IndexKey, encodeIndexScanKey} from './db/index.js';\nimport type {IterableUnion} from './iterable-union.js';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanOptionIndexedStartKey,\n type ScanOptions,\n isScanIndexOptions,\n normalizeScanOptionIndexedStartKey,\n} from './scan-options.js';\nimport {type Closed, throwIfClosed} from './transaction-closed-error.js';\nimport {type EntryForOptions, fromKeyForNonIndexScan} from './transactions.js';\n\ntype ScanKey = string | IndexKey;\n\ntype ToValue<Options extends ScanOptions, Value> = (\n entry: EntryForOptions<Options, ReadonlyJSONValue>,\n) => Value;\n\n/**\n * This class is used for the results of {@link ReadTransaction.scan | scan}. It\n * implements `AsyncIterable<JSONValue>` which allows you to use it in a `for\n * await` loop. There are also methods to iterate over the {@link keys},\n * {@link entries} or {@link values}.\n */\nexport class ScanResultImpl<Options extends ScanOptions, V>\n implements ScanResult<KeyTypeForScanOptions<Options>, V>\n{\n readonly #iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>;\n readonly #options: Options;\n readonly #dbDelegateOptions: Closed;\n readonly #onLimitKey: (inclusiveLimitKey: string) => void;\n\n constructor(\n iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>,\n options: Options,\n dbDelegateOptions: Closed,\n onLimitKey: (inclusiveLimitKey: string) => void,\n ) {\n this.#iter = iter;\n this.#options = options;\n this.#dbDelegateOptions = dbDelegateOptions;\n this.#onLimitKey = onLimitKey;\n }\n\n /** The default AsyncIterable. This is the same as {@link values}. */\n [Symbol.asyncIterator](): AsyncIterableIteratorToArray<V> {\n return this.values();\n }\n\n /** Async iterator over the values of the {@link ReadTransaction.scan | scan} call. */\n values(): AsyncIterableIteratorToArray<V> {\n return new AsyncIterableIteratorToArrayWrapperImpl(\n this.#newIterator(e => e[1] as V),\n );\n }\n\n /**\n * Async iterator over the keys of the {@link ReadTransaction.scan | scan}\n * call. If the {@link ReadTransaction.scan | scan} is over an index the key\n * is a tuple of `[secondaryKey: string, primaryKey]`\n */\n keys(): AsyncIterableIteratorToArray<KeyTypeForScanOptions<Options>> {\n type K = KeyTypeForScanOptions<Options>;\n return new AsyncIterableIteratorToArrayWrapperImpl<K>(\n this.#newIterator<K>(e => e[0] as K),\n );\n }\n\n /**\n * Async iterator over the entries of the {@link ReadTransaction.scan | scan}\n * call. An entry is a tuple of key values. If the\n * {@link ReadTransaction.scan | scan} is over an index the key is a tuple of\n * `[secondaryKey: string, primaryKey]`\n */\n entries(): AsyncIterableIteratorToArray<\n readonly [KeyTypeForScanOptions<Options>, V]\n > {\n type Key = KeyTypeForScanOptions<Options>;\n type Entry = readonly [Key, V];\n return new AsyncIterableIteratorToArrayWrapperImpl(\n this.#newIterator<Entry>(e => [e[0] as Key, e[1] as V]),\n );\n }\n\n /** Returns all the values as an array. Same as `values().toArray()` */\n toArray(): Promise<V[]> {\n return this.values().toArray();\n }\n\n #newIterator<T>(toValue: ToValue<Options, T>): AsyncIterableIterator<T> {\n return scanIterator(\n toValue,\n this.#iter,\n this.#options,\n this.#dbDelegateOptions,\n this.#onLimitKey,\n );\n }\n}\n\nexport interface ScanResult<K extends ScanKey, V> extends AsyncIterable<V> {\n /** The default AsyncIterable. This is the same as {@link values}. */\n [Symbol.asyncIterator](): AsyncIterableIteratorToArray<V>;\n\n /** Async iterator over the values of the {@link ReadTransaction.scan | scan} call. */\n values(): AsyncIterableIteratorToArray<V>;\n\n /**\n * Async iterator over the keys of the {@link ReadTransaction.scan | scan}\n * call. If the {@link ReadTransaction.scan | scan} is over an index the key\n * is a tuple of `[secondaryKey: string, primaryKey]`\n */\n keys(): AsyncIterableIteratorToArray<K>;\n\n /**\n * Async iterator over the entries of the {@link ReadTransaction.scan | scan}\n * call. An entry is a tuple of key values. If the\n * {@link ReadTransaction.scan | scan} is over an index the key is a tuple of\n * `[secondaryKey: string, primaryKey]`\n */\n entries(): AsyncIterableIteratorToArray<readonly [K, V]>;\n\n /** Returns all the values as an array. Same as `values().toArray()` */\n toArray(): Promise<V[]>;\n}\n\n/**\n * An interface that adds a {@link toArray} method to `AsyncIterableIterator`.\n *\n * Usage:\n *\n * ```ts\n * const keys: string[] = await rep.scan().keys().toArray();\n * ```\n */\nexport interface AsyncIterableIteratorToArray<V>\n extends AsyncIterableIterator<V> {\n toArray(): Promise<V[]>;\n}\n\nclass AsyncIterableIteratorToArrayWrapperImpl<V>\n implements AsyncIterableIterator<V>\n{\n readonly #it: AsyncIterableIterator<V>;\n\n constructor(it: AsyncIterableIterator<V>) {\n this.#it = it;\n }\n\n next() {\n return this.#it.next();\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<V> {\n return this.#it[Symbol.asyncIterator]();\n }\n\n toArray(): Promise<V[]> {\n return asyncIterableToArray(this.#it);\n }\n}\n\nasync function* scanIterator<Options extends ScanOptions, Value>(\n toValue: ToValue<Options, Value>,\n iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>,\n options: Options,\n closed: Closed,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): AsyncIterableIterator<Value> {\n throwIfClosed(closed);\n\n let {limit = Infinity} = options;\n const {prefix = ''} = options;\n let exclusive = options.start?.exclusive;\n\n const isIndexScan = isScanIndexOptions(options);\n\n // iter has already been moved to the first entry\n for await (const entry of iter) {\n const key = entry[0];\n const keyToMatch: string = isIndexScan ? key[0] : (key as string);\n if (!keyToMatch.startsWith(prefix)) {\n return;\n }\n\n if (exclusive) {\n exclusive = true;\n if (isIndexScan) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (shouldSkipIndexScan(key as IndexKey, options.start!.key)) {\n continue;\n }\n } else {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (shouldSkipNonIndexScan(key as string, options.start!.key)) {\n continue;\n }\n }\n }\n\n yield toValue(entry);\n\n if (--limit === 0) {\n // We do not do the limit optimization for index scans in subscriptions.\n if (!isIndexScan) {\n onLimitKey(key as string);\n }\n return;\n }\n }\n}\n\nfunction shouldSkipIndexScan(\n key: IndexKey,\n startKey: ScanOptionIndexedStartKey,\n): boolean {\n const [secondaryStartKey, primaryStartKey] =\n normalizeScanOptionIndexedStartKey(startKey);\n const [secondaryKey, primaryKey] = normalizeScanOptionIndexedStartKey(key);\n if (secondaryKey !== secondaryStartKey) {\n return false;\n }\n if (primaryStartKey === undefined) {\n return true;\n }\n return primaryKey === primaryStartKey;\n}\n\nfunction shouldSkipNonIndexScan(key: string, startKey: string): boolean {\n return key === startKey;\n}\n\nexport type Entry<V> = readonly [key: string, value: V];\n\n/**\n * This is called when doing a {@link ReadTransaction.scan | scan} without an\n * `indexName`.\n *\n * @param fromKey The `fromKey` is computed by `scan` and is the key of the\n * first entry to return in the iterator. It is based on `prefix` and\n * `start.key` of the {@link ScanNoIndexOptions}.\n */\nexport type GetScanIterator = (\n fromKey: string,\n) => IterableUnion<Entry<ReadonlyJSONValue>>;\n\n/**\n * When using {@link makeScanResult} this is the type used for the function called when doing a {@link ReadTransaction.scan | scan} with an\n * `indexName`.\n *\n * @param indexName The name of the index we are scanning over.\n * @param fromSecondaryKey The `fromSecondaryKey` is computed by `scan` and is\n * the secondary key of the first entry to return in the iterator. It is based\n * on `prefix` and `start.key` of the {@link ScanIndexOptions}.\n * @param fromPrimaryKey The `fromPrimaryKey` is computed by `scan` and is the\n * primary key of the first entry to return in the iterator. It is based on\n * `prefix` and `start.key` of the {@link ScanIndexOptions}.\n */\nexport type GetIndexScanIterator = (\n indexName: string,\n fromSecondaryKey: string,\n fromPrimaryKey: string | undefined,\n) => IterableUnion<readonly [key: IndexKey, value: ReadonlyJSONValue]>;\n\n/**\n * A helper function that makes it easier to implement {@link ReadTransaction.scan}\n * with a custom backend.\n *\n * If you are implementing a custom backend and have an in memory pending async\n * iterable we provide two helper functions to make it easier to merge these\n * together. {@link mergeAsyncIterables} and {@link filterAsyncIterable}.\n *\n * For example:\n *\n * ```ts\n * const scanResult = makeScanResult(\n * options,\n * options.indexName\n * ? () => {\n * throw Error('not implemented');\n * }\n * : fromKey => {\n * const persisted: AsyncIterable<Entry<ReadonlyJSONValue>> = ...;\n * const pending: AsyncIterable<Entry<ReadonlyJSONValue | undefined>> = ...;\n * const iter = await mergeAsyncIterables(persisted, pending);\n * const filteredIter = await filterAsyncIterable(\n * iter,\n * entry => entry[1] !== undefined,\n * );\n * return filteredIter;\n * },\n * );\n * ```\n */\nexport function makeScanResult<Options extends ScanOptions>(\n options: Options,\n getScanIterator: Options extends ScanIndexOptions\n ? GetIndexScanIterator\n : GetScanIterator,\n): ScanResult<KeyTypeForScanOptions<Options>, ReadonlyJSONValue> {\n type AsyncIter = AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>;\n\n if (isScanIndexOptions(options)) {\n const [fromSecondaryKey, fromPrimaryKey] = fromKeyForIndexScan(options);\n return new ScanResultImpl(\n (getScanIterator as GetIndexScanIterator)(\n options.indexName,\n fromSecondaryKey,\n fromPrimaryKey,\n ) as AsyncIter,\n options,\n {closed: false},\n _ => {\n // noop\n },\n );\n }\n const fromKey = fromKeyForNonIndexScan(options);\n return new ScanResultImpl(\n (getScanIterator as GetScanIterator)(fromKey) as AsyncIter,\n options,\n {closed: false},\n _ => {\n // noop\n },\n );\n}\n\nexport function fromKeyForIndexScan(\n options: ScanIndexOptions,\n): readonly [secondary: string, primary?: string | undefined] {\n const {prefix, start} = options;\n const prefixNormalized: [secondary: string, primary?: string | undefined] = [\n prefix ?? '',\n undefined,\n ];\n\n if (!start) {\n return prefixNormalized;\n }\n\n const startKeyNormalized = normalizeScanOptionIndexedStartKey(start.key);\n if (greaterThan(startKeyNormalized[0], prefixNormalized[0])) {\n return startKeyNormalized;\n }\n if (\n startKeyNormalized[0] === prefixNormalized[0] &&\n startKeyNormalized[1] !== undefined\n ) {\n return startKeyNormalized;\n }\n\n return prefixNormalized;\n}\n\nexport function fromKeyForIndexScanInternal(options: ScanIndexOptions): string {\n const {prefix, start} = options;\n let prefix2 = '';\n if (prefix !== undefined) {\n prefix2 = encodeIndexScanKey(prefix, undefined);\n }\n if (!start) {\n return prefix2;\n }\n\n const {key} = start;\n const [secondary, primary] = normalizeScanOptionIndexedStartKey(key);\n const startKey = encodeIndexScanKey(secondary, primary);\n\n if (greaterThan(startKey, prefix2)) {\n return startKey;\n }\n\n return prefix2;\n}\n", "export async function asyncIterableToArray<T>(\n it: AsyncIterable<T>,\n): Promise<T[]> {\n const arr: T[] = [];\n for await (const v of it) {\n arr.push(v);\n }\n return arr;\n}\n", "import type {IndexKey} from './db/index.js';\nimport type {ScanOptions as DbScanOptions} from './db/scan.js';\n\n/**\n * Options for {@link ReadTransaction.scan | scan}\n */\nexport type ScanOptions = ScanIndexOptions | ScanNoIndexOptions;\n\n/**\n * Options for {@link ReadTransaction.scan | scan} when scanning over the entire key\n * space.\n */\nexport type ScanNoIndexOptions = {\n /** Only include keys starting with `prefix`. */\n prefix?: string | undefined;\n\n /** Only include up to `limit` results. */\n limit?: number | undefined;\n\n /** When provided the scan starts at this key. */\n start?:\n | {\n key: string;\n\n /** Whether the `key` is exclusive or inclusive. */\n exclusive?: boolean | undefined;\n }\n | undefined;\n};\n\n/**\n * Options for {@link ReadTransaction.scan | scan} when scanning over an index. When\n * scanning over and index you need to provide the `indexName` and the `start`\n * `key` is now a tuple consisting of secondary and primary key\n */\nexport type ScanIndexOptions = {\n /** Only include results starting with the *secondary* keys starting with `prefix`. */\n prefix?: string | undefined;\n\n /** Only include up to `limit` results. */\n limit?: number | undefined;\n\n /** Do a {@link ReadTransaction.scan | scan} over a named index. The `indexName` is\n * the name of an index defined when creating the {@link Replicache} instance using\n * {@link ReplicacheOptions.indexes}. */\n indexName: string;\n\n /** When provided the scan starts at this key. */\n start?:\n | {\n key: ScanOptionIndexedStartKey;\n\n /** Whether the `key` is exclusive or inclusive. */\n exclusive?: boolean | undefined;\n }\n | undefined;\n};\n\n/**\n * Type narrowing of {@link ScanOptions}.\n */\nexport function isScanIndexOptions(\n options: ScanOptions,\n): options is ScanIndexOptions {\n return (options as ScanIndexOptions).indexName !== undefined;\n}\n\n/**\n * If the options contains an `indexName` then the key type is a tuple of\n * secondary and primary.\n */\nexport type KeyTypeForScanOptions<O extends ScanOptions> =\n O extends ScanIndexOptions ? IndexKey : string;\n\n/**\n * The key to start scanning at.\n *\n * If you are scanning the primary index (i.e., you did not specify\n * `indexName`), then pass a single string for this field, which is the key in\n * the primary index to scan at.\n *\n * If you are scanning a secondary index (i.e., you specified `indexName`), then\n * use the tuple form. In that case, `secondary` is the secondary key to start\n * scanning at, and `primary` (if any) is the primary key to start scanning at.\n */\nexport type ScanOptionIndexedStartKey =\n | readonly [secondary: string, primary?: string | undefined]\n | string;\n\nexport function normalizeScanOptionIndexedStartKey(\n startKey: string | readonly [secondary: string, primary?: string | undefined],\n): readonly [secondary: string, primary?: string | undefined] {\n if (typeof startKey === 'string') {\n return [startKey];\n }\n return startKey;\n}\n\nexport function toDbScanOptions(options?: ScanOptions): DbScanOptions {\n if (!options) {\n return {};\n }\n let key: string | ScanOptionIndexedStartKey | undefined;\n let exclusive: boolean | undefined;\n let primary: string | undefined;\n let secondary: string | undefined;\n type MaybeIndexName = {indexName?: string};\n if (options.start) {\n ({key, exclusive} = options.start);\n if ((options as MaybeIndexName).indexName) {\n if (typeof key === 'string') {\n secondary = key;\n } else {\n secondary = key[0];\n primary = key[1];\n }\n } else {\n primary = key as string;\n }\n }\n\n return {\n prefix: options.prefix,\n startSecondaryKey: secondary,\n startKey: primary,\n startExclusive: exclusive,\n limit: options.limit,\n indexName: (options as MaybeIndexName).indexName,\n };\n}\n", "import {asyncIterableToArray} from '../async-iterable-to-array.js';\nimport type {InternalDiff} from './node.js';\nimport type {BTreeRead} from './read.js';\n\nexport function diff(\n oldMap: BTreeRead,\n newMap: BTreeRead,\n): Promise<InternalDiff> {\n // Return an array to ensure we do not compute the diff more than once.\n return asyncIterableToArray(newMap.diff(oldMap));\n}\n", "import {Lock} from '@rocicorp/lock';\nimport {assert} from '../../../shared/src/asserts.js';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.js';\nimport {type Chunk, type CreateChunk, toRefs} from '../dag/chunk.js';\nimport type {Write} from '../dag/store.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {type Hash, emptyHash, newRandomHash} from '../hash.js';\nimport {getSizeOfEntry} from '../size-of-value.js';\nimport {\n DataNodeImpl,\n type Entry,\n InternalNodeImpl,\n createNewInternalEntryForNode,\n emptyDataNode,\n isDataNodeImpl,\n newNodeImpl,\n partition,\n toChunkData,\n} from './node.js';\nimport {BTreeRead} from './read.js';\n\nexport class BTreeWrite extends BTreeRead {\n /**\n * This rw lock is used to ensure we do not mutate the btree in parallel. It\n * would be a problem if we didn't have the lock in cases like this:\n *\n * ```ts\n * const p1 = tree.put('a', 0);\n * const p2 = tree.put('b', 1);\n * await p1;\n * await p2;\n * ```\n *\n * because both `p1` and `p2` would start from the old root hash but a put\n * changes the root hash so the two concurrent puts would lead to only one of\n * them actually working, and it is not deterministic which one would finish\n * last.\n */\n readonly #lock = new Lock();\n readonly #modified: Map<Hash, DataNodeImpl | InternalNodeImpl> = new Map();\n\n protected declare _dagRead: Write;\n\n readonly minSize: number;\n readonly maxSize: number;\n\n constructor(\n dagWrite: Write,\n formatVersion: FormatVersion,\n root: Hash = emptyHash,\n minSize = 8 * 1024,\n maxSize = 16 * 1024,\n getEntrySize: <K, V>(k: K, v: V) => number = getSizeOfEntry,\n chunkHeaderSize?: number,\n ) {\n super(dagWrite, formatVersion, root, getEntrySize, chunkHeaderSize);\n\n this.minSize = minSize;\n this.maxSize = maxSize;\n }\n\n #addToModified(node: DataNodeImpl | InternalNodeImpl): void {\n assert(node.isMutable);\n this.#modified.set(node.hash, node);\n this._cache.set(node.hash, node);\n }\n\n updateNode(node: DataNodeImpl | InternalNodeImpl): void {\n assert(node.isMutable);\n this.#modified.delete(node.hash);\n node.hash = newRandomHash();\n this.#addToModified(node);\n }\n\n newInternalNodeImpl(\n entries: Array<Entry<Hash>>,\n level: number,\n ): InternalNodeImpl {\n const n = new InternalNodeImpl(entries, newRandomHash(), level, true);\n this.#addToModified(n);\n return n;\n }\n\n newDataNodeImpl(entries: Entry<FrozenJSONValue>[]): DataNodeImpl {\n const n = new DataNodeImpl(entries, newRandomHash(), true);\n this.#addToModified(n);\n return n;\n }\n\n newNodeImpl(entries: Entry<FrozenJSONValue>[], level: number): DataNodeImpl;\n newNodeImpl(entries: Entry<Hash>[], level: number): InternalNodeImpl;\n newNodeImpl(\n entries: Entry<Hash>[] | Entry<FrozenJSONValue>[],\n level: number,\n ): InternalNodeImpl | DataNodeImpl;\n newNodeImpl(\n entries: Entry<Hash>[] | Entry<FrozenJSONValue>[],\n level: number,\n ): InternalNodeImpl | DataNodeImpl {\n const n = newNodeImpl(entries, newRandomHash(), level, true);\n this.#addToModified(n);\n return n;\n }\n\n put(key: string, value: FrozenJSONValue): Promise<void> {\n return this.#lock.withLock(async () => {\n const oldRootNode = await this.getNode(this.rootHash);\n const entrySize = this.getEntrySize(key, value);\n const rootNode = await oldRootNode.set(key, value, entrySize, this);\n\n // We do the rebalancing in the parent so we need to do it here as well.\n if (rootNode.getChildNodeSize(this) > this.maxSize) {\n const headerSize = this.chunkHeaderSize;\n const partitions = partition(\n rootNode.entries,\n value => value[2],\n this.minSize - headerSize,\n this.maxSize - headerSize,\n );\n const {level} = rootNode;\n const entries: Entry<Hash>[] = partitions.map(entries => {\n const node = this.newNodeImpl(entries, level);\n return createNewInternalEntryForNode(node, this.getEntrySize);\n });\n const newRoot = this.newInternalNodeImpl(entries, level + 1);\n this.rootHash = newRoot.hash;\n return;\n }\n\n this.rootHash = rootNode.hash;\n });\n }\n\n del(key: string): Promise<boolean> {\n return this.#lock.withLock(async () => {\n const oldRootNode = await this.getNode(this.rootHash);\n const newRootNode = await oldRootNode.del(key, this);\n\n // No need to rebalance here since if root gets too small there is nothing\n // we can do about that.\n const found = this.rootHash !== newRootNode.hash;\n if (found) {\n // Flatten one layer.\n if (newRootNode.level > 0 && newRootNode.entries.length === 1) {\n this.rootHash = (newRootNode as InternalNodeImpl).entries[0][1];\n } else {\n this.rootHash = newRootNode.hash;\n }\n }\n\n return found;\n });\n }\n\n clear(): Promise<void> {\n return this.#lock.withLock(() => {\n this.#modified.clear();\n this.rootHash = emptyHash;\n });\n }\n\n flush(): Promise<Hash> {\n return this.#lock.withLock(async () => {\n const dagWrite = this._dagRead;\n\n if (this.rootHash === emptyHash) {\n // Write a chunk for the empty tree.\n const chunk = dagWrite.createChunk(emptyDataNode, []);\n await dagWrite.putChunk(chunk as Chunk<ReadonlyJSONValue>);\n return chunk.hash;\n }\n\n const newChunks: Chunk[] = [];\n const newRoot = gatherNewChunks(\n this.rootHash,\n newChunks,\n dagWrite.createChunk,\n this.#modified,\n this._formatVersion,\n );\n await Promise.all(newChunks.map(chunk => dagWrite.putChunk(chunk)));\n this.#modified.clear();\n this.rootHash = newRoot;\n return newRoot;\n });\n }\n}\n\nfunction gatherNewChunks(\n hash: Hash,\n newChunks: Chunk[],\n createChunk: CreateChunk,\n modified: Map<Hash, DataNodeImpl | InternalNodeImpl>,\n formatVersion: FormatVersion,\n): Hash {\n const node = modified.get(hash);\n if (node === undefined) {\n // Not modified, use the original.\n return hash;\n }\n\n if (isDataNodeImpl(node)) {\n const chunk = createChunk(toChunkData(node, formatVersion), []);\n newChunks.push(chunk);\n return chunk.hash;\n }\n\n // The BTree cannot have duplicate keys so the child entry hashes are unique.\n // No need fot a set to dedupe here.\n const refs: Hash[] = [];\n const {entries} = node;\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i];\n const childHash = entry[1];\n const newChildHash = gatherNewChunks(\n childHash,\n newChunks,\n createChunk,\n modified,\n formatVersion,\n );\n if (newChildHash !== childHash) {\n // MUTATES the entries!\n // Hashes do not change the size of the entry because all hashes have the same length\n entries[i] = [entry[0], newChildHash, entry[2]];\n }\n refs.push(newChildHash);\n }\n const chunk = createChunk(toChunkData(node, formatVersion), toRefs(refs));\n newChunks.push(chunk);\n return chunk.hash;\n}\n", "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", "import {assert} from '../../../shared/src/asserts.js';\nimport {diff as btreeDiff} from '../btree/diff.js';\nimport type {InternalDiff} from '../btree/node.js';\nimport {allEntriesAsDiff, BTreeRead} from '../btree/read.js';\nimport type {Read} from '../dag/store.js';\nimport {Commit, commitFromHash, type Meta} from '../db/commit.js';\nimport {readIndexesForRead} from '../db/read.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {Hash} from '../hash.js';\n\n/**\n * Interface allowing different diff functions to skip costly diff computations.\n */\nexport interface DiffComputationConfig {\n shouldComputeDiffs(): boolean;\n shouldComputeDiffsForIndex(name: string): boolean;\n}\n\n/**\n * The diffs in different indexes. The key of the map is the index name.\n * \"\" is used for the primary index.\n */\nexport class DiffsMap extends Map<string, InternalDiff> {\n override set(key: string, value: InternalDiff): this {\n if (value.length === 0) {\n return this;\n }\n return super.set(key, value);\n }\n}\n\n/**\n * Diffs the state of the db at two different hashes.\n * It will include the primary indexes as well as all the secondary indexes.\n */\nexport async function diff(\n oldHash: Hash,\n newHash: Hash,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const [oldCommit, newCommit] = await Promise.all([\n commitFromHash(oldHash, read),\n commitFromHash(newHash, read),\n ]);\n\n return diffCommits(oldCommit, newCommit, read, diffConfig, formatVersion);\n}\n\n/**\n * Diffs the state of the db at two different commits.\n * It will include the primary indexes as well as all the secondary indexes.\n */\n// TODO: this should probably move to db/\nexport async function diffCommits(\n oldCommit: Commit<Meta>,\n newCommit: Commit<Meta>,\n read: Read,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n const oldMap = new BTreeRead(read, formatVersion, oldCommit.valueHash);\n const newMap = new BTreeRead(read, formatVersion, newCommit.valueHash);\n const valueDiff = await btreeDiff(oldMap, newMap);\n diffsMap.set('', valueDiff);\n\n await addDiffsForIndexes(\n oldCommit,\n newCommit,\n read,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n\n return diffsMap;\n}\n\nexport async function addDiffsForIndexes(\n mainCommit: Commit<Meta>,\n syncCommit: Commit<Meta>,\n read: Read,\n diffsMap: DiffsMap,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n) {\n const oldIndexes = readIndexesForRead(mainCommit, read, formatVersion);\n const newIndexes = readIndexesForRead(syncCommit, read, formatVersion);\n\n for (const [oldIndexName, oldIndex] of oldIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(oldIndexName)) {\n continue;\n }\n\n const newIndex = newIndexes.get(oldIndexName);\n if (newIndex !== undefined) {\n assert(newIndex !== oldIndex);\n const diffs = await btreeDiff(oldIndex.map, newIndex.map);\n newIndexes.delete(oldIndexName);\n diffsMap.set(oldIndexName, diffs);\n } else {\n // old index name is not in the new indexes. All entries removed!\n const diffs = await allEntriesAsDiff(oldIndex.map, 'del');\n diffsMap.set(oldIndexName, diffs);\n }\n }\n\n for (const [newIndexName, newIndex] of newIndexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(newIndexName)) {\n continue;\n }\n // new index name is not in the old indexes. All keys added!\n const diffs = await allEntriesAsDiff(newIndex.map, 'add');\n diffsMap.set(newIndexName, diffs);\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport {diff} from '../btree/diff.js';\nimport type {InternalDiff} from '../btree/node.js';\nimport {BTreeRead, allEntriesAsDiff} from '../btree/read.js';\nimport {BTreeWrite} from '../btree/write.js';\nimport type {FrozenCookie} from '../cookies.js';\nimport type {Write as DagWrite} from '../dag/store.js';\nimport * as FormatVersion from '../format-version-enum.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {type Hash, emptyHash} from '../hash.js';\nimport {lazy} from '../lazy.js';\nimport type {DiffComputationConfig} from '../sync/diff.js';\nimport {DiffsMap} from '../sync/diff.js';\nimport type {ClientID} from '../sync/ids.js';\nimport {\n Commit,\n type Meta as CommitMeta,\n type IndexRecord,\n type Meta,\n baseSnapshotHashFromHash,\n commitFromHash,\n newIndexChange as commitNewIndexChange,\n newLocalDD31 as commitNewLocalDD31,\n newLocalSDD as commitNewLocalSDD,\n newSnapshotDD31 as commitNewSnapshotDD31,\n newSnapshotSDD as commitNewSnapshotSDD,\n getMutationID,\n} from './commit.js';\nimport * as IndexOperation from './index-operation-enum.js';\nimport {IndexRead, IndexWrite, indexValue} from './index.js';\nimport * as MetaType from './meta-type-enum.js';\nimport {Read, readIndexesForRead} from './read.js';\n\nexport class Write extends Read {\n readonly #dagWrite: DagWrite;\n readonly #basis: Commit<CommitMeta> | undefined;\n readonly #meta: CommitMeta;\n\n declare map: BTreeWrite;\n\n declare readonly indexes: Map<string, IndexWrite>;\n readonly #clientID: ClientID;\n readonly #formatVersion: FormatVersion.Type;\n\n constructor(\n dagWrite: DagWrite,\n map: BTreeWrite,\n basis: Commit<CommitMeta> | undefined,\n meta: CommitMeta,\n indexes: Map<string, IndexWrite>,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n ) {\n // TypeScript has trouble\n super(dagWrite, map, indexes);\n this.#dagWrite = dagWrite;\n this.#basis = basis;\n this.#meta = meta;\n this.#clientID = clientID;\n this.#formatVersion = formatVersion;\n\n // TODO(arv): if (DEBUG) { ...\n if (basis === undefined) {\n assert(meta.basisHash === emptyHash);\n } else {\n assert(meta.basisHash === basis.chunk.hash);\n }\n }\n\n /**\n * The value needs to be frozen since it is kept in memory and used later for\n * comparison as well as returned in `get`.\n */\n async put(\n lc: LogContext,\n key: string,\n value: FrozenJSONValue,\n ): Promise<void> {\n if (this.#meta.type === MetaType.IndexChangeSDD) {\n throw new Error('Not allowed');\n }\n const oldVal = lazy(() => this.map.get(key));\n await updateIndexes(lc, this.indexes, key, oldVal, value);\n\n await this.map.put(key, value);\n }\n\n getMutationID(): Promise<number> {\n return getMutationID(this.#clientID, this.#dagWrite, this.#meta);\n }\n\n async del(lc: LogContext, key: string): Promise<boolean> {\n if (this.#meta.type === MetaType.IndexChangeSDD) {\n throw new Error('Not allowed');\n }\n\n // TODO(arv): This does the binary search twice. We can do better.\n const oldVal = lazy(() => this.map.get(key));\n if (oldVal !== undefined) {\n await updateIndexes(lc, this.indexes, key, oldVal, undefined);\n }\n return this.map.del(key);\n }\n\n async clear(): Promise<void> {\n if (this.#meta.type === MetaType.IndexChangeSDD) {\n throw new Error('Not allowed');\n }\n\n await this.map.clear();\n const ps = [];\n for (const idx of this.indexes.values()) {\n ps.push(idx.clear());\n }\n await Promise.all(ps);\n }\n\n async putCommit(): Promise<Commit<CommitMeta>> {\n const valueHash = await this.map.flush();\n const indexRecords: IndexRecord[] = [];\n\n for (const index of this.indexes.values()) {\n const valueHash = await index.flush();\n const indexRecord: IndexRecord = {\n definition: index.meta.definition,\n valueHash,\n };\n indexRecords.push(indexRecord);\n }\n\n let commit: Commit<Meta>;\n const meta = this.#meta;\n switch (meta.type) {\n case MetaType.LocalSDD: {\n const {\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n } = meta;\n commit = commitNewLocalSDD(\n this.#dagWrite.createChunk,\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n valueHash,\n indexRecords,\n timestamp,\n );\n break;\n }\n\n case MetaType.LocalDD31: {\n assert(this.#formatVersion >= FormatVersion.DD31);\n const {\n basisHash,\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n timestamp,\n } = meta;\n commit = commitNewLocalDD31(\n this.#dagWrite.createChunk,\n basisHash,\n await baseSnapshotHashFromHash(basisHash, this.#dagWrite),\n mutationID,\n mutatorName,\n mutatorArgsJSON,\n originalHash,\n valueHash,\n indexRecords,\n timestamp,\n this.#clientID,\n );\n break;\n }\n\n case MetaType.SnapshotSDD: {\n assert(this.#formatVersion <= FormatVersion.SDD);\n const {basisHash, lastMutationID, cookieJSON} = meta;\n commit = commitNewSnapshotSDD(\n this.#dagWrite.createChunk,\n basisHash,\n lastMutationID,\n cookieJSON,\n valueHash,\n indexRecords,\n );\n break;\n }\n\n case MetaType.SnapshotDD31: {\n assert(this.#formatVersion > FormatVersion.DD31);\n const {basisHash, lastMutationIDs, cookieJSON} = meta;\n commit = commitNewSnapshotDD31(\n this.#dagWrite.createChunk,\n basisHash,\n lastMutationIDs,\n cookieJSON,\n valueHash,\n indexRecords,\n );\n break;\n }\n\n case MetaType.IndexChangeSDD: {\n const {basisHash, lastMutationID} = meta;\n if (this.#basis !== undefined) {\n if (\n (await this.#basis.getMutationID(\n this.#clientID,\n this.#dagWrite,\n )) !== lastMutationID\n ) {\n throw new Error('Index change must not change mutationID');\n }\n if (this.#basis.valueHash !== valueHash) {\n throw new Error('Index change must not change valueHash');\n }\n }\n commit = commitNewIndexChange(\n this.#dagWrite.createChunk,\n basisHash,\n lastMutationID,\n valueHash,\n indexRecords,\n );\n break;\n }\n }\n await this.#dagWrite.putChunk(commit.chunk);\n return commit;\n }\n\n // Return value is the hash of the new commit.\n async commit(headName: string): Promise<Hash> {\n const commit = await this.putCommit();\n const commitHash = commit.chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return commitHash;\n }\n\n async commitWithDiffs(\n headName: string,\n diffConfig: DiffComputationConfig,\n ): Promise<DiffsMap> {\n const commit = this.putCommit();\n const diffMap = await this.#generateDiffs(diffConfig);\n const commitHash = (await commit).chunk.hash;\n await this.#dagWrite.setHead(headName, commitHash);\n await this.#dagWrite.commit();\n return diffMap;\n }\n\n async #generateDiffs(diffConfig: DiffComputationConfig): Promise<DiffsMap> {\n const diffsMap = new DiffsMap();\n if (!diffConfig.shouldComputeDiffs()) {\n return diffsMap;\n }\n\n let valueDiff: InternalDiff = [];\n if (this.#basis) {\n const basisMap = new BTreeRead(\n this.#dagWrite,\n this.#formatVersion,\n this.#basis.valueHash,\n );\n valueDiff = await diff(basisMap, this.map);\n }\n diffsMap.set('', valueDiff);\n let basisIndexes: Map<string, IndexRead>;\n if (this.#basis) {\n basisIndexes = readIndexesForRead(\n this.#basis,\n this.#dagWrite,\n this.#formatVersion,\n );\n } else {\n basisIndexes = new Map();\n }\n\n for (const [name, index] of this.indexes) {\n if (!diffConfig.shouldComputeDiffsForIndex(name)) {\n continue;\n }\n const basisIndex = basisIndexes.get(name);\n assert(index !== basisIndex);\n\n const indexDiffResult = await (basisIndex\n ? diff(basisIndex.map, index.map)\n : // No basis. All keys are new.\n allEntriesAsDiff(index.map, 'add'));\n diffsMap.set(name, indexDiffResult);\n }\n\n // Handle indexes in basisIndex but not in this.indexes. All keys are\n // deleted.\n for (const [name, basisIndex] of basisIndexes) {\n if (\n !this.indexes.has(name) &&\n diffConfig.shouldComputeDiffsForIndex(name)\n ) {\n const indexDiffResult = await allEntriesAsDiff(basisIndex.map, 'del');\n diffsMap.set(name, indexDiffResult);\n }\n }\n return diffsMap;\n }\n\n close(): void {\n this.#dagWrite.release();\n }\n}\n\nexport async function newWriteLocal(\n basisHash: Hash,\n mutatorName: string,\n mutatorArgsJSON: FrozenJSONValue,\n originalHash: Hash | null,\n dagWrite: DagWrite,\n timestamp: number,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n const mutationID = await basis.getNextMutationID(clientID, dagWrite);\n const indexes = readIndexesForWrite(basis, dagWrite, formatVersion);\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n formatVersion >= FormatVersion.DD31\n ? {\n type: MetaType.LocalDD31,\n basisHash,\n baseSnapshotHash: await baseSnapshotHashFromHash(basisHash, dagWrite),\n mutatorName,\n mutatorArgsJSON,\n mutationID,\n originalHash,\n timestamp,\n clientID,\n }\n : {\n type: MetaType.LocalSDD,\n basisHash,\n mutatorName,\n mutatorArgsJSON,\n mutationID,\n originalHash,\n timestamp,\n },\n indexes,\n clientID,\n formatVersion,\n );\n}\n\nexport async function newWriteSnapshotSDD(\n basisHash: Hash,\n lastMutationID: number,\n cookieJSON: FrozenJSONValue,\n dagWrite: DagWrite,\n indexes: Map<string, IndexWrite>,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Write> {\n assert(formatVersion <= FormatVersion.SDD);\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n {basisHash, type: MetaType.SnapshotSDD, lastMutationID, cookieJSON},\n indexes,\n clientID,\n formatVersion,\n );\n}\n\nexport async function newWriteSnapshotDD31(\n basisHash: Hash,\n lastMutationIDs: Record<ClientID, number>,\n cookieJSON: FrozenCookie,\n dagWrite: DagWrite,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Write> {\n const basis = await commitFromHash(basisHash, dagWrite);\n const bTreeWrite = new BTreeWrite(dagWrite, formatVersion, basis.valueHash);\n return new Write(\n dagWrite,\n bTreeWrite,\n basis,\n {basisHash, type: MetaType.SnapshotDD31, lastMutationIDs, cookieJSON},\n readIndexesForWrite(basis, dagWrite, formatVersion),\n clientID,\n formatVersion,\n );\n}\n\nexport async function updateIndexes(\n lc: LogContext,\n indexes: Map<string, IndexWrite>,\n key: string,\n oldValGetter: () => Promise<FrozenJSONValue | undefined>,\n newVal: FrozenJSONValue | undefined,\n): Promise<void> {\n const ps: Promise<void>[] = [];\n for (const idx of indexes.values()) {\n const {keyPrefix} = idx.meta.definition;\n if (!keyPrefix || key.startsWith(keyPrefix)) {\n const oldVal = await oldValGetter();\n if (oldVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Remove,\n key,\n oldVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n if (newVal !== undefined) {\n ps.push(\n indexValue(\n lc,\n idx.map,\n IndexOperation.Add,\n key,\n newVal,\n idx.meta.definition.jsonPointer,\n idx.meta.definition.allowEmpty ?? false,\n ),\n );\n }\n }\n }\n await Promise.all(ps);\n}\n\nexport function readIndexesForWrite(\n commit: Commit<CommitMeta>,\n dagWrite: DagWrite,\n formatVersion: FormatVersion.Type,\n): Map<string, IndexWrite> {\n const m = new Map();\n for (const index of commit.indexes) {\n m.set(\n index.definition.name,\n new IndexWrite(\n index,\n new BTreeWrite(dagWrite, formatVersion, index.valueHash),\n ),\n );\n }\n return m;\n}\n\nexport async function createIndexBTree(\n lc: LogContext,\n dagWrite: DagWrite,\n valueMap: BTreeRead,\n prefix: string,\n jsonPointer: string,\n allowEmpty: boolean,\n formatVersion: FormatVersion.Type,\n): Promise<BTreeWrite> {\n const indexMap = new BTreeWrite(dagWrite, formatVersion);\n for await (const entry of valueMap.scan(prefix)) {\n const key = entry[0];\n if (!key.startsWith(prefix)) {\n break;\n }\n await indexValue(\n lc,\n indexMap,\n IndexOperation.Add,\n key,\n entry[1],\n jsonPointer,\n allowEmpty,\n );\n }\n return indexMap;\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport type {Write as DagWrite} from '../dag/store.js';\nimport * as FormatVersion from '../format-version-enum.js';\nimport type {Hash} from '../hash.js';\nimport type {ClientID} from '../sync/ids.js';\nimport {WriteTransactionImpl} from '../transactions.js';\nimport type {MutatorDefs} from '../types.js';\nimport {\n Commit,\n type LocalMeta,\n type LocalMetaDD31,\n type LocalMetaSDD,\n type Meta,\n assertLocalMetaDD31,\n commitFromHash,\n isLocalMetaDD31,\n} from './commit.js';\nimport {Write, newWriteLocal} from './write.js';\n\nasync function rebaseMutation(\n mutation: Commit<LocalMetaDD31 | LocalMetaSDD>,\n dagWrite: DagWrite,\n basisHash: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n mutationClientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Write> {\n const localMeta = mutation.meta;\n const name = localMeta.mutatorName;\n if (isLocalMetaDD31(localMeta)) {\n assert(\n localMeta.clientID === mutationClientID,\n 'mutationClientID must match clientID of LocalMeta',\n );\n }\n const maybeMutatorImpl = mutators[name];\n if (!maybeMutatorImpl) {\n // Developers must not remove mutator names from code deployed with the\n // same schemaVersion because Replicache needs to be able to replay\n // mutations during pull.\n //\n // If we detect that this has happened, stub in a no-op mutator so that at\n // least sync can move forward. Note that the server-side mutation will\n // still get sent. This doesn't remove the queued local mutation, it just\n // removes its visible effects.\n lc.error?.(`Cannot rebase unknown mutator ${name}`);\n }\n const mutatorImpl =\n maybeMutatorImpl ||\n (async () => {\n // no op\n });\n\n const args = localMeta.mutatorArgsJSON;\n\n const basisCommit = await commitFromHash(basisHash, dagWrite);\n const nextMutationID = await basisCommit.getNextMutationID(\n mutationClientID,\n dagWrite,\n );\n if (nextMutationID !== localMeta.mutationID) {\n throw new Error(\n `Inconsistent mutation ID: original: ${localMeta.mutationID}, next: ${nextMutationID} - mutationClientID: ${mutationClientID} mutatorName: ${name}`,\n );\n }\n\n if (formatVersion >= FormatVersion.DD31) {\n assertLocalMetaDD31(localMeta);\n }\n\n const dbWrite = await newWriteLocal(\n basisHash,\n name,\n args,\n mutation.chunk.hash,\n dagWrite,\n localMeta.timestamp,\n mutationClientID,\n formatVersion,\n );\n\n const tx = new WriteTransactionImpl(\n mutationClientID,\n await dbWrite.getMutationID(),\n 'rebase',\n dbWrite,\n lc,\n );\n await mutatorImpl(tx, args);\n return dbWrite;\n}\n\nexport async function rebaseMutationAndPutCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Commit<Meta>> {\n const tx = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n );\n return tx.putCommit();\n}\n\nexport async function rebaseMutationAndCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n headName: string,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<Hash> {\n const dbWrite = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n );\n return dbWrite.commit(headName);\n}\n", "import {callDefaultFetch} from './call-default-fetch.js';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.js';\nimport type {Pusher, PusherResult} from './pusher.js';\nimport type {PushRequest} from './sync/push.js';\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", "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 | undefined,\n): LogContext {\n const logSink =\n logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);\n return new LogContext(logLevel, context, logSink);\n}\n", "import * as FormatVersion from './format-version-enum.js';\n\nexport function parseReplicacheFormatVersion(v: number): FormatVersion.Type {\n if (v !== (v | 0) || v < FormatVersion.SDD || v > FormatVersion.Latest) {\n throw new Error(`Unsupported format version: ${v}`);\n }\n return v as FormatVersion.Type;\n}\n", "import * as valita from '../../shared/src/valita.js';\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", "import {assert, assertObject} from '../../../shared/src/asserts.js';\nimport * as valita from '../../../shared/src/valita.js';\nimport {toRefs} from '../dag/chunk.js';\nimport type {Read, Write} from '../dag/store.js';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.js';\nimport {type Hash, hashSchema} from '../hash.js';\nimport {indexDefinitionsEqual, indexDefinitionsSchema} from '../index-defs.js';\nimport type {ClientGroupID} from '../sync/ids.js';\n\nexport type ClientGroupMap = ReadonlyMap<ClientGroupID, ClientGroup>;\n\nconst clientGroupSchema = valita.readonlyObject({\n /**\n * The hash of the commit in the perdag last persisted to this client group.\n * Should only be updated by clients assigned to this client group.\n */\n headHash: hashSchema,\n\n /**\n * Set of mutator names common to all clients assigned to this client group.\n */\n mutatorNames: valita.readonlyArray(valita.string()),\n\n /**\n * Index definitions common to all clients assigned to this client group.\n */\n indexes: indexDefinitionsSchema,\n\n /**\n * The highest mutation ID of every client assigned to this client group.\n * Should only be updated by clients assigned to this client group. Read by\n * other clients to determine if there are unacknowledged pending mutations\n * for them to try to recover. This is redundant with information in the\n * commit graph at `headHash`, but allows other clients to determine if there\n * are unacknowledged pending mutations without having to load the commit\n * graph.\n */\n mutationIDs: valita.readonlyRecord(valita.number()),\n\n /**\n * The highest lastMutationID received from the server for every client\n * assigned to this client group.\n *\n * Should be updated by the clients assigned to this client group whenever\n * they persist to this client group. Read by other clients to determine if\n * there are unacknowledged pending mutations for them to recover and\n * *updated* by other clients upon successfully recovering pending mutations\n * to avoid redundant pushes of pending mutations.\n *\n * Note: This will be the same as the `lastMutationIDs` of the base snapshot\n * of the client group's commit graph when written by clients assigned to this\n * client group. However, when written by another client recovering mutations\n * it may be different because the other client does not update the commit\n * graph.\n */\n lastServerAckdMutationIDs: valita.record(valita.number()),\n\n /**\n * If the server deletes this client group it can signal that the client group\n * was deleted. If that happens we mark this client group as disabled so that\n * we do not use it again when creating new clients.\n */\n disabled: valita.boolean(),\n});\n\nexport type ClientGroup = valita.Infer<typeof clientGroupSchema>;\n\nexport const CLIENT_GROUPS_HEAD_NAME = 'client-groups';\n\nfunction assertClientGroup(value: unknown): asserts value is ClientGroup {\n valita.assert(value, clientGroupSchema);\n}\n\nfunction chunkDataToClientGroupMap(chunkData: unknown): ClientGroupMap {\n assertObject(chunkData);\n const clientGroups = new Map<ClientGroupID, ClientGroup>();\n for (const [key, value] of Object.entries(chunkData)) {\n if (value !== undefined) {\n assertClientGroup(value);\n clientGroups.set(key, value);\n }\n }\n return clientGroups;\n}\n\nfunction clientGroupMapToChunkData(\n clientGroups: ClientGroupMap,\n dagWrite: Write,\n): FrozenJSONValue {\n const chunkData: {[id: ClientGroupID]: ClientGroup} = {};\n for (const [clientGroupID, clientGroup] of clientGroups.entries()) {\n dagWrite.assertValidHash(clientGroup.headHash);\n chunkData[clientGroupID] = {\n ...clientGroup,\n mutatorNames: [...clientGroup.mutatorNames.values()],\n };\n }\n return deepFreeze(chunkData);\n}\n\nasync function getClientGroupsAtHash(\n hash: Hash,\n dagRead: Read,\n): Promise<ClientGroupMap> {\n const chunk = await dagRead.getChunk(hash);\n return chunkDataToClientGroupMap(chunk?.data);\n}\n\nexport async function getClientGroups(dagRead: Read): Promise<ClientGroupMap> {\n const hash = await dagRead.getHead(CLIENT_GROUPS_HEAD_NAME);\n if (!hash) {\n return new Map();\n }\n return getClientGroupsAtHash(hash, dagRead);\n}\n\nexport async function setClientGroups(\n clientGroups: ClientGroupMap,\n dagWrite: Write,\n): Promise<ClientGroupMap> {\n const currClientGroups = await getClientGroups(dagWrite);\n for (const [clientGroupID, clientGroup] of clientGroups) {\n const currClientGroup = currClientGroups.get(clientGroupID);\n validateClientGroupUpdate(clientGroup, currClientGroup);\n }\n return setValidatedClientGroups(clientGroups, dagWrite);\n}\n\nexport async function setClientGroup(\n clientGroupID: ClientGroupID,\n clientGroup: ClientGroup,\n dagWrite: Write,\n): Promise<ClientGroupMap> {\n const currClientGroups = await getClientGroups(dagWrite);\n const currClientGroup = currClientGroups.get(clientGroupID);\n validateClientGroupUpdate(clientGroup, currClientGroup);\n const newClientGroups = new Map(currClientGroups);\n newClientGroups.set(clientGroupID, clientGroup);\n return setValidatedClientGroups(newClientGroups, dagWrite);\n}\n\nexport async function deleteClientGroup(\n clientGroupID: ClientGroupID,\n dagWrite: Write,\n): Promise<ClientGroupMap> {\n const currClientGroups = await getClientGroups(dagWrite);\n if (!currClientGroups.has(clientGroupID)) {\n return currClientGroups;\n }\n const newClientGroups = new Map(currClientGroups.entries());\n newClientGroups.delete(clientGroupID);\n return setValidatedClientGroups(newClientGroups, dagWrite);\n}\n\nfunction validateClientGroupUpdate(\n clientGroup: ClientGroup,\n currClientGroup: ClientGroup | undefined,\n) {\n const mutatorNamesSet = new Set(clientGroup.mutatorNames);\n assert(\n mutatorNamesSet.size === clientGroup.mutatorNames.length,\n \"A client group's mutatorNames must be a set.\",\n );\n if (currClientGroup !== undefined) {\n assert(\n indexDefinitionsEqual(currClientGroup.indexes, clientGroup.indexes),\n \"A client group's index definitions must never change.\",\n );\n assert(\n mutatorNamesEqual(mutatorNamesSet, currClientGroup.mutatorNames),\n \"A client group's mutatorNames must never change.\",\n );\n }\n}\n\nasync function setValidatedClientGroups(\n clientGroups: ClientGroupMap,\n dagWrite: Write,\n): Promise<ClientGroupMap> {\n const chunkData = clientGroupMapToChunkData(clientGroups, dagWrite);\n const refs: Set<Hash> = new Set();\n for (const clientGroup of clientGroups.values()) {\n refs.add(clientGroup.headHash);\n }\n const chunk = dagWrite.createChunk(chunkData, toRefs(refs));\n await dagWrite.putChunk(chunk);\n await dagWrite.setHead(CLIENT_GROUPS_HEAD_NAME, chunk.hash);\n return clientGroups;\n}\n\nexport function mutatorNamesEqual(\n mutatorNamesSet: ReadonlySet<string>,\n mutatorNames: readonly string[],\n): boolean {\n if (mutatorNames.length !== mutatorNamesSet.size) {\n return false;\n }\n for (const mutatorName of mutatorNames) {\n if (!mutatorNamesSet.has(mutatorName)) {\n return false;\n }\n }\n return true;\n}\n\nexport async function getClientGroup(\n id: ClientGroupID,\n dagRead: Read,\n): Promise<ClientGroup | undefined> {\n const clientGroups = await getClientGroups(dagRead);\n return clientGroups.get(id);\n}\n\nexport function clientGroupHasPendingMutations(clientGroup: ClientGroup) {\n for (const [clientID, mutationID] of Object.entries(\n clientGroup.mutationIDs,\n )) {\n const lastServerAckdMutationID =\n clientGroup.lastServerAckdMutationIDs[clientID];\n if (\n (lastServerAckdMutationID === undefined && mutationID !== 0) ||\n lastServerAckdMutationID < mutationID\n ) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Marks a client group as disabled. This can happen if the server deletes the\n * client group (servers should not delete clients or client groups but it often\n * happens in practice when developing).\n *\n * A disabled client group prevents pulls and pushes from happening.\n */\nexport async function disableClientGroup(\n clientGroupID: string,\n dagWrite: Write,\n): Promise<void> {\n const clientGroup = await getClientGroup(clientGroupID, dagWrite);\n if (!clientGroup) {\n // No client group matching in the database, so nothing to do.\n return;\n }\n const disabledClientGroup = {\n ...clientGroup,\n disabled: true,\n };\n await setClientGroup(clientGroupID, disabledClientGroup, dagWrite);\n}\n", "import * as valita from '../../../shared/src/valita.js';\n\n/**\n * The ID describing a group of clients. All clients in the same group share a\n * persistent storage (IDB).\n */\nexport type ClientGroupID = string;\n\nexport const clientGroupIDSchema: valita.Type<ClientGroupID> = valita.string();\n\n/**\n * The ID describing a client.\n */\nexport type ClientID = string;\n\nexport const clientIDSchema: valita.Type<ClientID> = valita.string();\n", "export interface Release {\n release(): void;\n}\n\nexport interface Commit {\n commit(): Promise<void>;\n}\n\ninterface ReadStore<Read extends Release> {\n read(): Promise<Read>;\n}\n\ninterface WriteStore<Write extends Release> {\n write(): Promise<Write>;\n}\n\nexport function withRead<Read extends Release, Return>(\n store: ReadStore<Read>,\n fn: (read: Read) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.read(), fn);\n}\n\nexport function withWriteNoImplicitCommit<Write extends Release, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), fn);\n}\n\nexport function withWrite<Write extends Release & Commit, Return>(\n store: WriteStore<Write>,\n fn: (write: Write) => Return | Promise<Return>,\n): Promise<Return> {\n return using(store.write(), async write => {\n const result = await fn(write);\n await write.commit();\n return result;\n });\n}\n\n/**\n * This function takes a promise for a resource and a function that uses that\n * resource. It will release the resource after the function returns by calling\n * the `release` function\n */\nexport async function using<TX extends Release, Return>(\n x: Promise<TX>,\n fn: (tx: TX) => Return | Promise<Return>,\n): Promise<Return> {\n const write = await x;\n try {\n return await fn(write);\n } finally {\n write.release();\n }\n}\n", "import {randomUint64} from '../../../shared/src/random-uint64.js';\n\n/**\n * Returns a random 18 character string encoded in base32 suitable as a client\n * ID.\n */\nexport function makeClientID(): string {\n const length = 18;\n const high = randomUint64();\n const low = randomUint64();\n const combined = (high << 64n) | low;\n return combined.toString(32).slice(-length).padStart(length, '0');\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert, assertObject} from '../../../shared/src/asserts.js';\nimport {hasOwn} from '../../../shared/src/has-own.js';\nimport * as valita from '../../../shared/src/valita.js';\nimport {emptyDataNode} from '../btree/node.js';\nimport {BTreeRead} from '../btree/read.js';\nimport {type FrozenCookie, compareCookies} from '../cookies.js';\nimport {type Refs, toRefs} from '../dag/chunk.js';\nimport type {Read, Store, Write} from '../dag/store.js';\nimport {\n type ChunkIndexDefinition,\n Commit,\n type IndexRecord,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromHash,\n chunkIndexDefinitionEqualIgnoreName,\n getRefs,\n newSnapshotCommitDataDD31,\n toChunkIndexDefinition,\n} from '../db/commit.js';\nimport {createIndexBTree} from '../db/write.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport {type FrozenJSONValue, deepFreeze} from '../frozen-json.js';\nimport {type Hash, hashSchema} from '../hash.js';\nimport {type IndexDefinitions, indexDefinitionsEqual} from '../index-defs.js';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n} from '../sync/ids.js';\nimport {withWriteNoImplicitCommit} from '../with-transactions.js';\nimport {\n type ClientGroup,\n getClientGroup,\n getClientGroups,\n mutatorNamesEqual,\n setClientGroup,\n} from './client-groups.js';\nimport {makeClientID} from './make-client-id.js';\n\nexport type ClientMap = ReadonlyMap<ClientID, ClientV4 | ClientV5 | ClientV6>;\nexport type ClientMapDD31 = ReadonlyMap<ClientID, ClientV5 | ClientV6>;\n\nconst clientV4Schema = valita.readonlyObject({\n /**\n * A UNIX timestamp in milliseconds updated by the client once a minute\n * while it is active and every time the client persists its state to\n * the perdag.\n * Should only be updated by the client represented by this structure.\n */\n heartbeatTimestampMs: valita.number(),\n\n /**\n * The hash of the commit in the perdag this client last persisted.\n * Should only be updated by the client represented by this structure.\n */\n headHash: hashSchema,\n\n /**\n * The mutationID of the commit at headHash (mutationID if it is a\n * local commit, lastMutationID if it is an index change or snapshot commit).\n * Should only be updated by the client represented by this structure.\n * Read by other clients to determine if there are unacknowledged pending\n * mutations for them to push on behalf of the client represented by this\n * structure.\n * This is redundant with information in the commit graph at headHash,\n * but allows other clients to determine if there are unacknowledged pending\n * mutations without having to load the commit graph at headHash.\n */\n mutationID: valita.number(),\n\n /**\n * The highest lastMutationID received from the server for this client.\n *\n * Should be updated by the client represented by this structure whenever\n * it persists its state to the perdag.\n * Read by other clients to determine if there are unacknowledged pending\n * mutations for them to push on behalf of the client represented by this\n * structure, and *updated* by other clients upon successfully pushing\n * pending mutations to avoid redundant pushes of those mutations.\n *\n * Note: This will be the same as the lastMutationID of the base snapshot of\n * the commit graph at headHash when written by the client represented by this\n * structure. However, when written by another client pushing pending\n * mutations on this client's behalf it will be different. This is because\n * the other client does not update the commit graph (it is unsafe to update\n * another client's commit graph).\n */\n lastServerAckdMutationID: valita.number(),\n});\n\nexport type ClientV4 = valita.Infer<typeof clientV4Schema>;\n\nconst clientV5Schema = valita.readonlyObject({\n heartbeatTimestampMs: valita.number(),\n\n headHash: hashSchema,\n\n /**\n * The hash of a commit we are in the middle of refreshing into this client's\n * memdag.\n */\n tempRefreshHash: hashSchema.nullable(),\n\n /**\n * ID of this client's perdag client group. This needs to be sent in pull\n * request (to enable syncing all last mutation ids in the client group).\n */\n clientGroupID: clientGroupIDSchema,\n});\n\nexport type ClientV5 = valita.Infer<typeof clientV5Schema>;\n\nconst clientV6Schema = valita.readonlyObject({\n heartbeatTimestampMs: valita.number(),\n\n /**\n * A set of hashes, which contains:\n * 1. The hash of the last commit this client refreshed from its client group\n * (this is the commit it bootstrapped from until it completes its first\n * refresh).\n * 2. One or more hashes that were added to retain chunks of a commit while it\n * was being refreshed into this client's memdag. (This can be one or more\n * because refresh's cleanup step is a separate transaction and can fail).\n * Upon refresh completing and successfully running its clean up step, this\n * set will contain a single hash: the hash of the last commit this client\n * refreshed.\n */\n refreshHashes: valita.readonlyArray(hashSchema),\n\n /**\n * The hash of the last snapshot commit persisted by this client to this\n * client's client group, or null if has never persisted a snapshot.\n */\n persistHash: hashSchema.nullable(),\n\n /**\n * ID of this client's perdag client group. This needs to be sent in pull\n * request (to enable syncing all last mutation ids in the client group).\n */\n clientGroupID: clientGroupIDSchema,\n});\n\nexport type ClientV6 = valita.Infer<typeof clientV6Schema>;\n\nexport type Client = ClientV4 | ClientV5 | ClientV6;\n\nfunction isClientV6(client: Client): client is ClientV6 {\n return (client as ClientV6).refreshHashes !== undefined;\n}\n\nfunction isClientV5(client: Client): client is ClientV5 {\n return (client as ClientV5).clientGroupID !== undefined;\n}\n\nexport function isClientV4(client: Client): client is ClientV4 {\n return (client as ClientV4).lastServerAckdMutationID !== undefined;\n}\n\nexport const CLIENTS_HEAD_NAME = 'clients';\n\nconst clientSchema = valita.union(\n clientV4Schema,\n clientV5Schema,\n clientV6Schema,\n);\n\nfunction assertClient(value: unknown): asserts value is Client {\n valita.assert(value, clientSchema);\n}\n\nexport function assertClientV4(value: unknown): asserts value is ClientV4 {\n valita.assert(value, clientV4Schema);\n}\n\nexport function assertClientV5(value: unknown): asserts value is ClientV5 {\n valita.assert(value, clientV5Schema);\n}\n\nexport function assertClientV6(value: unknown): asserts value is ClientV6 {\n valita.assert(value, clientV6Schema);\n}\n\nfunction chunkDataToClientMap(chunkData: unknown): ClientMap {\n assertObject(chunkData);\n const clients = new Map();\n for (const key in chunkData) {\n if (hasOwn(chunkData, key)) {\n const value = chunkData[key];\n if (value !== undefined) {\n assertClient(value);\n clients.set(key, value);\n }\n }\n }\n return clients;\n}\n\nfunction clientMapToChunkData(\n clients: ClientMap,\n dagWrite: Write,\n): FrozenJSONValue {\n for (const client of clients.values()) {\n if (isClientV6(client)) {\n client.refreshHashes.forEach(dagWrite.assertValidHash);\n if (client.persistHash) {\n dagWrite.assertValidHash(client.persistHash);\n }\n } else {\n dagWrite.assertValidHash(client.headHash);\n if (isClientV5(client) && client.tempRefreshHash) {\n dagWrite.assertValidHash(client.tempRefreshHash);\n }\n }\n }\n return deepFreeze(Object.fromEntries(clients));\n}\n\nexport async function getClients(dagRead: Read): Promise<ClientMap> {\n const hash = await dagRead.getHead(CLIENTS_HEAD_NAME);\n return getClientsAtHash(hash, dagRead);\n}\n\nasync function getClientsAtHash(\n hash: Hash | undefined,\n dagRead: Read,\n): Promise<ClientMap> {\n if (!hash) {\n return new Map();\n }\n const chunk = await dagRead.getChunk(hash);\n return chunkDataToClientMap(chunk?.data);\n}\n\n/**\n * Used to signal that a client does not exist. Maybe it was garbage collected?\n */\nexport class ClientStateNotFoundError extends Error {\n name = 'ClientStateNotFoundError';\n readonly id: string;\n constructor(id: ClientID) {\n super(`Client state not found, id: ${id}`);\n this.id = id;\n }\n}\n\n/**\n * Throws a `ClientStateNotFoundError` if the client does not exist.\n */\nexport async function assertHasClientState(\n id: ClientID,\n dagRead: Read,\n): Promise<void> {\n if (!(await hasClientState(id, dagRead))) {\n throw new ClientStateNotFoundError(id);\n }\n}\n\nexport async function hasClientState(\n id: ClientID,\n dagRead: Read,\n): Promise<boolean> {\n return !!(await getClient(id, dagRead));\n}\n\nexport async function getClient(\n id: ClientID,\n dagRead: Read,\n): Promise<Client | undefined> {\n const clients = await getClients(dagRead);\n return clients.get(id);\n}\n\nexport async function mustGetClient(\n id: ClientID,\n dagRead: Read,\n): Promise<Client> {\n const client = await getClient(id, dagRead);\n if (!client) {\n throw new ClientStateNotFoundError(id);\n }\n return client;\n}\n\ntype InitClientV6Result = [\n client: ClientV6,\n hash: Hash,\n clientMap: ClientMap,\n newClientGroup: boolean,\n];\n\nexport function initClientV6(\n newClientID: ClientID,\n lc: LogContext,\n perdag: Store,\n mutatorNames: string[],\n indexes: IndexDefinitions,\n formatVersion: FormatVersion,\n enableClientGroupForking: boolean,\n): Promise<InitClientV6Result> {\n return withWriteNoImplicitCommit(perdag, async dagWrite => {\n async function setClientsAndClientGroupAndCommit(\n basisHash: Hash | null,\n cookieJSON: FrozenCookie,\n valueHash: Hash,\n indexRecords: readonly IndexRecord[],\n ): Promise<InitClientV6Result> {\n const newSnapshotData = newSnapshotCommitDataDD31(\n basisHash,\n {},\n cookieJSON,\n valueHash,\n indexRecords,\n );\n const chunk = dagWrite.createChunk(\n newSnapshotData,\n getRefs(newSnapshotData),\n );\n\n const newClientGroupID = makeClientID();\n\n const newClient: ClientV6 = {\n heartbeatTimestampMs: Date.now(),\n refreshHashes: [chunk.hash],\n persistHash: null,\n clientGroupID: newClientGroupID,\n };\n\n const newClients = new Map(clients).set(newClientID, newClient);\n\n const clientGroup: ClientGroup = {\n headHash: chunk.hash,\n mutatorNames,\n indexes,\n mutationIDs: {},\n lastServerAckdMutationIDs: {},\n disabled: false,\n };\n\n await Promise.all([\n dagWrite.putChunk(chunk),\n setClients(newClients, dagWrite),\n setClientGroup(newClientGroupID, clientGroup, dagWrite),\n ]);\n\n await dagWrite.commit();\n\n return [newClient, chunk.hash, newClients, true];\n }\n\n const clients = await getClients(dagWrite);\n\n const res = await findMatchingClient(dagWrite, mutatorNames, indexes);\n if (res.type === FIND_MATCHING_CLIENT_TYPE_HEAD) {\n // We found a client group with matching mutators and indexes. We can\n // reuse it.\n const {clientGroupID, headHash} = res;\n\n const newClient: ClientV6 = {\n clientGroupID,\n refreshHashes: [headHash],\n heartbeatTimestampMs: Date.now(),\n persistHash: null,\n };\n const newClients = new Map(clients).set(newClientID, newClient);\n await setClients(newClients, dagWrite);\n\n await dagWrite.commit();\n return [newClient, headHash, newClients, false];\n }\n\n if (\n !enableClientGroupForking ||\n res.type === FIND_MATCHING_CLIENT_TYPE_NEW\n ) {\n // No client group to fork from. Create empty snapshot.\n const emptyBTreeChunk = dagWrite.createChunk(emptyDataNode, []);\n await dagWrite.putChunk(emptyBTreeChunk);\n\n // Create indexes\n const indexRecords: IndexRecord[] = [];\n\n // At this point the value of replicache is the empty tree so all index\n // maps will also be the empty tree.\n for (const [name, indexDefinition] of Object.entries(indexes)) {\n const chunkIndexDefinition = toChunkIndexDefinition(\n name,\n indexDefinition,\n );\n indexRecords.push({\n definition: chunkIndexDefinition,\n valueHash: emptyBTreeChunk.hash,\n });\n }\n\n return setClientsAndClientGroupAndCommit(\n null,\n null,\n emptyBTreeChunk.hash,\n indexRecords,\n );\n }\n\n // Now we create a new client and client group that we fork from the found\n // snapshot.\n assert(res.type === FIND_MATCHING_CLIENT_TYPE_FORK);\n\n const {snapshot} = res;\n\n // Create indexes\n const indexRecords: IndexRecord[] = [];\n const {valueHash, indexes: oldIndexes} = snapshot;\n const map = new BTreeRead(dagWrite, formatVersion, valueHash);\n\n for (const [name, indexDefinition] of Object.entries(indexes)) {\n const {prefix = '', jsonPointer, allowEmpty = false} = indexDefinition;\n const chunkIndexDefinition: ChunkIndexDefinition = {\n name,\n keyPrefix: prefix,\n jsonPointer,\n allowEmpty,\n };\n\n const oldIndex = findMatchingOldIndex(oldIndexes, chunkIndexDefinition);\n if (oldIndex) {\n indexRecords.push({\n definition: chunkIndexDefinition,\n valueHash: oldIndex.valueHash,\n });\n } else {\n const indexBTree = await createIndexBTree(\n lc,\n dagWrite,\n map,\n prefix,\n jsonPointer,\n allowEmpty,\n formatVersion,\n );\n indexRecords.push({\n definition: chunkIndexDefinition,\n valueHash: await indexBTree.flush(),\n });\n }\n }\n\n return setClientsAndClientGroupAndCommit(\n snapshot.meta.basisHash,\n snapshot.meta.cookieJSON,\n snapshot.valueHash,\n indexRecords,\n );\n });\n}\n\nfunction findMatchingOldIndex(\n oldIndexes: readonly IndexRecord[],\n chunkIndexDefinition: ChunkIndexDefinition,\n) {\n return oldIndexes.find(index =>\n chunkIndexDefinitionEqualIgnoreName(index.definition, chunkIndexDefinition),\n );\n}\n\nexport const FIND_MATCHING_CLIENT_TYPE_NEW = 0;\nexport const FIND_MATCHING_CLIENT_TYPE_FORK = 1;\nexport const FIND_MATCHING_CLIENT_TYPE_HEAD = 2;\n\nexport type FindMatchingClientResult =\n | {\n type: typeof FIND_MATCHING_CLIENT_TYPE_NEW;\n }\n | {\n type: typeof FIND_MATCHING_CLIENT_TYPE_FORK;\n snapshot: Commit<SnapshotMetaDD31>;\n }\n | {\n type: typeof FIND_MATCHING_CLIENT_TYPE_HEAD;\n clientGroupID: ClientGroupID;\n headHash: Hash;\n };\n\nexport async function findMatchingClient(\n dagRead: Read,\n mutatorNames: string[],\n indexes: IndexDefinitions,\n): Promise<FindMatchingClientResult> {\n let newestCookie: FrozenCookie | undefined;\n let bestSnapshot: Commit<SnapshotMetaDD31> | undefined;\n const mutatorNamesSet = new Set(mutatorNames);\n\n const clientGroups = await getClientGroups(dagRead);\n for (const [clientGroupID, clientGroup] of clientGroups) {\n if (\n !clientGroup.disabled &&\n mutatorNamesEqual(mutatorNamesSet, clientGroup.mutatorNames) &&\n indexDefinitionsEqual(indexes, clientGroup.indexes)\n ) {\n // exact match\n return {\n type: FIND_MATCHING_CLIENT_TYPE_HEAD,\n clientGroupID,\n headHash: clientGroup.headHash,\n };\n }\n\n const clientGroupSnapshotCommit = await baseSnapshotFromHash(\n clientGroup.headHash,\n dagRead,\n );\n assertSnapshotCommitDD31(clientGroupSnapshotCommit);\n\n const {cookieJSON} = clientGroupSnapshotCommit.meta;\n if (\n newestCookie === undefined ||\n compareCookies(cookieJSON, newestCookie) > 0\n ) {\n newestCookie = cookieJSON;\n bestSnapshot = clientGroupSnapshotCommit;\n }\n }\n\n if (bestSnapshot) {\n return {\n type: FIND_MATCHING_CLIENT_TYPE_FORK,\n snapshot: bestSnapshot,\n };\n }\n\n return {type: FIND_MATCHING_CLIENT_TYPE_NEW};\n}\n\nfunction getRefsForClients(clients: ClientMap): Refs {\n const refs: Set<Hash> = new Set();\n for (const client of clients.values()) {\n if (isClientV6(client)) {\n for (const hash of client.refreshHashes) {\n refs.add(hash);\n }\n if (client.persistHash) {\n refs.add(client.persistHash);\n }\n } else {\n refs.add(client.headHash);\n if (isClientV5(client) && client.tempRefreshHash) {\n refs.add(client.tempRefreshHash);\n }\n }\n }\n return toRefs(refs);\n}\n\nexport async function getClientGroupForClient(\n clientID: ClientID,\n read: Read,\n): Promise<ClientGroup | undefined> {\n const clientGroupID = await getClientGroupIDForClient(clientID, read);\n if (!clientGroupID) {\n return undefined;\n }\n return getClientGroup(clientGroupID, read);\n}\n\nexport async function getClientGroupIDForClient(\n clientID: ClientID,\n read: Read,\n): Promise<ClientGroupID | undefined> {\n const client = await getClient(clientID, read);\n if (!client || !isClientV5(client)) {\n return undefined;\n }\n return client.clientGroupID;\n}\n\n/**\n * Adds a Client to the ClientMap and updates the 'clients' head to point at\n * the updated clients.\n */\nexport async function setClient(\n clientID: ClientID,\n client: Client,\n dagWrite: Write,\n): Promise<Hash> {\n const clients = await getClients(dagWrite);\n const newClients = new Map(clients).set(clientID, client);\n return setClients(newClients, dagWrite);\n}\n\n/**\n * Sets the ClientMap and updates the 'clients' head top point at the new\n * clients.\n */\nexport async function setClients(\n clients: ClientMap,\n dagWrite: Write,\n): Promise<Hash> {\n const chunkData = clientMapToChunkData(clients, dagWrite);\n const chunk = dagWrite.createChunk(chunkData, getRefsForClients(clients));\n await dagWrite.putChunk(chunk);\n await dagWrite.setHead(CLIENTS_HEAD_NAME, chunk.hash);\n return chunk.hash;\n}\n", "export function toError(e: unknown): Error {\n if (e instanceof Error) {\n return e;\n }\n return new Error(String(e));\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const Applied = 0;\nexport const NoOp = 1;\nexport const CookieMismatch = 2;\n\nexport type Applied = typeof Applied;\nexport type NoOp = typeof NoOp;\nexport type CookieMismatch = typeof CookieMismatch;\n\nexport type Type = Applied | NoOp | CookieMismatch;\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assertObject} from '../../../shared/src/asserts.js';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../../shared/src/json.js';\nimport type {Write} from '../db/write.js';\nimport {\n type FrozenJSONObject,\n type FrozenJSONValue,\n deepFreeze,\n} from '../frozen-json.js';\nimport type {PatchOperationInternal} from '../patch-operation.js';\n\nexport async function apply(\n lc: LogContext,\n dbWrite: Write,\n patch: readonly PatchOperationInternal[],\n): Promise<void> {\n for (const p of patch) {\n switch (p.op) {\n case 'put': {\n await dbWrite.put(lc, p.key, deepFreeze(p.value));\n break;\n }\n case 'update': {\n const existing = await dbWrite.get(p.key);\n const entries: [\n string,\n FrozenJSONValue | ReadonlyJSONValue | undefined,\n ][] = [];\n const addToEntries = (toAdd: FrozenJSONObject | ReadonlyJSONObject) => {\n for (const [key, value] of Object.entries(toAdd)) {\n if (\n !p.constrain ||\n p.constrain.length === 0 ||\n p.constrain.indexOf(key) > -1\n ) {\n entries.push([key, value]);\n }\n }\n };\n if (existing !== undefined) {\n assertObject(existing);\n addToEntries(existing);\n }\n if (p.merge) {\n addToEntries(p.merge);\n }\n await dbWrite.put(lc, p.key, deepFreeze(Object.fromEntries(entries)));\n break;\n }\n case 'del':\n await dbWrite.del(lc, p.key);\n break;\n\n case 'clear':\n await dbWrite.clear();\n break;\n }\n }\n}\n", "/**\n * This error is thrown when the puller fails for any reason.\n */\n\nexport class PullError extends Error {\n name = 'PullError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to pull');\n this.causedBy = causedBy;\n }\n}\n", "export const SYNC_HEAD_NAME = 'sync';\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport {deepEqual, type ReadonlyJSONValue} from '../../../shared/src/json.js';\nimport {diff} from '../btree/diff.js';\nimport {BTreeRead} from '../btree/read.js';\nimport {compareCookies, type Cookie} from '../cookies.js';\nimport type {Store} from '../dag/store.js';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n Commit,\n commitChain,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n type LocalMetaSDD,\n localMutations as localMutations_1,\n type Meta,\n snapshotMetaParts,\n} from '../db/commit.js';\nimport {\n newWriteSnapshotDD31,\n newWriteSnapshotSDD,\n readIndexesForWrite,\n updateIndexes,\n} from '../db/write.js';\nimport {isErrorResponse} from '../error-responses.js';\nimport * as FormatVersion from '../format-version-enum.js';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.js';\nimport {\n assertPullerResultV0,\n assertPullerResultV1,\n} from '../get-default-puller.js';\nimport {emptyHash, type Hash} from '../hash.js';\nimport type {HTTPRequestInfo} from '../http-request-info.js';\nimport type {\n Puller,\n PullerResult,\n PullerResultV0,\n PullerResultV1,\n PullResponseOKV0,\n PullResponseOKV1Internal,\n PullResponseV0,\n PullResponseV1,\n} from '../puller.js';\nimport {ReportError} from '../replicache.js';\nimport {toError} from '../to-error.js';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.js';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.js';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.js';\nimport type {ClientGroupID, ClientID} from './ids.js';\nimport * as patch from './patch.js';\nimport {PullError} from './pull-error.js';\nimport {SYNC_HEAD_NAME} from './sync-head-name.js';\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1 | PullRequestV0;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull). This is the legacy version (V0) and it is\n * still used when recovering mutations from old clients.\n */\nexport type PullRequestV0 = {\n pullVersion: 0;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: ReadonlyJSONValue;\n\n clientID: ClientID;\n lastMutationID: number;\n};\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport type BeginPullResponseV0 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV0;\n syncHead: Hash;\n};\n\nexport async function beginPullV0(\n profileID: string,\n clientID: ClientID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion.Type,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV0> {\n const [lastMutationID, baseCookie] = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n const baseCookie = baseSnapshotMeta.cookieJSON;\n const lastMutationID = await baseSnapshot.getMutationID(clientID, dagRead);\n return [lastMutationID, baseCookie];\n });\n\n const pullReq: PullRequestV0 = {\n profileID,\n clientID,\n cookie: baseCookie,\n lastMutationID,\n pullVersion: PULL_VERSION_SDD,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = (await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n )) as PullerResultV0;\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info to the JS SDK.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV0(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n if (result.type === HandlePullResponseResultType.CookieMismatch) {\n throw new Error('Overlapping sync');\n }\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion.Type,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = (await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n )) as PullerResultV1;\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n if (isPullRequestV1(pullReq)) {\n assertPullerResultV1(pullerResult);\n } else {\n assertPullerResultV0(pullerResult);\n }\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\n// Returns new sync head, or null if response did not apply due to mismatched cookie.\nexport function handlePullResponseV0(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: ReadonlyJSONValue,\n response: PullResponseOKV0,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n assert(formatVersion <= FormatVersion.SDD);\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const [baseLastMutationID, baseCookie] = snapshotMetaParts(\n baseSnapshot,\n clientID,\n );\n\n // TODO(MP) Here we are using whether the cookie has changes as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // If other entities (eg, other clients) are modifying the client view\n // the client view can change but the lastMutationID stays the same.\n // So be careful here to reject only a lesser lastMutationID.\n if (response.lastMutationID < baseLastMutationID) {\n throw new Error(\n badOrderMessage(\n `lastMutationID`,\n String(response.lastMutationID),\n String(baseLastMutationID),\n ),\n );\n }\n\n const frozenCookie = deepFreeze(response.cookie ?? null);\n\n // If the cookie didn't change, it's a nop.\n // Otherwise, we will write a new commit, including for the case of just\n // a cookie change.\n if (deepEqual(frozenCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (response.lastMutationID !== baseLastMutationID) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationID did change`,\n );\n }\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n // We are going to need to adjust the indexes. Imagine we have just pulled:\n //\n // S1 - M1 - main\n // \\ S2 - sync\n //\n // Let's say S2 says that it contains up to M1. Are we safe at this moment\n // to set main to S2?\n //\n // No, because the Replicache protocol does not require a snapshot\n // containing M1 to have the same data as the client computed for M1!\n //\n // We must diff the main map in M1 against the main map in S2 and see if it\n // contains any changes. Whatever changes it contains must be applied to\n // all indexes.\n //\n // We start with the index definitions in the last commit that was\n // integrated into the new snapshot.\n const chain = await commitChain(mainHead, dagRead);\n let lastIntegrated: Commit<Meta> | undefined;\n for (const commit of chain) {\n if (\n (await commit.getMutationID(clientID, dagRead)) <=\n response.lastMutationID\n ) {\n lastIntegrated = commit;\n break;\n }\n }\n\n if (!lastIntegrated) {\n throw new Error('Internal invalid chain');\n }\n\n const dbWrite = await newWriteSnapshotSDD(\n baseSnapshot.chunk.hash,\n response.lastMutationID,\n frozenCookie,\n dagWrite,\n readIndexesForWrite(lastIntegrated, dagWrite, formatVersion),\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n const lastIntegratedMap = new BTreeRead(\n dagRead,\n formatVersion,\n lastIntegrated.valueHash,\n );\n\n for await (const change of dbWrite.map.diff(lastIntegratedMap)) {\n await updateIndexes(\n lc,\n dbWrite.indexes,\n change.key,\n () =>\n Promise.resolve((change as {oldValue?: FrozenJSONValue}).oldValue),\n (change as {newValue?: FrozenJSONValue}).newValue,\n );\n }\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion.Type,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n console.log(response.lastMutationIDChanges);\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\ntype MaybeEndPullResultBase<M extends Meta> = {\n replayMutations?: Commit<M>[];\n syncHead: Hash;\n diffs: DiffsMap;\n};\n\nexport type MaybeEndPullResultV0 = MaybeEndPullResultBase<LocalMetaSDD>;\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion.Type,\n): Promise<{\n syncHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const syncHead = await commitFromHash(syncHeadHash, dagRead);\n const pending: Commit<M>[] = [];\n const localMutations = await localMutations_1(mainHeadHash, dagRead);\n for (const commit of localMutations) {\n let cid = clientID;\n if (commitIsLocalDD31(commit)) {\n cid = commit.meta.clientID;\n }\n if (\n (await commit.getMutationID(cid, dagRead)) >\n (await syncHead.getMutationID(cid, dagRead))\n ) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n", "import * as valita from '@badrap/valita';\nimport {skipAssertJSONValue} from './config.js';\nimport type {ReadonlyJSONObject, ReadonlyJSONValue} from './json.js';\nimport {isJSONObject, isJSONValue} from './json.js';\nimport * as v from './valita.js';\n\nconst path: (string | number)[] = [];\n\nexport const jsonSchema: valita.Type<ReadonlyJSONValue> = v\n .unknown()\n .chain(v => {\n if (skipAssertJSONValue) {\n return valita.ok(v as ReadonlyJSONValue);\n }\n const rv = isJSONValue(v, path)\n ? valita.ok(v)\n : valita.err({\n message: `Not a JSON value`,\n path: path.slice(),\n });\n path.length = 0;\n return rv;\n });\n\nexport const jsonObjectSchema: valita.Type<ReadonlyJSONObject> = v\n .unknown()\n .chain(v => {\n if (skipAssertJSONValue) {\n return valita.ok(v as ReadonlyJSONObject);\n }\n const rv = isJSONObject(v, path)\n ? valita.ok(v)\n : valita.err({\n message: `Not a JSON object`,\n path: path.slice(),\n });\n path.length = 0;\n return rv;\n });\n", "import {assertObject} from '../../shared/src/asserts.js';\nimport {\n assertVersionNotSupportedResponse,\n type ClientStateNotFoundResponse,\n isClientStateNotFoundResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.js';\nimport {\n assertHTTPRequestInfo,\n type HTTPRequestInfo,\n} from './http-request-info.js';\nimport type {PushRequest} from './sync/push.js';\n\nexport type PusherResult = {\n response?: PushResponse | undefined;\n httpRequestInfo: HTTPRequestInfo;\n};\n\n/**\n * The response from a push can contain information about error conditions.\n */\nexport type PushResponse =\n | ClientStateNotFoundResponse\n | VersionNotSupportedResponse;\n\nexport function assertPusherResult(v: unknown): asserts v is PusherResult {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPushResponse(v.response);\n }\n}\n\nfunction assertPushResponse(v: unknown): asserts v is PushResponse {\n if (isClientStateNotFoundResponse(v)) {\n return;\n }\n assertVersionNotSupportedResponse(v);\n}\n\n/**\n * Pusher is the function type used to do the fetch part of a push. The request\n * is a POST request where the body is JSON with the type {@link PushRequest}.\n *\n * The return value should either be a {@link HTTPRequestInfo} or a\n * {@link PusherResult}. The reason for the two different return types is that\n * we didn't use to care about the response body of the push request. The\n * default pusher implementation checks if the response body is JSON and if it\n * matches the type {@link PusherResponse}. If it does, it is included in the\n * return value.\n */\nexport type Pusher = (\n requestBody: PushRequest,\n requestID: string,\n) => Promise<PusherResult>;\n\n/**\n * This error is thrown when the pusher fails for any reason.\n */\nexport class PushError extends Error {\n name = 'PushError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to push');\n this.causedBy = causedBy;\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport {jsonSchema} from '../../../shared/src/json-schema.js';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.js';\nimport * as valita from '../../../shared/src/valita.js';\nimport type {Store} from '../dag/store.js';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type LocalMetaSDD,\n commitIsLocalDD31,\n commitIsLocalSDD,\n localMutations,\n} from '../db/commit.js';\nimport type {FrozenJSONValue} from '../frozen-json.js';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.js';\nimport {ReportError} from '../replicache.js';\nimport {toError} from '../to-error.js';\nimport {withRead} from '../with-transactions.js';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.js';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client. This is the legacy\n * version (V0) and it is used when recovering mutations from old clients.\n */\nexport type MutationV0 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n};\n\nconst mutationV0Schema: valita.Type<MutationV0> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n});\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\ntype FrozenMutationV0 = Omit<MutationV0, 'args'> & {\n readonly args: FrozenJSONValue;\n};\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push). This is the legacy version (V0) and it is\n * still used when recovering mutations from old clients.\n */\nexport type PushRequestV0 = {\n pushVersion: 0;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientID: ClientID;\n mutations: MutationV0[];\n};\n\nconst pushRequestV0Schema: valita.Type<PushRequestV0> = valita.object({\n pushVersion: valita.literal(0),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientID: clientIDSchema,\n mutations: valita.array(mutationV0Schema),\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV0 | PushRequestV1;\n\nexport function assertPushRequestV0(\n value: unknown,\n): asserts value is PushRequestV0 {\n valita.assert(value, pushRequestV0Schema);\n}\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = FrozenMutationV0 & {\n readonly clientID: ClientID;\n};\n\nfunction convertSDD(lm: LocalMetaSDD): FrozenMutationV0 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n };\n}\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n let pushReq: PushRequestV0 | PushRequestV1;\n\n if (pushVersion === PUSH_VERSION_DD31) {\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID);\n const r: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n pushReq = r;\n } else {\n assert(pushVersion === PUSH_VERSION_SDD);\n const pushMutations: FrozenMutationV0[] = [];\n for (const commit of pending) {\n if (commitIsLocalSDD(commit)) {\n pushMutations.push(convertSDD(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n pushReq = {\n profileID,\n clientID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_SDD,\n schemaVersion,\n };\n }\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV0 | PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert, assertNotUndefined} from '../../shared/src/asserts.js';\nimport type {MaybePromise} from '../../shared/src/types.js';\nimport {throwChunkHasher} from './dag/chunk.js';\nimport {LazyStore} from './dag/lazy-store.js';\nimport {StoreImpl} from './dag/store-impl.js';\nimport type {Store} from './dag/store.js';\nimport {DEFAULT_HEAD_NAME} from './db/commit.js';\nimport {\n type ClientStateNotFoundResponse,\n type VersionNotSupportedResponse,\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.js';\nimport * as FormatVersion from './format-version-enum.js';\nimport {parseReplicacheFormatVersion as parseFormatVersion} from './format-version.js';\nimport {assertHash, newRandomHash} from './hash.js';\nimport type {HTTPRequestInfo} from './http-request-info.js';\nimport type {CreateStore} from './kv/store.js';\nimport {\n type ClientGroup,\n type ClientGroupMap,\n getClientGroups,\n disableClientGroup as persistDisableClientGroup,\n setClientGroups,\n} from './persist/client-groups.js';\nimport {\n type Client,\n type ClientMap,\n assertClientV4,\n getClients,\n setClients,\n} from './persist/clients.js';\nimport type {\n IDBDatabasesStore,\n IndexedDBDatabase,\n} from './persist/idb-databases-store.js';\nimport type {\n PullResponseOKV1,\n PullResponseV0,\n PullResponseV1,\n Puller,\n} from './puller.js';\nimport type {PushResponse, Pusher} from './pusher.js';\nimport type {ClientGroupID, ClientID} from './sync/ids.js';\nimport {beginPullV0, beginPullV1} from './sync/pull.js';\nimport {PUSH_VERSION_DD31, PUSH_VERSION_SDD, push} from './sync/push.js';\nimport {withRead, withWrite} from './with-transactions.js';\n\nconst MUTATION_RECOVERY_LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 10 * 2 ** 20; // 10 MB\n\ninterface ReplicacheDelegate {\n clientID: ClientID;\n closed: boolean;\n idbName: string;\n name: string;\n online: boolean;\n profileID: Promise<string>;\n puller: Puller;\n pusher: Pusher;\n}\n\ninterface MutationRecoveryOptions {\n delegate: ReplicacheDelegate;\n readonly wrapInOnlineCheck: (\n f: () => Promise<boolean>,\n name: string,\n ) => Promise<boolean>;\n readonly wrapInReauthRetries: <R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth?: () => MaybePromise<void>,\n postAuth?: () => MaybePromise<void>,\n ) => Promise<{\n result: R;\n authFailure: boolean;\n }>;\n readonly isPushDisabled: () => boolean;\n readonly isPullDisabled: () => boolean;\n readonly lc: LogContext;\n readonly enableMutationRecovery: boolean;\n readonly clientGroupIDPromise: Promise<ClientGroupID | undefined>;\n}\n\nexport class MutationRecovery {\n #recoveringMutations = false;\n readonly #options: MutationRecoveryOptions;\n\n constructor(options: MutationRecoveryOptions) {\n this.#options = options;\n }\n\n async recoverMutations(\n preReadClientMap: ClientMap | undefined,\n ready: Promise<unknown>,\n perdag: Store,\n idbDatabase: IndexedDBDatabase,\n idbDatabases: IDBDatabasesStore,\n createStore: CreateStore,\n ): Promise<boolean> {\n const {lc, enableMutationRecovery, isPushDisabled, delegate} =\n this.#options;\n\n if (\n !enableMutationRecovery ||\n this.#recoveringMutations ||\n !delegate.online ||\n delegate.closed ||\n isPushDisabled()\n ) {\n return false;\n }\n const stepDescription = 'Recovering mutations.';\n lc.debug?.('Start:', stepDescription);\n try {\n this.#recoveringMutations = true;\n await ready;\n await recoverMutationsFromPerdag(\n idbDatabase,\n this.#options,\n perdag,\n preReadClientMap,\n );\n for (const database of Object.values(await idbDatabases.getDatabases())) {\n if (delegate.closed) {\n lc.debug?.('Exiting early due to close:', stepDescription);\n return true;\n }\n if (\n database.replicacheName === delegate.name &&\n database.name !== delegate.idbName\n ) {\n switch (database.replicacheFormatVersion) {\n case FormatVersion.SDD:\n case FormatVersion.DD31:\n case FormatVersion.V6:\n case FormatVersion.V7:\n await recoverMutationsWithNewPerdag(\n database,\n this.#options,\n undefined,\n createStore,\n );\n }\n }\n }\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n } finally {\n lc.debug?.('End:', stepDescription);\n this.#recoveringMutations = false;\n }\n return true;\n }\n}\n\nfunction logMutationRecoveryError(\n e: unknown,\n lc: LogContext,\n stepDescription: string,\n closedDelegate: {closed: boolean},\n) {\n if (closedDelegate.closed) {\n lc.debug?.(\n `Mutation recovery error likely due to close during:\\n${stepDescription}\\nError:\\n`,\n e,\n );\n } else {\n lc.error?.(\n `Mutation recovery error during:\\n${stepDescription}\\nError:\\n`,\n e,\n );\n }\n}\n\n/**\n * @returns When mutations are recovered the resulting updated client map.\n * Otherwise undefined, which can be because there were no mutations to\n * recover, or because an error occurred when trying to recover the\n * mutations.\n */\nasync function recoverMutationsOfClientV4(\n client: Client,\n clientID: ClientID,\n perdag: Store,\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n formatVersion: FormatVersion.Type,\n): Promise<ClientMap | undefined> {\n assert(database.replicacheFormatVersion === FormatVersion.SDD);\n assertClientV4(client);\n\n const {\n delegate,\n lc,\n wrapInOnlineCheck,\n wrapInReauthRetries,\n isPushDisabled,\n isPullDisabled,\n } = options;\n const selfClientID = delegate.clientID;\n if (selfClientID === clientID) {\n return;\n }\n if (client.lastServerAckdMutationID >= client.mutationID) {\n return;\n }\n const stepDescription = `Recovering mutations for ${clientID}.`;\n lc.debug?.('Start:', stepDescription);\n const lazyDagForOtherClient = new LazyStore(\n perdag,\n MUTATION_RECOVERY_LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n throwChunkHasher,\n assertHash,\n );\n try {\n await withWrite(lazyDagForOtherClient, write =>\n write.setHead(DEFAULT_HEAD_NAME, client.headHash),\n );\n\n if (isPushDisabled()) {\n lc.debug?.(\n `Cannot recover mutations for client ${clientID} because push is disabled.`,\n );\n return;\n }\n const {pusher} = delegate;\n\n const pushDescription = 'recoveringMutationsPush';\n const pushSucceeded = await wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n assertNotUndefined(lazyDagForOtherClient);\n const pusherResult = await push(\n requestID,\n lazyDagForOtherClient,\n requestLc,\n await delegate.profileID,\n undefined,\n clientID,\n pusher,\n database.schemaVersion,\n PUSH_VERSION_SDD,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n },\n pushDescription,\n lc,\n );\n\n return (\n !!pusherResult && pusherResult.httpRequestInfo.httpStatusCode === 200\n );\n }, pushDescription);\n if (!pushSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientID} due to a push error.`,\n );\n return;\n }\n\n if (isPullDisabled()) {\n lc.debug?.(\n `Cannot confirm mutations were recovered for client ${clientID} ` +\n `because pull is disabled.`,\n );\n return;\n }\n const {puller} = delegate;\n\n const pullDescription = 'recoveringMutationsPull';\n let pullResponse: PullResponseV0 | undefined;\n const pullSucceeded = await wrapInOnlineCheck(async () => {\n const {result: beginPullResponse} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n const beginPullResponse = await beginPullV0(\n await delegate.profileID,\n clientID,\n database.schemaVersion,\n puller,\n requestID,\n lazyDagForOtherClient,\n formatVersion,\n requestLc,\n false,\n );\n return {\n result: beginPullResponse,\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n pullDescription,\n lc,\n );\n ({pullResponse} = beginPullResponse);\n return (\n !!pullResponse &&\n beginPullResponse.httpRequestInfo.httpStatusCode === 200\n );\n }, pullDescription);\n if (!pullSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientID} due to a pull error.`,\n );\n return;\n }\n\n if (lc.debug && pullResponse) {\n if (isClientStateNotFoundResponse(pullResponse)) {\n lc.debug?.(\n `Client ${selfClientID} cannot recover mutations for client ` +\n `${clientID}. The client no longer exists on the server.`,\n );\n } else if (isVersionNotSupportedResponse(pullResponse)) {\n lc.debug?.(\n `Version is not supported on the server. versionType: ${pullResponse.versionType}. Cannot recover mutations for client ${clientID}.`,\n );\n } else {\n lc.debug?.(\n `Client ${selfClientID} recovered mutations for client ` +\n `${clientID}. Details`,\n {\n mutationID: client.mutationID,\n lastServerAckdMutationID: client.lastServerAckdMutationID,\n lastMutationID: pullResponse.lastMutationID,\n },\n );\n }\n }\n\n return await withWrite(perdag, async dagWrite => {\n const clients = await getClients(dagWrite);\n const clientToUpdate = clients.get(clientID);\n if (!clientToUpdate) {\n return clients;\n }\n\n assertClientV4(clientToUpdate);\n\n const setNewClients = async (newClients: ClientMap) => {\n await setClients(newClients, dagWrite);\n return newClients;\n };\n\n if (\n isClientStateNotFoundResponse(pullResponse) ||\n // Even though SDD did not have VersionNotSupported we can still get\n // this if the server was upgraded to handle this. It seems better to\n // delete the client at this point.\n isVersionNotSupportedResponse(pullResponse)\n ) {\n const newClients = new Map(clients);\n newClients.delete(clientID);\n return setNewClients(newClients);\n }\n\n assert(pullResponse);\n if (\n clientToUpdate.lastServerAckdMutationID >= pullResponse.lastMutationID\n ) {\n return clients;\n }\n\n const newClients = new Map(clients).set(clientID, {\n ...clientToUpdate,\n lastServerAckdMutationID: pullResponse.lastMutationID,\n });\n return setNewClients(newClients);\n });\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n } finally {\n await lazyDagForOtherClient.close();\n lc.debug?.('End:', stepDescription);\n }\n return;\n}\n\nasync function recoverMutationsWithNewPerdag(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n preReadClientMap: ClientMap | undefined,\n createStore: CreateStore,\n) {\n const perKvStore = createStore(database.name);\n const perdag = new StoreImpl(perKvStore, newRandomHash, assertHash);\n try {\n await recoverMutationsFromPerdag(\n database,\n options,\n perdag,\n preReadClientMap,\n );\n } finally {\n await perdag.close();\n }\n}\n\nfunction recoverMutationsFromPerdag(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n perdag: Store,\n preReadClientMap: ClientMap | undefined,\n): Promise<void> {\n if (database.replicacheFormatVersion >= FormatVersion.DD31) {\n return recoverMutationsFromPerdagDD31(database, options, perdag);\n }\n return recoverMutationsFromPerdagSDD(\n database,\n options,\n perdag,\n preReadClientMap,\n );\n}\n\nasync function recoverMutationsFromPerdagSDD(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n perdag: Store,\n preReadClientMap: ClientMap | undefined,\n): Promise<void> {\n const {delegate, lc} = options;\n const stepDescription = `Recovering mutations from db ${database.name}.`;\n lc.debug?.('Start:', stepDescription);\n try {\n const formatVersion = parseFormatVersion(database.replicacheFormatVersion);\n let clientMap: ClientMap | undefined =\n preReadClientMap || (await withRead(perdag, read => getClients(read)));\n const clientIDsVisited = new Set<ClientID>();\n while (clientMap) {\n let newClientMap: ClientMap | undefined;\n for (const [clientID, client] of clientMap) {\n if (delegate.closed) {\n lc.debug?.('Exiting early due to close:', stepDescription);\n return;\n }\n if (!clientIDsVisited.has(clientID)) {\n clientIDsVisited.add(clientID);\n newClientMap = await recoverMutationsOfClientV4(\n client,\n clientID,\n perdag,\n database,\n options,\n formatVersion,\n );\n if (newClientMap) {\n break;\n }\n }\n }\n clientMap = newClientMap;\n }\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n }\n lc.debug?.('End:', stepDescription);\n}\n\nasync function recoverMutationsFromPerdagDD31(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n perdag: Store,\n): Promise<void> {\n const {delegate, lc} = options;\n const stepDescription = `Recovering mutations from db ${database.name}.`;\n lc.debug?.('Start:', stepDescription);\n try {\n const formatVersion = parseFormatVersion(database.replicacheFormatVersion);\n let clientGroups: ClientGroupMap | undefined = await withRead(\n perdag,\n read => getClientGroups(read),\n );\n const clientGroupIDsVisited = new Set<ClientGroupID>();\n while (clientGroups) {\n let newClientGroups: ClientGroupMap | undefined;\n for (const [clientGroupID, clientGroup] of clientGroups) {\n if (delegate.closed) {\n lc.debug?.('Exiting early due to close:', stepDescription);\n return;\n }\n if (!clientGroupIDsVisited.has(clientGroupID)) {\n clientGroupIDsVisited.add(clientGroupID);\n newClientGroups = await recoverMutationsOfClientGroupDD31(\n clientGroup,\n clientGroupID,\n perdag,\n database,\n options,\n formatVersion,\n );\n if (newClientGroups) {\n break;\n }\n }\n }\n clientGroups = newClientGroups;\n }\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n }\n lc.debug?.('End:', stepDescription);\n}\n\nfunction isResponseThatShouldDisableClientGroup(\n response: PushResponse | PullResponseV1 | undefined,\n): response is ClientStateNotFoundResponse | VersionNotSupportedResponse {\n return (\n isClientStateNotFoundResponse(response) ||\n isVersionNotSupportedResponse(response)\n );\n}\n\nasync function disableClientGroup(\n lc: LogContext,\n selfClientGroupID: string,\n clientGroupID: string,\n response: ClientStateNotFoundResponse | VersionNotSupportedResponse,\n perdag: Store,\n) {\n if (isClientStateNotFoundResponse(response)) {\n lc.debug?.(\n `Client group ${selfClientGroupID} cannot recover mutations for client group ${clientGroupID}. The client group is unknown on the server. Marking it as disabled.`,\n );\n } else if (isVersionNotSupportedResponse(response)) {\n lc.debug?.(\n `Client group ${selfClientGroupID} cannot recover mutations for client group ${clientGroupID}. The client group's version is not supported on the server. versionType: ${response.versionType}. Marking it as disabled.`,\n );\n }\n // The client group is not the main client group so we do not need the\n // Replicache instance to update its internal _isClientGroupDisabled\n // property.\n await withWrite(perdag, perdagWrite =>\n persistDisableClientGroup(clientGroupID, perdagWrite),\n );\n}\n\n/**\n * @returns When mutations are recovered the resulting updated client group map.\n * Otherwise undefined, which can be because there were no mutations to\n * recover, or because an error occurred when trying to recover the mutations.\n */\nasync function recoverMutationsOfClientGroupDD31(\n clientGroup: ClientGroup,\n clientGroupID: ClientGroupID,\n perdag: Store,\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n formatVersion: FormatVersion.Type,\n): Promise<ClientGroupMap | undefined> {\n assert(database.replicacheFormatVersion >= FormatVersion.DD31);\n\n const {\n delegate,\n lc,\n wrapInOnlineCheck,\n wrapInReauthRetries,\n isPushDisabled,\n isPullDisabled,\n clientGroupIDPromise,\n } = options;\n\n const selfClientGroupID = await clientGroupIDPromise;\n assertNotUndefined(selfClientGroupID);\n if (selfClientGroupID === clientGroupID) {\n return;\n }\n\n let clientID: ClientID | undefined;\n\n // If all local mutations have been applied then exit.\n let allAckd = true;\n for (const [cid, mutationID] of Object.entries(clientGroup.mutationIDs)) {\n // if not present then the server has not acknowledged this client's mutations.\n if (\n !clientGroup.lastServerAckdMutationIDs[cid] ||\n clientGroup.lastServerAckdMutationIDs[cid] < mutationID\n ) {\n clientID = cid;\n allAckd = false;\n break;\n }\n }\n if (allAckd) {\n return;\n }\n\n if (clientGroup.disabled) {\n lc.debug?.(\n `Not recovering mutations for client group ${clientGroupID} because group is disabled.`,\n );\n return;\n }\n\n const stepDescription = `Recovering mutations for client group ${clientGroupID}.`;\n lc.debug?.('Start:', stepDescription);\n const lazyDagForOtherClientGroup = new LazyStore(\n perdag,\n MUTATION_RECOVERY_LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n throwChunkHasher,\n assertHash,\n );\n try {\n await withWrite(lazyDagForOtherClientGroup, write =>\n write.setHead(DEFAULT_HEAD_NAME, clientGroup.headHash),\n );\n\n if (isPushDisabled()) {\n lc.debug?.(\n `Cannot recover mutations for client group ${clientGroupID} because push is disabled.`,\n );\n return;\n }\n\n const {pusher} = delegate;\n\n const pushDescription = 'recoveringMutationsPush';\n const pushSucceeded = await wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n assert(clientID);\n assert(lazyDagForOtherClientGroup);\n const pusherResult = await push(\n requestID,\n lazyDagForOtherClientGroup,\n requestLc,\n await delegate.profileID,\n clientGroupID,\n // TODO(DD31): clientID is not needed in DD31. It is currently kept for debugging purpose.\n clientID,\n pusher,\n database.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n },\n pushDescription,\n lc,\n );\n if (!pusherResult) {\n return false;\n }\n const pusherResponse = pusherResult.response;\n if (isResponseThatShouldDisableClientGroup(pusherResponse)) {\n await disableClientGroup(\n lc,\n selfClientGroupID,\n clientGroupID,\n pusherResponse,\n perdag,\n );\n return false;\n }\n return pusherResult.httpRequestInfo.httpStatusCode === 200;\n }, pushDescription);\n if (!pushSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientGroupID} due to a push error.`,\n );\n return;\n }\n\n if (isPullDisabled()) {\n lc.debug?.(\n `Cannot confirm mutations were recovered for client ${clientGroupID} ` +\n `because pull is disabled.`,\n );\n return;\n }\n const {puller} = delegate;\n\n const pullDescription = 'recoveringMutationsPull';\n let okPullResponse: PullResponseOKV1 | undefined;\n const pullSucceeded = await wrapInOnlineCheck(async () => {\n const {result: beginPullResponse} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n assert(clientID);\n const beginPullResponse = await beginPullV1(\n await delegate.profileID,\n clientID,\n clientGroupID,\n database.schemaVersion,\n puller,\n requestID,\n lazyDagForOtherClientGroup,\n formatVersion,\n requestLc,\n false,\n );\n return {\n result: beginPullResponse,\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n pullDescription,\n lc,\n );\n const {pullResponse} = beginPullResponse;\n if (isResponseThatShouldDisableClientGroup(pullResponse)) {\n await disableClientGroup(\n lc,\n selfClientGroupID,\n clientGroupID,\n pullResponse,\n perdag,\n );\n return false;\n }\n if (\n !pullResponse ||\n beginPullResponse.httpRequestInfo.httpStatusCode !== 200\n ) {\n return false;\n }\n okPullResponse = pullResponse;\n return true;\n }, pullDescription);\n if (!pullSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientGroupID} due to a pull error.`,\n );\n return;\n }\n\n // TODO(arv): Refactor to make pullResponse a const.\n // pullResponse must be non undefined because pullSucceeded is true.\n assert(okPullResponse);\n lc.debug?.(\n `Client group ${selfClientGroupID} recovered mutations for client group ${clientGroupID}. Details`,\n {\n mutationIDs: clientGroup.mutationIDs,\n lastServerAckdMutationIDs: clientGroup.lastServerAckdMutationIDs,\n lastMutationIDChanges: okPullResponse.lastMutationIDChanges,\n },\n );\n\n return await withWrite(perdag, async dagWrite => {\n const clientGroups = await getClientGroups(dagWrite);\n const clientGroupToUpdate = clientGroups.get(clientGroupID);\n if (!clientGroupToUpdate) {\n return clientGroups;\n }\n\n assert(okPullResponse);\n const lastServerAckdMutationIDsUpdates: Record<ClientID, number> = {};\n let anyMutationIDsUpdated = false;\n for (const [clientID, lastMutationIDChange] of Object.entries(\n okPullResponse.lastMutationIDChanges,\n )) {\n if (\n (clientGroupToUpdate.lastServerAckdMutationIDs[clientID] ?? 0) <\n lastMutationIDChange\n ) {\n lastServerAckdMutationIDsUpdates[clientID] = lastMutationIDChange;\n anyMutationIDsUpdated = true;\n }\n }\n if (!anyMutationIDsUpdated) {\n return clientGroups;\n }\n\n const newClientGroups = new Map(clientGroups).set(clientGroupID, {\n ...clientGroupToUpdate,\n lastServerAckdMutationIDs: {\n ...clientGroupToUpdate.lastServerAckdMutationIDs,\n ...lastServerAckdMutationIDsUpdates,\n },\n });\n await setClientGroups(newClientGroups, dagWrite);\n return newClientGroups;\n });\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n } finally {\n await lazyDagForOtherClientGroup.close();\n lc.debug?.('End:', stepDescription);\n }\n return;\n}\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\n\nclass NoopBroadcastChannel implements BroadcastChannel {\n readonly name: string;\n\n onmessage: ((this: BroadcastChannel, ev: MessageEvent<any>) => any) | null =\n null;\n\n onmessageerror:\n | ((this: BroadcastChannel, ev: MessageEvent<any>) => any)\n | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n addEventListener(): void {\n // noop\n }\n removeEventListener(): void {\n // noop\n }\n dispatchEvent(): boolean {\n return false;\n }\n\n close(): void {\n // noop\n }\n\n postMessage(): void {\n // noop\n }\n}\n\nconst bc: typeof BroadcastChannel =\n typeof BroadcastChannel === 'undefined'\n ? NoopBroadcastChannel\n : BroadcastChannel;\n\nexport {bc as BroadcastChannel};\n", "import {BroadcastChannel} from './broadcast-channel.js';\nimport type {Read, Store} from './dag/store.js';\nimport {getClientGroup} from './persist/client-groups.js';\nimport {withRead} from './with-transactions.js';\n\n// Older clients (<= replicache@13.0.1), listened on this channel name\n// and *asserted* that the messages received were an array containing exactly\n// one string.\nfunction makeChannelNameV0(replicacheName: string): string {\n return `replicache-new-client-group:${replicacheName}`;\n}\n\n// This channel name was introduced when we first needed to change the message\n// format. The design of the messages sent on this channel allows for\n// the message content to be extended in the future in a way that is\n// forward and backwards compatible. The message format can be extended\n// by adding new *optional* fields.\nfunction makeChannelNameV1(replicacheName: string): string {\n return `replicache-new-client-group-v1:${replicacheName}`;\n}\n\nexport {\n makeChannelNameV0 as makeChannelNameV0ForTesting,\n makeChannelNameV1 as makeChannelNameV1ForTesting,\n};\n\n// This message type can be extended with optional properties.\ntype NewClientChannelMessageV1 = {clientGroupID: string; idbName: string};\n\nfunction isNewClientChannelMessageV1(\n message: unknown,\n): message is NewClientChannelMessageV1 {\n return (\n typeof message === 'object' &&\n typeof (message as {clientGroupID: unknown}).clientGroupID === 'string' &&\n typeof (message as {idbName: unknown}).idbName === 'string'\n );\n}\n\nexport function initNewClientChannel(\n replicacheName: string,\n idbName: string,\n signal: AbortSignal,\n clientGroupID: string,\n isNewClientGroup: boolean,\n onUpdateNeeded: () => void,\n perdag: Store,\n) {\n if (signal.aborted) {\n return;\n }\n\n const channelV1 = new BroadcastChannel(makeChannelNameV1(replicacheName));\n if (isNewClientGroup) {\n channelV1.postMessage({clientGroupID, idbName});\n // Send expected format to V0 channel for old clients.\n const channelV0 = new BroadcastChannel(makeChannelNameV0(replicacheName));\n channelV0.postMessage([clientGroupID]);\n channelV0.close();\n }\n\n channelV1.onmessage = async (e: MessageEvent) => {\n const {data} = e;\n if (isNewClientChannelMessageV1(data)) {\n const {clientGroupID: newClientGroupID, idbName: newClientIDBName} = data;\n if (newClientGroupID !== clientGroupID) {\n if (newClientIDBName === idbName) {\n // Check if this client can see the new client's newClientGroupID in its\n // perdag. It should be able to if the clients share persistent\n // storage. However, with `ReplicacheOption.kvStore`\n // and `IDBStoreWithMemFallback` clients may not actually share\n // persistent storage. If storage is not shared, then there is no point\n // in updating, since clients cannot sync locally. If clients do update\n // in this case, they can continually cause each other to update, since\n // on each update the clients get assigned a new client group.\n const updateNeeded = await withRead(\n perdag,\n async (perdagRead: Read) =>\n (await getClientGroup(newClientGroupID, perdagRead)) !==\n undefined,\n );\n if (updateNeeded) {\n onUpdateNeeded();\n }\n } else {\n // Idb name is different, indicating new schema or format version.\n // Update to get assigned to newClientIDBName, and hopefully\n // newClientGroupID.\n // If storage is not actually shared (i.e. due to\n // `ReplicacheOption.kvStore`\n // or `IDBStoreWithMemFallback`) the new client will not\n // get assigned to newClientGroupID, but should get the\n // newClientIDBName.\n // Note: we don't try to read from newClientIDBName to see\n // if this client shares storage with the new client, because\n // the newClientIDBName may have a format version this client\n // cannot read.\n onUpdateNeeded();\n return;\n }\n }\n }\n };\n\n signal.addEventListener('abort', () => channelV1.close(), {once: true});\n}\n", "import {assertObject, assertString} from '../../shared/src/asserts.js';\nimport {BroadcastChannel} from './broadcast-channel.js';\nimport type {ClientGroupID, ClientID} from './sync/ids.js';\n\nfunction makeChannelName(replicacheName: string): string {\n return `replicache-on-persist:${replicacheName}`;\n}\n\nexport type PersistInfo = {\n clientGroupID: ClientGroupID;\n clientID: ClientID;\n};\n\nexport type OnPersist = (persistInfo: PersistInfo) => void;\n\ntype HandlePersist = OnPersist;\n\nfunction assertPersistInfo(value: unknown): asserts value is PersistInfo {\n assertObject(value);\n assertString(value.clientGroupID);\n assertString(value.clientID);\n}\n\nexport function initOnPersistChannel(\n replicacheName: string,\n signal: AbortSignal,\n handlePersist: HandlePersist,\n): OnPersist {\n if (signal.aborted) {\n return () => undefined;\n }\n const channel = new BroadcastChannel(makeChannelName(replicacheName));\n\n channel.onmessage = e => {\n const {data} = e;\n assertPersistInfo(data);\n handlePersist({\n clientGroupID: data.clientGroupID,\n clientID: data.clientID,\n });\n };\n\n signal.addEventListener('abort', () => channel.close(), {once: true});\n\n return (persistInfo: PersistInfo) => {\n if (signal.aborted) {\n return;\n }\n channel.postMessage(persistInfo);\n handlePersist(persistInfo);\n };\n}\n", "import type {ReadonlyJSONValue} from '../../shared/src/json.js';\nimport {mustGetHeadHash, type Read} from './dag/store.js';\nimport {DEFAULT_HEAD_NAME, localMutationsDD31} from './db/commit.js';\nimport type {ClientID} from './sync/ids.js';\n\nexport type PendingMutation = {\n readonly name: string;\n readonly id: number;\n readonly args: ReadonlyJSONValue;\n readonly clientID: ClientID;\n};\n\n/**\n * This returns the pending changes with the oldest mutations first.\n */\nexport async function pendingMutationsForAPI(\n dagRead: Read,\n): Promise<readonly PendingMutation[]> {\n const mainHeadHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagRead);\n const pending = await localMutationsDD31(mainHeadHash, dagRead);\n return pending\n .map(p => ({\n id: p.meta.mutationID,\n name: p.meta.mutatorName,\n args: p.meta.mutatorArgsJSON,\n clientID: p.meta.clientID,\n }))\n .reverse();\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.js';\nimport {sleep} from '../../shared/src/sleep.js';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.js';\nimport type {Store} from '../dag/store.js';\nimport type {ClientID} from '../sync/ids.js';\nimport {withWrite} from '../with-transactions.js';\nimport {type ClientMap, getClients, setClients} from './clients.js';\n\n/**\n * The maximum time a client can be inactive before it is garbage collected.\n * This means that this is the maximum time a tab can be in the background\n * (frozen) and still be able to sync when it comes back to the foreground.\n */\nexport const CLIENT_MAX_INACTIVE_TIME = 24 * 60 * 60 * 1000; // 24 hours\n\n/**\n * How frequently to try to garbage collect clients.\n */\nexport const GC_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\nlet latestGCUpdate: Promise<ClientMap> | undefined;\nexport function getLatestGCUpdate(): Promise<ClientMap> | undefined {\n return latestGCUpdate;\n}\n\nexport function initClientGC(\n clientID: ClientID,\n dagStore: Store,\n clientMaxInactiveTime: number,\n gcInterval: number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'ClientGC',\n () => {\n latestGCUpdate = gcClients(clientID, dagStore, clientMaxInactiveTime);\n return latestGCUpdate;\n },\n () => gcInterval,\n lc,\n signal,\n );\n}\n\nfunction gcClients(\n clientID: ClientID,\n dagStore: Store,\n clientMaxInactiveTime: number,\n): Promise<ClientMap> {\n return withWrite(dagStore, async dagWrite => {\n const now = Date.now();\n const clients = await getClients(dagWrite);\n const clientsAfterGC = Array.from(clients).filter(\n ([id, client]) =>\n id === clientID /* never collect ourself */ ||\n now - client.heartbeatTimestampMs <= clientMaxInactiveTime,\n );\n if (clientsAfterGC.length === clients.size) {\n return clients;\n }\n const newClients = new Map(clientsAfterGC);\n await setClients(newClients, dagWrite);\n return newClients;\n });\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.js';\nimport type {Store} from '../dag/store.js';\nimport {withWrite} from '../with-transactions.js';\nimport {\n type ClientGroupMap,\n clientGroupHasPendingMutations,\n getClientGroups,\n setClientGroups,\n} from './client-groups.js';\nimport {assertClientV6, getClients} from './clients.js';\n\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\nlet latestGCUpdate: Promise<ClientGroupMap> | undefined;\nexport function getLatestGCUpdate(): Promise<ClientGroupMap> | undefined {\n return latestGCUpdate;\n}\n\nexport function initClientGroupGC(\n dagStore: Store,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'ClientGroupGC',\n () => {\n latestGCUpdate = gcClientGroups(dagStore);\n return latestGCUpdate;\n },\n () => GC_INTERVAL_MS,\n lc,\n signal,\n );\n}\n\n/**\n * This removes client groups that have no clients and no pending mutations.\n */\nexport function gcClientGroups(dagStore: Store): Promise<ClientGroupMap> {\n return withWrite(dagStore, async tx => {\n const clients = await getClients(tx);\n const clientGroupIDs = new Set();\n for (const client of clients.values()) {\n assertClientV6(client);\n clientGroupIDs.add(client.clientGroupID);\n }\n const clientGroups = new Map();\n for (const [clientGroupID, clientGroup] of await getClientGroups(tx)) {\n if (\n clientGroupIDs.has(clientGroupID) ||\n clientGroupHasPendingMutations(clientGroup)\n ) {\n clientGroups.set(clientGroupID, clientGroup);\n }\n }\n await setClientGroups(clientGroups, tx);\n return clientGroups;\n });\n}\n", "import {randomUint64} from '../../../shared/src/random-uint64.js';\nimport {dropIDBStoreWithMemFallback} from '../kv/idb-store-with-mem-fallback.js';\n\nconst IDB_DATABASES_VERSION = 0;\nconst IDB_DATABASES_DB_NAME = 'replicache-dbs-v' + IDB_DATABASES_VERSION;\n\nlet testNamespace = '';\n\n/** Namespace db name in test to isolate tests' indexeddb state. */\nexport function setupForTest(): void {\n testNamespace = randomUint64().toString(36);\n}\n\nexport function teardownForTest(): Promise<void> {\n const idbDatabasesDBName = getIDBDatabasesDBName();\n testNamespace = '';\n return dropIDBStoreWithMemFallback(idbDatabasesDBName);\n}\n\nexport function getIDBDatabasesDBName(): string {\n return testNamespace + IDB_DATABASES_DB_NAME;\n}\n", "import {\n assert,\n assertNumber,\n assertObject,\n assertString,\n} from '../../../shared/src/asserts.js';\nimport {deepFreeze} from '../frozen-json.js';\nimport type {CreateStore, Read, Store} from '../kv/store.js';\nimport {withRead, withWrite} from '../with-transactions.js';\nimport {getIDBDatabasesDBName} from './idb-databases-store-db-name.js';\nimport {makeClientID} from './make-client-id.js';\n\nconst DBS_KEY = 'dbs';\nconst PROFILE_ID_KEY = 'profileId';\n\n// TODO: make an opaque type\nexport type IndexedDBName = string;\n\nexport type IndexedDBDatabase = {\n readonly name: IndexedDBName;\n readonly replicacheName: string;\n readonly replicacheFormatVersion: number;\n readonly schemaVersion: string;\n readonly lastOpenedTimestampMS?: number;\n};\n\nexport type IndexedDBDatabaseRecord = {\n readonly [name: IndexedDBName]: IndexedDBDatabase;\n};\n\nfunction assertIndexedDBDatabaseRecord(\n value: unknown,\n): asserts value is IndexedDBDatabaseRecord {\n assertObject(value);\n for (const [name, db] of Object.entries(value)) {\n assertString(name);\n assertIndexedDBDatabase(db);\n assert(name === db.name);\n }\n}\n\nfunction assertIndexedDBDatabase(\n value: unknown,\n): asserts value is IndexedDBDatabase {\n assertObject(value);\n assertString(value.name);\n assertString(value.replicacheName);\n assertNumber(value.replicacheFormatVersion);\n assertString(value.schemaVersion);\n if (value.lastOpenedTimestampMS !== undefined) {\n assertNumber(value.lastOpenedTimestampMS);\n }\n}\n\nexport class IDBDatabasesStore {\n readonly #kvStore: Store;\n\n constructor(createKVStore: CreateStore) {\n this.#kvStore = createKVStore(getIDBDatabasesDBName());\n }\n\n putDatabase(db: IndexedDBDatabase): Promise<IndexedDBDatabaseRecord> {\n return this.#putDatabase({...db, lastOpenedTimestampMS: Date.now()});\n }\n\n putDatabaseForTesting(\n db: IndexedDBDatabase,\n ): Promise<IndexedDBDatabaseRecord> {\n return this.#putDatabase(db);\n }\n\n #putDatabase(db: IndexedDBDatabase): Promise<IndexedDBDatabaseRecord> {\n return withWrite(this.#kvStore, async write => {\n const oldDbRecord = await getDatabases(write);\n const dbRecord = {\n ...oldDbRecord,\n [db.name]: db,\n };\n await write.put(DBS_KEY, dbRecord);\n return dbRecord;\n });\n }\n\n clearDatabases(): Promise<void> {\n return withWrite(this.#kvStore, write => write.del(DBS_KEY));\n }\n\n deleteDatabases(names: Iterable<IndexedDBName>): Promise<void> {\n return withWrite(this.#kvStore, async write => {\n const oldDbRecord = await getDatabases(write);\n const dbRecord = {\n ...oldDbRecord,\n };\n for (const name of names) {\n delete dbRecord[name];\n }\n await write.put(DBS_KEY, dbRecord);\n });\n }\n\n getDatabases(): Promise<IndexedDBDatabaseRecord> {\n return withRead(this.#kvStore, getDatabases);\n }\n\n close(): Promise<void> {\n return this.#kvStore.close();\n }\n\n getProfileID(): Promise<string> {\n return withWrite(this.#kvStore, async write => {\n let profileId = await write.get(PROFILE_ID_KEY);\n if (profileId === undefined) {\n // Profile id is 'p' followed by a random number.\n profileId = `p${makeClientID()}`;\n await write.put(PROFILE_ID_KEY, profileId);\n }\n assertString(profileId);\n return profileId;\n });\n }\n}\n\nasync function getDatabases(read: Read): Promise<IndexedDBDatabaseRecord> {\n let dbRecord = await read.get(DBS_KEY);\n if (!dbRecord) {\n dbRecord = deepFreeze({});\n }\n assertIndexedDBDatabaseRecord(dbRecord);\n return dbRecord;\n}\n", "import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport {initBgIntervalProcess} from '../bg-interval.js';\nimport {StoreImpl} from '../dag/store-impl.js';\nimport type {Store} from '../dag/store.js';\nimport * as FormatVersion from '../format-version-enum.js';\nimport {assertHash, newRandomHash} from '../hash.js';\nimport {IDBStore} from '../kv/idb-store.js';\nimport type {DropStore, StoreProvider} from '../kv/store.js';\nimport {createLogContext} from '../log-options.js';\nimport {getKVStoreProvider} from '../replicache.js';\nimport {withRead} from '../with-transactions.js';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.js';\nimport {type ClientMap, getClients} from './clients.js';\nimport type {IndexedDBDatabase} from './idb-databases-store.js';\nimport {IDBDatabasesStore} from './idb-databases-store.js';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * If an IDB database is older than MAX_AGE, then it can be collected.\n */\nexport const SDD_IDB_MAX_AGE = 30 * 24 * 60 * 60 * 1000; // 1 month\n\n/**\n * If an IDB database is older than DD31_MAX_AGE **and** has no pending\n * mutations, then it can be collected.\n */\nexport const DD31_IDB_MAX_AGE = 14 * 24 * 60 * 60 * 1000; // 2 weeks\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n collectInterval: number,\n initialCollectDelay: number,\n sddMaxAge: number,\n dd31MaxAge: number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n sddMaxAge,\n dd31MaxAge,\n kvDropStore,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n sddMaxAge: number,\n dd31MaxAge: number,\n kvDropStore: DropStore,\n newDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases) as IndexedDBDatabase[];\n const canCollectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await canCollectDatabase(db, now, sddMaxAge, dd31MaxAge, newDagStore),\n ] as const,\n ),\n );\n\n const namesToRemove = canCollectResults\n .filter(result => result[1])\n .map(result => result[0]);\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n namesToRemove,\n kvDropStore,\n );\n if (errors.length) {\n throw errors[0];\n }\n}\n\nasync function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\nfunction defaultNewDagStore(name: string): Store {\n const perKvStore = new IDBStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\nasync function canCollectDatabase(\n db: IndexedDBDatabase,\n now: number,\n sddMaxAge: number,\n dd31MaxAge: number,\n newDagStore: typeof defaultNewDagStore,\n): Promise<boolean> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return false;\n }\n\n // 0 is used in testing\n if (db.lastOpenedTimestampMS !== undefined) {\n const isDD31 = db.replicacheFormatVersion >= FormatVersion.DD31;\n\n // - For SDD we can delete the database if it is older than maxAge.\n // - For DD31 we can delete the database if it is older than dd31MaxAge and\n // there are no pending mutations.\n if (now - db.lastOpenedTimestampMS < (isDD31 ? dd31MaxAge : sddMaxAge)) {\n return false;\n }\n\n if (!isDD31) {\n return true;\n }\n\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n );\n return !(await anyPendingMutationsInClientGroups(newDagStore(db.name)));\n }\n\n // For legacy databases we do not have a lastOpenedTimestampMS so we check the\n // time stamps of the clients\n const perdag = newDagStore(db.name);\n const clientMap = await withRead(perdag, getClients);\n await perdag.close();\n\n return allClientsOlderThan(clientMap, now, sddMaxAge);\n}\n\nfunction allClientsOlderThan(\n clients: ClientMap,\n now: number,\n maxAge: number,\n): boolean {\n for (const client of clients.values()) {\n if (now - client.heartbeatTimestampMs < maxAge) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Deletes a single Replicache database.\n * @param dbName\n * @param createKVStore\n */\n\nexport async function dropDatabase(\n dbName: string,\n opts?: DropDatabaseOptions | undefined,\n) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n await dropDatabaseInternal(\n dbName,\n new IDBDatabasesStore(kvStoreProvider.create),\n kvStoreProvider.drop,\n );\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n */\nexport async function dropAllDatabases(\n opts?: DropDatabaseOptions | undefined,\n): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropAllDatabases: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n const store = new IDBDatabasesStore(kvStoreProvider.create);\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases).map(db => db.name);\n const result = await dropDatabases(store, dbNames, kvStoreProvider.drop);\n return result;\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(\n opts?: DropDatabaseOptions | undefined,\n) {\n return dropAllDatabases(opts);\n}\n\nasync function anyPendingMutationsInClientGroups(\n perdag: Store,\n): Promise<boolean> {\n const clientGroups = await withRead(perdag, getClientGroups);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return true;\n }\n }\n return false;\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.js';\nimport type {Store} from '../dag/store.js';\nimport type {ClientID} from '../sync/ids.js';\nimport {withWrite} from '../with-transactions.js';\nimport {\n type ClientMap,\n ClientStateNotFoundError,\n getClients,\n setClients,\n} from './clients.js';\n\nexport const HEARTBEAT_INTERVAL = 60 * 1000;\n\nexport let latestHeartbeatUpdate: Promise<ClientMap> | undefined;\n\nexport function startHeartbeats(\n clientID: ClientID,\n dagStore: Store,\n onClientStateNotFound: () => void,\n heartbeatIntervalMs: number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'Heartbeat',\n async () => {\n latestHeartbeatUpdate = writeHeartbeat(clientID, dagStore);\n try {\n return await latestHeartbeatUpdate;\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n onClientStateNotFound();\n return;\n }\n throw e;\n }\n },\n () => heartbeatIntervalMs,\n lc,\n signal,\n );\n}\n\nexport function writeHeartbeat(\n clientID: ClientID,\n dagStore: Store,\n): Promise<ClientMap> {\n return withWrite(dagStore, async dagWrite => {\n const clients = await getClients(dagWrite);\n const client = clients.get(clientID);\n if (!client) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const newClient = {\n ...client,\n heartbeatTimestampMs: Date.now(),\n };\n const newClients = new Map(clients).set(clientID, newClient);\n\n await setClients(newClients, dagWrite);\n return newClients;\n });\n}\n", "import type {Hash} from '../hash.js';\nimport type {Chunk} from './chunk.js';\nimport type {MustGetChunk} from './store.js';\n\n/**\n * A visitor walks the DAG starting at a given root and visits each chunk.\n */\nexport class Visitor {\n #seen: Set<Hash> = new Set();\n #dagRead: MustGetChunk;\n\n constructor(dagRead: MustGetChunk) {\n this.#dagRead = dagRead;\n }\n\n async visit(h: Hash) {\n if (this.#seen.has(h)) {\n return;\n }\n this.#seen.add(h);\n const chunk = await this.#dagRead.mustGetChunk(h);\n await this.visitChunk(chunk);\n }\n\n async visitChunk(chunk: Chunk<unknown>) {\n await Promise.all(chunk.meta.map(ref => this.visit(ref)));\n }\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {Chunk} from '../dag/chunk.js';\nimport type {LazyRead} from '../dag/lazy-store.js';\nimport {Visitor} from '../dag/visitor.js';\nimport type {Hash} from '../hash.js';\n\nexport class GatherMemoryOnlyVisitor extends Visitor {\n readonly #gatheredChunks: Map<Hash, Chunk> = new Map();\n readonly #lazyRead: LazyRead;\n\n constructor(dagRead: LazyRead) {\n super(dagRead);\n this.#lazyRead = dagRead;\n }\n\n get gatheredChunks(): ReadonlyMap<Hash, Chunk> {\n return this.#gatheredChunks;\n }\n\n override visit(h: Hash): Promise<void> {\n if (!this.#lazyRead.isMemOnlyChunkHash(h)) {\n // Not a memory-only hash, no need to visit anything else.\n return promiseVoid;\n }\n return super.visit(h);\n }\n\n override visitChunk(chunk: Chunk): Promise<void> {\n this.#gatheredChunks.set(chunk.hash, chunk);\n return super.visitChunk(chunk);\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.js';\nimport type {Chunk} from '../dag/chunk.js';\nimport type {LazyStore} from '../dag/lazy-store.js';\nimport type {Read, Store, Write} from '../dag/store.js';\nimport {\n Commit,\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.js';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {Hash} from '../hash.js';\nimport type {ClientGroupID, ClientID} from '../sync/ids.js';\nimport type {MutatorDefs} from '../types.js';\nimport {withRead, withWrite} from '../with-transactions.js';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.js';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.js';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.js';\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it\u2019s newer than the client's perdag client group\u2019s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] =\n await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n newMainClientGroupHeadHash = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n );\n }\n }\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n );\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n): Promise<Hash> {\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n const newMainHead = await commitFromHash(basis, write);\n if (\n (await mutationCommit.getMutationID(meta.clientID, write)) >\n (await newMainHead.getMutationID(meta.clientID, write))\n ) {\n mutationIDs[meta.clientID] = meta.mutationID;\n basis = (\n await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n )\n ).chunk.hash;\n }\n }\n return basis;\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {Chunk} from '../dag/chunk.js';\nimport type {LazyStore} from '../dag/lazy-store.js';\nimport type {Read} from '../dag/store.js';\nimport {Visitor} from '../dag/visitor.js';\nimport type {Hash} from '../hash.js';\nimport {getSizeOfValue} from '../size-of-value.js';\n\nexport type ChunkWithSize = {chunk: Chunk; size: number};\n\nexport class GatherNotCachedVisitor extends Visitor {\n readonly #gatheredChunks: Map<Hash, ChunkWithSize> = new Map();\n #gatheredChunksTotalSize = 0;\n readonly #lazyStore: LazyStore;\n readonly #gatherSizeLimit: number;\n readonly #getSizeOfChunk: (chunk: Chunk) => number;\n\n constructor(\n dagRead: Read,\n lazyStore: LazyStore,\n gatherSizeLimit: number,\n getSizeOfChunk: (chunk: Chunk) => number = getSizeOfValue,\n ) {\n super(dagRead);\n this.#lazyStore = lazyStore;\n this.#gatherSizeLimit = gatherSizeLimit;\n this.#getSizeOfChunk = getSizeOfChunk;\n }\n\n get gatheredChunks(): ReadonlyMap<Hash, ChunkWithSize> {\n return this.#gatheredChunks;\n }\n\n override visit(h: Hash): Promise<void> {\n if (\n this.#gatheredChunksTotalSize >= this.#gatherSizeLimit ||\n this.#lazyStore.isCached(h)\n ) {\n return promiseVoid;\n }\n return super.visit(h);\n }\n\n override visitChunk(chunk: Chunk): Promise<void> {\n if (this.#gatheredChunksTotalSize < this.#gatherSizeLimit) {\n const size = this.#getSizeOfChunk(chunk);\n this.#gatheredChunks.set(chunk.hash, {chunk, size});\n this.#gatheredChunksTotalSize += size;\n }\n\n return super.visitChunk(chunk);\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {sleep} from '../../../shared/src/sleep.js';\nimport type {LazyStore} from '../dag/lazy-store.js';\nimport type {Store} from '../dag/store.js';\nimport {\n Commit,\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.js';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.js';\nimport type {FormatVersion} from '../format-version-enum.js';\nimport type {Hash} from '../hash.js';\nimport {\n type DiffComputationConfig,\n DiffsMap,\n diffCommits,\n} from '../sync/diff.js';\nimport type {ClientID} from '../sync/ids.js';\nimport type {MutatorDefs} from '../types.js';\nimport {withRead, withWrite} from '../with-transactions.js';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.js';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.js';\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\nconst DELAY_MS = 300;\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n): Promise<DiffsMap | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n };\n }\n // pull/poke and refresh are racing to see who gets to update\n // the memdag (the one with the newer base snapshot cookie wins)\n // pull/poke updates are preferable so delay refresh slightly to\n // make pull/poke the winner except when pull/pokes are slow.\n // This is especially important for pokes, as refresh winning\n // will result in the next poke's cookie not matching necessitating\n // a disconnect/reconnect.\n await sleep(DELAY_MS);\n if (closed()) {\n return {\n type: 'aborted',\n };\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n newMemdagHeadHash = (\n await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n )\n ).chunk.hash;\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n };\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return result.diffs;\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n", "import {type Resolver, resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.js';\nimport {assert} from '../../shared/src/asserts.js';\nimport {sleep} from '../../shared/src/sleep.js';\nimport {requestIdle as defaultRequestIdle} from './request-idle.js';\n\nexport class ProcessScheduler {\n readonly #process: () => Promise<void>;\n readonly #idleTimeoutMs: number;\n readonly #throttleMs: number;\n readonly #abortSignal: AbortSignal;\n readonly #requestIdle: typeof defaultRequestIdle;\n #scheduledResolver: Resolver<void> | undefined = undefined;\n #runResolver: Resolver<void> | undefined = undefined;\n #runPromise = Promise.resolve();\n #throttlePromise = Promise.resolve();\n\n /**\n * Supports scheduling a `process` to be run with certain constraints.\n * - Process runs are never concurrent.\n * - Multiple calls to schedule will be fulfilled by a single process\n * run started after the call to schedule. A call is never fulfilled by an\n * already running process run. This can be thought of as debouncing.\n * - Process runs are throttled so that the process runs at most once every\n * `throttleMs`.\n * - Process runs try to run during an idle period, but will delay at most\n * `idleTimeoutMs`.\n * - Scheduled runs which have not completed when `abortSignal` is aborted\n * will reject with an `AbortError`.\n */\n constructor(\n process: () => Promise<void>,\n idleTimeoutMs: number,\n throttleMs: number,\n abortSignal: AbortSignal,\n requestIdle = defaultRequestIdle,\n ) {\n this.#process = process;\n this.#idleTimeoutMs = idleTimeoutMs;\n this.#throttleMs = throttleMs;\n this.#abortSignal = abortSignal;\n this.#requestIdle = requestIdle;\n this.#abortSignal.addEventListener(\n 'abort',\n () => {\n const abortError = new AbortError('Aborted');\n this.#runResolver?.reject(abortError);\n this.#scheduledResolver?.reject(abortError);\n this.#runResolver = undefined;\n this.#scheduledResolver = undefined;\n },\n {once: true},\n );\n }\n\n schedule(): Promise<void> {\n if (this.#abortSignal.aborted) {\n return Promise.reject(new AbortError('Aborted'));\n }\n if (this.#scheduledResolver) {\n return this.#scheduledResolver.promise;\n }\n this.#scheduledResolver = resolver();\n void this.#scheduleInternal();\n return this.#scheduledResolver.promise;\n }\n\n async #scheduleInternal(): Promise<void> {\n try {\n await this.#runPromise;\n // Prevent errors thrown by process from cancelling scheduled runs.\n // this._runPromise is also awaited below and errors are explicitly\n // propagated to promises returned from schedule.\n // eslint-disable-next-line no-empty\n } catch (e) {}\n await this.#throttlePromise;\n if (!this.#scheduledResolver) {\n return;\n }\n await this.#requestIdle(this.#idleTimeoutMs);\n if (!this.#scheduledResolver) {\n return;\n }\n this.#throttlePromise = throttle(this.#throttleMs, this.#abortSignal);\n this.#runResolver = this.#scheduledResolver;\n this.#scheduledResolver = undefined;\n try {\n this.#runPromise = this.#process();\n await this.#runPromise;\n this.#runResolver?.resolve();\n } catch (e) {\n this.#runResolver?.reject(e);\n }\n this.#runResolver = undefined;\n }\n}\n\nasync function throttle(\n timeMs: number,\n abortSignal: AbortSignal,\n): Promise<void> {\n try {\n await sleep(timeMs, abortSignal);\n } catch (e) {\n assert(e instanceof AbortError);\n }\n}\n", "// TODO(arv): Remove workaround once docs/ builds cleanly without this.\ndeclare function requestIdleCallback(\n callback: () => void,\n options?: {timeout?: number},\n): number;\n\n/**\n * A Promise wrapper for requestIdleCallback with fallback to setTimeout for\n * browsers without support (aka Safari)\n */\nexport function requestIdle(timeout: number): Promise<void> {\n return new Promise(resolve => {\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(() => resolve(), {timeout});\n } else {\n setTimeout(() => resolve(), timeout);\n }\n });\n}\n", "export function setIntervalWithSignal(\n fn: () => void,\n ms: number,\n signal: AbortSignal,\n): void {\n const interval = setInterval(fn, ms);\n signal.addEventListener('abort', () => {\n clearInterval(interval);\n });\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {compareUTF8, greaterThan, lessThan, lessThanEq} from 'compare-utf8';\nimport {assert} from '../../shared/src/asserts.js';\nimport {deepEqual} from '../../shared/src/json.js';\nimport {binarySearch} from './binary-search.js';\nimport type {\n Diff,\n DiffOperation,\n IndexDiff,\n InternalDiff,\n InternalDiffOperation,\n NoIndexDiff,\n} from './btree/node.js';\nimport type {IndexKey} from './db/index.js';\nimport {decodeIndexKey} from './db/index.js';\nimport type {ScanOptions} from './db/scan.js';\nimport * as InvokeKind from './invoke-kind-enum.js';\nimport type {DiffComputationConfig, DiffsMap} from './sync/diff.js';\nimport {\n type ReadTransaction,\n SubscriptionTransactionWrapper,\n} from './transactions.js';\nimport type {QueryInternal} from './types.js';\n\nexport interface Subscription<R> {\n hasIndexSubscription(indexName: string): boolean;\n\n invoke(\n tx: ReadTransaction,\n kind: InvokeKind.Type,\n diffs: DiffsMap | undefined,\n ): Promise<R>;\n\n matches(diffs: DiffsMap): boolean;\n\n updateDeps(\n keys: ReadonlySet<string>,\n scans: ReadonlyArray<Readonly<ScanSubscriptionInfo>>,\n ): void;\n\n readonly onData: (result: R) => void;\n readonly onError: ((error: unknown) => void) | undefined;\n readonly onDone: (() => void) | undefined;\n}\n\nconst emptySet: ReadonlySet<string> = new Set();\n\nconst unitializedLastValue = Symbol();\ntype UnitializedLastValue = typeof unitializedLastValue;\n\nexport class SubscriptionImpl<R> implements Subscription<R> {\n readonly #body: (tx: ReadTransaction) => Promise<R>;\n readonly #onData: (result: R) => void;\n #lastValue: R | UnitializedLastValue = unitializedLastValue;\n #keys = emptySet;\n #scans: readonly Readonly<ScanSubscriptionInfo>[] = [];\n\n readonly onError: ((error: unknown) => void) | undefined;\n readonly onDone: (() => void) | undefined;\n readonly #isEqual: (a: R, b: R) => boolean;\n\n constructor(\n body: (tx: ReadTransaction) => Promise<R>,\n onData: (result: R) => void,\n onError: ((error: unknown) => void) | undefined,\n onDone: (() => void) | undefined,\n // deepEqual operates on any JSON value but argument might be more specific.\n isEqual: (a: R, b: R) => boolean = deepEqual as (a: R, b: R) => boolean,\n ) {\n this.#body = body;\n this.#onData = onData;\n this.onError = onError;\n this.onDone = onDone;\n this.#isEqual = isEqual;\n }\n\n hasIndexSubscription(indexName: string): boolean {\n for (const scan of this.#scans) {\n if (scan.options.indexName === indexName) {\n return true;\n }\n }\n return false;\n }\n\n invoke(\n tx: ReadTransaction,\n _kind: InvokeKind.Type,\n _diffs: DiffsMap | undefined,\n ): Promise<R> {\n return this.#body(tx);\n }\n\n matches(diffs: DiffsMap): boolean {\n for (const [indexName, diff] of diffs) {\n if (diffMatchesSubscription(this.#keys, this.#scans, indexName, diff)) {\n return true;\n }\n }\n\n return false;\n }\n\n updateDeps(\n keys: ReadonlySet<string>,\n scans: readonly Readonly<ScanSubscriptionInfo>[],\n ): void {\n this.#keys = keys;\n this.#scans = scans;\n }\n\n onData(result: R): void {\n if (\n this.#lastValue === unitializedLastValue ||\n !this.#isEqual(this.#lastValue, result)\n ) {\n this.#lastValue = result;\n this.#onData(result);\n }\n }\n}\n\nexport {SubscriptionImpl as SubscriptionImplForTesting};\n\n/**\n * Function that gets passed into {@link Replicache.experimentalWatch} and gets\n * called when the data in Replicache changes.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type WatchNoIndexCallback = (diff: NoIndexDiff) => void;\n\nexport type WatchCallbackForOptions<Options extends WatchOptions> =\n Options extends WatchIndexOptions ? WatchIndexCallback : WatchNoIndexCallback;\n\n/**\n * Function that gets passed into {@link Replicache.experimentalWatch} when doing a\n * watch on a secondary index map and gets called when the data in Replicache\n * changes.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type WatchIndexCallback = (diff: IndexDiff) => void;\n\n/**\n * Options for {@link Replicache.experimentalWatch}.\n *\n * @experimental This interface is experimental and may change in the future.\n */\nexport type WatchOptions = WatchIndexOptions | WatchNoIndexOptions;\n\n/**\n * Options object passed to {@link Replicache.experimentalWatch}. This is for an\n * index watch.\n */\nexport type WatchIndexOptions = WatchNoIndexOptions & {\n /**\n * When provided, the `watch` is limited to the changes that apply to the index map.\n */\n indexName: string;\n};\n\n/**\n * Options object passed to {@link Replicache.experimentalWatch}. This is for a non\n * index watch.\n */\nexport type WatchNoIndexOptions = {\n /**\n * When provided, the `watch` is limited to changes where the `key` starts\n * with `prefix`.\n */\n prefix?: string | undefined;\n\n /**\n * When this is set to `true` (default is `false`), the `watch` callback will\n * be called once asynchronously when watch is called. The arguments in that\n * case is a diff where we consider all the existing values in Replicache as\n * being added.\n */\n initialValuesInFirstDiff?: boolean | undefined;\n};\n\nexport type WatchCallback = (diff: Diff) => void;\n\nexport class WatchSubscription implements Subscription<Diff | undefined> {\n readonly #callback: WatchCallback;\n readonly #prefix: string;\n readonly #indexName: string | undefined;\n readonly #initialValuesInFirstDiff: boolean;\n\n readonly onError: ((error: unknown) => void) | undefined = undefined;\n readonly onDone: (() => void) | undefined = undefined;\n\n constructor(callback: WatchCallback, options?: WatchOptions) {\n this.#callback = callback;\n this.#prefix = options?.prefix ?? '';\n this.#indexName = (options as WatchIndexOptions)?.indexName;\n this.#initialValuesInFirstDiff = options?.initialValuesInFirstDiff ?? false;\n }\n\n hasIndexSubscription(indexName: string): boolean {\n return this.#indexName === indexName;\n }\n\n onData(result: Diff | undefined): void {\n if (result !== undefined) {\n this.#callback(result);\n }\n }\n\n invoke(\n tx: ReadTransaction,\n kind: InvokeKind.Type,\n diffs: DiffsMap | undefined,\n ): Promise<Diff | undefined> {\n const invoke = async <Key extends IndexKey | string>(\n indexName: string | undefined,\n prefix: string,\n compareKey: (diff: DiffOperation<Key>) => string,\n convertInternalDiff: (\n diff: InternalDiff,\n ) => readonly DiffOperation<Key>[],\n ): Promise<readonly DiffOperation<Key>[] | undefined> => {\n let diff: readonly DiffOperation<Key>[];\n if (kind === InvokeKind.InitialRun) {\n if (!this.#initialValuesInFirstDiff) {\n // We are using `undefined` here as a sentinel value to indicate that we\n // should not call the callback in `onDone`.\n return undefined;\n }\n\n // For the initial run, we need to get the \"diffs\" for the whole tree.\n assert(diffs === undefined);\n\n const newDiff: DiffOperation<Key>[] = [];\n for await (const entry of tx.scan({prefix, indexName}).entries()) {\n newDiff.push({\n op: 'add',\n key: entry[0] as Key,\n newValue: entry[1],\n });\n }\n diff = newDiff;\n } else {\n assert(diffs);\n const maybeDiff = diffs.get(indexName ?? '') ?? [];\n diff = convertInternalDiff(maybeDiff);\n }\n const newDiff: DiffOperation<Key>[] = [];\n const {length} = diff;\n for (\n let i = diffBinarySearch(diff, prefix, compareKey);\n i < length;\n i++\n ) {\n if (compareKey(diff[i]).startsWith(prefix)) {\n newDiff.push(diff[i]);\n } else {\n break;\n }\n }\n\n // For initial run we should always return something.\n return kind === InvokeKind.InitialRun || newDiff.length > 0\n ? newDiff\n : undefined;\n };\n\n if (this.#indexName) {\n return invoke<IndexKey>(\n this.#indexName,\n this.#prefix,\n diff => diff.key[0],\n internalDiff => convertDiffValues(internalDiff, decodeIndexKey),\n );\n }\n\n return invoke<string>(\n undefined,\n this.#prefix,\n diff => diff.key,\n internalDiff => convertDiffValues(internalDiff, k => k),\n );\n }\n\n matches(diffs: DiffsMap): boolean {\n const diff = diffs.get(this.#indexName ?? '');\n if (diff === undefined) {\n return false;\n }\n\n return watcherMatchesDiff(diff, this.#prefix, this.#indexName);\n }\n\n updateDeps(\n _keys: ReadonlySet<string>,\n _scans: readonly Readonly<ScanSubscriptionInfo>[],\n ): void {\n // not used\n }\n}\n\nfunction convertDiffValues<Key>(\n diff: InternalDiff,\n convertKey: (k: string) => Key,\n): DiffOperation<Key>[] {\n return diff.map(op => {\n const key = convertKey(op.key);\n switch (op.op) {\n case 'add':\n return {\n op: 'add',\n key,\n newValue: op.newValue,\n };\n case 'change':\n return {\n op: 'change',\n key,\n oldValue: op.oldValue,\n newValue: op.newValue,\n };\n case 'del':\n return {\n op: 'del',\n key,\n oldValue: op.oldValue,\n };\n }\n });\n}\n\n/**\n * The options passed to {@link Replicache.subscribe}.\n */\nexport interface SubscribeOptions<R> {\n /**\n * Called when the return value of the body function changes.\n */\n onData: (result: R) => void;\n\n /**\n * If present, called when an error occurs.\n */\n onError?: ((error: unknown) => void) | undefined;\n\n /**\n * If present, called when the subscription is removed/done.\n */\n onDone?: (() => void) | undefined;\n\n /**\n * If present this function is used to determine if the value returned by the\n * body function has changed. If not provided a JSON deep equality check is\n * used.\n */\n isEqual?: ((a: R, b: R) => boolean) | undefined;\n}\n\nexport type UnknownSubscription = Subscription<unknown>;\n\ntype SubscriptionSet = Set<UnknownSubscription>;\n\nexport interface SubscriptionsManager extends DiffComputationConfig {\n clear(): void;\n fire(diffs: DiffsMap): Promise<void>;\n hasPendingSubscriptionRuns: boolean;\n add<R>(subscription: Subscription<R>): () => void;\n}\n\nexport class SubscriptionsManagerImpl implements SubscriptionsManager {\n readonly #subscriptions: SubscriptionSet = new Set();\n readonly #pendingSubscriptions: SubscriptionSet = new Set();\n readonly #queryInternal: QueryInternal;\n readonly #lc: LogContext;\n hasPendingSubscriptionRuns = false;\n readonly #signal: AbortSignal;\n\n constructor(\n queryInternal: QueryInternal,\n lc: LogContext,\n signal: AbortSignal,\n ) {\n this.#queryInternal = queryInternal;\n this.#lc = lc;\n this.#signal = signal;\n }\n\n add<R>(subscription: Subscription<R>): () => void {\n this.#subscriptions.add(subscription as UnknownSubscription);\n void this.#scheduleInitialSubscriptionRun(\n subscription as UnknownSubscription,\n );\n return () =>\n this.#subscriptions.delete(subscription as UnknownSubscription);\n }\n\n clear(): void {\n for (const subscription of this.#subscriptions) {\n subscription.onDone?.();\n }\n this.#subscriptions.clear();\n }\n\n async fire(diffs: DiffsMap): Promise<void> {\n const subscriptions = subscriptionsForDiffs(this.#subscriptions, diffs);\n await this.#fireSubscriptions(subscriptions, InvokeKind.Regular, diffs);\n }\n\n async #fireSubscriptions(\n subscriptions: Iterable<UnknownSubscription>,\n kind: InvokeKind.Type,\n diffs: DiffsMap | undefined,\n ) {\n if (this.#signal.aborted) {\n return;\n }\n\n const subs = [...subscriptions] as readonly Subscription<unknown>[];\n if (subs.length === 0) {\n return;\n }\n\n // Use allSettled to gather fulfilled and rejected promises.\n const results = await this.#queryInternal(tx =>\n Promise.allSettled(\n subs.map(async s => {\n const stx = new SubscriptionTransactionWrapper(tx);\n try {\n return await s.invoke(stx, kind, diffs);\n } finally {\n // We need to keep track of the subscription keys even if there was an\n // exception because changes to the keys can make the subscription\n // body succeed.\n s.updateDeps(stx.keys, stx.scans);\n }\n }),\n ),\n );\n\n this.callCallbacks(subs, results);\n }\n\n // Public method so that ZQL can wrap it in a transaction.\n callCallbacks(\n subs: readonly Subscription<unknown>[],\n results: PromiseSettledResult<unknown>[],\n ) {\n for (let i = 0; i < subs.length; i++) {\n const s = subs[i];\n const result = results[i];\n if (result.status === 'fulfilled') {\n s.onData(result.value);\n } else {\n if (s.onError) {\n s.onError(result.reason);\n } else {\n this.#lc.error?.('Error in subscription body:', result.reason);\n }\n }\n }\n }\n\n async #scheduleInitialSubscriptionRun(s: UnknownSubscription) {\n this.#pendingSubscriptions.add(s);\n\n if (!this.hasPendingSubscriptionRuns) {\n this.hasPendingSubscriptionRuns = true;\n await Promise.resolve();\n this.hasPendingSubscriptionRuns = false;\n const subscriptions = [...this.#pendingSubscriptions];\n this.#pendingSubscriptions.clear();\n await this.#fireSubscriptions(\n subscriptions,\n InvokeKind.InitialRun,\n undefined,\n );\n }\n }\n\n shouldComputeDiffs(): boolean {\n return this.#subscriptions.size > 0;\n }\n\n shouldComputeDiffsForIndex(indexName: string): boolean {\n for (const s of this.#subscriptions) {\n if (s.hasIndexSubscription(indexName)) {\n return true;\n }\n }\n return false;\n }\n}\n\nexport type ScanSubscriptionInfo = {\n options: ScanOptions;\n inclusiveLimitKey?: string | undefined;\n};\n\nfunction diffMatchesSubscription(\n keys: ReadonlySet<string>,\n scans: Iterable<Readonly<ScanSubscriptionInfo>>,\n indexName: string,\n diff: InternalDiff,\n): boolean {\n // Keys can only match for non index scans.\n if (indexName === '') {\n for (const diffEntry of diff) {\n if (keys.has(diffEntry.key)) {\n return true;\n }\n }\n }\n\n for (const scanInfo of scans) {\n if (scanInfoMatchesDiff(scanInfo, indexName, diff)) {\n return true;\n }\n }\n return false;\n}\n\nfunction scanInfoMatchesDiff(\n scanInfo: ScanSubscriptionInfo,\n changeIndexName: string,\n diff: InternalDiff,\n): boolean {\n // TODO(arv): Use binary search\n for (const diffEntry of diff) {\n if (scanInfoMatchesKey(scanInfo, changeIndexName, diffEntry.key)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function scanInfoMatchesKey(\n scanInfo: ScanSubscriptionInfo,\n changeIndexName: string,\n changedKey: string,\n): boolean {\n const {\n indexName = '',\n limit,\n prefix,\n startKey,\n startExclusive,\n startSecondaryKey,\n } = scanInfo.options;\n\n if (changeIndexName !== indexName) {\n return false;\n }\n\n if (!indexName) {\n // A scan with limit <= 0 can have no matches\n if (limit !== undefined && limit <= 0) {\n return false;\n }\n\n // No prefix and no start. Must recompute the subscription because all keys\n // will have an effect on the subscription.\n if (!prefix && !startKey) {\n return true;\n }\n\n if (\n prefix &&\n (!changedKey.startsWith(prefix) ||\n isKeyPastInclusiveLimit(scanInfo, changedKey))\n ) {\n return false;\n }\n\n if (\n startKey &&\n ((startExclusive && lessThanEq(changedKey, startKey)) ||\n lessThan(changedKey, startKey) ||\n isKeyPastInclusiveLimit(scanInfo, changedKey))\n ) {\n return false;\n }\n\n return true;\n }\n\n // No prefix and no start. Must recompute the subscription because all keys\n // will have an effect on the subscription.\n if (!prefix && !startKey && !startSecondaryKey) {\n return true;\n }\n\n const [changedKeySecondary, changedKeyPrimary] = decodeIndexKey(changedKey);\n\n if (prefix) {\n if (!changedKeySecondary.startsWith(prefix)) {\n return false;\n }\n }\n\n if (\n startSecondaryKey &&\n ((startExclusive && lessThanEq(changedKeySecondary, startSecondaryKey)) ||\n lessThan(changedKeySecondary, startSecondaryKey))\n ) {\n return false;\n }\n\n if (\n startKey &&\n ((startExclusive && lessThanEq(changedKeyPrimary, startKey)) ||\n lessThan(changedKeyPrimary, startKey))\n ) {\n return false;\n }\n\n return true;\n}\n\nfunction isKeyPastInclusiveLimit(\n scanInfo: ScanSubscriptionInfo,\n changedKey: string,\n): boolean {\n const {inclusiveLimitKey} = scanInfo;\n return (\n scanInfo.options.limit !== undefined &&\n inclusiveLimitKey !== undefined &&\n greaterThan(changedKey, inclusiveLimitKey)\n );\n}\n\nfunction* subscriptionsForDiffs<V>(\n subscriptions: Set<Subscription<V>>,\n diffs: DiffsMap,\n): Generator<Subscription<V>> {\n for (const subscription of subscriptions) {\n if (subscription.matches(diffs)) {\n yield subscription;\n }\n }\n}\n\nfunction watcherMatchesDiff(\n diff: InternalDiff,\n prefix: string,\n indexName: string | undefined,\n): boolean {\n if (prefix === '') {\n return true;\n }\n\n const compareKey = indexName\n ? (diffOp: InternalDiffOperation) => decodeIndexKey(diffOp.key)[0]\n : (diffOp: InternalDiffOperation) => diffOp.key;\n const i = diffBinarySearch(diff, prefix, compareKey);\n return i < diff.length && compareKey(diff[i]).startsWith(prefix);\n}\n\nfunction diffBinarySearch<Key, Value>(\n diff: readonly InternalDiffOperation<Key, Value>[],\n prefix: string,\n compareKey: (diff: InternalDiffOperation<Key, Value>) => string,\n): number {\n return binarySearch(diff.length, i =>\n compareUTF8(prefix, compareKey(diff[i])),\n );\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n\nexport const InitialRun = 0;\nexport const Regular = 1;\n\nexport type InitialRun = typeof InitialRun;\nexport type Regular = typeof Regular;\n\nexport type Type = InitialRun | Regular;\n", "export function getNonCryptoRandomValues(array: Uint8Array) {\n if (array === null) {\n throw new TypeError('array cannot be null');\n }\n\n // Fill the array with random values\n for (let i = 0; i < array.length; i++) {\n array[i] = Math.floor(Math.random() * 256); // Random byte (0-255)\n }\n\n return array;\n}\n\nexport function randomCharacters(length: number) {\n let result = '';\n const characters =\n 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n const charactersLength = characters.length;\n let counter = 0;\n while (counter < length) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n counter += 1;\n }\n return result;\n}\n", "import {getNonCryptoRandomValues} from '../../../shared/src/random-values.js';\nimport type {ClientID} from './ids.js';\n\nlet sessionID = '';\nfunction getSessionID() {\n if (sessionID === '') {\n const buf = new Uint8Array(4);\n getNonCryptoRandomValues(buf);\n sessionID = Array.from(buf, x => x.toString(16)).join('');\n }\n return sessionID;\n}\n\nconst REQUEST_COUNTERS: Map<string, number> = new Map();\n\n/**\n * Returns a new requestID of the form <client ID>-<session ID>-<request\n * count>. The request count enables one to find the request following or\n * preceding a given request. The sessionid scopes the request count, ensuring\n * the requestID is probabilistically unique across restarts (which is good\n * enough).\n */\nexport function newRequestID(clientID: ClientID): string {\n let counter = REQUEST_COUNTERS.get(clientID);\n if (!counter) {\n REQUEST_COUNTERS.set(clientID, 0);\n counter = 0;\n } else {\n counter++;\n REQUEST_COUNTERS.set(clientID, counter);\n }\n return `${clientID}-${getSessionID()}-${counter}`;\n}\n", "// The env value should be filled in by esbuild.\n\ndeclare const process: {\n env: {\n ['REPLICACHE_VERSION']?: string;\n };\n};\n\n/**\n * The current version of Replicache.\n */\nexport const version: string = process.env.REPLICACHE_VERSION ?? '0.0.0';\n", "import type {LogContext} from '@rocicorp/logger';\nimport type {MaybePromise} from '../../shared/src/types.js';\nimport * as FormatVersion from './format-version-enum.js';\nimport {\n dropIDBStoreWithMemFallback,\n newIDBStoreWithMemFallback,\n} from './kv/idb-store-with-mem-fallback.js';\nimport {MemStore, dropMemStore} from './kv/mem-store.js';\nimport type {StoreProvider} from './kv/store.js';\nimport type {PendingMutation} from './pending-mutations.js';\nimport type {Puller} from './puller.js';\nimport type {Pusher} from './pusher.js';\nimport {ReplicacheImpl} from './replicache-impl.js';\nimport type {ReplicacheOptions} from './replicache-options.js';\nimport type {\n SubscribeOptions,\n WatchCallbackForOptions,\n WatchNoIndexCallback,\n WatchOptions,\n} from './subscriptions.js';\nimport type {ReadTransaction} from './transactions.js';\nimport type {\n MakeMutators,\n MutatorDefs,\n Poke,\n RequestOptions,\n UpdateNeededReason,\n} from './types.js';\n\ntype MakeImpl = <MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n) => ReplicacheImpl<MD>;\n\nconst defaultMakeImpl: MakeImpl = <MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n) => new ReplicacheImpl<MD>(options);\nlet makeImpl: MakeImpl = defaultMakeImpl;\n\nexport function setMakeImplForTest(testMakeImpl: MakeImpl) {\n makeImpl = testMakeImpl;\n}\n\nexport function restoreMakeImplForTest() {\n makeImpl = defaultMakeImpl;\n}\n\nexport const httpStatusUnauthorized = 401;\n\n/**\n * Returns the name of the IDB database that will be used for a particular Replicache instance.\n * @param name The name of the Replicache instance (i.e., the `name` field of `ReplicacheOptions`).\n * @param schemaVersion The schema version of the database (i.e., the `schemaVersion` field of `ReplicacheOptions`).\n * @returns\n */\nexport function makeIDBName(name: string, schemaVersion?: string): string {\n return makeIDBNameInternal(name, schemaVersion, FormatVersion.Latest);\n}\n\nfunction makeIDBNameInternal(\n name: string,\n schemaVersion: string | undefined,\n formatVersion: number,\n): string {\n const n = `rep:${name}:${formatVersion}`;\n return schemaVersion ? `${n}:${schemaVersion}` : n;\n}\n\nexport {makeIDBNameInternal as makeIDBNameForTesting};\n\n// eslint-disable-next-line @typescript-eslint/ban-types\nexport class Replicache<MD extends MutatorDefs = {}> {\n readonly #impl: ReplicacheImpl<MD>;\n\n constructor(options: ReplicacheOptions<MD>) {\n this.#impl = makeImpl(options);\n }\n\n /** The URL to use when doing a pull request. */\n get pullURL(): string {\n return this.#impl.pullURL;\n }\n set pullURL(value: string) {\n this.#impl.pullURL = value;\n }\n\n /** The URL to use when doing a push request. */\n get pushURL(): string {\n return this.#impl.pushURL;\n }\n set pushURL(value: string) {\n this.#impl.pushURL = value;\n }\n\n /** The authorization token used when doing a push request. */\n get auth(): string {\n return this.#impl.auth;\n }\n set auth(value: string) {\n this.#impl.auth = value;\n }\n\n /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */\n get name(): string {\n return this.#impl.name;\n }\n\n /**\n * This is the name Replicache uses for the IndexedDB database where data is\n * stored.\n */\n get idbName(): string {\n return makeIDBName(this.name, this.schemaVersion);\n }\n\n /** The schema version of the data understood by this application. */\n get schemaVersion(): string {\n return this.#impl.schemaVersion;\n }\n\n /**\n * The mutators that was registered in the constructor.\n */\n get mutate(): MakeMutators<MD> {\n return this.#impl.mutate;\n }\n\n /**\n * The duration between each periodic {@link pull}. Setting this to `null`\n * disables periodic pull completely. Pull will still happen if you call\n * {@link pull} manually.\n */\n get pullInterval(): number | null {\n return this.#impl.pullInterval;\n }\n set pullInterval(value: number | null) {\n this.#impl.pullInterval = value;\n }\n\n /**\n * The delay between when a change is made to Replicache and when Replicache\n * attempts to push that change.\n */\n get pushDelay(): number {\n return this.#impl.pushDelay;\n }\n set pushDelay(value: number) {\n this.#impl.pushDelay = value;\n }\n\n /**\n * The function to use to pull data from the server.\n */\n get puller(): Puller {\n return this.#impl.puller;\n }\n set puller(value: Puller) {\n this.#impl.puller = value;\n }\n\n /**\n * The function to use to push data to the server.\n */\n get pusher(): Pusher {\n return this.#impl.pusher;\n }\n set pusher(value: Pusher) {\n this.#impl.pusher = value;\n }\n\n /**\n * The options used to control the {@link pull} and push request behavior. This\n * object is live so changes to it will affect the next pull or push call.\n */\n get requestOptions(): Required<RequestOptions> {\n return this.#impl.requestOptions;\n }\n\n /**\n * `onSync(true)` is called when Replicache transitions from no push or pull\n * happening to at least one happening. `onSync(false)` is called in the\n * opposite case: when Replicache transitions from at least one push or pull\n * happening to none happening.\n *\n * This can be used in a React like app by doing something like the following:\n *\n * ```js\n * const [syncing, setSyncing] = useState(false);\n * useEffect(() => {\n * rep.onSync = setSyncing;\n * }, [rep]);\n * ```\n */\n get onSync(): ((syncing: boolean) => void) | null {\n return this.#impl.onSync;\n }\n set onSync(value: ((syncing: boolean) => void) | null) {\n this.#impl.onSync = value;\n }\n\n /**\n * `onClientStateNotFound` is called when the persistent client has been\n * garbage collected. This can happen if the client has no pending mutations\n * and has not been used for a while.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n get onClientStateNotFound(): (() => void) | null {\n return this.#impl.onClientStateNotFound;\n }\n set onClientStateNotFound(value: (() => void) | null) {\n this.#impl.onClientStateNotFound = value;\n }\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the {@link pushVersion},\n * {@link pullVersion} or {@link schemaVersion} of the current code.\n * - a new Replicache client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Replicache client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Replicache client (i.e. to sync while offline, the clients can can\n * still sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n get onUpdateNeeded(): ((reason: UpdateNeededReason) => void) | null {\n return this.#impl.onUpdateNeeded;\n }\n set onUpdateNeeded(value: ((reason: UpdateNeededReason) => void) | null) {\n this.#impl.onUpdateNeeded = value;\n }\n\n /**\n * This gets called when we get an HTTP unauthorized (401) response from the\n * push or pull endpoint. Set this to a function that will ask your user to\n * reauthenticate.\n */\n get getAuth():\n | (() => MaybePromise<string | null | undefined>)\n | null\n | undefined {\n return this.#impl.getAuth;\n }\n set getAuth(\n value: (() => MaybePromise<string | null | undefined>) | null | undefined,\n ) {\n this.#impl.getAuth = value;\n }\n\n /**\n * The browser profile ID for this browser profile. Every instance of Replicache\n * browser-profile-wide shares the same profile ID.\n */\n get profileID(): Promise<string> {\n return this.#impl.profileID;\n }\n\n /**\n * The client ID for this instance of Replicache. Each instance of Replicache\n * gets a unique client ID.\n */\n get clientID(): string {\n return this.#impl.clientID;\n }\n\n /**\n * The client group ID for this instance of Replicache. Instances of\n * Replicache will have the same client group ID if and only if they have\n * the same name, mutators, indexes, schema version, format version, and\n * browser profile.\n */\n get clientGroupID(): Promise<string> {\n return this.#impl.clientGroupID;\n }\n\n /**\n * `onOnlineChange` is called when the {@link online} property changes. See\n * {@link online} for more details.\n */\n get onOnlineChange(): ((online: boolean) => void) | null {\n return this.#impl.onOnlineChange;\n }\n set onOnlineChange(value: ((online: boolean) => void) | null) {\n this.#impl.onOnlineChange = value;\n }\n\n /**\n * A rough heuristic for whether the client is currently online. Note that\n * there is no way to know for certain whether a client is online - the next\n * request can always fail. This property returns true if the last sync attempt succeeded,\n * and false otherwise.\n */\n get online(): boolean {\n return this.#impl.online;\n }\n\n /**\n * Whether the Replicache database has been closed. Once Replicache has been\n * closed it no longer syncs and you can no longer read or write data out of\n * it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#impl.closed;\n }\n\n /**\n * Closes this Replicache instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n close(): Promise<void> {\n return this.#impl.close();\n }\n\n /**\n * Push pushes pending changes to the {@link pushURL}.\n *\n * You do not usually need to manually call push. If {@link pushDelay} is\n * non-zero (which it is by default) pushes happen automatically shortly after\n * mutations.\n *\n * If the server endpoint fails push will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, push will happen immediately and ignore\n * {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the\n * exponential backoff in case of errors.\n * @returns A promise that resolves when the next push completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n push({now = false} = {}): Promise<void> {\n return this.#impl.push({now});\n }\n\n /**\n * Pull pulls changes from the {@link pullURL}. If there are any changes local\n * changes will get replayed on top of the new server state.\n *\n * If the server endpoint fails pull will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, pull will happen immediately and ignore\n * {@link RequestOptions.minDelayMs} as well as the exponential backoff in\n * case of errors.\n * @returns A promise that resolves when the next pull completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n pull({now = false} = {}): Promise<void> {\n return this.#impl.pull({now});\n }\n\n /**\n * Applies an update from the server to Replicache.\n * Throws an error if cookie does not match. In that case the server thinks\n * this client has a different cookie than it does; the caller should disconnect\n * from the server and re-register, which transmits the cookie the client actually\n * has.\n *\n * @experimental This method is under development and its semantics will change.\n */\n poke(poke: Poke): Promise<void> {\n return this.#impl.poke(poke);\n }\n\n /**\n * Subscribe to the result of a {@link query}. The `body` function is\n * evaluated once and its results are returned via `onData`.\n *\n * Thereafter, each time the the result of `body` changes, `onData` is fired\n * again with the new result.\n *\n * `subscribe()` goes to significant effort to avoid extraneous work\n * re-evaluating subscriptions:\n *\n * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`\n * is only re-evaluated when those keys change.\n * 2. subscribe only re-fires `onData` in the case that a result changes by\n * way of the `isEqual` option which defaults to doing a deep JSON value\n * equality check.\n *\n * Because of (1), `body` must be a pure function of the data in Replicache.\n * `body` must not access anything other than the `tx` parameter passed to it.\n *\n * Although subscribe is as efficient as it can be, it is somewhat constrained\n * by the goal of returning an arbitrary computation of the cache. For even\n * better performance (but worse dx), see {@link experimentalWatch}.\n *\n * If an error occurs in the `body` the `onError` function is called if\n * present. Otherwise, the error is logged at log level 'error'.\n *\n * To cancel the subscription, call the returned function.\n *\n * @param body The function to evaluate to get the value to pass into\n * `onData`.\n * @param options Options is either a function or an object. If it is a\n * function it is equivalent to passing it as the `onData` property of an\n * object.\n */\n subscribe<R>(\n body: (tx: ReadTransaction) => Promise<R>,\n options: SubscribeOptions<R> | ((result: R) => void),\n ): () => void {\n return this.#impl.subscribe(body, options);\n }\n\n /**\n * Watches Replicache for changes.\n *\n * The `callback` gets called whenever the underlying data changes and the\n * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or\n * {@link ExperimentalWatchNoIndexOptions} if present. If a change\n * occurs to the data but the change does not impact the key space the\n * callback is not called. In other words, the callback is never called with\n * an empty diff.\n *\n * This gets called after commit (a mutation or a rebase).\n *\n * @experimental This method is under development and its semantics will\n * change.\n */\n experimentalWatch(callback: WatchNoIndexCallback): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void {\n return this.#impl.experimentalWatch(callback, options);\n }\n\n /**\n * Query is used for read transactions. It is recommended to use transactions\n * to ensure you get a consistent view across multiple calls to `get`, `has`\n * and `scan`.\n */\n query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R> {\n return this.#impl.query(body);\n }\n\n /**\n * List of pending mutations. The order of this is from oldest to newest.\n *\n * Gives a list of local mutations that have `mutationID` >\n * `syncHead.mutationID` that exists on the main client group.\n *\n * @experimental This method is experimental and may change in the future.\n */\n experimentalPendingMutations(): Promise<readonly PendingMutation[]> {\n return this.#impl.experimentalPendingMutations();\n }\n}\n\n/**\n * Wrapper error class that should be reported as error (logger.error)\n */\nexport class ReportError extends Error {}\n\nfunction createMemStore(name: string): MemStore {\n return new MemStore(name);\n}\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: string) => newIDBStoreWithMemFallback(lc, name),\n drop: dropIDBStoreWithMemFallback,\n };\n case 'mem':\n return {\n create: createMemStore,\n drop: (name: string) => dropMemStore(name),\n };\n default:\n return kvStore;\n }\n}\n", "export {consoleLogSink} from '@rocicorp/logger';\nexport type {LogLevel, LogSink} from '@rocicorp/logger';\nexport type {\n JSONObject,\n JSONValue,\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../shared/src/json.js';\nexport type {MaybePromise} from '../../shared/src/types.js';\nexport type {\n Diff as ExperimentalDiff,\n DiffOperation as ExperimentalDiffOperation,\n DiffOperationAdd as ExperimentalDiffOperationAdd,\n DiffOperationChange as ExperimentalDiffOperationChange,\n DiffOperationDel as ExperimentalDiffOperationDel,\n IndexDiff as ExperimentalIndexDiff,\n NoIndexDiff as ExperimentalNoIndexDiff,\n} from './btree/node.js';\nexport type {Cookie} from './cookies.js';\nexport type {IndexKey} from './db/index.js';\nexport type {\n ClientStateNotFoundResponse,\n VersionNotSupportedResponse,\n} from './error-responses.js';\nexport {filterAsyncIterable} from './filter-async-iterable.js';\nexport {getDefaultPuller} from './get-default-puller.js';\nexport type {HTTPRequestInfo} from './http-request-info.js';\nexport type {IndexDefinition, IndexDefinitions} from './index-defs.js';\nexport type {IterableUnion} from './iterable-union.js';\nexport {IDBNotFoundError} from './kv/idb-store.js';\nexport type {\n CreateStore as CreateKVStore,\n DropStore as DropKVStore,\n Read as KVRead,\n Store as KVStore,\n StoreProvider as KVStoreProvider,\n Write as KVWrite,\n} from './kv/store.js';\nexport {mergeAsyncIterables} from './merge-async-iterables.js';\nexport type {PatchOperation} from './patch-operation.js';\nexport type {PendingMutation} from './pending-mutations.js';\nexport {\n deleteAllReplicacheData,\n dropAllDatabases,\n dropDatabase,\n type DropDatabaseOptions,\n} from './persist/collect-idb-databases.js';\nexport type {\n PullResponse,\n PullResponseOKV0,\n PullResponseOKV1,\n PullResponseV0,\n PullResponseV1,\n Puller,\n PullerResult,\n PullerResultV0,\n PullerResultV1,\n} from './puller.js';\nexport type {PushError, PushResponse, Pusher, PusherResult} from './pusher.js';\nexport type {ReplicacheOptions} from './replicache-options.js';\nexport {Replicache, makeIDBName} from './replicache.js';\nexport {makeScanResult} from './scan-iterator.js';\nexport type {\n AsyncIterableIteratorToArray,\n GetIndexScanIterator,\n GetScanIterator,\n ScanResult,\n} from './scan-iterator.js';\nexport {isScanIndexOptions} from './scan-options.js';\nexport type {\n KeyTypeForScanOptions,\n ScanIndexOptions,\n ScanNoIndexOptions,\n ScanOptionIndexedStartKey,\n ScanOptions,\n} from './scan-options.js';\nexport type {\n WatchCallbackForOptions as ExperimentalWatchCallbackForOptions,\n WatchIndexCallback as ExperimentalWatchIndexCallback,\n WatchIndexOptions as ExperimentalWatchIndexOptions,\n WatchNoIndexCallback as ExperimentalWatchNoIndexCallback,\n WatchNoIndexOptions as ExperimentalWatchNoIndexOptions,\n WatchOptions as ExperimentalWatchOptions,\n SubscribeOptions,\n} from './subscriptions.js';\nexport type {ClientGroupID, ClientID} from './sync/ids.js';\nexport {PullError} from './sync/pull-error.js';\nexport type {PullRequest, PullRequestV0, PullRequestV1} from './sync/pull.js';\nexport type {\n MutationV0,\n MutationV1,\n PushRequest,\n PushRequestV0,\n PushRequestV1,\n} from './sync/push.js';\nexport {TEST_LICENSE_KEY} from './test-license-key.js';\nexport {TransactionClosedError} from './transaction-closed-error.js';\nexport type {\n CreateIndexDefinition,\n DeepReadonly,\n DeepReadonlyObject,\n ReadTransaction,\n TransactionEnvironment,\n TransactionLocation,\n TransactionReason,\n WriteTransaction,\n} from './transactions.js';\nexport type {\n MakeMutator,\n MakeMutators,\n MutatorDefs,\n MutatorReturn,\n Poke,\n RequestOptions,\n UpdateNeededReason,\n} from './types.js';\nexport {version} from './version.js';\n", "import type {TableSchemaBase} from '../ivm/schema.js';\n\nexport type TableSchema = TableSchemaBase & {\n readonly relationships: {readonly [name: string]: Relationship};\n};\n\nexport function createTableSchema<const T extends TableSchema>(schema: T) {\n return schema as T;\n}\n\nexport type Supertype<TSchemas extends TableSchema[]> = {\n tableName: TSchemas[number]['tableName'];\n primaryKey: TSchemas[number]['primaryKey'];\n columns: {\n [K in keyof TSchemas[number]['columns']]: TSchemas[number]['columns'][K];\n };\n relationships: {\n [K in keyof TSchemas[number]['relationships']]: TSchemas[number]['relationships'][K];\n };\n};\n\n/**\n * A schema might have a relationship to itself.\n * Given we cannot reference a variable in the same statement we initialize\n * the variable, we use a function to get around this.\n */\nexport type Lazy<T> = () => T;\n\nexport type Relationship =\n | FieldRelationship<TableSchema, TableSchema>\n | JunctionRelationship<TableSchema, TableSchema, TableSchema>;\n\n/**\n * A relationship between two entities where\n * that relationship is defined via fields on both entities.\n */\nexport type FieldRelationship<\n TSourceSchema extends TableSchema,\n TDestSchema extends TableSchema,\n> = {\n source: keyof TSourceSchema['columns'];\n dest: {\n field: keyof TDestSchema['columns'];\n schema: TDestSchema | Lazy<TDestSchema>;\n };\n};\n\n/**\n * A relationship between two entities where\n * that relationship is defined via a junction table.\n */\nexport type JunctionRelationship<\n TSourceSchema extends TableSchema,\n TJunctionSchema extends TableSchema,\n TDestSchema extends TableSchema,\n> = {\n source: keyof TSourceSchema['columns'];\n junction: {\n sourceField: keyof TJunctionSchema['columns'];\n destField: keyof TJunctionSchema['columns'];\n schema: TDestSchema | Lazy<TJunctionSchema>;\n };\n dest: {\n field: keyof TDestSchema['columns'];\n schema: TDestSchema | Lazy<TJunctionSchema>;\n };\n};\n\nexport function isFieldRelationship(\n relationship: Relationship,\n): relationship is FieldRelationship<TableSchema, TableSchema> {\n return (\n (\n relationship as JunctionRelationship<\n TableSchema,\n TableSchema,\n TableSchema\n >\n ).junction === undefined\n );\n}\n\nexport function isJunctionRelationship(\n relationship: Relationship,\n): relationship is JunctionRelationship<TableSchema, TableSchema, TableSchema> {\n return !isFieldRelationship(relationship);\n}\n\n/**\n * Calling `related` on `Query` returns a new Query\n * since `related` moves through the relationship. This function takes\n * 1. A schema\n * 2. A relationship name\n * and returns the schema of the entity at the other end of the\n * relationship.\n */\nexport type PullSchemaForRelationship<\n TSchema extends TableSchema,\n TRelationship extends keyof TSchema['relationships'],\n> = TSchema['relationships'][TRelationship] extends FieldRelationship<\n TableSchema,\n infer TSchema\n>\n ? TSchema\n : TSchema['relationships'][TRelationship] extends JunctionRelationship<\n TableSchema,\n TableSchema,\n infer TSchema\n >\n ? TSchema\n : never;\n", "/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type {\n SimpleOperator,\n ValuePosition,\n} from '../../../../zero-protocol/src/ast.js';\nimport type {\n GetFieldTypeNoNullOrUndefined,\n Operator,\n Parameter,\n Selector,\n} from './query.js';\nimport type {TableSchema} from './schema.js';\n\nexport type GenericCondition<TSchema extends TableSchema> =\n | GenericConjunction<TSchema>\n | GenericDisjunction<TSchema>\n | {\n type: 'simple';\n op: SimpleOperator;\n field: Selector<TSchema>;\n value: ValuePosition;\n };\n\ntype GenericConjunction<TSchema extends TableSchema> = {\n type: 'and';\n conditions: readonly GenericCondition<TSchema>[];\n};\n\ntype GenericDisjunction<TSchema extends TableSchema> = {\n type: 'or';\n conditions: readonly GenericCondition<TSchema>[];\n};\n\nexport function cmp<\n TSchema extends TableSchema,\n TSelector extends Selector<TSchema>,\n TOperator extends Operator,\n TParamAnchor = never,\n TParamField extends keyof TParamAnchor = never,\n TParamTypeBound extends GetFieldTypeNoNullOrUndefined<\n TSchema,\n TSelector,\n TOperator\n > = never,\n>(\n field: TSelector,\n op: TOperator,\n value:\n | GetFieldTypeNoNullOrUndefined<TSchema, TSelector, TOperator>\n | Parameter<TParamAnchor, TParamField, TParamTypeBound>,\n): GenericCondition<TSchema>;\nexport function cmp<\n TSchema extends TableSchema,\n TSelector extends Selector<TSchema>,\n TParamAnchor = never,\n TParamField extends keyof TParamAnchor = never,\n TParamTypeBound extends GetFieldTypeNoNullOrUndefined<\n TSchema,\n TSelector,\n '='\n > = never,\n>(\n field: TSelector,\n value:\n | GetFieldTypeNoNullOrUndefined<TSchema, TSelector, '='>\n | Parameter<TParamAnchor, TParamField, TParamTypeBound>,\n): GenericCondition<TSchema>;\nexport function cmp(\n field: string,\n opOrValue:\n | Operator\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n value?:\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n): GenericCondition<any>;\nexport function cmp(\n field: string,\n opOrValue:\n | Operator\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n value?:\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n): GenericCondition<any> {\n let op: Operator;\n if (value === undefined) {\n value = opOrValue;\n op = '=';\n } else {\n op = opOrValue as Operator;\n }\n\n return {\n type: 'simple',\n field,\n op,\n value,\n };\n}\n\nexport function and<TSchema extends TableSchema>(\n ...conditions: GenericCondition<TSchema>[]\n): GenericCondition<TSchema> {\n // If any internal conditions are `or` then we distribute `or` over the `and`.\n // This allows the graph and pipeline builder to remain simple and not have to deal with\n // nested conditions.\n // In other words, conditions are in [DNF](https://en.wikipedia.org/wiki/Disjunctive_normal_form).\n const ands: GenericCondition<TSchema>[] = conditions.flatMap(c => {\n if (c.type === 'and') {\n return c.conditions;\n } else if (c.type === 'simple') {\n return [c];\n }\n return [];\n });\n const ors: GenericCondition<TSchema>[] = conditions.filter(\n c => c.type === 'or',\n );\n\n if (ors.length === 0) {\n return {type: 'and', conditions: ands};\n }\n\n const flatOrs = flatten('or', ors);\n const flatAnds = flatten('and', ands);\n\n return {\n type: 'or',\n conditions: flatOrs.conditions.map(part => ({\n type: 'and',\n conditions: [\n ...(part.type === 'and' ? part.conditions : [part]),\n ...flatAnds.conditions,\n ],\n })),\n };\n}\n\nexport function or<TSchema extends TableSchema>(\n ...conditions: GenericCondition<TSchema>[]\n): GenericCondition<TSchema> {\n return flatten('or', conditions);\n}\n\nexport function not<TSchema extends TableSchema>(\n expr: GenericCondition<TSchema>,\n): GenericCondition<TSchema> {\n switch (expr.type) {\n case 'and':\n return {\n type: 'or',\n conditions: expr.conditions.map(not),\n };\n case 'or':\n return {\n type: 'and',\n conditions: expr.conditions.map(not),\n };\n default:\n return {\n type: 'simple',\n op: negateOperator(expr.op),\n field: expr.field,\n value: expr.value,\n };\n }\n}\n\nfunction flatten<TSchema extends TableSchema, TConnector extends 'and' | 'or'>(\n type: TConnector,\n conditions: GenericCondition<TSchema>[],\n): TConnector extends 'and'\n ? GenericConjunction<TSchema>\n : GenericDisjunction<TSchema> {\n const flattened: GenericCondition<TSchema>[] = [];\n for (const c of conditions) {\n if (c.type === type) {\n flattened.push(...c.conditions);\n } else {\n flattened.push(c);\n }\n }\n\n return {\n type,\n conditions: flattened,\n } satisfies GenericCondition<TSchema> as any;\n}\n\nfunction negateOperator(op: SimpleOperator): SimpleOperator {\n switch (op) {\n case '=':\n return '!=';\n case '!=':\n return '=';\n case '<':\n return '>=';\n case '>':\n return '<=';\n case '>=':\n return '<';\n case '<=':\n return '>';\n case 'IN':\n return 'NOT IN';\n case 'NOT IN':\n return 'IN';\n case 'LIKE':\n return 'NOT LIKE';\n case 'NOT LIKE':\n return 'LIKE';\n case 'ILIKE':\n return 'NOT ILIKE';\n case 'NOT ILIKE':\n return 'ILIKE';\n }\n}\n", "/* eslint-disable @typescript-eslint/naming-convention */\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {resolver} from '@rocicorp/resolver';\nimport {assert} from '../../../../shared/src/asserts.js';\nimport {hashOfAST} from '../../../../zero-protocol/src/ast-hash.js';\nimport type {\n AST,\n Condition,\n Ordering,\n} from '../../../../zero-protocol/src/ast.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport {buildPipeline, type BuilderDelegate} from '../builder/builder.js';\nimport {ArrayView} from '../ivm/array-view.js';\nimport type {Input} from '../ivm/operator.js';\nimport type {Format, ViewFactory} from '../ivm/view.js';\nimport {\n normalizeTableSchema,\n type NormalizedTableSchema,\n} from './normalize-table-schema.js';\nimport type {AdvancedQuery} from './query-internal.js';\nimport type {\n AddSelections,\n AddSubselect,\n DefaultQueryResultRow,\n GetFieldTypeNoNullOrUndefined,\n MakeSingular,\n Operator,\n Parameter,\n Query,\n QueryType,\n SchemaToRow,\n Selector,\n Smash,\n} from './query.js';\nimport {\n isFieldRelationship,\n isJunctionRelationship,\n type PullSchemaForRelationship,\n type TableSchema,\n} from './schema.js';\nimport type {TypedView} from './typed-view.js';\nimport {and, cmp, type GenericCondition} from './expression.js';\n\nexport function newQuery<\n TSchema extends TableSchema,\n TReturn extends QueryType = DefaultQueryResultRow<TSchema>,\n>(delegate: QueryDelegate, tableSchema: TSchema): Query<TSchema, TReturn> {\n return new QueryImpl(delegate, normalizeTableSchema(tableSchema));\n}\n\nfunction newQueryWithDetails<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n>(\n delegate: QueryDelegate,\n schema: NormalizedTableSchema,\n ast: AST,\n format: Format | undefined,\n): Query<TSchema, TReturn> {\n return new QueryImpl(delegate, schema, ast, format);\n}\n\nexport type CommitListener = () => void;\nexport type GotCallback = (got: boolean) => void;\nexport interface QueryDelegate extends BuilderDelegate {\n addServerQuery(ast: AST, gotCallback?: GotCallback | undefined): () => void;\n onTransactionCommit(cb: CommitListener): () => void;\n batchViewUpdates<T>(applyViewUpdates: () => T): T;\n}\n\nexport function staticParam<TAnchor, TField extends keyof TAnchor>(\n anchorClass: 'authData' | 'preMutationRow',\n field: TField,\n): Parameter<TAnchor, TField, TAnchor[TField]> {\n return {\n type: 'static',\n anchor: anchorClass,\n field,\n };\n}\n\nexport abstract class AbstractQuery<\n TSchema extends TableSchema,\n TReturn extends QueryType = DefaultQueryResultRow<TSchema>,\n> implements AdvancedQuery<TSchema, TReturn>\n{\n readonly #ast: AST;\n readonly #schema: NormalizedTableSchema;\n readonly #format: Format;\n #hash: string = '';\n\n constructor(\n schema: NormalizedTableSchema,\n ast: AST,\n format?: Format | undefined,\n ) {\n this.#ast = ast;\n this.#format = format ?? {singular: false, relationships: {}};\n this.#schema = schema;\n }\n\n get format(): Format {\n return this.#format;\n }\n\n hash(): string {\n if (!this.#hash) {\n const ast = this._completeAst();\n const hash = hashOfAST(ast);\n this.#hash = hash;\n }\n return this.#hash;\n }\n\n select<TFields extends Selector<TSchema>[]>(\n ..._fields: TFields\n ): Query<TSchema, AddSelections<TSchema, TFields, TReturn>> {\n // we return all columns for now so we ignore the selection set and only use it for type inference\n return this._newQuery(this.#schema, this.#ast, this.#format);\n }\n\n protected abstract _newQuery<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n >(\n schema: NormalizedTableSchema,\n ast: AST,\n format: Format | undefined,\n ): Query<TSchema, TReturn>;\n\n one(): Query<TSchema, MakeSingular<TReturn>> {\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n limit: 1,\n },\n {\n ...this.#format,\n singular: true,\n },\n );\n }\n\n related<TRelationship extends keyof TSchema['relationships']>(\n relationship: TRelationship,\n ): Query<\n TSchema,\n AddSubselect<\n Query<\n PullSchemaForRelationship<TSchema, TRelationship>,\n DefaultQueryResultRow<PullSchemaForRelationship<TSchema, TRelationship>>\n >,\n TReturn,\n TRelationship & string\n >\n >;\n related<\n TRelationship extends keyof TSchema['relationships'],\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n TSub extends Query<any, any>,\n >(\n relationship: TRelationship,\n cb: (\n query: Query<\n PullSchemaForRelationship<TSchema, TRelationship>,\n DefaultQueryResultRow<PullSchemaForRelationship<TSchema, TRelationship>>\n >,\n ) => TSub = q => q as any,\n ) {\n const related = this.#schema.relationships[relationship as string];\n assert(related, 'Invalid relationship');\n const related1 = related;\n const related2 = related;\n if (isFieldRelationship(related1)) {\n const destSchema = related1.dest.schema;\n const sq = cb(\n this._newQuery(\n destSchema,\n {\n table: destSchema.tableName,\n alias: relationship as string,\n },\n undefined,\n ),\n ) as unknown as QueryImpl<any, any>;\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n correlation: {\n parentField: related1.source,\n childField: related1.dest.field,\n op: '=',\n },\n subquery: addPrimaryKeysToAst(destSchema, sq.#ast),\n },\n ],\n },\n {\n ...this.#format,\n relationships: {\n ...this.#format.relationships,\n [relationship as string]: sq.#format,\n },\n },\n );\n }\n\n if (isJunctionRelationship(related2)) {\n const destSchema = related2.dest.schema;\n const junctionSchema = related2.junction.schema;\n const sq = cb(\n this._newQuery(\n destSchema,\n {\n table: destSchema.tableName,\n alias: relationship as string,\n },\n undefined,\n ),\n ) as unknown as QueryImpl<any, any>;\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n related: [\n ...(this.#ast.related ?? []),\n {\n correlation: {\n parentField: related2.source,\n childField: related2.junction.sourceField,\n op: '=',\n },\n subquery: {\n table: junctionSchema.tableName,\n alias: relationship as string,\n orderBy: addPrimaryKeys(junctionSchema, undefined),\n related: [\n {\n correlation: {\n parentField: related2.junction.destField,\n childField: related2.dest.field,\n op: '=',\n },\n hidden: true,\n subquery: addPrimaryKeysToAst(destSchema, sq.#ast),\n },\n ],\n },\n },\n ],\n },\n {\n ...this.#format,\n relationships: {\n ...this.#format.relationships,\n [relationship as string]: sq.#format,\n },\n },\n );\n }\n throw new Error(`Invalid relationship ${relationship as string}`);\n }\n\n where(\n field: string | GenericCondition<TSchema>,\n opOrValue?:\n | Operator\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n value?:\n | GetFieldTypeNoNullOrUndefined<any, any, any>\n | Parameter<any, any, any>,\n ): Query<TSchema, TReturn> {\n let cond: Condition;\n if (opOrValue === undefined && value === undefined) {\n assert(typeof field !== 'string', `Invalid condition: ${field}`);\n cond = field as Condition;\n } else {\n cond = cmp(field as string, opOrValue!, value) as Condition;\n }\n\n const existingWhere = this.#ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n where: cond,\n },\n this.#format,\n );\n }\n\n start(\n row: Partial<SchemaToRow<TSchema>>,\n opts?: {inclusive: boolean} | undefined,\n ): Query<TSchema, TReturn> {\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.#format,\n );\n }\n\n limit(limit: number): Query<TSchema, TReturn> {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n limit,\n },\n this.#format,\n );\n }\n\n orderBy<TSelector extends keyof TSchema['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TSchema, TReturn> {\n return this._newQuery(\n this.#schema,\n {\n ...this.#ast,\n orderBy: [...(this.#ast.orderBy ?? []), [field as string, direction]],\n },\n this.#format,\n );\n }\n\n #completedAST: AST | undefined;\n\n protected _completeAst(): AST {\n if (!this.#completedAST) {\n const finalOrderBy = addPrimaryKeys(this.#schema, this.#ast.orderBy);\n if (this.#ast.start) {\n const {row} = this.#ast.start;\n const narrowedRow: Row = {};\n for (const [field] of finalOrderBy) {\n narrowedRow[field] = row[field];\n }\n this.#completedAST = {\n ...this.#ast,\n start: {\n ...this.#ast.start,\n row: narrowedRow,\n },\n orderBy: finalOrderBy,\n };\n } else {\n this.#completedAST = {\n ...this.#ast,\n orderBy: addPrimaryKeys(this.#schema, this.#ast.orderBy),\n };\n }\n }\n return this.#completedAST;\n }\n\n abstract materialize(): TypedView<Smash<TReturn>>;\n abstract materialize<T>(factory: ViewFactory<TSchema, TReturn, T>): T;\n abstract run(): Smash<TReturn>;\n abstract preload(): {\n cleanup: () => void;\n complete: Promise<void>;\n };\n}\n\nexport const astForTestingSymbol = Symbol();\n\nexport class QueryImpl<\n TSchema extends TableSchema,\n TReturn extends QueryType = DefaultQueryResultRow<TSchema>,\n> extends AbstractQuery<TSchema, TReturn> {\n readonly #delegate: QueryDelegate;\n readonly #ast: AST;\n\n constructor(\n delegate: QueryDelegate,\n schema: NormalizedTableSchema,\n ast: AST = {table: schema.tableName},\n format?: Format | undefined,\n ) {\n super(schema, ast, format);\n this.#delegate = delegate;\n this.#ast = ast;\n }\n\n // Not part of Query or QueryInternal interface\n get [astForTestingSymbol](): AST {\n return this.#ast;\n }\n\n protected _newQuery<TSchema extends TableSchema, TReturn extends QueryType>(\n schema: NormalizedTableSchema,\n ast: AST,\n format: Format | undefined,\n ): Query<TSchema, TReturn> {\n return newQueryWithDetails(this.#delegate, schema, ast, format);\n }\n\n materialize<T>(factory?: ViewFactory<TSchema, TReturn, T>): T {\n const ast = this._completeAst();\n const removeServerQuery = this.#delegate.addServerQuery(ast);\n\n const input = buildPipeline(ast, this.#delegate, undefined);\n let removeCommitObserver: (() => void) | undefined;\n\n const onDestroy = () => {\n input.destroy();\n removeCommitObserver?.();\n removeServerQuery();\n };\n\n const view = this.#delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(this, input, this.format, onDestroy, cb => {\n removeCommitObserver = this.#delegate.onTransactionCommit(cb);\n }),\n );\n\n return view as T;\n }\n\n run() {\n const v: TypedView<Smash<TReturn>> = this.materialize();\n const ret = v.data;\n v.destroy();\n return ret;\n }\n\n preload(): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n const {resolve, promise: complete} = resolver<void>();\n const ast = this._completeAst();\n const unsub = this.#delegate.addServerQuery(ast, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup: unsub,\n complete,\n };\n }\n}\n\nfunction addPrimaryKeys(\n schema: NormalizedTableSchema,\n orderBy: Ordering | undefined,\n): Ordering {\n orderBy = orderBy ?? [];\n const {primaryKey} = schema;\n const primaryKeysToAdd = new Set(primaryKey);\n\n for (const [field] of orderBy) {\n primaryKeysToAdd.delete(field);\n }\n\n if (primaryKeysToAdd.size === 0) {\n return orderBy;\n }\n\n return [\n ...orderBy,\n ...[...primaryKeysToAdd].map(key => [key, 'asc'] as [string, 'asc']),\n ];\n}\n\nfunction addPrimaryKeysToAst(schema: NormalizedTableSchema, ast: AST): AST {\n return {\n ...ast,\n orderBy: addPrimaryKeys(schema, ast.orderBy),\n };\n}\n\nfunction arrayViewFactory<\n TSchema extends TableSchema,\n TReturn extends QueryType,\n>(\n _query: Query<TSchema, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n): TypedView<Smash<TReturn>> {\n const v = new ArrayView<Smash<TReturn>>(input, format);\n v.onDestroy = onDestroy;\n onTransactionCommit(() => {\n v.flush();\n });\n return v;\n}\n", "import xxhash from 'xxhash-wasm';\n\nconst {create64, h32, h64} = await xxhash();\n\nexport {create64, h32, h64};\n", "/**\n * Wire-format representation of the zql AST interface.\n *\n * `v.Type<...>` types are explicitly declared to facilitate Typescript verification\n * that the schemas satisfy the zql type definitions. (Incidentally, explicit types\n * are also required for recursive schema definitions.)\n */\n\nimport {compareUTF8} from 'compare-utf8';\nimport {must} from '../../shared/src/must.js';\nimport * as v from '../../shared/src/valita.js';\nimport {defined} from '../../shared/src/arrays.js';\nimport {rowSchema, type Row} from './data.js';\n\nexport const selectorSchema = v.string();\n\nconst orderingElementSchema = v.readonly(\n v.tuple([selectorSchema, v.union(v.literal('asc'), v.literal('desc'))]),\n);\n\nexport const orderingSchema = v.readonlyArray(orderingElementSchema);\n\nexport const primitiveSchema = v.union(\n v.string(),\n v.number(),\n v.boolean(),\n v.null(),\n);\n\nexport const equalityOpsSchema = v.union(v.literal('='), v.literal('!='));\n\nexport const orderOpsSchema = v.union(\n v.literal('<'),\n v.literal('>'),\n v.literal('<='),\n v.literal('>='),\n);\n\nexport const likeOpsSchema = v.union(\n v.literal('LIKE'),\n v.literal('NOT LIKE'),\n v.literal('ILIKE'),\n v.literal('NOT ILIKE'),\n);\n\nexport const inOpsSchema = v.union(v.literal('IN'), v.literal('NOT IN'));\n\nexport const simpleOperatorSchema = v.union(\n equalityOpsSchema,\n orderOpsSchema,\n likeOpsSchema,\n inOpsSchema,\n);\n\nexport const simpleConditionSchema = v.object({\n type: v.literal('simple'),\n op: simpleOperatorSchema,\n field: selectorSchema,\n value: v.union(\n v.string(),\n v.number(),\n v.boolean(),\n v.readonlyArray(v.union(v.string(), v.number(), v.boolean())),\n v.object({\n type: v.literal('static'),\n anchor: v.union(v.literal('authData'), v.literal('preMutationRow')),\n field: v.string(),\n }),\n ),\n});\n\nexport const conditionSchema = v.union(\n simpleConditionSchema,\n v.lazy(() => conjunctionSchema),\n v.lazy(() => disjunctionSchema),\n);\n\nconst conjunctionSchema: v.Type<Conjunction> = v.readonlyObject({\n type: v.literal('and'),\n conditions: v.readonlyArray(conditionSchema),\n});\n\nconst disjunctionSchema: v.Type<Disjunction> = v.readonlyObject({\n type: v.literal('or'),\n conditions: v.readonlyArray(conditionSchema),\n});\n\n// Split out so that its inferred type can be checked against\n// Omit<CorrelatedSubQuery, 'correlation'> in ast-type-test.ts.\n// The mutually-recursive reference of the 'other' field to astSchema\n// is the only thing added in v.lazy. The v.lazy is necessary due to the\n// mutually-recursive types, but v.lazy prevents inference of the resulting\n// type.\nexport const correlatedSubquerySchemaOmitSubquery = v.readonlyObject({\n correlation: v.object({\n parentField: v.string(),\n childField: v.string(),\n op: v.literal('='),\n }),\n hidden: v.boolean().optional(),\n});\n\nexport const correlatedSubquerySchema: v.Type<CorrelatedSubQuery> =\n correlatedSubquerySchemaOmitSubquery.extend({\n subquery: v.lazy(() => astSchema),\n });\n\nexport const astSchema = v.object({\n schema: v.string().optional(),\n table: v.string(),\n alias: v.string().optional(),\n where: conditionSchema.optional(),\n related: v.readonlyArray(correlatedSubquerySchema).optional(),\n limit: v.number().optional(),\n orderBy: orderingSchema.optional(),\n start: v\n .object({\n row: rowSchema,\n exclusive: v.boolean(),\n })\n .optional(),\n});\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * As in SQL you can have multiple orderings. We don't currently\n * support ordering on anything other than the root query.\n */\nexport type OrderPart = readonly [field: string, direction: 'asc' | 'desc'];\nexport type Ordering = readonly OrderPart[];\n\nexport type SimpleOperator = EqualityOps | OrderOps | LikeOps | InOps;\nexport type EqualityOps = '=' | '!=';\nexport type OrderOps = '<' | '>' | '<=' | '>=';\nexport type LikeOps = 'LIKE' | 'NOT LIKE' | 'ILIKE' | 'NOT ILIKE';\nexport type InOps = 'IN' | 'NOT IN';\n\nexport type AST = {\n readonly schema?: string | undefined;\n readonly table: string;\n\n // A query would be aliased if the AST is a subquery.\n // e.g., when two subqueries select from the same table\n // they need an alias to differentiate them.\n // `SELECT\n // [SELECT * FROM issue WHERE issue.id = outer.parentId] AS parent\n // [SELECT * FROM issue WHERE issue.parentId = outer.id] AS children\n // FROM issue as outer`\n readonly alias?: string | undefined;\n\n // `select` is missing given we return all columns for now.\n\n // The PipelineBuilder will pick what to use to correlate\n // a subquery with a parent query. It can choose something from the\n // where conditions or choose the _first_ `related` entry.\n // Choosing the first `related` entry is almost always the best choice if\n // one exists.\n readonly where?: Condition | undefined;\n\n readonly related?: readonly CorrelatedSubQuery[] | undefined;\n readonly start?: Bound | undefined;\n readonly limit?: number | undefined;\n readonly orderBy?: Ordering | undefined;\n};\n\nexport type CorrelatedSubQuery = {\n /**\n * Only equality correlations are supported for now.\n * E.g., direct foreign key relationships.\n */\n readonly correlation: {\n readonly parentField: string;\n readonly childField: string;\n readonly op: '=';\n };\n readonly subquery: AST;\n // If a hop in the subquery chain should be hidden from the output view.\n // A common example is junction edges. The query API provides the illusion\n // that they don't exist: `issue.related('labels')` instead of `issue.related('issue_labels').related('labels')`.\n // To maintain this illusion, the junction edge should be hidden.\n // When `hidden` is set to true, this hop will not be included in the output view\n // but its children will be.\n readonly hidden?: boolean | undefined;\n};\n\nexport type ValuePosition = LiteralValue | Parameter;\n\nexport type LiteralValue =\n | string\n | number\n | boolean\n | ReadonlyArray<string | number | boolean>;\n\n/**\n * Starting only with SimpleCondition for now.\n * ivm1 supports Conjunctions and Disjunctions.\n * We'll support them in the future.\n */\nexport type Condition = SimpleCondition | Conjunction | Disjunction;\n\nexport type SimpleCondition = {\n type: 'simple';\n op: SimpleOperator;\n\n /**\n * Not a path yet as we're currently not allowing\n * comparisons across tables. This will need to\n * be a path through the tree in the near future.\n */\n field: string;\n\n /**\n * `null` is absent since we do not have an `IS` or `IS NOT`\n * operator defined and `null != null` in SQL.\n */\n value: ValuePosition;\n};\n\nexport type Conjunction = {\n type: 'and';\n conditions: readonly Condition[];\n};\n\nexport type Disjunction = {\n type: 'or';\n conditions: readonly Condition[];\n};\n\n/**\n * A parameter is a value that is not known at the time the query is written\n * and is resolved at runtime.\n *\n * StaticParameters refer to something provided by the caller.\n * StaticParameters are injected when the query pipeline is built from the AST\n * and do not change for the life of that pipeline.\n *\n * An example StaticParameter is the current authentication data.\n * When a user is authenticated, queries on the server have access\n * to the user's authentication data in order to evaluate authorization rules.\n * Authentication data doesn't change over the life of a query as a change\n * in auth data would represent a log-in / log-out of the user.\n *\n * AncestorParameters refer to rows encountered while running the query.\n * They are used by subqueries to refer to rows emitted by parent queries.\n */\nexport type Parameter = StaticParameter;\ntype StaticParameter = {\n type: 'static';\n // The \"namespace\" of the injected parameter.\n // Write authorization will send the value of a row\n // prior to the mutation being run (preMutationRow).\n // Read and write authorization will both send the\n // current authentication data (authData).\n anchor: 'authData' | 'preMutationRow';\n field: string;\n};\n\nconst normalizeCache = new WeakMap<AST, Required<AST>>();\nexport function normalizeAST(ast: AST): Required<AST> {\n const cached = normalizeCache.get(ast);\n if (cached) {\n return cached;\n }\n const where = flattened(ast.where);\n const normalized = {\n schema: ast.schema,\n table: ast.table,\n alias: ast.alias,\n where: where ? sortedWhere(where) : undefined,\n related: ast.related\n ? sortedRelated(\n ast.related.map(\n r =>\n ({\n correlation: {\n parentField: r.correlation.parentField,\n childField: r.correlation.childField,\n op: r.correlation.op,\n },\n hidden: r.hidden,\n subquery: normalizeAST(r.subquery),\n }) satisfies Required<CorrelatedSubQuery>,\n ),\n )\n : undefined,\n start: ast.start,\n limit: ast.limit,\n orderBy: ast.orderBy,\n };\n\n normalizeCache.set(ast, normalized);\n return normalized;\n}\n\nfunction sortedWhere(where: Condition): Condition {\n if (where.type === 'simple') {\n return where;\n }\n return {\n type: where.type,\n conditions: where.conditions.map(w => sortedWhere(w)).sort(cmpCondition),\n };\n}\n\nfunction sortedRelated(\n related: CorrelatedSubQuery[],\n): readonly CorrelatedSubQuery[] {\n return related.sort(cmpRelated);\n}\n\nfunction cmpCondition(a: Condition, b: Condition): number {\n if (a.type === 'simple') {\n if (b.type !== 'simple') {\n return -1; // Order SimpleConditions first to simplify logic for invalidation filtering.\n }\n return (\n compareUTF8MaybeNull(a.field, b.field) ||\n compareUTF8MaybeNull(a.op, b.op) ||\n // Comparing the same field with the same op more than once doesn't make logical\n // sense, but is technically possible. Assume the values are of the same type and\n // sort by their String forms.\n compareUTF8MaybeNull(String(a.value), String(b.value))\n );\n }\n\n if (b.type === 'simple') {\n return 1; // Order SimpleConditions first to simplify logic for invalidation filtering.\n }\n\n const val = compareUTF8MaybeNull(a.type, b.type);\n if (val !== 0) {\n return val;\n }\n for (\n let l = 0, r = 0;\n l < a.conditions.length && r < b.conditions.length;\n l++, r++\n ) {\n const val = cmpCondition(a.conditions[l], b.conditions[r]);\n if (val !== 0) {\n return val;\n }\n }\n // prefixes first\n return a.conditions.length - b.conditions.length;\n}\n\nfunction cmpRelated(a: CorrelatedSubQuery, b: CorrelatedSubQuery): number {\n return compareUTF8(must(a.subquery.alias), must(b.subquery.alias));\n}\n\n/**\n * Returns a flattened version of the Conditions in which nested Conjunctions with\n * the same operation ('AND' or 'OR') are flattened to the same level. e.g.\n *\n * ```\n * ((a AND b) AND (c AND (d OR (e OR f)))) -> (a AND b AND c AND (d OR e OR f))\n * ```\n *\n * Also flattens singleton Conjunctions regardless of operator, and removes\n * empty Conjunctions.\n */\nfunction flattened<T extends Condition>(cond: T | undefined): T | undefined {\n if (cond === undefined) {\n return undefined;\n }\n if (cond.type === 'simple') {\n return cond;\n }\n const conditions = defined(\n cond.conditions.flatMap(c =>\n c.type === cond.type ? c.conditions.map(c => flattened(c)) : flattened(c),\n ),\n );\n\n switch (conditions.length) {\n case 0:\n return undefined;\n case 1:\n return conditions[0] as T;\n default:\n return {\n type: cond.type,\n conditions,\n } as unknown as T;\n }\n}\n\nfunction compareUTF8MaybeNull(a: string | null, b: string | null): number {\n if (a !== null && b !== null) {\n return compareUTF8(a, b);\n }\n if (b !== null) {\n return -1;\n }\n if (a !== null) {\n return 1;\n }\n return 0;\n}\n", "/**\n * Returns `arr` as is if none of the elements are `undefined`.\n * Otherwise returns a new array with only defined elements in `arr`.\n */\nexport function defined<T>(arr: (T | undefined)[]): T[] {\n // avoid an array copy if possible\n let i = arr.findIndex(x => x === undefined);\n if (i < 0) {\n return arr as T[];\n }\n const defined: T[] = arr.slice(0, i) as T[];\n for (i++; i < arr.length; i++) {\n const x = arr[i];\n if (x !== undefined) {\n defined.push(x);\n }\n }\n return defined;\n}\n", "import {jsonSchema} from '../../shared/src/json-schema.js';\nimport * as v from '../../shared/src/valita.js';\n\nexport const valueSchema = v.union(jsonSchema, v.undefined());\n\nexport const rowSchema = v.record(valueSchema);\n\n/**\n * The data types that Zero can represent are limited by two things:\n *\n * 1. The underlying Replicache sync layer currently can only represent JSON\n * types. This could possibly be expanded in the future, but we do want to be\n * careful of adding encoding overhead. By using JSON, we are taking\n * advantage of IndexedDB\u2019s fast native JSValue [de]serialization which has\n * historically been a perf advantage for us.\n *\n * 2. IDs in Zero need to be comparable because we use them for sorting and row\n * identity. We could expand the set of allowed value types (to include,\n * i.e., Objects) but we would then need to restrict IDs to only comparable\n * types.\n *\n * These two facts leave us with the following allowed types. Zero's replication\n * layer must convert other types into these for tables to be used with Zero.\n *\n * For developer convenience we also allow `undefined`, which we treat\n * equivalently to `null`.\n */\nexport type Value = v.Infer<typeof valueSchema>;\n\n/**\n * A Row is represented as a JS Object.\n *\n * We do everything in IVM as loosely typed values because these pipelines are\n * going to be constructed at runtime by other code, so type-safety can't buy us\n * anything.\n *\n * Also since the calling code on the client ultimately wants objects to work\n * with we end up with a lot less copies by using objects throughout.\n */\nexport type Row = v.Infer<typeof rowSchema>;\n", "import {h64} from '../../shared/src/xxhash.js';\nimport {normalizeAST, type AST} from './ast.js';\n\nconst hashCache = new WeakMap<AST, string>();\n\nexport function hashOfAST(ast: AST): string {\n const normalized = normalizeAST(ast);\n const cached = hashCache.get(normalized);\n if (cached) {\n return cached;\n }\n const hash = h64(JSON.stringify(normalized)).toString(36);\n hashCache.set(normalized, hash);\n return hash;\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport {mergeIterables} from '../../../../shared/src/iterables.js';\nimport {\n deepEqual,\n type ReadonlyJSONValue,\n} from '../../../../shared/src/json.js';\nimport {must} from '../../../../shared/src/must.js';\nimport type {Change} from './change.js';\nimport type {Node} from './data.js';\nimport type {FanOut} from './fan-out.js';\nimport type {FetchRequest, Input, Operator, Output} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport type {Stream} from './stream.js';\n\n/**\n * The FanIn operator merges multiple streams into one.\n * It eliminates duplicates and must be paired with a fan-out operator\n * somewhere upstream of the fan-in.\n *\n * issue\n * |\n * fan-out\n * / \\\n * a b\n * \\ /\n * fan-in\n * |\n */\nexport class FanIn implements Operator {\n readonly #inputs: readonly Input[];\n readonly #fanOut: FanOut;\n #output: Output | undefined;\n #schema: TableSchema | undefined;\n\n constructor(fanOut: FanOut, inputs: [Input, ...Input[]]) {\n this.#inputs = inputs;\n this.#schema = inputs[0].getSchema();\n this.#fanOut = fanOut;\n for (const input of inputs) {\n input.setOutput(this);\n assert(\n deepEqual(\n this.#schema as unknown as ReadonlyJSONValue,\n input.getSchema() as unknown as ReadonlyJSONValue,\n ),\n `Schema mismatch in fan-in`,\n );\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n getSchema() {\n return this.#inputs[0].getSchema();\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n return this.#fetchOrCleanup(input => input.fetch(req));\n }\n\n cleanup(req: FetchRequest): Stream<Node> {\n return this.#fetchOrCleanup(input => input.cleanup(req));\n }\n\n *#fetchOrCleanup(streamProvider: (input: Input) => Stream<Node>) {\n const iterables = this.#inputs.map(input => streamProvider(input));\n for (const node of mergeIterables(\n iterables,\n (l, r) => must(this.#schema).compareRows(l.row, r.row),\n true,\n )) {\n yield node;\n }\n }\n\n push(change: Change) {\n this.#fanOut.onFanInReceivedPush();\n this.#output?.push(change);\n }\n}\n", "import type {Change} from './change.js';\nimport type {FetchRequest, Input, Operator, Output} from './operator.js';\n\n/**\n * Forks a stream into multiple streams.\n * Is meant to be paired with a `FanIn` operator which will\n * later merge the forks back together.\n */\nexport class FanOut implements Operator {\n readonly #input: Input;\n readonly #outputs: Output[];\n #fanInReceivedPush: boolean;\n #destroyCount: number;\n\n constructor(input: Input) {\n this.#input = input;\n this.#input.setOutput(this);\n this.#outputs = [];\n this.#fanInReceivedPush = false;\n this.#destroyCount = 0;\n }\n\n setOutput(output: Output): void {\n this.#outputs.push(output);\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n if (this.#destroyCount === 0) {\n this.#input.destroy();\n }\n ++this.#destroyCount;\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n\n getSchema() {\n return this.#input.getSchema();\n }\n\n fetch(req: FetchRequest) {\n return this.#input.fetch(req);\n }\n\n cleanup(req: FetchRequest) {\n return this.#input.cleanup(req);\n }\n\n onFanInReceivedPush() {\n this.#fanInReceivedPush = true;\n }\n\n push(change: Change) {\n this.#fanInReceivedPush = false;\n for (const out of this.#outputs) {\n out.push(change);\n if (this.#fanInReceivedPush) {\n return;\n }\n }\n }\n}\n", "import type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {EditChange} from './change.js';\nimport type {Output} from './operator.js';\n\n/**\n * This takes an {@linkcode EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n) {\n const oldWasPresent = predicate(change.oldRow);\n const newIsPresent = predicate(change.row);\n\n if (oldWasPresent && newIsPresent) {\n output.push(change);\n } else if (oldWasPresent && !newIsPresent) {\n // The relationships are empty at this point and that is fine since\n // splitAndPushEditChange is only used by operators that are before the Join\n // operator.\n output.push({\n type: 'remove',\n node: {\n row: change.oldRow,\n relationships: {},\n },\n });\n } else if (!oldWasPresent && newIsPresent) {\n output.push({\n type: 'add',\n node: {\n row: change.row,\n relationships: {},\n },\n });\n }\n}\n", "import {assert, unreachable} from '../../../../shared/src/asserts.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {Change} from './change.js';\nimport type {Node} from './data.js';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.js';\nimport type {FetchRequest, Input, Operator, Output} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport type {Stream} from './stream.js';\n\n/**\n * Apply filter to all data flowing through, or just pushes. Pipeline builder\n * can hoist some filters up to source, so it will tell Filter to apply only to\n * pushes in that case.\n */\nexport type Mode = 'all' | 'push-only';\n\n/**\n * The Filter operator filters data through a predicate. It is stateless.\n *\n * The predicate must be pure.\n */\nexport class Filter implements Operator {\n readonly #input: Input;\n readonly #mode: Mode;\n readonly #predicate: (row: Row) => boolean;\n\n #output: Output | undefined;\n\n constructor(input: Input, mode: Mode, predicate: (row: Row) => boolean) {\n this.#input = input;\n this.#mode = mode;\n this.#predicate = predicate;\n this.#input.setOutput(this);\n }\n\n setOutput(output: Output) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): TableSchema {\n return this.#input.getSchema();\n }\n\n fetch(req: FetchRequest) {\n return this.#filter(this.#input.fetch(req));\n }\n\n cleanup(req: FetchRequest) {\n return this.#filter(this.#input.cleanup(req));\n }\n\n *#filter(stream: Stream<Node>) {\n for (const node of stream) {\n if (this.#mode === 'push-only' || this.#predicate(node.row)) {\n yield node;\n }\n }\n }\n\n push(change: Change) {\n assert(this.#output, 'Output not set');\n\n switch (change.type) {\n case 'add':\n case 'remove':\n if (this.#predicate(change.node.row)) {\n this.#output.push(change);\n }\n break;\n case 'child':\n if (this.#predicate(change.row)) {\n this.#output.push(change);\n }\n break;\n case 'edit':\n maybeSplitAndPushEditChange(change, this.#predicate, this.#output);\n break;\n default:\n unreachable(change);\n }\n }\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../../shared/src/asserts.js';\nimport type {Ordering} from '../../../../zero-protocol/src/ast.js';\nimport type {Row, Value} from '../../../../zero-protocol/src/data.js';\nimport type {Stream} from './stream.js';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n relationships: Record<string, Stream<Node>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(order: Ordering): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n return ord[1] === 'asc' ? comp : -comp;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n if (a === null || b === null) {\n return false;\n }\n return a === b;\n}\n", "/**\n * streams are lazy forward-only iterables.\n * Once a stream reaches the end it can't be restarted.\n * They are iterable, not iterator, so that they can be used in for-each,\n * and so that we know when consumer has stopped iterating the stream. This allows us\n * to clean up resources like sql statements.\n */\nexport type Stream<T> = Iterable<T>;\n\nexport function* take<T>(stream: Stream<T>, limit: number): Stream<T> {\n if (limit < 1) {\n return;\n }\n let count = 0;\n for (const v of stream) {\n yield v;\n if (++count === limit) {\n break;\n }\n }\n}\n\nexport function first<T>(stream: Stream<T>): T | undefined {\n const it = stream[Symbol.iterator]();\n const {value} = it.next();\n it.return?.();\n return value;\n}\n", "import {assert, unreachable} from '../../../../shared/src/asserts.js';\nimport {must} from '../../../../shared/src/must.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {PrimaryKey} from '../../../../zero-protocol/src/primary-key.js';\nimport type {Change, ChildChange} from './change.js';\nimport {normalizeUndefined, type Node, type NormalizedValue} from './data.js';\nimport type {FetchRequest, Input, Output, Storage} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport {first, take, type Stream} from './stream.js';\n\ntype Args = {\n parent: Input;\n child: Input;\n storage: Storage;\n parentKey: string;\n childKey: string;\n relationshipName: string;\n hidden: boolean;\n};\n/**\n * The Join operator joins the output from two upstream inputs. Zero's join\n * is a little different from SQL's join in that we output hierarchical data,\n * not a flat table. This makes it a lot more useful for UI programming and\n * avoids duplicating tons of data like left join would.\n *\n * The Nodes output from Join have a new relationship added to them, which has\n * the name #relationshipName. The value of the relationship is a stream of\n * child nodes which are the corresponding values from the child source.\n */\nexport class Join implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #storage: Storage;\n readonly #parentKey: string;\n readonly #childKey: string;\n readonly #relationshipName: string;\n readonly #schema: TableSchema;\n\n #output: Output | null = null;\n\n constructor({\n parent,\n child,\n storage,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n\n this.#parent = parent;\n this.#child = child;\n this.#storage = storage;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n isHidden: hidden,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: childSchema,\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#parent.destroy();\n this.#child.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): TableSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n for (const parentNode of this.#parent.fetch(req)) {\n yield this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n 'fetch',\n );\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n for (const parentNode of this.#parent.cleanup(req)) {\n yield this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n 'cleanup',\n );\n }\n }\n\n #pushParent(change: Change): void {\n assert(this.#output, 'Output not set');\n\n switch (change.type) {\n case 'add':\n this.#output.push({\n type: 'add',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'fetch',\n ),\n });\n break;\n case 'remove':\n this.#output.push({\n type: 'remove',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'cleanup',\n ),\n });\n break;\n case 'child':\n this.#output.push(change);\n break;\n case 'edit': {\n // When an edit comes in we need to:\n // - Update the parent node.\n // - If the value of the join key changed we need to remove the old relation rows and add the new ones.\n\n this.#output.push({\n type: 'edit',\n row: change.row,\n oldRow: change.oldRow,\n });\n\n const oldKeyValue = normalizeUndefined(change.oldRow[this.#parentKey]);\n const newKeyValue = normalizeUndefined(change.row[this.#parentKey]);\n\n if (newKeyValue !== oldKeyValue) {\n const childrenToRemoveStream = this.#child.cleanup({\n constraint: {\n key: this.#childKey,\n value: oldKeyValue,\n },\n });\n for (const childNode of childrenToRemoveStream) {\n this.#output.push({\n type: 'child',\n // This is the new row since we already changed it in the edit above.\n row: change.row,\n child: {\n relationshipName: this.#relationshipName,\n change: {\n type: 'remove',\n node: childNode,\n },\n },\n });\n }\n\n const childrenToAddStream = this.#child.fetch({\n constraint: {\n key: this.#childKey,\n value: newKeyValue,\n },\n });\n for (const childNode of childrenToAddStream) {\n this.#output.push({\n type: 'child',\n row: change.row,\n child: {\n relationshipName: this.#relationshipName,\n change: {\n type: 'add',\n node: childNode,\n },\n },\n });\n }\n }\n\n const {primaryKey} = this.#parent.getSchema();\n const oldStorageKey = makeStorageKey(\n oldKeyValue,\n primaryKey,\n change.oldRow,\n );\n const newStorageKey = makeStorageKey(\n newKeyValue,\n primaryKey,\n change.row,\n );\n\n // This can be true for both cases. Even if the join key value didn't\n // change the primary key values might have.\n if (oldStorageKey !== newStorageKey) {\n this.#storage.del(oldStorageKey);\n this.#storage.set(newStorageKey, true);\n }\n\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n #pushChild(change: Change): void {\n const pushChildChange = (childRow: Row, change: Change) => {\n assert(this.#output, 'Output not set');\n\n const parentNodes = this.#parent.fetch({\n constraint: {\n key: this.#parentKey,\n value: childRow[this.#childKey],\n },\n });\n\n for (const parentNode of parentNodes) {\n const childChange: ChildChange = {\n type: 'child',\n row: parentNode.row,\n child: {\n relationshipName: this.#relationshipName,\n change,\n },\n };\n this.#output.push(childChange);\n }\n };\n\n switch (change.type) {\n case 'add':\n case 'remove':\n pushChildChange(change.node.row, change);\n break;\n case 'child':\n pushChildChange(change.row, change);\n break;\n case 'edit': {\n const childRow = change.row;\n const oldChildRow = change.oldRow;\n if (\n normalizeUndefined(oldChildRow[this.#childKey]) ===\n normalizeUndefined(childRow[this.#childKey])\n ) {\n // The child row was edited in a way that does not change the relationship.\n // We can therefore just push the change down (wrapped in a child change).\n pushChildChange(childRow, change);\n } else {\n // The child row was edited in a way that changes the relationship. We\n // therefore treat this as a remove from the old row followed by an\n // add to the new row.\n\n const {relationships} = must(\n first(\n this.#child.fetch({\n constraint: {\n key: this.#childKey,\n value: oldChildRow[this.#childKey],\n },\n }),\n ),\n );\n\n pushChildChange(oldChildRow, {\n type: 'remove',\n node: {\n row: oldChildRow,\n relationships,\n },\n });\n pushChildChange(childRow, {\n type: 'add',\n node: {\n row: childRow,\n relationships,\n },\n });\n }\n break;\n }\n\n default:\n unreachable(change);\n }\n }\n\n #processParentNode(\n parentNodeRow: Row,\n parentNodeRelations: Record<string, Stream<Node>>,\n mode: ProcessParentMode,\n ): Node {\n const parentKeyValue = normalizeUndefined(parentNodeRow[this.#parentKey]);\n\n // This storage key tracks the primary keys seen for each unique\n // value joined on. This is used to know when to cleanup a child's state.\n const storageKey = makeStorageKey(\n parentKeyValue,\n this.#parent.getSchema().primaryKey,\n parentNodeRow,\n );\n\n let method: ProcessParentMode = mode;\n if (mode === 'cleanup') {\n const [, second] = take(\n this.#storage.scan({\n prefix: createPrimaryKeySetStorageKeyPrefix(parentKeyValue),\n }),\n 2,\n );\n method = second ? 'fetch' : 'cleanup';\n }\n\n const childStream = this.#child[method]({\n constraint: {\n key: this.#childKey,\n value: parentKeyValue,\n },\n });\n\n if (mode === 'fetch') {\n this.#storage.set(storageKey, true);\n } else {\n mode satisfies 'cleanup';\n this.#storage.del(storageKey);\n }\n\n return {\n row: parentNodeRow,\n relationships: {\n ...parentNodeRelations,\n [this.#relationshipName]: childStream,\n },\n };\n }\n}\n\ntype ProcessParentMode = 'fetch' | 'cleanup';\n\n/** Exported for testing. */\nexport function createPrimaryKeySetStorageKey(\n values: readonly NormalizedValue[],\n): string {\n const json = JSON.stringify(['pKeySet', ...values]);\n return json.substring(1, json.length - 1) + ',';\n}\n\nexport function createPrimaryKeySetStorageKeyPrefix(\n value: NormalizedValue,\n): string {\n return createPrimaryKeySetStorageKey([value]);\n}\n\nfunction makeStorageKey(\n keyValue: NormalizedValue,\n primaryKey: PrimaryKey,\n row: Row,\n): string {\n const parentPrimaryKey: NormalizedValue[] = [keyValue];\n for (const key of primaryKey) {\n parentPrimaryKey.push(normalizeUndefined(row[key]));\n }\n return createPrimaryKeySetStorageKey(parentPrimaryKey);\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {AddChange, Change, ChildChange, RemoveChange} from './change.js';\nimport type {Comparator, Node} from './data.js';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.js';\nimport type {FetchRequest, Input, Operator, Output, Start} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport type {Stream} from './stream.js';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output | undefined;\n\n constructor(input: Input, bound: Bound) {\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n this.#input.setOutput(this);\n }\n\n getSchema(): TableSchema {\n return this.#input.getSchema();\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n return this.#input.fetch({...req, start: this.#getStart(req)});\n }\n\n cleanup(req: FetchRequest): Stream<Node> {\n return this.#input.cleanup({...req, start: this.#getStart(req)});\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n push(change: Change): void {\n assert(this.#output, 'Output not set');\n\n const shouldBePresent = (row: Row) => {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n };\n\n if (change.type === 'edit') {\n maybeSplitAndPushEditChange(change, shouldBePresent, this.#output);\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n const changeRow = change.type === 'child' ? change.row : change.node.row;\n if (shouldBePresent(changeRow)) {\n this.#output.push(change);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n // There is the case where the requested bound is basis: 'before', but\n // that cannot be relevant.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n assert(cmp < 0);\n\n // The skip bound is before the requested bound. If the requested bound is\n // either 'at' or 'after', the skip bound cannot be relevant. Return the\n // requested bound.\n if (req.start.basis === 'at' || req.start.basis === 'after') {\n return req.start;\n }\n\n // That leaves the one interesting case: the skip bound is before the\n // requested bound, but the requested bound is basis: 'before'. It is\n // possible that the first element before the requested bound is itself the\n // skip bound, or there could be some other element between. We'll have to\n // fetch to find out.\n req.start.basis satisfies 'before';\n\n const [node] = this.#input.fetch(req) as Array<Node | undefined>;\n\n // There's no element at all before the requested bound, not even the skip\n // bound. In this case we may as well return the requested bound with 'at'\n // to simplify work for the source.\n if (!node) {\n return {\n row: req.start.row,\n basis: 'at',\n };\n }\n\n // If there's an element before the requested bound, but it's before the\n // skip bound, then we'll use the skip bound afterall.\n if (this.#comparator(node.row, this.#bound.row) <= 0) {\n return boundStart;\n }\n\n // Finally, if there's an element before the requested bound, and it's after\n // the skip bound, then that's the element we should start at.\n return {\n row: node.row,\n basis: 'at',\n };\n }\n}\n", "import {assert, unreachable} from '../../../../shared/src/asserts.js';\nimport {must} from '../../../../shared/src/must.js';\nimport type {Row, Value} from '../../../../zero-protocol/src/data.js';\nimport {assertOrderingIncludesPK} from '../builder/builder.js';\nimport type {Change, EditChange, RemoveChange} from './change.js';\nimport {normalizeUndefined, type Node} from './data.js';\nimport type {\n Constraint,\n FetchRequest,\n Input,\n Operator,\n Output,\n Storage,\n} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport {first, take, type Stream} from './stream.js';\n\nconst MAX_BOUND_KEY = 'maxBound';\n\ntype TakeState = {\n size: number;\n bound: Row | undefined;\n};\n\ninterface TakeStorage {\n get(key: typeof MAX_BOUND_KEY): Row | undefined;\n get(key: string): TakeState | undefined;\n set(key: typeof MAX_BOUND_KEY, value: Row): void;\n set(key: string, value: TakeState): void;\n del(key: string): void;\n}\n\n/**\n * The Take operator is for implementing limit queries. It takes the first n\n * nodes of its input as determined by the input\u2019s comparator. It then keeps\n * a *bound* of the last item it has accepted so that it can evaluate whether\n * new incoming pushes should be accepted or rejected.\n *\n * Take can count rows globally or by unique value of some field.\n */\nexport class Take implements Operator {\n readonly #input: Input;\n readonly #storage: TakeStorage;\n readonly #limit: number;\n readonly #partitionKey: string | undefined;\n\n #output: Output | null = null;\n\n constructor(\n input: Input,\n storage: Storage,\n limit: number,\n partitionKey?: string | undefined,\n ) {\n this.#input = input;\n this.#storage = storage as TakeStorage;\n this.#limit = limit;\n this.#partitionKey = partitionKey;\n assert(limit >= 0);\n assertOrderingIncludesPK(\n this.#input.getSchema().sort,\n this.#input.getSchema().primaryKey,\n );\n this.#input.setOutput(this);\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): TableSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n if (\n this.#partitionKey === undefined ||\n req.constraint?.key === this.#partitionKey\n ) {\n const partitionValue =\n this.#partitionKey === undefined ? undefined : req.constraint?.value;\n const takeStateKey = getTakeStateKey(partitionValue);\n const takeState = this.#storage.get(takeStateKey);\n if (!takeState) {\n yield* this.#initialFetch(req);\n return;\n }\n if (takeState.bound === undefined) {\n return;\n }\n for (const inputNode of this.#input.fetch(req)) {\n if (this.getSchema().compareRows(takeState.bound, inputNode.row) < 0) {\n return;\n }\n yield inputNode;\n }\n return;\n }\n // There is a partition key, but the fetch is not constrained or constrained\n // on a different key. Thus we don't have a single take state to bound by.\n // This currently only happens with nested sub-queries\n // e.g. issues include issuelabels include label. We could remove this\n // case if we added a translation layer (powered by some state) in join.\n // Specifically we need joinKeyValue => parent constraint key\n const maxBound = this.#storage.get(MAX_BOUND_KEY);\n if (maxBound === undefined) {\n return;\n }\n for (const inputNode of this.#input.fetch(req)) {\n if (this.getSchema().compareRows(inputNode.row, maxBound) > 0) {\n return;\n }\n const partitionValue = inputNode.row[this.#partitionKey];\n const takeStateKey = getTakeStateKey(partitionValue);\n const takeState = this.#storage.get(takeStateKey);\n if (\n takeState?.bound !== undefined &&\n this.getSchema().compareRows(takeState.bound, inputNode.row) >= 0\n ) {\n yield inputNode;\n }\n }\n }\n\n *#initialFetch(req: FetchRequest): Stream<Node> {\n assert(req.start === undefined);\n assert(\n this.#partitionKey === undefined ||\n (req.constraint !== undefined &&\n req.constraint.key === this.#partitionKey),\n );\n\n if (this.#limit === 0) {\n return;\n }\n\n const partitionValue =\n this.#partitionKey === undefined ? undefined : req.constraint?.value;\n const takeStateKey = getTakeStateKey(partitionValue);\n assert(this.#storage.get(takeStateKey) === undefined);\n\n let size = 0;\n let bound: Row | undefined;\n let downstreamEarlyReturn = true;\n try {\n for (const inputNode of this.#input.fetch(req)) {\n yield inputNode;\n bound = inputNode.row;\n size++;\n if (size === this.#limit) {\n break;\n }\n }\n downstreamEarlyReturn = false;\n } finally {\n this.#setTakeState(\n takeStateKey,\n size,\n bound,\n this.#storage.get(MAX_BOUND_KEY),\n );\n // If it becomes necessary to support downstream early return, this\n // assert should be removed, and replaced with code that consumes\n // the input stream until limit is reached or the input stream is\n // exhausted so that takeState is properly hydrated.\n assert(\n !downstreamEarlyReturn,\n 'Unexpected early return prevented full hydration',\n );\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n assert(req.start === undefined);\n assert(\n this.#partitionKey === undefined ||\n (req.constraint !== undefined &&\n req.constraint.key === this.#partitionKey),\n );\n\n let takeState: TakeState | undefined;\n if (this.#limit > 0) {\n const partitionValue =\n this.#partitionKey === undefined ? undefined : req.constraint?.value;\n const takeStateKey = getTakeStateKey(partitionValue);\n takeState = this.#storage.get(takeStateKey);\n assert(takeState !== undefined);\n this.#storage.del(takeStateKey);\n }\n for (const inputNode of this.#input.cleanup(req)) {\n if (\n takeState?.bound === undefined ||\n this.getSchema().compareRows(takeState.bound, inputNode.row) < 0\n ) {\n return;\n }\n yield inputNode;\n }\n }\n\n #getStateAndConstraint(row: Row) {\n const partitionValue =\n this.#partitionKey === undefined ? undefined : row[this.#partitionKey];\n const takeStateKey = getTakeStateKey(partitionValue);\n const takeState = this.#storage.get(takeStateKey);\n let maxBound: Row | undefined;\n let constraint: Constraint | undefined;\n // The partition key was never fetched, so this push can be discarded.\n if (takeState) {\n maxBound = this.#storage.get(MAX_BOUND_KEY);\n constraint = this.#partitionKey\n ? {\n key: this.#partitionKey,\n value: partitionValue,\n }\n : undefined;\n }\n\n return {takeState, takeStateKey, maxBound, constraint} as\n | {\n takeState: undefined;\n takeStateKey: string;\n maxBound: undefined;\n constraint: undefined;\n }\n | {\n takeState: TakeState;\n takeStateKey: string;\n maxBound: Row | undefined;\n constraint: Constraint | undefined;\n };\n }\n\n push(change: Change): void {\n if (change.type === 'edit') {\n this.#pushEditChange(change);\n return;\n }\n\n assert(this.#output, 'Output not set');\n // When take below join is supported, this assert should be removed\n // and a 'child' change should be pushed to output if its row\n // is <= bound.\n assert(change.type !== 'child', 'child changes are not supported');\n\n const {takeState, takeStateKey, maxBound, constraint} =\n this.#getStateAndConstraint(change.node.row);\n if (!takeState) {\n return;\n }\n const {compareRows} = this.getSchema();\n\n if (change.type === 'add') {\n if (takeState.size < this.#limit) {\n this.#setTakeState(\n takeStateKey,\n takeState.size + 1,\n takeState.bound === undefined ||\n compareRows(takeState.bound, change.node.row) < 0\n ? change.node.row\n : takeState.bound,\n maxBound,\n );\n this.#output.push(change);\n return;\n }\n // size === limit\n if (\n takeState.bound === undefined ||\n compareRows(change.node.row, takeState.bound) >= 0\n ) {\n return;\n }\n // added row < bound\n let beforeBoundNode: Node | undefined;\n let boundNode: Node;\n if (this.#limit === 1) {\n boundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n }),\n ),\n );\n } else {\n [beforeBoundNode, boundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'before',\n },\n constraint,\n }),\n 2,\n );\n }\n const removeChange: RemoveChange = {\n type: 'remove',\n node: boundNode,\n };\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n beforeBoundNode === undefined ||\n compareRows(change.node.row, beforeBoundNode.row) > 0\n ? change.node.row\n : beforeBoundNode.row,\n maxBound,\n );\n this.#output.push(removeChange);\n this.#output.push(change);\n } else if (change.type === 'remove') {\n if (takeState.bound === undefined) {\n // change is after bound\n return;\n }\n const compToBound = compareRows(change.node.row, takeState.bound);\n if (compToBound > 0) {\n // change is after bound\n return;\n }\n if (takeState.size === 1) {\n this.#storage.set(takeStateKey, {\n size: 0,\n bound: undefined,\n });\n this.#output.push(change);\n return;\n }\n // The bound is removed\n let beforeBoundNode: Node | undefined;\n let afterBoundNode: Node | undefined;\n if (compToBound === 0) {\n [beforeBoundNode, afterBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'before',\n },\n constraint,\n }),\n 2,\n );\n } else {\n [beforeBoundNode, , afterBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'before',\n },\n constraint,\n }),\n 3,\n );\n }\n\n if (afterBoundNode) {\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n afterBoundNode.row,\n maxBound,\n );\n this.#output.push(change);\n this.#output.push({\n type: 'add',\n node: afterBoundNode,\n });\n return;\n }\n this.#setTakeState(\n takeStateKey,\n takeState.size - 1,\n compToBound === 0 ? beforeBoundNode.row : takeState.bound,\n maxBound,\n );\n this.#output.push(change);\n }\n }\n\n #pushEditChange(change: EditChange): void {\n assert(this.#output, 'Output not set');\n\n if (\n this.#partitionKey !== undefined &&\n change.oldRow[this.#partitionKey] !== change.row[this.#partitionKey]\n ) {\n // different partition key so fall back to remove/add.\n\n // TODO: So in some cases these don't need to be transformed into a remove\n // + add.\n //\n // If the oldRow was <= the bound of the old partition value, and the\n // newRow is <= the bound of the new partition value, this can be sent as\n // an edit, as the row is present in the output of this operator before\n // and after applying this push.\n\n // We do not need the relationships because Take comes before Join\n this.push({\n type: 'remove',\n node: {\n row: change.oldRow,\n relationships: {},\n },\n });\n this.push({\n type: 'add',\n node: {\n row: change.row,\n relationships: {},\n },\n });\n return;\n }\n\n const {takeState, takeStateKey, maxBound, constraint} =\n this.#getStateAndConstraint(change.oldRow);\n if (!takeState) {\n return;\n }\n\n assert(takeState.bound, 'Bound should be set');\n const {compareRows} = this.getSchema();\n const oldCmp = compareRows(change.oldRow, takeState.bound);\n const newCmp = compareRows(change.row, takeState.bound);\n\n const replaceBoundAndForwardChange = () => {\n this.#setTakeState(takeStateKey, takeState.size, change.row, maxBound);\n this.#output!.push(change);\n };\n\n // The bounds row was changed.\n if (oldCmp === 0) {\n // The new row is the new bound.\n if (newCmp === 0) {\n // no need to update the state since we are keeping the bounds\n this.#output.push(change);\n return;\n }\n\n if (newCmp < 0) {\n if (this.#limit === 1) {\n replaceBoundAndForwardChange();\n return;\n }\n\n // New row will be in the result but it might not be the bounds any\n // more. We need to find the row before the bounds to determine the new\n // bounds.\n\n const beforeBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'before',\n },\n constraint,\n }),\n ),\n );\n\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n beforeBoundNode.row,\n maxBound,\n );\n this.#output.push(change);\n return;\n }\n\n assert(newCmp > 0);\n // Find the first item at the old bounds. This will be the new bounds.\n const newBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n }),\n ),\n );\n\n // The next row is the new row. We can replace the bounds and keep the\n // edit change.\n if (compareRows(newBoundNode.row, change.row) === 0) {\n replaceBoundAndForwardChange();\n return;\n }\n\n // The new row is now outside the bounds, so we need to remove the old\n // row and add the new bounds row.\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n newBoundNode.row,\n maxBound,\n );\n this.#output.push({\n type: 'remove',\n node: {\n row: change.oldRow,\n relationships: {},\n },\n });\n this.#output.push({\n type: 'add',\n node: newBoundNode,\n });\n return;\n }\n\n if (oldCmp > 0) {\n assert(newCmp !== 0, 'Invalid state. Row has duplicate primary key');\n\n // Both old and new outside of bounds\n if (newCmp > 0) {\n return;\n }\n\n // old was outside, new is inside. Pushing out the old bounds\n assert(newCmp < 0);\n\n const [newBoundNode, oldBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'before',\n },\n constraint,\n }),\n 2,\n );\n\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n newBoundNode.row,\n maxBound,\n );\n\n this.#output.push({\n type: 'remove',\n node: oldBoundNode,\n });\n\n // We do not need the relationships because Take comes before Join\n this.#output.push({\n type: 'add',\n node: {\n row: change.row,\n relationships: {},\n },\n });\n\n return;\n }\n\n if (oldCmp < 0) {\n assert(newCmp !== 0, 'Invalid state. Row has duplicate primary key');\n\n // Both old and new inside of bounds\n if (newCmp < 0) {\n this.#output.push(change);\n return;\n }\n\n // old was inside, new is larger than old bound\n\n assert(newCmp > 0);\n\n // at this point we need to find the row after the bound and use that or\n // the newRow as the new bound.\n const afterBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'after',\n },\n constraint,\n }),\n ),\n );\n\n // The new row is the new bound. Use an edit change.\n if (compareRows(afterBoundNode.row, change.row) === 0) {\n replaceBoundAndForwardChange();\n return;\n }\n\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n afterBoundNode.row,\n maxBound,\n );\n\n // We do not need the relationships because Take comes before Join\n this.#output.push({\n type: 'remove',\n node: {\n row: change.oldRow,\n relationships: {},\n },\n });\n this.#output.push({\n type: 'add',\n node: afterBoundNode,\n });\n return;\n }\n\n unreachable();\n }\n\n #setTakeState(\n takeStateKey: string,\n size: number,\n bound: Row | undefined,\n maxBound: Row | undefined,\n ) {\n this.#storage.set(takeStateKey, {\n size,\n bound,\n });\n if (\n bound !== undefined &&\n (maxBound === undefined ||\n this.getSchema().compareRows(bound, maxBound) > 0)\n ) {\n this.#storage.set(MAX_BOUND_KEY, bound);\n }\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n}\n\nfunction getTakeStateKey(partitionValue: Value): string {\n return JSON.stringify(['take', normalizeUndefined(partitionValue)]);\n}\n", "export class MissingParameterError extends Error {}\n", "import {assertString} from '../../../../shared/src/asserts.js';\nimport type {NonNullValue, SimplePredicate} from './filter.js';\n\nexport function getLikePredicate(\n pattern: NonNullValue,\n flags: 'i' | '',\n): SimplePredicate {\n const op = getLikeOp(String(pattern), flags);\n return (lhs: NonNullValue) => {\n assertString(lhs);\n return op(String(lhs));\n };\n}\n\nfunction getLikeOp(pattern: string, flags: 'i' | ''): (lhs: string) => boolean {\n // if lhs does not contain '%' or '_' then it is a simple string comparison.\n // if it does contain '%' or '_' then it is a regex comparison.\n // '%' is a wildcard for any number of characters\n // '_' is a wildcard for a single character\n // Postgres SQL allows escaping using `\\`.\n\n if (!/_|%|\\\\/.test(pattern)) {\n if (flags === 'i') {\n const rhsLower = pattern.toLowerCase();\n return (lhs: string) => lhs.toLowerCase() === rhsLower;\n }\n return (lhs: string) => lhs === pattern;\n }\n const re = patternToRegExp(pattern, flags);\n return (lhs: string) => re.test(lhs);\n}\n\nconst specialCharsRe = /[$()*+.?[\\]\\\\^{|}]/;\n\nfunction patternToRegExp(source: string, flags: '' | 'i' = ''): RegExp {\n // There are a few cases:\n // % => .*\n // _ => .\n // \\x => \\x for any x except special regexp chars\n // special regexp chars => \\special regexp chars\n let pattern = '^';\n for (let i = 0; i < source.length; i++) {\n let c = source[i];\n switch (c) {\n case '%':\n pattern += '.*';\n break;\n case '_':\n pattern += '.';\n break;\n\n // @ts-expect-error fallthrough\n case '\\\\':\n if (i === source.length - 1) {\n throw new Error('LIKE pattern must not end with escape character');\n }\n i++;\n c = source[i];\n\n // fall through\n default:\n if (specialCharsRe.test(c)) {\n pattern += '\\\\';\n }\n pattern += c;\n\n break;\n }\n }\n return new RegExp(pattern + '$', flags + 'm');\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport type {\n LiteralValue,\n SimpleCondition,\n SimpleOperator,\n} from '../../../../zero-protocol/src/ast.js';\nimport type {Row, Value} from '../../../../zero-protocol/src/data.js';\nimport {getLikePredicate} from './like.js';\n\nexport type NonNullValue = Exclude<Value, null | undefined>;\nexport type SimplePredicate = (rhs: NonNullValue) => boolean;\n\nexport function createPredicate(condition: SimpleCondition) {\n const impl = createPredicateImpl(\n condition.value as LiteralValue,\n condition.op,\n );\n return (row: Row) => {\n const lhs = row[condition.field];\n if (lhs === null || lhs === undefined) {\n return false;\n }\n return impl(lhs);\n };\n}\n\nfunction createPredicateImpl(\n rhs: NonNullValue | readonly NonNullValue[],\n operator: SimpleOperator,\n): SimplePredicate {\n switch (operator) {\n case '=':\n return lhs => lhs === rhs;\n case '!=':\n return lhs => lhs !== rhs;\n case '<':\n return lhs => lhs < rhs;\n case '<=':\n return lhs => lhs <= rhs;\n case '>':\n return lhs => lhs > rhs;\n case '>=':\n return lhs => lhs >= rhs;\n case 'LIKE':\n return getLikePredicate(rhs as NonNullValue, '');\n case 'NOT LIKE':\n return not(getLikePredicate(rhs as NonNullValue, ''));\n case 'ILIKE':\n return getLikePredicate(rhs as NonNullValue, 'i');\n case 'NOT ILIKE':\n return not(getLikePredicate(rhs as NonNullValue, 'i'));\n case 'IN': {\n assert(Array.isArray(rhs));\n const set = new Set(rhs);\n return lhs => set.has(lhs);\n }\n case 'NOT IN': {\n assert(Array.isArray(rhs));\n const set = new Set(rhs);\n return lhs => !set.has(lhs);\n }\n default:\n operator satisfies never;\n throw new Error(`Unexpected operator: ${operator}`);\n }\n}\n\nfunction not<T>(f: (lhs: T) => boolean) {\n return (lhs: T) => !f(lhs);\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport type {JSONValue} from '../../../../shared/src/json.js';\nimport {must} from '../../../../shared/src/must.js';\nimport type {\n AST,\n Condition,\n Conjunction,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../../zero-protocol/src/ast.js';\nimport type {Row} from '../../../../zero-protocol/src/data.js';\nimport type {PrimaryKey} from '../../../../zero-protocol/src/primary-key.js';\nimport {FanIn} from '../ivm/fan-in.js';\nimport {FanOut} from '../ivm/fan-out.js';\nimport {Filter} from '../ivm/filter.js';\nimport {Join} from '../ivm/join.js';\nimport type {Input, Storage} from '../ivm/operator.js';\nimport {Skip} from '../ivm/skip.js';\nimport type {Source} from '../ivm/source.js';\nimport {Take} from '../ivm/take.js';\nimport {MissingParameterError} from './error.js';\nimport {createPredicate} from './filter.js';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(): Storage;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * this.#input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate);\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n staticQueryParameters: StaticQueryParameters | undefined,\n): Input {\n return buildPipelineInternal(\n bindStaticParameters(ast, staticQueryParameters),\n delegate,\n staticQueryParameters,\n );\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => {\n if (node.where) {\n return {\n ...node,\n where: bindCondition(node.where),\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n };\n }\n return node;\n };\n\n function bindCondition(condition: Condition): Condition {\n return condition.type === 'simple'\n ? {\n ...condition,\n value: bindValue(condition.value),\n }\n : {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): LiteralValue => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n assert(anchor !== undefined, `Missing parameter: ${value.anchor}`);\n const resolvedValue = anchor[value.field];\n // eslint-disable-next-line eqeqeq\n if (resolvedValue == null) {\n throw new MissingParameterError();\n }\n return resolvedValue as LiteralValue;\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction isParameter(value: unknown): value is Parameter {\n return typeof value === 'object' && value !== null && 'type' in value;\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n staticQueryParameters: StaticQueryParameters | undefined,\n partitionKey?: string | undefined,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n const conn = source.connect(must(ast.orderBy), ast.where);\n let end: Input = conn;\n const {appliedFilters} = conn;\n\n if (ast.start) {\n end = new Skip(end, ast.start);\n }\n\n if (ast.where) {\n end = applyWhere(end, ast.where, appliedFilters);\n }\n\n if (ast.limit) {\n end = new Take(end, delegate.createStorage(), ast.limit, partitionKey);\n }\n\n if (ast.related) {\n for (const sq of ast.related) {\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n staticQueryParameters,\n sq.correlation.childField,\n );\n end = new Join({\n parent: end,\n child,\n storage: delegate.createStorage(),\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n });\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n // Remove `appliedFilter`\n // Each branch can `fetch` with different filters from the same source.\n // Or we do the union of queries approach and retain this `appliedFilters` and `sourceConnect` behavior.\n // Downside of that being unbounded memory usage.\n appliedFilters: boolean,\n): Input {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, appliedFilters);\n case 'or':\n return applyOr(input, condition, appliedFilters);\n default:\n return applySimpleCondition(input, condition, appliedFilters);\n }\n}\n\nfunction applyAnd(\n input: Input,\n condition: Conjunction,\n appliedFilters: boolean,\n) {\n for (const subCondition of condition.conditions) {\n input = applyWhere(input, subCondition, appliedFilters);\n }\n return input;\n}\n\nfunction applyOr(\n input: Input,\n condition: Disjunction,\n appliedFilters: boolean,\n): Input {\n const fanOut = new FanOut(input);\n const branches: Input[] = [];\n for (const subCondition of condition.conditions) {\n branches.push(applyWhere(fanOut, subCondition, appliedFilters));\n }\n assert(branches.length > 0, 'Or condition must have at least one branch');\n return new FanIn(fanOut, branches as [Input, ...Input[]]);\n}\n\nfunction applySimpleCondition(\n input: Input,\n condition: SimpleCondition,\n appliedFilters: boolean,\n): Input {\n return new Filter(\n input,\n appliedFilters ? 'push-only' : 'all',\n createPredicate(condition),\n );\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}`,\n );\n }\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport type {Immutable} from '../../../../shared/src/immutable.js';\nimport type {Listener, TypedView} from '../query/typed-view.js';\nimport type {Change} from './change.js';\nimport type {Input, Output} from './operator.js';\nimport type {TableSchema} from './schema.js';\nimport {applyChange} from './view-apply-change.js';\nimport type {Entry, Format, View} from './view.js';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: TableSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n\n constructor(\n input: Input,\n format: Format = {singular: false, relationships: {}},\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#input.setOutput(this);\n this.#root = {'': format.singular ? undefined : []};\n\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n listener(this.data as Immutable<V>);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n listener(this.data as Immutable<V>);\n }\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of this.#input.fetch({})) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change): void {\n this.#dirty = true;\n applyChange(this.#root, change, this.#schema, '', this.#format);\n }\n\n flush() {\n if (!this.#dirty) {\n return;\n }\n this.#dirty = false;\n this.#fireListeners();\n }\n}\n", "import {stringCompare} from './string-compare.js';\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function sortedEntries<T extends Record<string, any>>(\n object: T,\n): [keyof T & string, T[keyof T]][] {\n return Object.entries(object).sort((a, b) => stringCompare(a[0], b[0]));\n}\n", "import {assert} from '../../../../shared/src/asserts.js';\nimport {sortedEntries} from '../../../../shared/src/sorted-entries.js';\nimport type {Writable} from '../../../../shared/src/writable.js';\nimport type {PrimaryKey} from '../../../../zero-protocol/src/primary-key.js';\nimport type {SchemaValue} from '../ivm/schema.js';\nimport {\n isFieldRelationship,\n type FieldRelationship,\n type JunctionRelationship,\n type TableSchema,\n} from './schema.js';\n\ndeclare const normalized: unique symbol;\n\ntype Normalized<T> = T & {readonly [normalized]: true};\n\n/**\n * We need a cache of the normalized table schemas to handle circular\n * dependencies.\n */\nexport type TableSchemaCache = Map<TableSchema, NormalizedTableSchema>;\n\nexport class NormalizedTableSchema {\n declare readonly [normalized]: true;\n readonly tableName: string;\n readonly primaryKey: NormalizedPrimaryKey;\n readonly columns: Record<string, SchemaValue>;\n readonly relationships: {readonly [name: string]: NormalizedRelationship};\n\n constructor(tableSchema: TableSchema, tableSchemaCache: TableSchemaCache) {\n this.tableName = tableSchema.tableName;\n const primaryKey = normalizePrimaryKey(tableSchema.primaryKey);\n this.primaryKey = primaryKey;\n this.columns = normalizeColumns(tableSchema.columns, primaryKey);\n tableSchemaCache.set(tableSchema, this);\n this.relationships = normalizeRelationships(\n tableSchema.relationships,\n tableSchemaCache,\n );\n }\n}\n\nexport function normalizeTableSchema(\n tableSchema: TableSchema | NormalizedTableSchema,\n): NormalizedTableSchema {\n return normalizeTableSchemaWithCache(\n tableSchema,\n tableSchema.tableName,\n new Map(),\n );\n}\n\nexport function normalizeTableSchemaWithCache(\n tableSchema: TableSchema | NormalizedTableSchema,\n expectedName: string,\n tableSchemaCache: TableSchemaCache,\n): NormalizedTableSchema {\n if (tableSchema instanceof NormalizedTableSchema) {\n return tableSchema;\n }\n assert(\n tableSchema.tableName === expectedName,\n `Table name mismatch: \"${tableSchema.tableName}\" !== \"${expectedName}\"`,\n );\n\n let normalizedTableSchema = tableSchemaCache.get(tableSchema);\n if (normalizedTableSchema) {\n return normalizedTableSchema as NormalizedTableSchema;\n }\n\n normalizedTableSchema = new NormalizedTableSchema(\n tableSchema,\n tableSchemaCache,\n );\n return normalizedTableSchema as NormalizedTableSchema;\n}\n\nexport type NormalizedPrimaryKey = Normalized<PrimaryKey>;\n\nfunction isSorted(arr: readonly string[]): boolean {\n for (let i = 1; i < arr.length; i++) {\n if (arr[i - 1] >= arr[i]) {\n return false;\n }\n }\n return true;\n}\n\nfunction assertNoDuplicates(arr: readonly string[]): void {\n // arr is already sorted.\n for (let i = 1; i < arr.length; i++) {\n assert(arr[i - 1] !== arr[i], 'Primary key must not contain duplicates');\n }\n}\n\nexport function normalizePrimaryKey(arr: PrimaryKey): NormalizedPrimaryKey {\n if (isSorted(arr)) {\n return arr as NormalizedPrimaryKey;\n }\n\n arr = [...arr].sort() as unknown as PrimaryKey;\n assertNoDuplicates(arr);\n return arr as NormalizedPrimaryKey;\n}\n\nfunction normalizeColumns(\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n): Record<string, SchemaValue> {\n const rv: Writable<Record<string, SchemaValue>> = {};\n for (const pk of primaryKey) {\n const schemaValue = columns[pk];\n assert(schemaValue, `Primary key column \"${pk}\" not found`);\n const {type, optional} = schemaValue;\n assert(!optional, `Primary key column \"${pk}\" cannot be optional`);\n assert(\n type === 'string' || type === 'number' || type === 'boolean',\n `Primary key column \"${pk}\" must be a string, number, or boolean. Got ${type}`,\n );\n }\n for (const [name, column] of sortedEntries(columns)) {\n rv[name] = normalizeSchemaValue(column);\n }\n return rv;\n}\n\nfunction normalizeSchemaValue(value: SchemaValue): SchemaValue {\n return {\n type: value.type,\n optional: value.optional ?? false,\n };\n}\n\ntype Relationships = TableSchema['relationships'];\n\ntype NormalizedRelationships = {\n readonly [name: string]: NormalizedRelationship;\n};\n\nfunction normalizeRelationships(\n relationships: Relationships,\n tableSchemaCache: TableSchemaCache,\n): NormalizedRelationships {\n const rv: Writable<NormalizedRelationships> = {};\n for (const [name, relationship] of sortedEntries(relationships)) {\n rv[name] = normalizeRelationship(relationship, tableSchemaCache);\n }\n return rv;\n}\n\ntype NormalizedRelationship =\n | NormalizedFieldRelationship\n | NormalizedJunctionRelationship;\n\ntype Relationship = TableSchema['relationships'][string];\n\nfunction normalizeRelationship(\n relationship: Relationship,\n tableSchemaCache: TableSchemaCache,\n): NormalizedRelationship {\n if (isFieldRelationship(relationship)) {\n return normalizeFieldRelationship(relationship, tableSchemaCache);\n }\n return normalizeJunctionRelationship(relationship, tableSchemaCache);\n}\n\ntype NormalizedFieldRelationship = {\n source: string;\n dest: {\n field: string;\n schema: NormalizedTableSchema;\n };\n};\n\nfunction normalizeFieldRelationship(\n relationship: FieldRelationship<TableSchema, TableSchema>,\n tableSchemaCache: TableSchemaCache,\n): NormalizedFieldRelationship {\n return {\n source: relationship.source,\n dest: {\n field: relationship.dest.field,\n schema: normalizeLazyTableSchema(\n relationship.dest.schema,\n tableSchemaCache,\n ),\n },\n };\n}\n\ntype NormalizedJunctionRelationship = {\n source: string;\n junction: {\n sourceField: string;\n destField: string;\n schema: NormalizedTableSchema;\n };\n dest: {\n field: string;\n schema: NormalizedTableSchema;\n };\n};\n\nfunction normalizeJunctionRelationship(\n relationship: JunctionRelationship<TableSchema, TableSchema, TableSchema>,\n tableSchemaCache: TableSchemaCache,\n): NormalizedJunctionRelationship {\n return {\n source: relationship.source,\n junction: {\n sourceField: relationship.junction.sourceField,\n destField: relationship.junction.destField,\n schema: normalizeLazyTableSchema(\n relationship.junction.schema,\n tableSchemaCache,\n ),\n },\n dest: {\n field: relationship.dest.field,\n schema: normalizeLazyTableSchema(\n relationship.dest.schema,\n tableSchemaCache,\n ),\n },\n };\n}\n\nfunction normalizeLazyTableSchema<TS extends TableSchema>(\n tableSchema: TS | (() => TS),\n buildCache: TableSchemaCache,\n): NormalizedTableSchema {\n const tableSchemaInstance =\n typeof tableSchema === 'function' ? tableSchema() : tableSchema;\n return normalizeTableSchemaWithCache(\n tableSchemaInstance,\n tableSchemaInstance.tableName, // Don't care about name here.\n buildCache,\n );\n}\n", "export function escapeLike(val: string) {\n return val.replace(/[%_]/g, '\\\\$&');\n}\n", "import {LogContext, type LogLevel} from '@rocicorp/logger';\nimport {type Resolver, resolver} from '@rocicorp/resolver';\nimport {\n ReplicacheImpl,\n type ReplicacheImplOptions,\n} from '../../../replicache/src/impl.js';\nimport {\n type ClientGroupID,\n type ClientID,\n type ExperimentalNoIndexDiff,\n type MutatorDefs,\n type PullRequestV0,\n type PullRequestV1,\n type Puller,\n type PullerResultV1,\n type PushRequestV0,\n type PushRequestV1,\n type Pusher,\n type PusherResult,\n type ReplicacheOptions,\n type UpdateNeededReason as ReplicacheUpdateNeededReason,\n dropDatabase,\n} from '../../../replicache/src/mod.js';\nimport {assert, unreachable} from '../../../shared/src/asserts.js';\nimport {\n getBrowserGlobal,\n mustGetBrowserGlobal,\n} from '../../../shared/src/browser-env.js';\nimport {getDocumentVisibilityWatcher} from '../../../shared/src/document-visible.js';\nimport {must} from '../../../shared/src/must.js';\nimport {navigator} from '../../../shared/src/navigator.js';\nimport {sleep, sleepWithAbort} from '../../../shared/src/sleep.js';\nimport type {MaybePromise} from '../../../shared/src/types.js';\nimport * as valita from '../../../shared/src/valita.js';\nimport type {ChangeDesiredQueriesMessage} from '../../../zero-protocol/src/change-desired-queries.js';\nimport {\n type CRUDMutation,\n type CRUDMutationArg,\n CRUD_MUTATION_NAME,\n type ConnectedMessage,\n type CustomMutation,\n type Downstream,\n ErrorKind,\n type ErrorMessage,\n MutationType,\n type NullableVersion,\n type PingMessage,\n type PokeEndMessage,\n type PokePartMessage,\n type PokeStartMessage,\n type PushMessage,\n type QueriesPatchOp,\n downstreamSchema,\n encodeSecProtocols,\n nullableVersionSchema,\n} from '../../../zero-protocol/src/mod.js';\nimport type {\n PullRequestMessage,\n PullResponseBody,\n PullResponseMessage,\n} from '../../../zero-protocol/src/pull.js';\nimport {newQuery} from '../../../zql/src/zql/query/query-impl.js';\nimport type {Query} from '../../../zql/src/zql/query/query.js';\nimport type {TableSchema} from '../../../zql/src/zql/query/schema.js';\nimport {nanoid} from '../util/nanoid.js';\nimport {send} from '../util/socket.js';\nimport {ZeroContext} from './context.js';\nimport {\n type MakeCRUDMutate,\n type WithCRUD,\n makeCRUDMutate,\n makeCRUDMutator,\n} from './crud.js';\nimport {shouldEnableAnalytics} from './enable-analytics.js';\nimport {type HTTPString, type WSString, toWSString} from './http-string.js';\nimport {ENTITIES_KEY_PREFIX} from './keys.js';\nimport {type LogOptions, createLogOptions} from './log-options.js';\nimport {\n DID_NOT_CONNECT_VALUE,\n type DisconnectReason,\n MetricManager,\n REPORT_INTERVAL_MS,\n type Series,\n getLastConnectErrorValue,\n} from './metrics.js';\nimport {type NormalizedSchema, normalizeSchema} from './normalized-schema.js';\nimport type {ZeroOptions, ZeroAdvancedOptions} from './options.js';\nimport {QueryManager} from './query-manager.js';\nimport {reloadWithReason, reportReloadReason} from './reload-error-handler.js';\nimport {ServerError, isAuthError, isServerError} from './server-error.js';\nimport {getServer} from './server-option.js';\nimport {version} from './version.js';\nimport {PokeHandler} from './zero-poke-handler.js';\n\nexport type Schema = {\n readonly version: number;\n readonly tables: {readonly [table: string]: TableSchema};\n};\n\nexport function createSchema<const S extends Schema>(schema: S): S {\n return schema as S & {readonly [K in keyof S]: S[K]};\n}\n\nexport type NoRelations = Record<string, never>;\n\nexport type MakeEntityQueriesFromSchema<S extends Schema> = {\n readonly [K in keyof S['tables']]: Query<S['tables'][K]>;\n};\n\ndeclare const TESTING: boolean;\n\nexport type TestingContext = {\n puller: Puller;\n pusher: Pusher;\n setReload: (r: () => void) => void;\n logOptions: LogOptions;\n connectStart: () => number | undefined;\n socketResolver: () => Resolver<WebSocket>;\n connectionState: () => ConnectionState;\n};\n\nexport const onSetConnectionStateSymbol = Symbol();\nexport const exposedToTestingSymbol = Symbol();\nexport const createLogOptionsSymbol = Symbol();\n\ninterface TestZero {\n [exposedToTestingSymbol]?: TestingContext;\n [onSetConnectionStateSymbol]?: (state: ConnectionState) => void;\n [createLogOptionsSymbol]?: (options: {\n consoleLogLevel: LogLevel;\n server: string | null;\n }) => LogOptions;\n}\n\nfunction asTestZero<S extends Schema>(z: Zero<S>): TestZero {\n return z as TestZero;\n}\n\nexport const enum ConnectionState {\n Disconnected,\n Connecting,\n Connected,\n}\n\nexport const RUN_LOOP_INTERVAL_MS = 5_000;\n\n/**\n * How frequently we should ping the server to keep the connection alive.\n */\nexport const PING_INTERVAL_MS = 5_000;\n\n/**\n * The amount of time we wait for a pong before we consider the ping timed out.\n */\nexport const PING_TIMEOUT_MS = 5_000;\n\n/**\n * The amount of time we wait for a pull response before we consider a pull\n * request timed out.\n */\nexport const PULL_TIMEOUT_MS = 5_000;\n\nexport const DEFAULT_DISCONNECT_HIDDEN_DELAY_MS = 5_000;\n\n/**\n * The amount of time we wait for a connection to be established before we\n * consider it timed out.\n */\nexport const CONNECT_TIMEOUT_MS = 10_000;\n\nconst CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY = 6;\n\nconst NULL_LAST_MUTATION_ID_SENT = {clientID: '', id: -1} as const;\n\n// When the protocol changes (pull, push, poke,...) we need to bump this.\nconst REFLECT_VERSION = 1;\n\n/**\n * The reason {@link onUpdateNeeded} was called.\n */\nexport type UpdateNeededReason =\n // There is a new client group due to a new tab loading new code with\n // different mutators, indexes, schema version, or format version.\n // This tab cannot sync locally with this new tab until it updates to\n // the new code.\n | {type: 'NewClientGroup'}\n // This is used when Zero tries to connect with a version that the server\n // does not support\n | {type: 'VersionNotSupported'}\n // This is used when Zero tries to connect with a schema version that the\n // server does not support\n | {type: 'SchemaVersionNotSupported'};\n\nfunction convertOnUpdateNeededReason(\n reason: ReplicacheUpdateNeededReason,\n): UpdateNeededReason {\n return {type: reason.type};\n}\n\nfunction updateNeededReloadReason(\n reason: UpdateNeededReason,\n serverErrMsg?: string | undefined,\n) {\n const {type} = reason;\n let reasonMsg = '';\n switch (type) {\n case 'NewClientGroup':\n reasonMsg =\n \"This client could not sync with a newer client. This is probably due to another tab loading a newer incompatible version of the app's code.\";\n break;\n case 'VersionNotSupported':\n reasonMsg =\n \"The server no longer supports this client's protocol version.\";\n break;\n case 'SchemaVersionNotSupported':\n reasonMsg = \"The server no longer supports this client's schema version.\";\n break;\n default:\n unreachable(type);\n }\n if (serverErrMsg) {\n reasonMsg += ' ' + serverErrMsg;\n }\n return reasonMsg;\n}\n\nfunction serverAheadReloadReason(kind: string) {\n return `Server reported that client is ahead of server (${kind}). This probably happened because the server is in development mode and restarted. Currently when this happens, the dev server loses its state and on reconnect sees the client as ahead. If you see this in other cases, it may be a bug in Zero.`;\n}\n\nfunction onClientStateNotFoundServerReason(serverErrMsg: string) {\n return `Server could not find state needed to synchronize this client. ${serverErrMsg}`;\n}\nconst ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT =\n 'The local persistent state needed to synchronize this client has been garbage collected.';\n\nconst enum PingResult {\n TimedOut = 0,\n Success = 1,\n}\n\n// Keep in sync with packages/replicache/src/replicache-options.ts\nexport interface ReplicacheInternalAPI {\n lastMutationID(): number;\n}\n\nconst internalReplicacheImplMap = new WeakMap<object, ReplicacheImpl>();\n\nexport function getInternalReplicacheImplForTesting<\n MD extends MutatorDefs,\n S extends Schema,\n>(z: Zero<S>): ReplicacheImpl<MD> {\n return must(internalReplicacheImplMap.get(z)) as ReplicacheImpl<MD>;\n}\n\nexport class Zero<const S extends Schema> {\n readonly version = version;\n\n readonly #rep: ReplicacheImpl<WithCRUD<MutatorDefs>>;\n readonly #server: HTTPString | null;\n readonly userID: string;\n\n readonly #lc: LogContext;\n readonly #logOptions: LogOptions;\n readonly #enableAnalytics: boolean;\n\n readonly #pokeHandler: PokeHandler;\n readonly #queryManager: QueryManager;\n\n /**\n * The queries we sent when inside the sec-protocol header when establishing a connection.\n * More queries could be registered while we're waiting for the 'connected' message\n * to come back from the server. To understand what queries we need to send\n * to the server, we diff the `initConnectionQueries` with the current set of desired queries.\n *\n * If this is set to `undefined` that means no queries were sent inside the `sec-protocol` header\n * and an `initConnection` message must be sent to the server after receiving the `connected` message.\n */\n #initConnectionQueries: Map<string, QueriesPatchOp> | undefined;\n\n #lastMutationIDSent: {clientID: string; id: number} =\n NULL_LAST_MUTATION_ID_SENT;\n\n #onPong: () => void = () => undefined;\n\n #online = false;\n\n /**\n * `onOnlineChange` is called when the Zero instance's online status\n * changes.\n */\n onOnlineChange: ((online: boolean) => void) | null | undefined = null;\n\n #onUpdateNeeded:\n | ((reason: UpdateNeededReason, serverErrorMsg?: string) => void)\n | null = null;\n #onClientStateNotFound: ((reason?: string) => void) | null = null;\n readonly #jurisdiction: 'eu' | undefined;\n // Last cookie used to initiate a connection\n #connectCookie: NullableVersion = null;\n // Total number of sockets successfully connected by this client\n #connectedCount = 0;\n // Number of messages received over currently connected socket. Reset\n // on disconnect.\n #messageCount = 0;\n #connectedAt = 0;\n // Reset on successful connection.\n #connectErrorCount = 0;\n\n #abortPingTimeout = () => {\n // intentionally empty\n };\n\n readonly #zeroContext: ZeroContext;\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the protocol version of the current code,\n * - a new Zero client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Zero client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Zero client (i.e. to sync while offline, the clients can can\n * still sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n get onUpdateNeeded(): ((reason: UpdateNeededReason) => void) | null {\n return this.#onUpdateNeeded;\n }\n set onUpdateNeeded(callback: ((reason: UpdateNeededReason) => void) | null) {\n this.#onUpdateNeeded = callback;\n this.#rep.onUpdateNeeded =\n callback &&\n (reason => {\n callback(convertOnUpdateNeededReason(reason));\n });\n }\n\n /**\n * `onClientStateNotFound` is called when this client will no longer be able\n * to sync due to missing synchronization state. This can be because:\n * - the local persistent synchronization state has been garbage collected.\n * This can happen if the client has no pending mutations and has not been\n * used for a while.\n * - the zero-cache fails to find the synchronization state of this client.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n get onClientStateNotFound(): (() => void) | null {\n return this.#onClientStateNotFound;\n }\n set onClientStateNotFound(value: (() => void) | null) {\n this.#onClientStateNotFound = value;\n this.#rep.onClientStateNotFound = value;\n }\n\n #connectResolver = resolver<void>();\n #pendingPullsByRequestID: Map<string, Resolver<PullResponseBody>> = new Map();\n #lastMutationIDReceived = 0;\n\n #socket: WebSocket | undefined = undefined;\n #socketResolver = resolver<WebSocket>();\n\n #connectionStateChangeResolver = resolver<ConnectionState>();\n\n /**\n * This resolver is only used for rejections. It is awaited in the connected\n * state (including when waiting for a pong). It is rejected when we get an\n * invalid message or an 'error' message.\n */\n #rejectMessageError: Resolver<never> | undefined = undefined;\n\n #closeAbortController = new AbortController();\n\n readonly #visibilityWatcher;\n\n // We use an accessor pair to allow the subclass to override the setter.\n #connectionState: ConnectionState = ConnectionState.Disconnected;\n\n #setConnectionState(state: ConnectionState) {\n if (state === this.#connectionState) {\n return;\n }\n\n this.#connectionState = state;\n this.#connectionStateChangeResolver.resolve(state);\n this.#connectionStateChangeResolver = resolver();\n\n if (TESTING) {\n asTestZero(this)[onSetConnectionStateSymbol]?.(state);\n }\n }\n\n #connectStart: number | undefined = undefined;\n // Set on connect attempt if currently undefined.\n // Reset to undefined when\n // 1. client stops trying to connect because it is hidden\n // 2. client encounters a connect error and canary request indicates\n // the client is offline\n // 2. client successfully connects\n #totalToConnectStart: number | undefined = undefined;\n\n readonly #options: ZeroOptions<S>;\n\n readonly query: MakeEntityQueriesFromSchema<S>;\n\n // TODO: Metrics needs to be rethought entirely as we're not going to\n // send metrics to customer server.\n #metrics: MetricManager;\n\n // Store as field to allow test subclass to override. Web API doesn't allow\n // overwriting location fields for security reasons.\n #reload = () => getBrowserGlobal('location')?.reload();\n\n /**\n * Constructs a new Zero client.\n */\n constructor(options: ZeroOptions<S>) {\n const {\n userID,\n onOnlineChange,\n jurisdiction,\n hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,\n kvStore = 'idb',\n schema,\n batchViewUpdates = applyViewUpdates => applyViewUpdates(),\n } = options as ZeroAdvancedOptions<S>;\n if (!userID) {\n throw new Error('ZeroOptions.userID must not be empty.');\n }\n const server = getServer(options.server);\n this.#enableAnalytics = shouldEnableAnalytics(\n server,\n options.enableAnalytics,\n );\n\n if (jurisdiction !== undefined && jurisdiction !== 'eu') {\n throw new Error('ZeroOptions.jurisdiction must be \"eu\" if present.');\n }\n if (hiddenTabDisconnectDelay < 0) {\n throw new Error(\n 'ZeroOptions.hiddenTabDisconnectDelay must not be negative.',\n );\n }\n\n this.onOnlineChange = onOnlineChange;\n this.#options = options;\n\n this.#logOptions = this.#createLogOptions({\n consoleLogLevel: options.logLevel ?? 'error',\n server: null, //server, // Reenable remote logging\n enableAnalytics: this.#enableAnalytics,\n });\n const logOptions = this.#logOptions;\n\n const normalizedSchema = normalizeSchema(schema);\n\n const replicacheMutators = {\n ['_zero_crud']: makeCRUDMutator(normalizedSchema),\n };\n\n const replicacheOptions: ReplicacheOptions<WithCRUD<MutatorDefs>> = {\n schemaVersion: normalizedSchema.version.toString(),\n logLevel: logOptions.logLevel,\n logSinks: [logOptions.logSink],\n mutators: replicacheMutators,\n name: `zero-${userID}`,\n pusher: (req, reqID) => this.#pusher(req, reqID),\n puller: (req, reqID) => this.#puller(req, reqID),\n pushDelay: 0,\n requestOptions: {\n maxDelayMs: 0,\n minDelayMs: 0,\n },\n licenseKey: 'zero-client-static-key',\n kvStore,\n };\n const replicacheImplOptions: ReplicacheImplOptions = {\n enableClientGroupForking: false,\n };\n\n const rep = new ReplicacheImpl(replicacheOptions, replicacheImplOptions);\n this.#rep = rep;\n\n if (TESTING) {\n internalReplicacheImplMap.set(this, rep);\n }\n\n rep.getAuth = this.#getAuthToken;\n this.#server = server;\n this.userID = userID;\n this.#jurisdiction = jurisdiction;\n this.#lc = new LogContext(\n logOptions.logLevel,\n {clientID: rep.clientID},\n logOptions.logSink,\n );\n this.onUpdateNeeded = (\n reason: UpdateNeededReason,\n serverErrorMsg?: string | undefined,\n ) => {\n reloadWithReason(\n this.#lc,\n this.#reload,\n updateNeededReloadReason(reason, serverErrorMsg),\n );\n };\n this.onClientStateNotFound = (reason?: string) => {\n reloadWithReason(\n this.#lc,\n this.#reload,\n reason ?? ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT,\n );\n };\n\n this.mutate = makeCRUDMutate<S>(normalizedSchema, rep.mutate);\n\n this.#queryManager = new QueryManager(\n rep.clientID,\n msg => this.#sendChangeDesiredQueries(msg),\n rep.experimentalWatch.bind(rep),\n );\n\n this.#zeroContext = new ZeroContext(\n normalizedSchema.tables,\n (ast, gotCallback) => this.#queryManager.add(ast, gotCallback),\n batchViewUpdates,\n );\n\n rep.experimentalWatch(\n diff => this.#zeroContext.processChanges(diff as ExperimentalNoIndexDiff),\n {\n prefix: ENTITIES_KEY_PREFIX,\n initialValuesInFirstDiff: true,\n },\n );\n\n this.query = this.#registerQueries(normalizedSchema);\n\n reportReloadReason(this.#lc);\n\n this.#metrics = new MetricManager({\n reportIntervalMs: REPORT_INTERVAL_MS,\n host: getBrowserGlobal('location')?.host ?? '',\n source: 'client',\n reporter: this.#enableAnalytics\n ? allSeries => this.#reportMetrics(allSeries)\n : () => Promise.resolve(),\n lc: this.#lc,\n });\n this.#metrics.tags.push(`version:${this.version}`);\n\n this.#pokeHandler = new PokeHandler(\n poke => this.#rep.poke(poke),\n () => this.#onPokeError(),\n rep.clientID,\n normalizedSchema,\n this.#lc,\n );\n\n this.#visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n hiddenTabDisconnectDelay,\n this.#closeAbortController.signal,\n );\n\n void this.#runLoop();\n\n if (TESTING) {\n asTestZero(this)[exposedToTestingSymbol] = {\n puller: this.#puller,\n pusher: this.#pusher,\n setReload: (r: () => void) => {\n this.#reload = r;\n },\n logOptions: this.#logOptions,\n connectStart: () => this.#connectStart,\n socketResolver: () => this.#socketResolver,\n connectionState: () => this.#connectionState,\n };\n }\n }\n\n #sendChangeDesiredQueries(msg: ChangeDesiredQueriesMessage): void {\n if (this.#socket && this.#connectionState === ConnectionState.Connected) {\n send(this.#socket, msg);\n }\n }\n\n #createLogOptions(options: {\n consoleLogLevel: LogLevel;\n server: string | null;\n enableAnalytics: boolean;\n }): LogOptions {\n if (TESTING) {\n const testZero = asTestZero(this);\n if (testZero[createLogOptionsSymbol]) {\n return testZero[createLogOptionsSymbol](options);\n }\n }\n return createLogOptions(options);\n }\n\n /**\n * The name of the IndexedDB database in which the data of this\n * instance of Zero is stored.\n */\n get idbName(): string {\n return this.#rep.idbName;\n }\n\n /**\n * The schema version of the data understood by this application.\n * See [[ZeroOptions.schemaVersion]].\n */\n get schemaVersion(): string {\n return this.#rep.schemaVersion;\n }\n\n /**\n * The client ID for this instance of Zero. Each instance\n * gets a unique client ID.\n */\n get clientID(): ClientID {\n return this.#rep.clientID;\n }\n\n get clientGroupID(): Promise<ClientGroupID> {\n return this.#rep.clientGroupID;\n }\n\n /**\n * Provides facilities to write data to Zero.\n *\n * `mutate` is a function as well as a \"namespace\" object for doing CRUD style\n * mutations. When used as a function it is used to batch multiple mutations.\n *\n * ```ts\n * await zero.mutate.issue.create({id: '1', title: 'First issue'});\n * await zero.mutate.comment.create({id: '1', text: 'First comment', issueID: '1'});\n *\n * // or as a function:\n * await zero.mutate(m => {\n * await m.issue.create({id: '1', title: 'First issue'});\n * await m.comment.create({id: '1', text: 'First comment', issueID: '1'});\n * });\n * ```\n *\n * The benefit of using the function form is that it allows you to batch\n * multiple mutations together. This can be more efficient than making\n * individual calls to `create`, `update`, `set`, and `delete`.\n *\n * The function form of `mutate` is not allowed to be called inside another\n * `mutate` function. Doing so will throw an error.\n */\n readonly mutate: MakeCRUDMutate<S>;\n\n /**\n * Whether this Zero instance has been closed. Once a Zero instance has\n * been closed it no longer syncs and you can no longer read or write data out\n * of it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#rep.closed;\n }\n\n /**\n * Closes this Zero instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n close(): Promise<void> {\n const lc = this.#lc.withContext('close');\n\n if (this.#connectionState !== ConnectionState.Disconnected) {\n this.#disconnect(lc, {\n client: 'ClientClosed',\n });\n }\n lc.debug?.('Aborting closeAbortController due to close()');\n this.#closeAbortController.abort();\n this.#metrics.stop();\n return this.#rep.close();\n }\n\n #onMessage = (e: MessageEvent<string>) => {\n const lc = this.#lc;\n lc.debug?.('received message', e.data);\n if (this.closed) {\n lc.debug?.('ignoring message because already closed');\n return;\n }\n\n const rejectInvalidMessage = (e?: unknown) =>\n this.#rejectMessageError?.reject(\n new Error(\n `Invalid message received from server: ${\n e instanceof Error ? e.message + '. ' : ''\n }${data}`,\n ),\n );\n\n let downMessage: Downstream;\n const {data} = e;\n try {\n downMessage = valita.parse(JSON.parse(data), downstreamSchema);\n } catch (e) {\n rejectInvalidMessage(e);\n return;\n }\n this.#messageCount++;\n const msgType = downMessage[0];\n switch (msgType) {\n case 'connected':\n return this.#handleConnectedMessage(lc, downMessage);\n\n case 'error':\n return this.#handleErrorMessage(lc, downMessage);\n\n case 'pong':\n return this.#onPong();\n\n case 'pokeStart':\n return this.#handlePokeStart(lc, downMessage);\n\n case 'pokePart':\n return this.#handlePokePart(lc, downMessage);\n\n case 'pokeEnd':\n return this.#handlePokeEnd(lc, downMessage);\n\n case 'pull':\n return this.#handlePullResponse(lc, downMessage);\n case 'warm':\n // we ignore warming messages\n break;\n default:\n msgType satisfies never;\n rejectInvalidMessage();\n }\n };\n\n #onOpen = (e: Event) => {\n const l = addWebSocketIDFromSocketToLogContext(\n e.target as WebSocket,\n this.#lc,\n );\n if (this.#connectStart === undefined) {\n l.error?.(\n 'Got open event but connect start time is undefined. This should not happen.',\n );\n } else {\n const now = Date.now();\n const timeToOpenMs = now - this.#connectStart;\n l.info?.('Got socket open event', {\n navigatorOnline: navigator?.onLine,\n timeToOpenMs,\n });\n }\n };\n\n #onClose = (e: CloseEvent) => {\n const l = addWebSocketIDFromSocketToLogContext(\n e.target as WebSocket,\n this.#lc,\n );\n const {code, reason, wasClean} = e;\n l.info?.('Got socket close event', {code, reason, wasClean});\n\n const closeKind = wasClean ? 'CleanClose' : 'AbruptClose';\n this.#connectResolver.reject(new CloseError(closeKind));\n this.#disconnect(l, {client: closeKind});\n };\n\n // An error on the connection is fatal for the connection.\n async #handleErrorMessage(\n lc: LogContext,\n downMessage: ErrorMessage,\n ): Promise<void> {\n const [, kind, message] = downMessage;\n\n // Rate limit errors are not fatal to the connection.\n // We really don't want to disconnect and reconnect a rate limited user as\n // it'll use more resources on the server\n if (kind === ErrorKind.MutationRateLimited) {\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n lc.error?.('Mutation rate limited', {message});\n return;\n }\n\n lc.info?.(`${kind}: ${message}}`);\n const error = new ServerError(kind, message);\n\n this.#rejectMessageError?.reject(error);\n lc.debug?.('Rejecting connect resolver due to error', error);\n this.#connectResolver.reject(error);\n this.#disconnect(lc, {server: kind});\n\n if (kind === ErrorKind.VersionNotSupported) {\n this.#onUpdateNeeded?.({type: kind}, message);\n } else if (kind === ErrorKind.SchemaVersionNotSupported) {\n await this.#rep.disableClientGroup();\n this.#onUpdateNeeded?.({type: 'SchemaVersionNotSupported'}, message);\n } else if (kind === ErrorKind.ClientNotFound) {\n await this.#rep.disableClientGroup();\n this.#onClientStateNotFound?.(onClientStateNotFoundServerReason(message));\n } else if (\n kind === ErrorKind.InvalidConnectionRequestLastMutationID ||\n kind === ErrorKind.InvalidConnectionRequestBaseCookie\n ) {\n await dropDatabase(this.#rep.idbName);\n reloadWithReason(lc, this.#reload, serverAheadReloadReason(kind));\n }\n }\n\n async #handleConnectedMessage(\n lc: LogContext,\n connectedMessage: ConnectedMessage,\n ) {\n const now = Date.now();\n const [, connectBody] = connectedMessage;\n lc = addWebSocketIDToLogContext(connectBody.wsid, lc);\n\n if (this.#connectedCount === 0) {\n this.#checkConnectivity('firstConnect');\n } else if (this.#connectErrorCount > 0) {\n this.#checkConnectivity('connectAfterError');\n }\n this.#connectedCount++;\n this.#connectedAt = now;\n this.#metrics.lastConnectError.clear();\n const proceedingConnectErrorCount = this.#connectErrorCount;\n this.#connectErrorCount = 0;\n\n let timeToConnectMs = undefined;\n let connectMsgLatencyMs = undefined;\n if (this.#connectStart === undefined) {\n lc.error?.(\n 'Got connected message but connect start time is undefined. This should not happen.',\n );\n } else {\n timeToConnectMs = now - this.#connectStart;\n this.#metrics.timeToConnectMs.set(timeToConnectMs);\n connectMsgLatencyMs =\n connectBody.timestamp !== undefined\n ? now - connectBody.timestamp\n : undefined;\n this.#connectStart = undefined;\n }\n let totalTimeToConnectMs = undefined;\n if (this.#totalToConnectStart === undefined) {\n lc.error?.(\n 'Got connected message but total to connect start time is undefined. This should not happen.',\n );\n } else {\n totalTimeToConnectMs = now - this.#totalToConnectStart;\n this.#totalToConnectStart = undefined;\n }\n\n this.#metrics.setConnected(timeToConnectMs ?? 0, totalTimeToConnectMs ?? 0);\n\n lc.info?.('Connected', {\n navigatorOnline: navigator?.onLine,\n timeToConnectMs,\n totalTimeToConnectMs,\n connectMsgLatencyMs,\n connectedCount: this.#connectedCount,\n proceedingConnectErrorCount,\n });\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n\n lc.debug?.('Resolving connect resolver');\n assert(this.#socket);\n\n const queriesPatch = await this.#rep.query(tx =>\n this.#queryManager.getQueriesPatch(tx, this.#initConnectionQueries),\n );\n if (queriesPatch.size > 0 && this.#initConnectionQueries !== undefined) {\n send(this.#socket, [\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [...queriesPatch.values()],\n },\n ]);\n } else if (this.#initConnectionQueries === undefined) {\n // if #initConnectionQueries was undefined that means we never\n // sent `initConnection` to the server inside the sec-protocol header.\n send(this.#socket, [\n 'initConnection',\n {\n desiredQueriesPatch: [...queriesPatch.values()],\n },\n ]);\n }\n this.#initConnectionQueries = undefined;\n\n this.#setConnectionState(ConnectionState.Connected);\n this.#connectResolver.resolve();\n }\n\n /**\n * Starts a new connection. This will create the WebSocket that does the HTTP\n * request to the server.\n *\n * {@link #connect} will throw an assertion error if the\n * {@link #connectionState} is not {@link ConnectionState.Disconnected}.\n * Callers MUST check the connection state before calling this method and log\n * an error as needed.\n *\n * The function will resolve once the socket is connected. If you need to know\n * when a connection has been established, as in we have received the\n * {@link ConnectedMessage}, you should await the {@link #connectResolver}\n * promise. The {@link #connectResolver} promise rejects if an error message\n * is received before the connected message is received or if the connection\n * attempt times out.\n */\n async #connect(l: LogContext): Promise<void> {\n assert(this.#server);\n\n // All the callers check this state already.\n assert(this.#connectionState === ConnectionState.Disconnected);\n\n const wsid = nanoid();\n l = addWebSocketIDToLogContext(wsid, l);\n l.info?.('Connecting...', {navigatorOnline: navigator?.onLine});\n\n this.#setConnectionState(ConnectionState.Connecting);\n\n // connect() called but connect start time is defined. This should not\n // happen.\n assert(this.#connectStart === undefined);\n\n const now = Date.now();\n this.#connectStart = now;\n if (this.#totalToConnectStart === undefined) {\n this.#totalToConnectStart = now;\n }\n\n if (this.closed) {\n return;\n }\n this.#connectCookie = valita.parse(\n await this.#rep.cookie,\n nullableVersionSchema,\n );\n if (this.closed) {\n return;\n }\n // Reject connect after a timeout.\n const timeoutID = setTimeout(() => {\n l.debug?.('Rejecting connect resolver due to timeout');\n this.#connectResolver.reject(new TimedOutError('Connect'));\n this.#disconnect(l, {\n client: 'ConnectTimeout',\n });\n }, CONNECT_TIMEOUT_MS);\n const abortHandler = () => {\n clearTimeout(timeoutID);\n };\n this.#closeAbortController.signal.addEventListener('abort', abortHandler);\n\n const [ws, initConnectionQueries] = await createSocket(\n this.#rep,\n this.#queryManager,\n toWSString(this.#server),\n this.#connectCookie,\n this.clientID,\n await this.clientGroupID,\n this.#options.schema.version,\n this.userID,\n this.#rep.auth,\n this.#jurisdiction,\n this.#lastMutationIDReceived,\n wsid,\n this.#options.logLevel === 'debug',\n l,\n this.#options.maxHeaderLength,\n );\n\n if (this.closed) {\n return;\n }\n\n this.#initConnectionQueries = initConnectionQueries;\n ws.addEventListener('message', this.#onMessage);\n ws.addEventListener('open', this.#onOpen);\n ws.addEventListener('close', this.#onClose);\n this.#socket = ws;\n this.#socketResolver.resolve(ws);\n\n try {\n l.debug?.('Waiting for connection to be acknowledged');\n await this.#connectResolver.promise;\n } finally {\n clearTimeout(timeoutID);\n this.#closeAbortController.signal.removeEventListener(\n 'abort',\n abortHandler,\n );\n }\n }\n\n #disconnect(l: LogContext, reason: DisconnectReason): void {\n if (this.#connectionState === ConnectionState.Connecting) {\n this.#connectErrorCount++;\n }\n l.info?.('disconnecting', {\n navigatorOnline: navigator?.onLine,\n reason,\n connectStart: this.#connectStart,\n totalToConnectStart: this.#totalToConnectStart,\n connectedAt: this.#connectedAt,\n connectionDuration: this.#connectedAt\n ? Date.now() - this.#connectedAt\n : 0,\n messageCount: this.#messageCount,\n connectionState: this.#connectionState,\n connectErrorCount: this.#connectErrorCount,\n });\n\n switch (this.#connectionState) {\n case ConnectionState.Connected: {\n if (this.#connectStart !== undefined) {\n l.error?.(\n 'disconnect() called while connected but connect start time is defined. This should not happen.',\n );\n // this._connectStart reset below.\n }\n\n break;\n }\n case ConnectionState.Connecting: {\n this.#metrics.lastConnectError.set(getLastConnectErrorValue(reason));\n this.#metrics.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#metrics.setConnectError(reason);\n if (\n this.#connectErrorCount % CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY ===\n 1\n ) {\n this.#checkConnectivity(\n `connectErrorCount=${this.#connectErrorCount}`,\n );\n }\n // this._connectStart reset below.\n if (this.#connectStart === undefined) {\n l.error?.(\n 'disconnect() called while connecting but connect start time is undefined. This should not happen.',\n );\n }\n\n break;\n }\n case ConnectionState.Disconnected:\n l.error?.('disconnect() called while disconnected');\n break;\n }\n\n this.#socketResolver = resolver();\n l.debug?.('Creating new connect resolver');\n this.#connectResolver = resolver();\n this.#setConnectionState(ConnectionState.Disconnected);\n this.#messageCount = 0;\n this.#connectStart = undefined; // don't reset this._totalToConnectStart\n this.#connectedAt = 0;\n this.#socket?.removeEventListener('message', this.#onMessage);\n this.#socket?.removeEventListener('open', this.#onOpen);\n this.#socket?.removeEventListener('close', this.#onClose);\n this.#socket?.close();\n this.#socket = undefined;\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n this.#pokeHandler.handleDisconnect();\n }\n\n async #handlePokeStart(_lc: LogContext, pokeMessage: PokeStartMessage) {\n this.#abortPingTimeout();\n await this.#pokeHandler.handlePokeStart(pokeMessage[1]);\n }\n\n async #handlePokePart(_lc: LogContext, pokeMessage: PokePartMessage) {\n this.#abortPingTimeout();\n const lastMutationIDChangeForSelf = await this.#pokeHandler.handlePokePart(\n pokeMessage[1],\n );\n if (lastMutationIDChangeForSelf !== undefined) {\n this.#lastMutationIDReceived = lastMutationIDChangeForSelf;\n }\n }\n\n async #handlePokeEnd(_lc: LogContext, pokeMessage: PokeEndMessage) {\n this.#abortPingTimeout();\n await this.#pokeHandler.handlePokeEnd(pokeMessage[1]);\n }\n\n #onPokeError() {\n const lc = this.#lc;\n lc.info?.(\n 'poke error, disconnecting?',\n this.#connectionState !== ConnectionState.Disconnected,\n );\n\n // It is theoretically possible that we get disconnected during the\n // async poke above. Only disconnect if we are not already\n // disconnected.\n if (this.#connectionState !== ConnectionState.Disconnected) {\n this.#disconnect(lc, {\n client: 'UnexpectedBaseCookie',\n });\n }\n }\n\n #handlePullResponse(\n lc: LogContext,\n pullResponseMessage: PullResponseMessage,\n ) {\n this.#abortPingTimeout();\n const body = pullResponseMessage[1];\n lc = lc.withContext('requestID', body.requestID);\n lc.debug?.('Handling pull response', body);\n const resolver = this.#pendingPullsByRequestID.get(body.requestID);\n if (!resolver) {\n // This can happen because resolvers are deleted\n // from this._pendingPullsByRequestID when pulls timeout.\n lc.debug?.('No resolver found');\n return;\n }\n resolver.resolve(pullResponseMessage[1]);\n }\n\n async #pusher(\n req: PushRequestV0 | PushRequestV1,\n requestID: string,\n ): Promise<PusherResult> {\n // The deprecation of pushVersion 0 predates zero-client\n assert(req.pushVersion === 1);\n // If we are connecting we wait until we are connected.\n await this.#connectResolver.promise;\n const lc = this.#lc.withContext('requestID', requestID);\n lc.debug?.(`pushing ${req.mutations.length} mutations`);\n const socket = this.#socket;\n assert(socket);\n\n const isMutationRecoveryPush =\n req.clientGroupID !== (await this.clientGroupID);\n const start = isMutationRecoveryPush\n ? 0\n : req.mutations.findIndex(\n m =>\n m.clientID === this.#lastMutationIDSent.clientID &&\n m.id === this.#lastMutationIDSent.id,\n ) + 1;\n lc.debug?.(\n isMutationRecoveryPush ? 'pushing for recovery' : 'pushing',\n req.mutations.length - start,\n 'mutations of',\n req.mutations.length,\n 'mutations.',\n );\n const now = Date.now();\n for (let i = start; i < req.mutations.length; i++) {\n const m = req.mutations[i];\n const timestamp = now - Math.round(performance.now() - m.timestamp);\n const zeroM =\n m.name === CRUD_MUTATION_NAME\n ? ({\n type: MutationType.CRUD,\n timestamp,\n id: m.id,\n clientID: m.clientID,\n name: m.name,\n args: [m.args as CRUDMutationArg],\n } satisfies CRUDMutation)\n : ({\n type: MutationType.Custom,\n timestamp,\n id: m.id,\n clientID: m.clientID,\n name: m.name,\n args: [m.args],\n } satisfies CustomMutation);\n const msg: PushMessage = [\n 'push',\n {\n timestamp: now,\n clientGroupID: req.clientGroupID,\n mutations: [zeroM],\n pushVersion: req.pushVersion,\n // Zero schema versions are always numbers.\n schemaVersion: parseInt(req.schemaVersion),\n requestID,\n },\n ];\n send(socket, msg);\n if (!isMutationRecoveryPush) {\n this.#lastMutationIDSent = {clientID: m.clientID, id: m.id};\n }\n }\n return {\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n\n #getAuthToken = (): MaybePromise<string> | undefined => {\n const {auth} = this.#options;\n return typeof auth === 'function' ? auth() : auth;\n };\n\n async #updateAuthToken(lc: LogContext): Promise<void> {\n const auth = await this.#getAuthToken();\n if (auth) {\n lc.debug?.('Got auth token');\n this.#rep.auth = auth;\n }\n }\n\n async #runLoop() {\n this.#lc.info?.(`Starting Zero version: ${this.version}`);\n\n if (this.#server === null) {\n this.#lc.info?.('No socket origin provided, not starting connect loop.');\n return;\n }\n\n let runLoopCounter = 0;\n const bareLogContext = this.#lc;\n const getLogContext = () => {\n let lc = bareLogContext;\n if (this.#socket) {\n lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);\n }\n return lc.withContext('runLoopCounter', runLoopCounter);\n };\n\n await this.#updateAuthToken(bareLogContext);\n\n let needsReauth = false;\n let gotError = false;\n\n while (!this.closed) {\n runLoopCounter++;\n let lc = getLogContext();\n\n try {\n switch (this.#connectionState) {\n case ConnectionState.Disconnected: {\n if (this.#visibilityWatcher.visibilityState === 'hidden') {\n this.#metrics.setDisconnectedWaitingForVisible();\n // reset this._totalToConnectStart since this client\n // is no longer trying to connect due to being hidden.\n this.#totalToConnectStart = undefined;\n }\n // If hidden, we wait for the tab to become visible before trying again.\n await this.#visibilityWatcher.waitForVisible();\n\n // If we got an auth error we try to get a new auth token before reconnecting.\n if (needsReauth) {\n await this.#updateAuthToken(lc);\n }\n\n await this.#connect(lc);\n if (this.closed) {\n break;\n }\n\n // Now we have a new socket, update lc with the new wsid.\n assert(this.#socket);\n lc = getLogContext();\n\n lc.debug?.('Connected successfully');\n gotError = false;\n needsReauth = false;\n this.#setOnline(true);\n break;\n }\n\n case ConnectionState.Connecting:\n // Can't get here because Disconnected waits for Connected or\n // rejection.\n lc.error?.('unreachable');\n gotError = true;\n break;\n\n case ConnectionState.Connected: {\n // When connected we wait for whatever happens first out of:\n // - After PING_INTERVAL_MS we send a ping\n // - We get disconnected\n // - We get a message\n // - We get an error (rejectMessageError rejects)\n // - The tab becomes hidden (with a delay)\n\n const controller = new AbortController();\n this.#abortPingTimeout = () => controller.abort();\n const [pingTimeoutPromise, pingTimeoutAborted] = sleepWithAbort(\n PING_INTERVAL_MS,\n controller.signal,\n );\n\n this.#rejectMessageError = resolver();\n\n const enum RaceCases {\n Ping = 0,\n Hidden = 2,\n }\n\n const raceResult = await promiseRace([\n pingTimeoutPromise,\n pingTimeoutAborted,\n this.#visibilityWatcher.waitForHidden(),\n this.#connectionStateChangeResolver.promise,\n this.#rejectMessageError.promise,\n ]);\n\n if (this.closed) {\n this.#rejectMessageError = undefined;\n break;\n }\n\n switch (raceResult) {\n case RaceCases.Ping: {\n const pingResult = await this.#ping(\n lc,\n this.#rejectMessageError.promise,\n );\n if (pingResult === PingResult.TimedOut) {\n gotError = true;\n }\n break;\n }\n case RaceCases.Hidden:\n this.#disconnect(lc, {\n client: 'Hidden',\n });\n this.#setOnline(false);\n break;\n }\n\n this.#rejectMessageError = undefined;\n }\n }\n } catch (ex) {\n if (this.#connectionState !== ConnectionState.Connected) {\n lc.error?.('Failed to connect', ex, {\n lmid: this.#lastMutationIDReceived,\n baseCookie: this.#connectCookie,\n });\n }\n\n lc.debug?.(\n 'Got an exception in the run loop',\n 'state:',\n this.#connectionState,\n 'exception:',\n ex,\n );\n\n if (isAuthError(ex)) {\n if (!needsReauth) {\n needsReauth = true;\n // First auth error, try right away without waiting.\n continue;\n }\n needsReauth = true;\n }\n\n if (\n isServerError(ex) ||\n ex instanceof TimedOutError ||\n ex instanceof CloseError\n ) {\n gotError = true;\n }\n }\n\n // Only authentication errors are retried immediately the first time they\n // occur. All other errors wait a few seconds before retrying the first\n // time. We specifically do not use a backoff for consecutive errors\n // because it's a bad experience to wait many seconds for reconnection.\n\n if (gotError) {\n this.#setOnline(false);\n let cfGetCheckSucceeded = false;\n const cfGetCheckURL = new URL(this.#server);\n cfGetCheckURL.pathname = '/api/canary/v0/get';\n cfGetCheckURL.searchParams.set('id', nanoid());\n const cfGetCheckController = new AbortController();\n fetch(cfGetCheckURL, {signal: cfGetCheckController.signal})\n .then(_ => {\n cfGetCheckSucceeded = true;\n })\n .catch(_ => {\n cfGetCheckSucceeded = false;\n });\n\n lc.debug?.(\n 'Sleeping',\n RUN_LOOP_INTERVAL_MS,\n 'ms before reconnecting due to error, state:',\n this.#connectionState,\n );\n await sleep(RUN_LOOP_INTERVAL_MS);\n cfGetCheckController.abort();\n if (!cfGetCheckSucceeded) {\n lc.info?.(\n 'Canary request failed, resetting total time to connect start time.',\n );\n this.#totalToConnectStart = undefined;\n }\n }\n }\n }\n\n async #puller(\n req: PullRequestV0 | PullRequestV1,\n requestID: string,\n ): Promise<PullerResultV1> {\n // The deprecation of pushVersion 0 predates zero-client\n assert(req.pullVersion === 1);\n const lc = this.#lc.withContext('requestID', requestID);\n lc.debug?.('Pull', req);\n // Pull request for this instance's client group. A no-op response is\n // returned as pulls for this client group are handled via poke over the\n // socket.\n if (req.clientGroupID === (await this.clientGroupID)) {\n return {\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n\n // If we are connecting we wait until we are connected.\n await this.#connectResolver.promise;\n const socket = this.#socket;\n assert(socket);\n // Mutation recovery pull.\n lc.debug?.('Pull is for mutation recovery');\n const cookie = valita.parse(req.cookie, nullableVersionSchema);\n const pullRequestMessage: PullRequestMessage = [\n 'pull',\n {\n clientGroupID: req.clientGroupID,\n cookie,\n requestID,\n },\n ];\n send(socket, pullRequestMessage);\n const pullResponseResolver: Resolver<PullResponseBody> = resolver();\n this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);\n try {\n const enum RaceCases {\n Timeout = 0,\n Response = 1,\n }\n const raceResult = await promiseRace([\n sleep(PULL_TIMEOUT_MS),\n pullResponseResolver.promise,\n ]);\n switch (raceResult) {\n case RaceCases.Timeout:\n lc.debug?.('Mutation recovery pull timed out');\n throw new Error('Pull timed out');\n case RaceCases.Response: {\n lc.debug?.('Returning mutation recovery pull response');\n const response = await pullResponseResolver.promise;\n return {\n response: {\n cookie: response.cookie,\n lastMutationIDChanges: response.lastMutationIDChanges,\n patch: [],\n },\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n default:\n assert(false, 'unreachable');\n }\n } finally {\n pullResponseResolver.reject('timed out');\n this.#pendingPullsByRequestID.delete(requestID);\n }\n }\n\n #setOnline(online: boolean): void {\n if (this.#online === online) {\n return;\n }\n\n this.#online = online;\n this.onOnlineChange?.(online);\n }\n\n /**\n * A rough heuristic for whether the client is currently online and\n * authenticated.\n */\n get online(): boolean {\n return this.#online;\n }\n\n /**\n * Starts a a ping and waits for a pong.\n *\n * If it takes too long to get a pong we disconnect and this returns\n * {@code PingResult.TimedOut}.\n */\n async #ping(\n l: LogContext,\n messageErrorRejectionPromise: Promise<never>,\n ): Promise<PingResult> {\n l.debug?.('pinging');\n const {promise, resolve} = resolver();\n this.#onPong = resolve;\n const pingMessage: PingMessage = ['ping', {}];\n const t0 = performance.now();\n assert(this.#socket);\n send(this.#socket, pingMessage);\n\n const connected =\n (await promiseRace([\n promise,\n sleep(PING_TIMEOUT_MS),\n messageErrorRejectionPromise,\n ])) === 0;\n\n const delta = performance.now() - t0;\n if (!connected) {\n l.info?.('ping failed in', delta, 'ms - disconnecting');\n this.#disconnect(l, {\n client: 'PingTimeout',\n });\n return PingResult.TimedOut;\n }\n\n l.debug?.('ping succeeded in', delta, 'ms');\n return PingResult.Success;\n }\n\n // Sends a set of metrics to the server. Throws unless the server\n // returns 200.\n // TODO: Reenable metrics reporting\n async #reportMetrics(_allSeries: Series[]) {\n // if (this.#server === null) {\n // this.#lc.info?.('Skipping metrics report, socketOrigin is null');\n // return;\n // }\n // const body = JSON.stringify({series: allSeries});\n // const url = new URL('/api/metrics/v0/report', this.#server);\n // url.searchParams.set('clientID', this.clientID);\n // url.searchParams.set('clientGroupID', await this.clientGroupID);\n // url.searchParams.set('userID', this.userID);\n // url.searchParams.set('requestID', nanoid());\n // const res = await fetch(url.toString(), {\n // method: 'POST',\n // body,\n // keepalive: true,\n // });\n // if (!res.ok) {\n // const maybeBody = await res.text();\n // throw new Error(\n // `unexpected response: ${res.status} ${res.statusText} body: ${maybeBody}`,\n // );\n // }\n }\n\n #checkConnectivity(reason: string) {\n void this.#checkConnectivityAsync(reason);\n }\n\n #checkConnectivityAsync(_reason: string) {\n // skipping connectivity checks for now - the server doesn't respond to\n // them so it just creates noise.\n // assert(this.#server);\n // if (this.closed) {\n // return;\n // }\n // try {\n // await checkConnectivity(\n // reason,\n // this.#server,\n // this.#lc,\n // this.#closeAbortController.signal,\n // this.#enableAnalytics,\n // );\n // } catch (e) {\n // this.#lc.info?.('Error checking connectivity for', reason, e);\n // }\n }\n\n #registerQueries(schema: NormalizedSchema): MakeEntityQueriesFromSchema<S> {\n const rv = {} as Record<string, Query<TableSchema>>;\n const context = this.#zeroContext;\n // Not using parse yet\n for (const [name, table] of Object.entries(schema.tables)) {\n rv[name] = newQuery(context, table);\n }\n\n return rv as MakeEntityQueriesFromSchema<S>;\n }\n}\n\nexport async function createSocket(\n rep: ReplicacheImpl,\n queryManager: QueryManager,\n socketOrigin: WSString,\n baseCookie: NullableVersion,\n clientID: string,\n clientGroupID: string,\n schemaVersion: number,\n userID: string,\n auth: string | undefined,\n jurisdiction: 'eu' | undefined,\n lmid: number,\n wsid: string,\n debugPerf: boolean,\n lc: LogContext,\n maxHeaderLength = 1024 * 8,\n): Promise<[WebSocket, Map<string, QueriesPatchOp> | undefined]> {\n const url = new URL(socketOrigin);\n // Keep this in sync with the server.\n url.pathname = `/api/sync/v${REFLECT_VERSION}/connect`;\n const {searchParams} = url;\n searchParams.set('clientID', clientID);\n searchParams.set('clientGroupID', clientGroupID);\n searchParams.set('schemaVersion', schemaVersion.toString());\n searchParams.set('userID', userID);\n if (jurisdiction !== undefined) {\n searchParams.set('jurisdiction', jurisdiction);\n }\n searchParams.set('baseCookie', baseCookie === null ? '' : String(baseCookie));\n searchParams.set('ts', String(performance.now()));\n searchParams.set('lmid', String(lmid));\n searchParams.set('wsid', wsid);\n if (debugPerf) {\n searchParams.set('debugPerf', true.toString());\n }\n\n lc.info?.('Connecting to', url.toString());\n\n // Pass auth to the server via the `Sec-WebSocket-Protocol` header by passing\n // it as a `protocol` to the `WebSocket` constructor. The empty string is an\n // invalid `protocol`, and will result in an exception, so pass undefined\n // instead. encodeURIComponent to ensure it only contains chars allowed\n // for a `protocol`.\n const WS = mustGetBrowserGlobal('WebSocket');\n let queriesPatch: Map<string, QueriesPatchOp> | undefined = await rep.query(\n tx => queryManager.getQueriesPatch(tx),\n );\n let secProtocol = encodeSecProtocols(\n ['initConnection', {desiredQueriesPatch: [...queriesPatch.values()]}],\n auth,\n );\n if (secProtocol.length > maxHeaderLength) {\n secProtocol = encodeSecProtocols(undefined, auth);\n queriesPatch = undefined;\n }\n return [\n new WS(\n // toString() required for RN URL polyfill.\n url.toString(),\n secProtocol,\n ),\n queriesPatch,\n ];\n}\n\n/**\n * Adds the wsid query parameter to the log context. If the URL does not\n * have a wsid we use a randomID instead.\n */\nfunction addWebSocketIDFromSocketToLogContext(\n {url}: {url: string},\n lc: LogContext,\n): LogContext {\n const wsid = new URL(url).searchParams.get('wsid') ?? nanoid();\n return addWebSocketIDToLogContext(wsid, lc);\n}\n\nfunction addWebSocketIDToLogContext(wsid: string, lc: LogContext): LogContext {\n return lc.withContext('wsid', wsid);\n}\n\n/**\n * Like Promise.race but returns the index of the first promise that resolved.\n */\nfunction promiseRace(ps: Promise<unknown>[]): Promise<number> {\n return Promise.race(ps.map((p, i) => p.then(() => i)));\n}\n\nclass TimedOutError extends Error {\n constructor(m: string) {\n super(`${m} timed out`);\n }\n}\n\nclass CloseError extends Error {}\n", "import * as v from '../../shared/src/valita.js';\nimport {astSchema} from './ast.js';\n\nconst putOpSchema = v.object({\n op: v.literal('put'),\n hash: v.string(),\n ast: astSchema,\n});\n\nconst delOpSchema = v.object({\n op: v.literal('del'),\n hash: v.string(),\n});\n\nconst clearOpSchema = v.object({\n op: v.literal('clear'),\n});\n\nconst patchOpSchema = v.union(putOpSchema, delOpSchema, clearOpSchema);\n\nexport const queriesPatchSchema = v.array(patchOpSchema);\n\nexport type QueriesPutOp = v.Infer<typeof putOpSchema>;\nexport type QueriesDelOp = v.Infer<typeof delOpSchema>;\nexport type QueriesClearOp = v.Infer<typeof clearOpSchema>;\nexport type QueriesPatchOp = v.Infer<typeof patchOpSchema>;\nexport type QueriesPatch = v.Infer<typeof queriesPatchSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {queriesPatchSchema} from './queries-patch.js';\n\nconst changeDesiredQueriesBodySchema = v.object({\n desiredQueriesPatch: queriesPatchSchema,\n});\n\nexport const changeDesiredQueriesMessageSchema = v.tuple([\n v.literal('changeDesiredQueries'),\n changeDesiredQueriesBodySchema,\n]);\n\nexport type ChangeDesiredQueriesBody = v.Infer<\n typeof changeDesiredQueriesBodySchema\n>;\nexport type ChangeDesiredQueriesMessage = v.Infer<\n typeof changeDesiredQueriesMessageSchema\n>;\n", "import * as v from '../../shared/src/valita.js';\n\nconst putOpSchema = v.object({\n op: v.literal('put'),\n clientID: v.string(),\n});\n\nconst delOpSchema = v.object({\n op: v.literal('del'),\n clientID: v.string(),\n});\n\nconst clearOpSchema = v.object({\n op: v.literal('clear'),\n});\n\nconst patchOpSchema = v.union(putOpSchema, delOpSchema, clearOpSchema);\n\nexport const clientsPatchSchema = v.array(patchOpSchema);\n\nexport type ClientsPutOp = v.Infer<typeof putOpSchema>;\nexport type ClientsDelOp = v.Infer<typeof delOpSchema>;\nexport type ClientsClearOp = v.Infer<typeof clearOpSchema>;\nexport type ClientsPatchOp = v.Infer<typeof patchOpSchema>;\nexport type ClientsPatch = v.Infer<typeof clientsPatchSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {queriesPatchSchema} from './queries-patch.js';\n\n/**\n * After opening a websocket the client waits for a `connected` message\n * from the server. It then sends an `initConnection` message to the\n * server. The server waits for the `initConnection` message before\n * beginning to send pokes to the newly connected client, so as to avoid\n * syncing lots of queries which are no longer desired by the client.\n */\n\nexport const connectedBodySchema = v.object({\n wsid: v.string(),\n timestamp: v.number().optional(),\n});\n\nexport const connectedMessageSchema = v.tuple([\n v.literal('connected'),\n connectedBodySchema,\n]);\n\nconst initConnectionBodySchema = v.object({\n desiredQueriesPatch: queriesPatchSchema,\n});\n\nexport const initConnectionMessageSchema = v.tuple([\n v.literal('initConnection'),\n initConnectionBodySchema,\n]);\n\nexport type ConnectedBody = v.Infer<typeof connectedBodySchema>;\nexport type ConnectedMessage = v.Infer<typeof connectedMessageSchema>;\n\nexport type InitConnectionBody = v.Infer<typeof initConnectionBodySchema>;\nexport type InitConnectionMessage = v.Infer<typeof initConnectionMessageSchema>;\n\nexport function encodeSecProtocols(\n initConnectionMessage: InitConnectionMessage | undefined,\n authToken: string | undefined,\n) {\n const protocols = {\n initConnectionMessage,\n authToken,\n };\n // base64 encoding the JSON before URI encoding it results in a smaller payload.\n return encodeURIComponent(btoa(JSON.stringify(protocols)));\n}\n\nexport function decodeSecProtocols(secProtocol: string): {\n initConnectionMessage: InitConnectionMessage | undefined;\n authToken: string | undefined;\n} {\n return JSON.parse(atob(decodeURIComponent(secProtocol)));\n}\n", "import * as v from '../../shared/src/valita.js';\n\n// Note: Metric names depend on these values,\n// so if you add or change on here a corresponding dashboard\n// change will likely be needed.\n\nexport enum ErrorKind {\n AuthInvalidated = 'AuthInvalidated',\n ClientNotFound = 'ClientNotFound',\n InvalidConnectionRequest = 'InvalidConnectionRequest',\n InvalidConnectionRequestBaseCookie = 'InvalidConnectionRequestBaseCookie',\n InvalidConnectionRequestLastMutationID = 'InvalidConnectionRequestLastMutationID',\n InvalidConnectionRequestClientDeleted = 'InvalidConnectionRequestClientDeleted',\n InvalidMessage = 'InvalidMessage',\n InvalidPush = 'InvalidPush',\n MutationFailed = 'MutationFailed',\n MutationRateLimited = 'MutationRateLimited',\n Unauthorized = 'Unauthorized',\n VersionNotSupported = 'VersionNotSupported',\n SchemaVersionNotSupported = 'SchemaVersionNotSupported',\n Internal = 'Internal',\n}\n\nexport const errorKindSchema = v.union(\n v.literal(ErrorKind.AuthInvalidated),\n v.literal(ErrorKind.ClientNotFound),\n v.literal(ErrorKind.InvalidConnectionRequest),\n v.literal(ErrorKind.InvalidConnectionRequestBaseCookie),\n v.literal(ErrorKind.InvalidConnectionRequestLastMutationID),\n v.literal(ErrorKind.InvalidConnectionRequestClientDeleted),\n v.literal(ErrorKind.InvalidMessage),\n v.literal(ErrorKind.InvalidPush),\n v.literal(ErrorKind.MutationRateLimited),\n v.literal(ErrorKind.MutationFailed),\n v.literal(ErrorKind.Unauthorized),\n v.literal(ErrorKind.VersionNotSupported),\n v.literal(ErrorKind.SchemaVersionNotSupported),\n v.literal(ErrorKind.Internal),\n);\n\nexport const errorMessageSchema: v.Type<ErrorMessage> = v.tuple([\n v.literal('error'),\n errorKindSchema,\n v.string(),\n]);\n\nexport type ErrorMessage = ['error', ErrorKind, string];\n", "import * as v from '../../shared/src/valita.js';\n\nexport const primaryKeySchema = v.readonly(\n v.tuple([v.string()]).concat(v.array(v.string())),\n);\n\nexport type PrimaryKey = v.Infer<typeof primaryKeySchema>;\n\nexport const primaryKeyValueSchema = v.union(\n v.string(),\n v.number(),\n v.boolean(),\n);\n\nexport type PrimaryKeyValue = v.Infer<typeof primaryKeyValueSchema>;\n\nexport const primaryKeyValueRecordSchema = v.readonlyRecord(\n primaryKeyValueSchema,\n);\n\nexport type PrimaryKeyValueRecord = v.Infer<typeof primaryKeyValueRecordSchema>;\n", "import {jsonObjectSchema} from '../../shared/src/json-schema.js';\nimport * as v from '../../shared/src/valita.js';\nimport {rowSchema} from './data.js';\nimport {primaryKeyValueRecordSchema} from './primary-key.js';\n\nconst putOpSchema = v.object({\n op: v.literal('put'),\n tableName: v.string(),\n value: rowSchema,\n});\n\nconst updateOpSchema = v.object({\n op: v.literal('update'),\n tableName: v.string(),\n id: primaryKeyValueRecordSchema,\n merge: jsonObjectSchema.optional(),\n constrain: v.array(v.string()).optional(),\n});\n\nconst delOpSchema = v.object({\n op: v.literal('del'),\n tableName: v.string(),\n id: primaryKeyValueRecordSchema,\n});\n\nconst clearOpSchema = v.object({\n op: v.literal('clear'),\n});\n\nconst rowPatchOpSchema = v.union(\n putOpSchema,\n updateOpSchema,\n delOpSchema,\n clearOpSchema,\n);\n\nexport const rowsPatchSchema = v.array(rowPatchOpSchema);\nexport type RowPatchOp = v.Infer<typeof rowPatchOpSchema>;\n", "import * as v from '../../shared/src/valita.js';\n\nexport const versionSchema = v.string();\nexport const nullableVersionSchema = v.union(versionSchema, v.null());\n\nexport type Version = v.Infer<typeof versionSchema>;\nexport type NullableVersion = v.Infer<typeof nullableVersionSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {clientsPatchSchema} from './clients-patch.js';\nimport {queriesPatchSchema} from './queries-patch.js';\nimport {rowsPatchSchema} from './row-patch.js';\nimport {nullableVersionSchema, versionSchema} from './version.js';\n\n/**\n * Pokes use a multi-part format. Pokes send entity data to the client and can\n * be multiple mega-bytes in size. Using a multi-part format allows the server\n * to avoid having to have the full poke in memory at one time.\n *\n * Each poke is assigned a `pokeID`, a unique id (within the context of the\n * connection) for identifying the poke. All messages for a poke will have the\n * same `pokeID`.\n *\n * A poke begins with a `poke-start` message which contains the `baseCookie`\n * the poke is updating from and the `cookie` the poke is updating to.\n *\n * The poke continues with zero to many `poke-part` messages, each of which\n * can contain patch parts. These patch parts should be merged in the order\n * received.\n *\n * Finally, the poke ends with a `poke-end` message. The merged `poke-parts`\n * can now be applied as a whole to update from `baseCookie` to `cookie`.\n *\n * Poke messages can be intermingled with other `down` messages, but cannot be\n * intermingled with poke messages for a different `pokeID`. If this is\n * observed it is an unexpected error; the client should ignore both pokes,\n * disconnect, and reconnect.\n */\n\nexport const pokeStartBodySchema = v.object({\n pokeID: v.string(),\n // We always specify a Version as our cookie, but Replicache starts clients\n // with initial cookie `null`, before the first request. So we have to be\n // able to send a base cookie with value `null` to match that state.\n baseCookie: nullableVersionSchema,\n cookie: versionSchema,\n schemaVersions: v.object({\n minSupportedVersion: v.number(),\n maxSupportedVersion: v.number(),\n }),\n timestamp: v.number().optional(),\n});\n\nexport const pokePartBodySchema = v.object({\n pokeID: v.string(),\n // Changes to last mutation id by client id.\n lastMutationIDChanges: v.record(v.number()).optional(),\n // Patches to the set of \"alive\" clients (according to server) belonging to\n // this client group.\n clientsPatch: clientsPatchSchema.optional(),\n // Patches to the desired query sets by client id.\n desiredQueriesPatches: v.record(queriesPatchSchema).optional(),\n // Patches to the set of queries for which entities are sync'd in\n // rowsPatch.\n gotQueriesPatch: queriesPatchSchema.optional(),\n // Patches to the rows set.\n rowsPatch: rowsPatchSchema.optional(),\n});\n\nexport const pokeEndBodySchema = v.object({\n pokeID: v.string(),\n // If `true`, the poke with id `pokeID` should be discarded without\n // applying it.\n cancel: v.boolean().optional(),\n});\n\nexport const pokeStartMessageSchema = v.tuple([\n v.literal('pokeStart'),\n pokeStartBodySchema,\n]);\nexport const pokePartMessageSchema = v.tuple([\n v.literal('pokePart'),\n pokePartBodySchema,\n]);\nexport const pokeEndMessageSchema = v.tuple([\n v.literal('pokeEnd'),\n pokeEndBodySchema,\n]);\n\nexport type PokeStartBody = v.Infer<typeof pokeStartBodySchema>;\nexport type PokePartBody = v.Infer<typeof pokePartBodySchema>;\nexport type PokeEndBody = v.Infer<typeof pokeEndBodySchema>;\n\nexport type PokeStartMessage = v.Infer<typeof pokeStartMessageSchema>;\nexport type PokePartMessage = v.Infer<typeof pokePartMessageSchema>;\nexport type PokeEndMessage = v.Infer<typeof pokeEndMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\n\nexport const pongBodySchema = v.object({});\nexport const pongMessageSchema = v.tuple([v.literal('pong'), pongBodySchema]);\n\nexport type PongBody = v.Infer<typeof pongBodySchema>;\nexport type PongMessage = v.Infer<typeof pongMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {nullableVersionSchema, versionSchema} from './version.js';\n\nexport const pullRequestBodySchema = v.object({\n clientGroupID: v.string(),\n cookie: nullableVersionSchema,\n requestID: v.string(),\n});\n\nexport const pullResponseBodySchema = v.object({\n cookie: versionSchema,\n // Matches pullRequestBodySchema requestID that initiated this response\n requestID: v.string(),\n lastMutationIDChanges: v.record(v.number()),\n // Pull is currently only used for mutation recovery which does not use\n // the patch so we save work by not computing the patch.\n});\n\nexport const pullRequestMessageSchema = v.tuple([\n v.literal('pull'),\n pullRequestBodySchema,\n]);\n\nexport const pullResponseMessageSchema = v.tuple([\n v.literal('pull'),\n pullResponseBodySchema,\n]);\n\nexport type PullRequestBody = v.Infer<typeof pullRequestBodySchema>;\nexport type PullResponseBody = v.Infer<typeof pullResponseBodySchema>;\n\nexport type PullRequestMessage = v.Infer<typeof pullRequestMessageSchema>;\nexport type PullResponseMessage = v.Infer<typeof pullResponseMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\n\nexport const warmBodySchema = v.object({\n payload: v.string(),\n});\n\nexport const warmMessageSchema = v.tuple([v.literal('warm'), warmBodySchema]);\n\nexport type WarmBody = v.Infer<typeof warmBodySchema>;\nexport type WarmMessage = v.Infer<typeof warmMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {connectedMessageSchema} from './connect.js';\nimport {errorMessageSchema} from './error.js';\nimport {\n pokeEndMessageSchema,\n pokePartMessageSchema,\n pokeStartMessageSchema,\n} from './poke.js';\nimport {pongMessageSchema} from './pong.js';\nimport {pullResponseMessageSchema} from './pull.js';\nimport {warmMessageSchema} from './warm.js';\n\nexport const downstreamSchema = v.union(\n connectedMessageSchema,\n warmMessageSchema,\n errorMessageSchema,\n pongMessageSchema,\n pokeStartMessageSchema,\n pokePartMessageSchema,\n pokeEndMessageSchema,\n pullResponseMessageSchema,\n);\n\nexport type Downstream = v.Infer<typeof downstreamSchema>;\n", "import * as v from '../../shared/src/valita.js';\n\nexport const pingBodySchema = v.object({});\nexport const pingMessageSchema = v.tuple([v.literal('ping'), pingBodySchema]);\n\nexport type PingBody = v.Infer<typeof pingBodySchema>;\nexport type PingMessage = v.Infer<typeof pingMessageSchema>;\n", "import {jsonSchema} from '../../shared/src/json-schema.js';\nimport * as v from '../../shared/src/valita.js';\nimport {rowSchema} from './data.js';\nimport {primaryKeySchema, primaryKeyValueRecordSchema} from './primary-key.js';\n\nexport const CRUD_MUTATION_NAME = '_zero_crud';\n\nexport enum MutationType {\n CRUD = 'crud',\n Custom = 'custom',\n}\n\n/**\n * Inserts if entity with id does not already exist.\n */\nconst createOpSchema = v.object({\n op: v.literal('create'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n value: rowSchema,\n});\n\n/**\n * Upsert semantics. Inserts if entity with id does not already exist,\n * otherwise updates existing entity with id.\n */\nconst setOpSchema = v.object({\n op: v.literal('set'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n value: rowSchema,\n});\n\n/**\n * Updates if entity with id exists, otherwise does nothing.\n */\nconst updateOpSchema = v.object({\n op: v.literal('update'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n // Partial value with at least the primary key fields\n value: rowSchema,\n});\n\n/**\n * Deletes entity with id if it exists, otherwise does nothing.\n */\nconst deleteOpSchema = v.object({\n op: v.literal('delete'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n // Partial value representing the primary key\n value: primaryKeyValueRecordSchema,\n});\n\nconst crudOpSchema = v.union(\n createOpSchema,\n setOpSchema,\n updateOpSchema,\n deleteOpSchema,\n);\n\nconst crudArgSchema = v.object({\n ops: v.array(crudOpSchema),\n});\n\nconst crudArgsSchema = v.tuple([crudArgSchema]);\n\nexport const crudMutationSchema = v.object({\n type: v.literal(MutationType.CRUD),\n id: v.number(),\n clientID: v.string(),\n name: v.literal(CRUD_MUTATION_NAME),\n args: crudArgsSchema,\n timestamp: v.number(),\n});\n\nexport const customMutationSchema = v.object({\n type: v.literal(MutationType.Custom),\n id: v.number(),\n clientID: v.string(),\n name: v.string(),\n args: v.array(jsonSchema),\n timestamp: v.number(),\n});\n\nexport const mutationSchema = v.union(crudMutationSchema, customMutationSchema);\n\nexport const pushBodySchema = v.object({\n clientGroupID: v.string(),\n mutations: v.array(mutationSchema),\n pushVersion: v.number(),\n schemaVersion: v.number(),\n timestamp: v.number(),\n requestID: v.string(),\n});\n\nexport const pushMessageSchema = v.tuple([v.literal('push'), pushBodySchema]);\n\nexport type CreateOp = v.Infer<typeof createOpSchema>;\nexport type SetOp = v.Infer<typeof setOpSchema>;\nexport type UpdateOp = v.Infer<typeof updateOpSchema>;\nexport type DeleteOp = v.Infer<typeof deleteOpSchema>;\nexport type CRUDOp = v.Infer<typeof crudOpSchema>;\nexport type CRUDOpKind = CRUDOp['op'];\nexport type CRUDMutationArg = v.Infer<typeof crudArgSchema>;\nexport type CRUDMutation = v.Infer<typeof crudMutationSchema>;\nexport type CustomMutation = v.Infer<typeof customMutationSchema>;\nexport type Mutation = v.Infer<typeof mutationSchema>;\nexport type PushBody = v.Infer<typeof pushBodySchema>;\nexport type PushMessage = v.Infer<typeof pushMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\n\nconst deleteClientsBodySchema = v.object({\n clientIDs: v.array(v.string()),\n});\n\nexport const deleteClientsMessageSchema = v.tuple([\n v.literal('deleteClients'),\n deleteClientsBodySchema,\n]);\n\nexport type DeleteClientsBody = v.Infer<typeof deleteClientsBodySchema>;\nexport type DeleteClientsMessage = v.Infer<typeof deleteClientsMessageSchema>;\n", "import * as v from '../../shared/src/valita.js';\nimport {pingMessageSchema} from './ping.js';\nimport {deleteClientsMessageSchema} from './delete-clients.js';\nimport {initConnectionMessageSchema} from './connect.js';\nimport {pullRequestMessageSchema} from './pull.js';\nimport {pushMessageSchema} from './push.js';\nimport {changeDesiredQueriesMessageSchema} from './change-desired-queries.js';\n\nexport const upstreamSchema = v.union(\n initConnectionMessageSchema,\n pingMessageSchema,\n deleteClientsMessageSchema,\n changeDesiredQueriesMessageSchema,\n pullRequestMessageSchema,\n pushMessageSchema,\n);\n\nexport type Upstream = v.Infer<typeof upstreamSchema>;\n", "// This is taken from https://github.com/ai/nanoid/blob/main/index.browser.js We\n// copy this because we want to use `--platform=neutral` which doesn't work with\n// the npm package.\n// Also we changed the random number generator to use Math.random() for compat\n// with React Native.\n\nimport {getNonCryptoRandomValues} from '../../../shared/src/random-values.js';\n\nexport function nanoid(size = 21): string {\n // Use our custom getRandomValues function to fill a Uint8Array with random values.\n const randomBytes = getNonCryptoRandomValues(new Uint8Array(size));\n\n return randomBytes.reduce((id, byte) => {\n // It is incorrect to use bytes exceeding the alphabet size.\n // The following mask reduces the random byte in the 0-255 value\n // range to the 0-63 value range. Therefore, adding hacks, such\n // as empty string fallback or magic numbers, is unneccessary because\n // the bitmask trims bytes down to the alphabet size.\n byte &= 63;\n if (byte < 36) {\n // `0-9a-z`\n id += byte.toString(36);\n } else if (byte < 62) {\n // `A-Z`\n id += (byte - 26).toString(36).toUpperCase();\n } else if (byte > 62) {\n id += '-';\n } else {\n id += '_';\n }\n return id;\n }, '');\n}\n", "import type {Upstream} from '../../../zero-protocol/src/up.js';\n\nexport function send(ws: WebSocket, data: Upstream) {\n ws.send(JSON.stringify(data));\n}\n", "/* eslint-disable */\n// B+ tree by David Piepgrass. License: MIT\nimport type {ISortedMap, ISortedMapF, ISortedSet} from './interfaces.js';\n\nexport type {\n ISetSource,\n ISetSink,\n ISet,\n ISetF,\n ISortedSetSource,\n ISortedSet,\n ISortedSetF,\n IMapSource,\n IMapSink,\n IMap,\n IMapF,\n ISortedMapSource,\n ISortedMap,\n ISortedMapF,\n} from './interfaces.js';\n\nexport type EditRangeResult<V, R = number> = {\n value?: V;\n break?: R;\n delete?: boolean;\n};\n\ntype index = number;\n\n// Informative microbenchmarks & stuff:\n// http://www.jayconrod.com/posts/52/a-tour-of-v8-object-representation (very educational)\n// https://blog.mozilla.org/luke/2012/10/02/optimizing-javascript-variable-access/ (local vars are faster than properties)\n// http://benediktmeurer.de/2017/12/13/an-introduction-to-speculative-optimization-in-v8/ (other stuff)\n// https://jsperf.com/js-in-operator-vs-alternatives (avoid 'in' operator; `.p!==undefined` faster than `hasOwnProperty('p')` in all browsers)\n// https://jsperf.com/instanceof-vs-typeof-vs-constructor-vs-member (speed of type tests varies wildly across browsers)\n// https://jsperf.com/detecting-arrays-new (a.constructor===Array is best across browsers, assuming a is an object)\n// https://jsperf.com/shallow-cloning-methods (a constructor is faster than Object.create; hand-written clone faster than Object.assign)\n// https://jsperf.com/ways-to-fill-an-array (slice-and-replace is fastest)\n// https://jsperf.com/math-min-max-vs-ternary-vs-if (Math.min/max is slow on Edge)\n// https://jsperf.com/array-vs-property-access-speed (v.x/v.y is faster than a[0]/a[1] in major browsers IF hidden class is constant)\n// https://jsperf.com/detect-not-null-or-undefined (`x==null` slightly slower than `x===null||x===undefined` on all browsers)\n// Overall, microbenchmarks suggest Firefox is the fastest browser for JavaScript and Edge is the slowest.\n// Lessons from https://v8project.blogspot.com/2017/09/elements-kinds-in-v8.html:\n// - Avoid holes in arrays. Avoid `new Array(N)`, it will be \"holey\" permanently.\n// - Don't read outside bounds of an array (it scans prototype chain).\n// - Small integer arrays are stored differently from doubles\n// - Adding non-numbers to an array deoptimizes it permanently into a general array\n// - Objects can be used like arrays (e.g. have length property) but are slower\n// - V8 source (NewElementsCapacity in src/objects.h): arrays grow by 50% + 16 elements\n\n/**\n * Types that BTree supports by default\n */\nexport type DefaultComparable =\n | number\n | string\n | Date\n | boolean\n | null\n | undefined\n | (number | string)[]\n | {\n valueOf: () =>\n | number\n | string\n | Date\n | boolean\n | null\n | undefined\n | (number | string)[];\n };\n\n/**\n * Compares DefaultComparables to form a strict partial ordering.\n *\n * Handles +/-0 and NaN like Map: NaN is equal to NaN, and -0 is equal to +0.\n *\n * Arrays are compared using '<' and '>', which may cause unexpected equality:\n * for example [1] will be considered equal to ['1'].\n *\n * Two objects with equal valueOf compare the same, but compare unequal to\n * primitives that have the same value.\n */\nexport function defaultComparator(\n a: DefaultComparable,\n b: DefaultComparable,\n): number {\n // Special case finite numbers first for performance.\n // Note that the trick of using 'a - b' and checking for NaN to detect non-numbers\n // does not work if the strings are numeric (ex: \"5\"). This would leading most\n // comparison functions using that approach to fail to have transitivity.\n if (Number.isFinite(a as any) && Number.isFinite(b as any)) {\n return (a as number) - (b as number);\n }\n\n // The default < and > operators are not totally ordered. To allow types to be mixed\n // in a single collection, compare types and order values of different types by type.\n let ta = typeof a;\n let tb = typeof b;\n if (ta !== tb) {\n return ta < tb ? -1 : 1;\n }\n\n if (ta === 'object') {\n // standardized JavaScript bug: null is not an object, but typeof says it is\n if (a === null) return b === null ? 0 : -1;\n else if (b === null) return 1;\n\n a = a!.valueOf() as DefaultComparable;\n b = b!.valueOf() as DefaultComparable;\n ta = typeof a;\n tb = typeof b;\n // Deal with the two valueOf()s producing different types\n if (ta !== tb) {\n return ta < tb ? -1 : 1;\n }\n }\n\n // a and b are now the same type, and will be a number, string or array\n // (which we assume holds numbers or strings), or something unsupported.\n if (a! < b!) return -1;\n if (a! > b!) return 1;\n if (a === b) return 0;\n\n // Order NaN less than other numbers\n if (Number.isNaN(a as any)) return Number.isNaN(b as any) ? 0 : -1;\n else if (Number.isNaN(b as any)) return 1;\n // This could be two objects (e.g. [7] and ['7']) that aren't ordered\n return Array.isArray(a) ? 0 : Number.NaN;\n}\n\n/**\n * Compares items using the < and > operators. This function is probably slightly\n * faster than the defaultComparator for Dates and strings, but has not been benchmarked.\n * Unlike defaultComparator, this comparator doesn't support mixed types correctly,\n * i.e. use it with `BTree<string>` or `BTree<number>` but not `BTree<string|number>`.\n *\n * NaN is not supported.\n *\n * Note: null is treated like 0 when compared with numbers or Date, but in general\n * null is not ordered with respect to strings (neither greater nor less), and\n * undefined is not ordered with other types.\n */\nexport function simpleComparator(a: string, b: string): number;\nexport function simpleComparator(a: number | null, b: number | null): number;\nexport function simpleComparator(a: Date | null, b: Date | null): number;\nexport function simpleComparator(\n a: (number | string)[],\n b: (number | string)[],\n): number;\nexport function simpleComparator(a: any, b: any): number {\n return a > b ? 1 : a < b ? -1 : 0;\n}\n\n/**\n * A reasonably fast collection of key-value pairs with a powerful API.\n * Largely compatible with the standard Map. BTree is a B+ tree data structure,\n * so the collection is sorted by key.\n *\n * B+ trees tend to use memory more efficiently than hashtables such as the\n * standard Map, especially when the collection contains a large number of\n * items. However, maintaining the sort order makes them modestly slower:\n * O(log size) rather than O(1). This B+ tree implementation supports O(1)\n * fast cloning. It also supports freeze(), which can be used to ensure that\n * a BTree is not changed accidentally.\n *\n * Confusingly, the ES6 Map.forEach(c) method calls c(value,key) instead of\n * c(key,value), in contrast to other methods such as set() and entries()\n * which put the key first. I can only assume that the order was reversed on\n * the theory that users would usually want to examine values and ignore keys.\n * BTree's forEach() therefore works the same way, but a second method\n * `.forEachPair((key,value)=>{...})` is provided which sends you the key\n * first and the value second; this method is slightly faster because it is\n * the \"native\" for-each method for this class.\n *\n * Out of the box, BTree supports keys that are numbers, strings, arrays of\n * numbers/strings, Date, and objects that have a valueOf() method returning a\n * number or string. Other data types, such as arrays of Date or custom\n * objects, require a custom comparator, which you must pass as the second\n * argument to the constructor (the first argument is an optional list of\n * initial items). Symbols cannot be used as keys because they are unordered\n * (one Symbol is never \"greater\" or \"less\" than another).\n *\n * @example\n * Given a {name: string, age: number} object, you can create a tree sorted by\n * name and then by age like this:\n *\n * var tree = new BTree(undefined, (a, b) => {\n * if (a.name > b.name)\n * return 1; // Return a number >0 when a > b\n * else if (a.name < b.name)\n * return -1; // Return a number <0 when a < b\n * else // names are equal (or incomparable)\n * return a.age - b.age; // Return >0 when a.age > b.age\n * });\n *\n * tree.set({name:\"Bill\", age:17}, \"happy\");\n * tree.set({name:\"Fran\", age:40}, \"busy & stressed\");\n * tree.set({name:\"Bill\", age:55}, \"recently laid off\");\n * tree.forEachPair((k, v) => {\n * console.log(`Name: ${k.name} Age: ${k.age} Status: ${v}`);\n * });\n *\n * @description\n * The \"range\" methods (`forEach, forRange, editRange`) will return the number\n * of elements that were scanned. In addition, the callback can return {break:R}\n * to stop early and return R from the outer function.\n *\n * - TODO: Test performance of preallocating values array at max size\n * - TODO: Add fast initialization when a sorted array is provided to constructor\n *\n * For more documentation see https://github.com/qwertie/btree-typescript\n *\n * Are you a C# developer? You might like the similar data structures I made for C#:\n * BDictionary, BList, etc. See http://core.loyc.net/collections/\n *\n * @author David Piepgrass\n */\nexport default class BTree<K = any, V = any>\n implements ISortedMapF<K, V>, ISortedMap<K, V>\n{\n private _root: BNode<K, V> = EmptyLeaf as BNode<K, V>;\n _size: number = 0;\n _maxNodeSize: number;\n\n /**\n * provides a total order over keys (and a strict partial order over the type K)\n * @returns a negative value if a < b, 0 if a === b and a positive value if a > b\n */\n _compare: (a: K, b: K) => number;\n\n /**\n * Initializes an empty B+ tree.\n * @param compare Custom function to compare pairs of elements in the tree.\n * If not specified, defaultComparator will be used which is valid as long as K extends DefaultComparable.\n * @param entries A set of key-value pairs to initialize the tree\n * @param maxNodeSize Branching factor (maximum items or children per node)\n * Must be in range 4..256. If undefined or <4 then default is used; if >256 then 256.\n */\n public constructor(\n entries?: [K, V][],\n compare?: (a: K, b: K) => number,\n maxNodeSize?: number,\n ) {\n this._maxNodeSize = maxNodeSize! >= 4 ? Math.min(maxNodeSize!, 256) : 32;\n this._compare =\n compare || (defaultComparator as any as (a: K, b: K) => number);\n if (entries) this.setPairs(entries);\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // ES6 Map<K,V> methods /////////////////////////////////////////////////////\n\n /** Gets the number of key-value pairs in the tree. */\n get size() {\n return this._size;\n }\n /** Gets the number of key-value pairs in the tree. */\n get length() {\n return this._size;\n }\n /** Returns true iff the tree contains no key-value pairs. */\n get isEmpty() {\n return this._size === 0;\n }\n\n /** Releases the tree so that its size is 0. */\n clear() {\n this._root = EmptyLeaf as BNode<K, V>;\n this._size = 0;\n }\n\n forEach(\n callback: (v: V, k: K, tree: BTree<K, V>) => void,\n thisArg?: any,\n ): number;\n\n /** Runs a function for each key-value pair, in order from smallest to\n * largest key. For compatibility with ES6 Map, the argument order to\n * the callback is backwards: value first, then key. Call forEachPair\n * instead to receive the key as the first argument.\n * @param thisArg If provided, this parameter is assigned as the `this`\n * value for each callback.\n * @returns the number of values that were sent to the callback,\n * or the R value if the callback returned {break:R}. */\n forEach<R = number>(\n callback: (v: V, k: K, tree: BTree<K, V>) => {break?: R} | void,\n thisArg?: any,\n ): R | number {\n if (thisArg !== undefined) callback = callback.bind(thisArg);\n return this.forEachPair((k, v) => callback(v, k, this));\n }\n\n /** Runs a function for each key-value pair, in order from smallest to\n * largest key. The callback can return {break:R} (where R is any value\n * except undefined) to stop immediately and return R from forEachPair.\n * @param onFound A function that is called for each key-value pair. This\n * function can return {break:R} to stop early with result R.\n * The reason that you must return {break:R} instead of simply R\n * itself is for consistency with editRange(), which allows\n * multiple actions, not just breaking.\n * @param initialCounter This is the value of the third argument of\n * `onFound` the first time it is called. The counter increases\n * by one each time `onFound` is called. Default value: 0\n * @returns the number of pairs sent to the callback (plus initialCounter,\n * if you provided one). If the callback returned {break:R} then\n * the R value is returned instead. */\n forEachPair<R = number>(\n callback: (k: K, v: V, counter: number) => {break?: R} | void,\n initialCounter?: number,\n ): R | number {\n var low = this.minKey(),\n high = this.maxKey();\n return this.forRange(low!, high!, true, callback, initialCounter);\n }\n\n /**\n * Finds a pair in the tree and returns the associated value.\n * @param defaultValue a value to return if the key was not found.\n * @returns the value, or defaultValue if the key was not found.\n * @description Computational complexity: O(log size)\n */\n get(key: K, defaultValue?: V): V | undefined {\n return this._root.get(key, defaultValue, this);\n }\n\n /**\n * Adds or overwrites a key-value pair in the B+ tree.\n * @param key the key is used to determine the sort order of\n * data in the tree.\n * @param value data to associate with the key (optional)\n * @param overwrite Whether to overwrite an existing key-value pair\n * (default: true). If this is false and there is an existing\n * key-value pair then this method has no effect.\n * @returns true if a new key-value pair was added.\n * @description Computational complexity: O(log size)\n * Note: when overwriting a previous entry, the key is updated\n * as well as the value. This has no effect unless the new key\n * has data that does not affect its sort order.\n */\n set(key: K, value: V, overwrite?: boolean): boolean {\n if (this._root.isShared) this._root = this._root.clone();\n var result = this._root.set(key, value, overwrite, this);\n if (result === true || result === false) return result;\n // Root node has split, so create a new root node.\n this._root = new BNodeInternal<K, V>([this._root, result]);\n return true;\n }\n\n /**\n * Returns true if the key exists in the B+ tree, false if not.\n * Use get() for best performance; use has() if you need to\n * distinguish between \"undefined value\" and \"key not present\".\n * @param key Key to detect\n * @description Computational complexity: O(log size)\n */\n has(key: K): boolean {\n return this.forRange(key, key, true, undefined) !== 0;\n }\n\n /**\n * Removes a single key-value pair from the B+ tree.\n * @param key Key to find\n * @returns true if a pair was found and removed, false otherwise.\n * @description Computational complexity: O(log size)\n */\n delete(key: K): boolean {\n return this.editRange(key, key, true, DeleteRange) !== 0;\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Clone-mutators ///////////////////////////////////////////////////////////\n\n /** Returns a copy of the tree with the specified key set (the value is undefined). */\n with(key: K): BTree<K, V | undefined>;\n /** Returns a copy of the tree with the specified key-value pair set. */\n with<V2>(key: K, value: V2, overwrite?: boolean): BTree<K, V | V2>;\n with<V2>(\n key: K,\n value?: V2,\n overwrite?: boolean,\n ): BTree<K, V | V2 | undefined> {\n let nu = this.clone() as BTree<K, V | V2 | undefined>;\n return nu.set(key, value, overwrite) || overwrite ? nu : this;\n }\n\n /** Returns a copy of the tree with the specified key-value pairs set. */\n withPairs<V2>(pairs: [K, V | V2][], overwrite: boolean): BTree<K, V | V2> {\n let nu = this.clone() as BTree<K, V | V2>;\n return nu.setPairs(pairs, overwrite) !== 0 || overwrite ? nu : this;\n }\n\n /** Returns a copy of the tree with the specified keys present.\n * @param keys The keys to add. If a key is already present in the tree,\n * neither the existing key nor the existing value is modified.\n * @param returnThisIfUnchanged if true, returns this if all keys already\n * existed. Performance note: due to the architecture of this class, all\n * node(s) leading to existing keys are cloned even if the collection is\n * ultimately unchanged.\n */\n withKeys(\n keys: K[],\n returnThisIfUnchanged?: boolean,\n ): BTree<K, V | undefined> {\n let nu = this.clone() as BTree<K, V | undefined>,\n changed = false;\n for (var i = 0; i < keys.length; i++)\n changed = nu.set(keys[i], undefined, false) || changed;\n return returnThisIfUnchanged && !changed ? this : nu;\n }\n\n /** Returns a copy of the tree with the specified key removed.\n * @param returnThisIfUnchanged if true, returns this if the key didn't exist.\n * Performance note: due to the architecture of this class, node(s) leading\n * to where the key would have been stored are cloned even when the key\n * turns out not to exist and the collection is unchanged.\n */\n without(key: K, returnThisIfUnchanged?: boolean): BTree<K, V> {\n return this.withoutRange(key, key, true, returnThisIfUnchanged);\n }\n\n /** Returns a copy of the tree with the specified keys removed.\n * @param returnThisIfUnchanged if true, returns this if none of the keys\n * existed. Performance note: due to the architecture of this class,\n * node(s) leading to where the key would have been stored are cloned\n * even when the key turns out not to exist.\n */\n withoutKeys(keys: K[], returnThisIfUnchanged?: boolean): BTree<K, V> {\n let nu = this.clone();\n return nu.deleteKeys(keys) || !returnThisIfUnchanged ? nu : this;\n }\n\n /** Returns a copy of the tree with the specified range of keys removed. */\n withoutRange(\n low: K,\n high: K,\n includeHigh: boolean,\n returnThisIfUnchanged?: boolean,\n ): BTree<K, V> {\n let nu = this.clone();\n if (nu.deleteRange(low, high, includeHigh) === 0 && returnThisIfUnchanged)\n return this;\n return nu;\n }\n\n /** Returns a copy of the tree with pairs removed whenever the callback\n * function returns false. `where()` is a synonym for this method. */\n filter(\n callback: (k: K, v: V, counter: number) => boolean,\n returnThisIfUnchanged?: boolean,\n ): BTree<K, V> {\n var nu = this.greedyClone();\n var del: any;\n nu.editAll((k, v, i) => {\n if (!callback(k, v, i)) return (del = Delete);\n return undefined;\n });\n if (!del && returnThisIfUnchanged) return this;\n return nu;\n }\n\n /** Returns a copy of the tree with all values altered by a callback function. */\n mapValues<R>(callback: (v: V, k: K, counter: number) => R): BTree<K, R> {\n var tmp = {} as {value: R};\n var nu = this.greedyClone();\n nu.editAll((k, v, i) => {\n return (tmp.value = callback(v, k, i)), tmp as any;\n });\n return nu as any as BTree<K, R>;\n }\n\n /** Performs a reduce operation like the `reduce` method of `Array`.\n * It is used to combine all pairs into a single value, or perform\n * conversions. `reduce` is best understood by example. For example,\n * `tree.reduce((P, pair) => P * pair[0], 1)` multiplies all keys\n * together. It means \"start with P=1, and for each pair multiply\n * it by the key in pair[0]\". Another example would be converting\n * the tree to a Map (in this example, note that M.set returns M):\n *\n * var M = tree.reduce((M, pair) => M.set(pair[0],pair[1]), new Map())\n *\n * **Note**: the same array is sent to the callback on every iteration.\n */\n reduce<R>(\n callback: (\n previous: R,\n currentPair: [K, V],\n counter: number,\n tree: BTree<K, V>,\n ) => R,\n initialValue: R,\n ): R;\n reduce<R>(\n callback: (\n previous: R | undefined,\n currentPair: [K, V],\n counter: number,\n tree: BTree<K, V>,\n ) => R,\n ): R | undefined;\n reduce<R>(\n callback: (\n previous: R | undefined,\n currentPair: [K, V],\n counter: number,\n tree: BTree<K, V>,\n ) => R,\n initialValue?: R,\n ): R | undefined {\n let i = 0,\n p = initialValue;\n var it = this.entries(this.minKey(), ReusedArray),\n next;\n while (!(next = it.next()).done) p = callback(p, next.value, i++, this);\n return p;\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Iterator methods /////////////////////////////////////////////////////////\n\n /** Returns an iterator that provides items in order (ascending order if\n * the collection's comparator uses ascending order, as is the default.)\n * @param lowestKey First key to be iterated, or undefined to start at\n * minKey(). If the specified key doesn't exist then iteration\n * starts at the next higher key (according to the comparator).\n * @param reusedArray Optional array used repeatedly to store key-value\n * pairs, to avoid creating a new array on every iteration.\n */\n entries(lowestKey?: K, reusedArray?: (K | V)[]): IterableIterator<[K, V]> {\n var info = this.findPath(lowestKey);\n if (info === undefined) return iterator<[K, V]>();\n var {nodequeue, nodeindex, leaf} = info;\n var state = reusedArray !== undefined ? 1 : 0;\n var i =\n lowestKey === undefined\n ? -1\n : leaf.indexOf(lowestKey, 0, this._compare) - 1;\n\n return iterator<[K, V]>(() => {\n jump: for (;;) {\n switch (state) {\n case 0:\n if (++i < leaf.keys.length)\n return {done: false, value: [leaf.keys[i], leaf.values[i]]};\n state = 2;\n continue;\n // @ts-ignore\n case 1:\n if (++i < leaf.keys.length) {\n (reusedArray![0] = leaf.keys[i]),\n (reusedArray![1] = leaf.values[i]);\n return {done: false, value: reusedArray as [K, V]};\n }\n state = 2;\n case 2:\n // Advance to the next leaf node\n for (var level = -1; ; ) {\n if (++level >= nodequeue.length) {\n state = 3;\n continue jump;\n }\n if (++nodeindex[level] < nodequeue[level].length) break;\n }\n for (; level > 0; level--) {\n nodequeue[level - 1] = (\n nodequeue[level][nodeindex[level]] as BNodeInternal<K, V>\n ).children;\n nodeindex[level - 1] = 0;\n }\n leaf = nodequeue[0][nodeindex[0]];\n i = -1;\n state = reusedArray !== undefined ? 1 : 0;\n continue;\n case 3:\n return {done: true, value: undefined};\n }\n }\n });\n }\n\n /** Returns an iterator that provides items in reversed order.\n * @param highestKey Key at which to start iterating, or undefined to\n * start at maxKey(). If the specified key doesn't exist then iteration\n * starts at the next lower key (according to the comparator).\n * @param reusedArray Optional array used repeatedly to store key-value\n * pairs, to avoid creating a new array on every iteration.\n * @param skipHighest Iff this flag is true and the highestKey exists in the\n * collection, the pair matching highestKey is skipped, not iterated.\n */\n entriesReversed(\n highestKey?: K,\n reusedArray?: (K | V)[],\n skipHighest?: boolean,\n ): IterableIterator<[K, V]> {\n if (highestKey === undefined) {\n highestKey = this.maxKey();\n skipHighest = undefined;\n if (highestKey === undefined) return iterator<[K, V]>(); // collection is empty\n }\n var {nodequeue, nodeindex, leaf} =\n this.findPath(highestKey) || this.findPath(this.maxKey())!;\n check(!nodequeue[0] || leaf === nodequeue[0][nodeindex[0]], 'wat!');\n var i = leaf.indexOf(highestKey, 0, this._compare);\n if (\n !skipHighest &&\n i < leaf.keys.length &&\n this._compare(leaf.keys[i], highestKey) <= 0\n )\n i++;\n var state = reusedArray !== undefined ? 1 : 0;\n\n return iterator<[K, V]>(() => {\n jump: for (;;) {\n switch (state) {\n case 0:\n if (--i >= 0)\n return {done: false, value: [leaf.keys[i], leaf.values[i]]};\n state = 2;\n continue;\n // @ts-ignore\n case 1:\n if (--i >= 0) {\n (reusedArray![0] = leaf.keys[i]),\n (reusedArray![1] = leaf.values[i]);\n return {done: false, value: reusedArray as [K, V]};\n }\n state = 2;\n case 2:\n // Advance to the next leaf node\n for (var level = -1; ; ) {\n if (++level >= nodequeue.length) {\n state = 3;\n continue jump;\n }\n if (--nodeindex[level] >= 0) break;\n }\n for (; level > 0; level--) {\n nodequeue[level - 1] = (\n nodequeue[level][nodeindex[level]] as BNodeInternal<K, V>\n ).children;\n nodeindex[level - 1] = nodequeue[level - 1].length - 1;\n }\n leaf = nodequeue[0][nodeindex[0]];\n i = leaf.keys.length;\n state = reusedArray !== undefined ? 1 : 0;\n continue;\n case 3:\n return {done: true, value: undefined};\n }\n }\n });\n }\n\n /* Used by entries() and entriesReversed() to prepare to start iterating.\n * It develops a \"node queue\" for each non-leaf level of the tree.\n * Levels are numbered \"bottom-up\" so that level 0 is a list of leaf\n * nodes from a low-level non-leaf node. The queue at a given level L\n * consists of nodequeue[L] which is the children of a BNodeInternal,\n * and nodeindex[L], the current index within that child list, such\n * such that nodequeue[L-1] === nodequeue[L][nodeindex[L]].children.\n * (However inside this function the order is reversed.)\n */\n private findPath(\n key?: K,\n ):\n | {nodequeue: BNode<K, V>[][]; nodeindex: number[]; leaf: BNode<K, V>}\n | undefined {\n var nextnode = this._root;\n var nodequeue: BNode<K, V>[][], nodeindex: number[];\n\n if (nextnode.isLeaf) {\n (nodequeue = EmptyArray), (nodeindex = EmptyArray); // avoid allocations\n } else {\n (nodequeue = []), (nodeindex = []);\n for (var d = 0; !nextnode.isLeaf; d++) {\n nodequeue[d] = (nextnode as BNodeInternal<K, V>).children;\n nodeindex[d] =\n key === undefined ? 0 : nextnode.indexOf(key, 0, this._compare);\n if (nodeindex[d] >= nodequeue[d].length) return; // first key > maxKey()\n nextnode = nodequeue[d][nodeindex[d]];\n }\n nodequeue.reverse();\n nodeindex.reverse();\n }\n return {nodequeue, nodeindex, leaf: nextnode};\n }\n\n /**\n * Computes the differences between `this` and `other`.\n * For efficiency, the diff is returned via invocations of supplied handlers.\n * The computation is optimized for the case in which the two trees have large amounts\n * of shared data (obtained by calling the `clone` or `with` APIs) and will avoid\n * any iteration of shared state.\n * The handlers can cause computation to early exit by returning {break: R}.\n * Neither of the collections should be changed during the comparison process (in your callbacks), as this method assumes they will not be mutated.\n * @param other The tree to compute a diff against.\n * @param onlyThis Callback invoked for all keys only present in `this`.\n * @param onlyOther Callback invoked for all keys only present in `other`.\n * @param different Callback invoked for all keys with differing values.\n */\n diffAgainst<R>(\n other: BTree<K, V>,\n onlyThis?: (k: K, v: V) => {break?: R} | void,\n onlyOther?: (k: K, v: V) => {break?: R} | void,\n different?: (k: K, vThis: V, vOther: V) => {break?: R} | void,\n ): R | undefined {\n if (other._compare !== this._compare) {\n throw new Error('Tree comparators are not the same.');\n }\n\n if (this.isEmpty || other.isEmpty) {\n if (this.isEmpty && other.isEmpty) return undefined;\n // If one tree is empty, everything will be an onlyThis/onlyOther.\n if (this.isEmpty)\n return onlyOther === undefined\n ? undefined\n : BTree.stepToEnd(BTree.makeDiffCursor(other), onlyOther);\n return onlyThis === undefined\n ? undefined\n : BTree.stepToEnd(BTree.makeDiffCursor(this), onlyThis);\n }\n\n // Cursor-based diff algorithm is as follows:\n // - Until neither cursor has navigated to the end of the tree, do the following:\n // - If the `this` cursor is \"behind\" the `other` cursor (strictly <, via compare), advance it.\n // - Otherwise, advance the `other` cursor.\n // - Any time a cursor is stepped, perform the following:\n // - If either cursor points to a key/value pair:\n // - If thisCursor === otherCursor and the values differ, it is a Different.\n // - If thisCursor > otherCursor and otherCursor is at a key/value pair, it is an OnlyOther.\n // - If thisCursor < otherCursor and thisCursor is at a key/value pair, it is an OnlyThis as long as the most recent\n // cursor step was *not* otherCursor advancing from a tie. The extra condition avoids erroneous OnlyOther calls\n // that would occur due to otherCursor being the \"leader\".\n // - Otherwise, if both cursors point to nodes, compare them. If they are equal by reference (shared), skip\n // both cursors to the next node in the walk.\n // - Once one cursor has finished stepping, any remaining steps (if any) are taken and key/value pairs are logged\n // as OnlyOther (if otherCursor is stepping) or OnlyThis (if thisCursor is stepping).\n // This algorithm gives the critical guarantee that all locations (both nodes and key/value pairs) in both trees that\n // are identical by value (and possibly by reference) will be visited *at the same time* by the cursors.\n // This removes the possibility of emitting incorrect diffs, as well as allowing for skipping shared nodes.\n const {_compare} = this;\n const thisCursor = BTree.makeDiffCursor(this);\n const otherCursor = BTree.makeDiffCursor(other);\n // It doesn't matter how thisSteppedLast is initialized.\n // Step order is only used when either cursor is at a leaf, and cursors always start at a node.\n let thisSuccess = true,\n otherSuccess = true,\n prevCursorOrder = BTree.compare(thisCursor, otherCursor, _compare);\n while (thisSuccess && otherSuccess) {\n const cursorOrder = BTree.compare(thisCursor, otherCursor, _compare);\n const {\n leaf: thisLeaf,\n internalSpine: thisInternalSpine,\n levelIndices: thisLevelIndices,\n } = thisCursor;\n const {\n leaf: otherLeaf,\n internalSpine: otherInternalSpine,\n levelIndices: otherLevelIndices,\n } = otherCursor;\n if (thisLeaf || otherLeaf) {\n // If the cursors were at the same location last step, then there is no work to be done.\n if (prevCursorOrder !== 0) {\n if (cursorOrder === 0) {\n if (thisLeaf && otherLeaf && different) {\n // Equal keys, check for modifications\n const valThis =\n thisLeaf.values[thisLevelIndices[thisLevelIndices.length - 1]];\n const valOther =\n otherLeaf.values[\n otherLevelIndices[otherLevelIndices.length - 1]\n ];\n if (!Object.is(valThis, valOther)) {\n const result = different(\n thisCursor.currentKey,\n valThis,\n valOther,\n );\n if (result && result.break) return result.break;\n }\n }\n } else if (cursorOrder > 0) {\n // If this is the case, we know that either:\n // 1. otherCursor stepped last from a starting position that trailed thisCursor, and is still behind, or\n // 2. thisCursor stepped last and leapfrogged otherCursor\n // Either of these cases is an \"only other\"\n if (otherLeaf && onlyOther) {\n const otherVal =\n otherLeaf.values[\n otherLevelIndices[otherLevelIndices.length - 1]\n ];\n const result = onlyOther(otherCursor.currentKey, otherVal);\n if (result && result.break) return result.break;\n }\n } else if (onlyThis) {\n if (thisLeaf && prevCursorOrder !== 0) {\n const valThis =\n thisLeaf.values[thisLevelIndices[thisLevelIndices.length - 1]];\n const result = onlyThis(thisCursor.currentKey, valThis);\n if (result && result.break) return result.break;\n }\n }\n }\n } else if (!thisLeaf && !otherLeaf && cursorOrder === 0) {\n const lastThis = thisInternalSpine.length - 1;\n const lastOther = otherInternalSpine.length - 1;\n const nodeThis =\n thisInternalSpine[lastThis][thisLevelIndices[lastThis]];\n const nodeOther =\n otherInternalSpine[lastOther][otherLevelIndices[lastOther]];\n if (nodeOther === nodeThis) {\n prevCursorOrder = 0;\n thisSuccess = BTree.step(thisCursor, true);\n otherSuccess = BTree.step(otherCursor, true);\n continue;\n }\n }\n prevCursorOrder = cursorOrder;\n if (cursorOrder < 0) {\n thisSuccess = BTree.step(thisCursor);\n } else {\n otherSuccess = BTree.step(otherCursor);\n }\n }\n\n if (thisSuccess && onlyThis)\n return BTree.finishCursorWalk(\n thisCursor,\n otherCursor,\n _compare,\n onlyThis,\n );\n if (otherSuccess && onlyOther)\n return BTree.finishCursorWalk(\n otherCursor,\n thisCursor,\n _compare,\n onlyOther,\n );\n\n return undefined;\n }\n\n ///////////////////////////////////////////////////////////////////////////\n // Helper methods for diffAgainst /////////////////////////////////////////\n\n private static finishCursorWalk<K, V, R>(\n cursor: DiffCursor<K, V>,\n cursorFinished: DiffCursor<K, V>,\n compareKeys: (a: K, b: K) => number,\n callback: (k: K, v: V) => {break?: R} | void,\n ): R | undefined {\n const compared = BTree.compare(cursor, cursorFinished, compareKeys);\n if (compared === 0) {\n if (!BTree.step(cursor)) return undefined;\n } else if (compared < 0) {\n check(false, 'cursor walk terminated early');\n }\n return BTree.stepToEnd(cursor, callback);\n }\n\n private static stepToEnd<K, V, R>(\n cursor: DiffCursor<K, V>,\n callback: (k: K, v: V) => {break?: R} | void,\n ): R | undefined {\n let canStep: boolean = true;\n while (canStep) {\n const {leaf, levelIndices, currentKey} = cursor;\n if (leaf) {\n const value = leaf.values[levelIndices[levelIndices.length - 1]];\n const result = callback(currentKey, value);\n if (result && result.break) return result.break;\n }\n canStep = BTree.step(cursor);\n }\n return undefined;\n }\n\n private static makeDiffCursor<K, V>(tree: BTree<K, V>): DiffCursor<K, V> {\n const {_root, height} = tree;\n return {\n height: height,\n internalSpine: [[_root]],\n levelIndices: [0],\n leaf: undefined,\n currentKey: _root.maxKey(),\n };\n }\n\n /**\n * Advances the cursor to the next step in the walk of its tree.\n * Cursors are walked backwards in sort order, as this allows them to leverage maxKey() in order to be compared in O(1).\n * @param cursor The cursor to step\n * @param stepToNode If true, the cursor will be advanced to the next node (skipping values)\n * @returns true if the step was completed and false if the step would have caused the cursor to move beyond the end of the tree.\n */\n private static step<K, V>(\n cursor: DiffCursor<K, V>,\n stepToNode?: boolean,\n ): boolean {\n const {internalSpine, levelIndices, leaf} = cursor;\n if (stepToNode === true || leaf) {\n const levelsLength = levelIndices.length;\n // Step to the next node only if:\n // - We are explicitly directed to via stepToNode, or\n // - There are no key/value pairs left to step to in this leaf\n if (stepToNode === true || levelIndices[levelsLength - 1] === 0) {\n const spineLength = internalSpine.length;\n // Root is leaf\n if (spineLength === 0) return false;\n // Walk back up the tree until we find a new subtree to descend into\n const nodeLevelIndex = spineLength - 1;\n let levelIndexWalkBack = nodeLevelIndex;\n while (levelIndexWalkBack >= 0) {\n if (levelIndices[levelIndexWalkBack] > 0) {\n if (levelIndexWalkBack < levelsLength - 1) {\n // Remove leaf state from cursor\n cursor.leaf = undefined;\n levelIndices.pop();\n }\n // If we walked upwards past any internal node, slice them out\n if (levelIndexWalkBack < nodeLevelIndex)\n cursor.internalSpine = internalSpine.slice(\n 0,\n levelIndexWalkBack + 1,\n );\n // Move to new internal node\n cursor.currentKey =\n internalSpine[levelIndexWalkBack][\n --levelIndices[levelIndexWalkBack]\n ].maxKey();\n return true;\n }\n levelIndexWalkBack--;\n }\n // Cursor is in the far left leaf of the tree, no more nodes to enumerate\n return false;\n } else {\n // Move to new leaf value\n const valueIndex = --levelIndices[levelsLength - 1];\n cursor.currentKey = (leaf as unknown as BNode<K, V>).keys[valueIndex];\n return true;\n }\n } else {\n // Cursor does not point to a value in a leaf, so move downwards\n const nextLevel = internalSpine.length;\n const currentLevel = nextLevel - 1;\n const node = internalSpine[currentLevel][levelIndices[currentLevel]];\n if (node.isLeaf) {\n // Entering into a leaf. Set the cursor to point at the last key/value pair.\n cursor.leaf = node;\n const valueIndex = (levelIndices[nextLevel] = node.values.length - 1);\n cursor.currentKey = node.keys[valueIndex];\n } else {\n const children = (node as BNodeInternal<K, V>).children;\n internalSpine[nextLevel] = children;\n const childIndex = children.length - 1;\n levelIndices[nextLevel] = childIndex;\n cursor.currentKey = children[childIndex].maxKey();\n }\n return true;\n }\n }\n\n /**\n * Compares the two cursors. Returns a value indicating which cursor is ahead in a walk.\n * Note that cursors are advanced in reverse sorting order.\n */\n private static compare<K, V>(\n cursorA: DiffCursor<K, V>,\n cursorB: DiffCursor<K, V>,\n compareKeys: (a: K, b: K) => number,\n ): number {\n const {\n height: heightA,\n currentKey: currentKeyA,\n levelIndices: levelIndicesA,\n } = cursorA;\n const {\n height: heightB,\n currentKey: currentKeyB,\n levelIndices: levelIndicesB,\n } = cursorB;\n // Reverse the comparison order, as cursors are advanced in reverse sorting order\n const keyComparison = compareKeys(currentKeyB, currentKeyA);\n if (keyComparison !== 0) {\n return keyComparison;\n }\n\n // Normalize depth values relative to the shortest tree.\n // This ensures that concurrent cursor walks of trees of differing heights can reliably land on shared nodes at the same time.\n // To accomplish this, a cursor that is on an internal node at depth D1 with maxKey X is considered \"behind\" a cursor on an\n // internal node at depth D2 with maxKey Y, when D1 < D2. Thus, always walking the cursor that is \"behind\" will allow the cursor\n // at shallower depth (but equal maxKey) to \"catch up\" and land on shared nodes.\n const heightMin = heightA < heightB ? heightA : heightB;\n const depthANormalized = levelIndicesA.length - (heightA - heightMin);\n const depthBNormalized = levelIndicesB.length - (heightB - heightMin);\n return depthANormalized - depthBNormalized;\n }\n\n // End of helper methods for diffAgainst //////////////////////////////////\n ///////////////////////////////////////////////////////////////////////////\n\n /** Returns a new iterator for iterating the keys of each pair in ascending order.\n * @param firstKey: Minimum key to include in the output. */\n keys(firstKey?: K): IterableIterator<K> {\n var it = this.entries(firstKey, ReusedArray);\n return iterator<K>(() => {\n var n: IteratorResult<any> = it.next();\n if (n.value) n.value = n.value[0];\n return n;\n });\n }\n\n /** Returns a new iterator for iterating the values of each pair in order by key.\n * @param firstKey: Minimum key whose associated value is included in the output. */\n values(firstKey?: K): IterableIterator<V> {\n var it = this.entries(firstKey, ReusedArray);\n return iterator<V>(() => {\n var n: IteratorResult<any> = it.next();\n if (n.value) n.value = n.value[1];\n return n;\n });\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Additional methods ///////////////////////////////////////////////////////\n\n /** Returns the maximum number of children/values before nodes will split. */\n get maxNodeSize() {\n return this._maxNodeSize;\n }\n\n /** Gets the lowest key in the tree. Complexity: O(log size) */\n minKey(): K | undefined {\n return this._root.minKey();\n }\n\n /** Gets the highest key in the tree. Complexity: O(1) */\n maxKey(): K | undefined {\n return this._root.maxKey();\n }\n\n /** Quickly clones the tree by marking the root node as shared.\n * Both copies remain editable. When you modify either copy, any\n * nodes that are shared (or potentially shared) between the two\n * copies are cloned so that the changes do not affect other copies.\n * This is known as copy-on-write behavior, or \"lazy copying\". */\n clone(): BTree<K, V> {\n this._root.isShared = true;\n var result = new BTree<K, V>(undefined, this._compare, this._maxNodeSize);\n result._root = this._root;\n result._size = this._size;\n return result;\n }\n\n /** Performs a greedy clone, immediately duplicating any nodes that are\n * not currently marked as shared, in order to avoid marking any\n * additional nodes as shared.\n * @param force Clone all nodes, even shared ones.\n */\n greedyClone(force?: boolean): BTree<K, V> {\n var result = new BTree<K, V>(undefined, this._compare, this._maxNodeSize);\n result._root = this._root.greedyClone(force);\n result._size = this._size;\n return result;\n }\n\n /** Gets an array filled with the contents of the tree, sorted by key */\n toArray(maxLength: number = 0x7fffffff): [K, V][] {\n let min = this.minKey(),\n max = this.maxKey();\n if (min !== undefined) return this.getRange(min, max!, true, maxLength);\n return [];\n }\n\n /** Gets an array of all keys, sorted */\n keysArray() {\n var results: K[] = [];\n this._root.forRange(\n this.minKey()!,\n this.maxKey()!,\n true,\n false,\n this,\n 0,\n (k, _v) => {\n results.push(k);\n },\n );\n return results;\n }\n\n /** Gets an array of all values, sorted by key */\n valuesArray() {\n var results: V[] = [];\n this._root.forRange(\n this.minKey()!,\n this.maxKey()!,\n true,\n false,\n this,\n 0,\n (_k, v) => {\n results.push(v);\n },\n );\n return results;\n }\n\n /** Gets a string representing the tree's data based on toArray(). */\n toString() {\n return this.toArray().toString();\n }\n\n /** Stores a key-value pair only if the key doesn't already exist in the tree.\n * @returns true if a new key was added\n */\n setIfNotPresent(key: K, value: V): boolean {\n return this.set(key, value, false);\n }\n\n /** Returns the next pair whose key is larger than the specified key (or undefined if there is none).\n * If key === undefined, this function returns the lowest pair.\n * @param key The key to search for.\n * @param reusedArray Optional array used repeatedly to store key-value pairs, to\n * avoid creating a new array on every iteration.\n */\n nextHigherPair(key: K | undefined, reusedArray?: [K, V]): [K, V] | undefined {\n reusedArray = reusedArray || ([] as unknown as [K, V]);\n if (key === undefined) {\n return this._root.minPair(reusedArray);\n }\n return this._root.getPairOrNextHigher(\n key,\n this._compare,\n false,\n reusedArray,\n );\n }\n\n /** Returns the next key larger than the specified key, or undefined if there is none.\n * Also, nextHigherKey(undefined) returns the lowest key.\n */\n nextHigherKey(key: K | undefined): K | undefined {\n var p = this.nextHigherPair(key, ReusedArray as [K, V]);\n return p && p[0];\n }\n\n /** Returns the next pair whose key is smaller than the specified key (or undefined if there is none).\n * If key === undefined, this function returns the highest pair.\n * @param key The key to search for.\n * @param reusedArray Optional array used repeatedly to store key-value pairs, to\n * avoid creating a new array each time you call this method.\n */\n nextLowerPair(key: K | undefined, reusedArray?: [K, V]): [K, V] | undefined {\n reusedArray = reusedArray || ([] as unknown as [K, V]);\n if (key === undefined) {\n return this._root.maxPair(reusedArray);\n }\n return this._root.getPairOrNextLower(\n key,\n this._compare,\n false,\n reusedArray,\n );\n }\n\n /** Returns the next key smaller than the specified key, or undefined if there is none.\n * Also, nextLowerKey(undefined) returns the highest key.\n */\n nextLowerKey(key: K | undefined): K | undefined {\n var p = this.nextLowerPair(key, ReusedArray as [K, V]);\n return p && p[0];\n }\n\n /** Returns the key-value pair associated with the supplied key if it exists\n * or the pair associated with the next lower pair otherwise. If there is no\n * next lower pair, undefined is returned.\n * @param key The key to search for.\n * @param reusedArray Optional array used repeatedly to store key-value pairs, to\n * avoid creating a new array each time you call this method.\n * */\n getPairOrNextLower(key: K, reusedArray?: [K, V]): [K, V] | undefined {\n return this._root.getPairOrNextLower(\n key,\n this._compare,\n true,\n reusedArray || ([] as unknown as [K, V]),\n );\n }\n\n /** Returns the key-value pair associated with the supplied key if it exists\n * or the pair associated with the next lower pair otherwise. If there is no\n * next lower pair, undefined is returned.\n * @param key The key to search for.\n * @param reusedArray Optional array used repeatedly to store key-value pairs, to\n * avoid creating a new array each time you call this method.\n * */\n getPairOrNextHigher(key: K, reusedArray?: [K, V]): [K, V] | undefined {\n return this._root.getPairOrNextHigher(\n key,\n this._compare,\n true,\n reusedArray || ([] as unknown as [K, V]),\n );\n }\n\n /** Edits the value associated with a key in the tree, if it already exists.\n * @returns true if the key existed, false if not.\n */\n changeIfPresent(key: K, value: V): boolean {\n return this.editRange(key, key, true, (_k, _v) => ({value})) !== 0;\n }\n\n /**\n * Builds an array of pairs from the specified range of keys, sorted by key.\n * Each returned pair is also an array: pair[0] is the key, pair[1] is the value.\n * @param low The first key in the array will be greater than or equal to `low`.\n * @param high This method returns when a key larger than this is reached.\n * @param includeHigh If the `high` key is present, its pair will be included\n * in the output if and only if this parameter is true. Note: if the\n * `low` key is present, it is always included in the output.\n * @param maxLength Length limit. getRange will stop scanning the tree when\n * the array reaches this size.\n * @description Computational complexity: O(result.length + log size)\n */\n getRange(\n low: K,\n high: K,\n includeHigh?: boolean,\n maxLength: number = 0x3ffffff,\n ): [K, V][] {\n var results: [K, V][] = [];\n this._root.forRange(low, high, includeHigh, false, this, 0, (k, v) => {\n results.push([k, v]);\n return results.length > maxLength ? Break : undefined;\n });\n return results;\n }\n\n /** Adds all pairs from a list of key-value pairs.\n * @param pairs Pairs to add to this tree. If there are duplicate keys,\n * later pairs currently overwrite earlier ones (e.g. [[0,1],[0,7]]\n * associates 0 with 7.)\n * @param overwrite Whether to overwrite pairs that already exist (if false,\n * pairs[i] is ignored when the key pairs[i][0] already exists.)\n * @returns The number of pairs added to the collection.\n * @description Computational complexity: O(pairs.length * log(size + pairs.length))\n */\n setPairs(pairs: [K, V][], overwrite?: boolean): number {\n var added = 0;\n for (var i = 0; i < pairs.length; i++)\n if (this.set(pairs[i][0], pairs[i][1], overwrite)) added++;\n return added;\n }\n\n forRange(\n low: K,\n high: K,\n includeHigh: boolean,\n onFound?: (k: K, v: V, counter: number) => void,\n initialCounter?: number,\n ): number;\n\n /**\n * Scans the specified range of keys, in ascending order by key.\n * Note: the callback `onFound` must not insert or remove items in the\n * collection. Doing so may cause incorrect data to be sent to the\n * callback afterward.\n * @param low The first key scanned will be greater than or equal to `low`.\n * @param high Scanning stops when a key larger than this is reached.\n * @param includeHigh If the `high` key is present, `onFound` is called for\n * that final pair if and only if this parameter is true.\n * @param onFound A function that is called for each key-value pair. This\n * function can return {break:R} to stop early with result R.\n * @param initialCounter Initial third argument of onFound. This value\n * increases by one each time `onFound` is called. Default: 0\n * @returns The number of values found, or R if the callback returned\n * `{break:R}` to stop early.\n * @description Computational complexity: O(number of items scanned + log size)\n */\n forRange<R = number>(\n low: K,\n high: K,\n includeHigh: boolean,\n onFound?: (k: K, v: V, counter: number) => {break?: R} | void,\n initialCounter?: number,\n ): R | number {\n var r = this._root.forRange(\n low,\n high,\n includeHigh,\n false,\n this,\n initialCounter || 0,\n onFound,\n );\n return typeof r === 'number' ? r : r.break!;\n }\n\n /**\n * Scans and potentially modifies values for a subsequence of keys.\n * Note: the callback `onFound` should ideally be a pure function.\n * Specfically, it must not insert items, call clone(), or change\n * the collection except via return value; out-of-band editing may\n * cause an exception or may cause incorrect data to be sent to\n * the callback (duplicate or missed items). It must not cause a\n * clone() of the collection, otherwise the clone could be modified\n * by changes requested by the callback.\n * @param low The first key scanned will be greater than or equal to `low`.\n * @param high Scanning stops when a key larger than this is reached.\n * @param includeHigh If the `high` key is present, `onFound` is called for\n * that final pair if and only if this parameter is true.\n * @param onFound A function that is called for each key-value pair. This\n * function can return `{value:v}` to change the value associated\n * with the current key, `{delete:true}` to delete the current pair,\n * `{break:R}` to stop early with result R, or it can return nothing\n * (undefined or {}) to cause no effect and continue iterating.\n * `{break:R}` can be combined with one of the other two commands.\n * The third argument `counter` is the number of items iterated\n * previously; it equals 0 when `onFound` is called the first time.\n * @returns The number of values scanned, or R if the callback returned\n * `{break:R}` to stop early.\n * @description\n * Computational complexity: O(number of items scanned + log size)\n * Note: if the tree has been cloned with clone(), any shared\n * nodes are copied before `onFound` is called. This takes O(n) time\n * where n is proportional to the amount of shared data scanned.\n */\n editRange<R = V>(\n low: K,\n high: K,\n includeHigh: boolean,\n onFound: (k: K, v: V, counter: number) => EditRangeResult<V, R> | void,\n initialCounter?: number,\n ): R | number {\n var root = this._root;\n if (root.isShared) this._root = root = root.clone();\n try {\n var r = root.forRange(\n low,\n high,\n includeHigh,\n true,\n this,\n initialCounter || 0,\n onFound,\n );\n return typeof r === 'number' ? r : r.break!;\n } finally {\n let isShared;\n while (root.keys.length <= 1 && !root.isLeaf) {\n isShared ||= root.isShared;\n this._root = root =\n root.keys.length === 0\n ? EmptyLeaf\n : (root as any as BNodeInternal<K, V>).children[0];\n }\n // If any ancestor of the new root was shared, the new root must also be shared\n if (isShared) {\n root.isShared = true;\n }\n }\n }\n\n /** Same as `editRange` except that the callback is called for all pairs. */\n editAll<R = V>(\n onFound: (k: K, v: V, counter: number) => EditRangeResult<V, R> | void,\n initialCounter?: number,\n ): R | number {\n return this.editRange(\n this.minKey()!,\n this.maxKey()!,\n true,\n onFound,\n initialCounter,\n );\n }\n\n /**\n * Removes a range of key-value pairs from the B+ tree.\n * @param low The first key scanned will be greater than or equal to `low`.\n * @param high Scanning stops when a key larger than this is reached.\n * @param includeHigh Specifies whether the `high` key, if present, is deleted.\n * @returns The number of key-value pairs that were deleted.\n * @description Computational complexity: O(log size + number of items deleted)\n */\n deleteRange(low: K, high: K, includeHigh: boolean): number {\n return this.editRange(low, high, includeHigh, DeleteRange);\n }\n\n /** Deletes a series of keys from the collection. */\n deleteKeys(keys: K[]): number {\n for (var i = 0, r = 0; i < keys.length; i++) if (this.delete(keys[i])) r++;\n return r;\n }\n\n /** Gets the height of the tree: the number of internal nodes between the\n * BTree object and its leaf nodes (zero if there are no internal nodes). */\n get height(): number {\n let node: BNode<K, V> | undefined = this._root;\n let height = -1;\n while (node) {\n height++;\n node = node.isLeaf\n ? undefined\n : (node as unknown as BNodeInternal<K, V>).children[0];\n }\n return height;\n }\n\n /** Makes the object read-only to ensure it is not accidentally modified.\n * Freezing does not have to be permanent; unfreeze() reverses the effect.\n * This is accomplished by replacing mutator functions with a function\n * that throws an Error. Compared to using a property (e.g. this.isFrozen)\n * this implementation gives better performance in non-frozen BTrees.\n */\n freeze() {\n var t = this as any;\n // Note: all other mutators ultimately call set() or editRange()\n // so we don't need to override those others.\n t.clear =\n t.set =\n t.editRange =\n function () {\n throw new Error('Attempted to modify a frozen BTree');\n };\n }\n\n /** Ensures mutations are allowed, reversing the effect of freeze(). */\n unfreeze() {\n // @ts-ignore \"The operand of a 'delete' operator must be optional.\"\n // (wrong: delete does not affect the prototype.)\n delete this.clear;\n // @ts-ignore\n delete this.set;\n // @ts-ignore\n delete this.editRange;\n }\n\n /** Returns true if the tree appears to be frozen. */\n get isFrozen() {\n return this.hasOwnProperty('editRange');\n }\n\n /** Scans the tree for signs of serious bugs (e.g. this.size doesn't match\n * number of elements, internal nodes not caching max element properly...)\n * Computational complexity: O(number of nodes), i.e. O(size). This method\n * skips the most expensive test - whether all keys are sorted - but it\n * does check that maxKey() of the children of internal nodes are sorted. */\n checkValid() {\n var size = this._root.checkValid(0, this, 0);\n check(\n size === this.size,\n 'size mismatch: counted ',\n size,\n 'but stored',\n this.size,\n );\n }\n\n [Symbol.iterator] = this.entries.bind(this);\n where = this.filter.bind(this);\n setRange = this.setPairs.bind(this);\n add = this.set.bind(this); // for compatibility with ISetSink<K>\n}\n\n/** A TypeScript helper function that simply returns its argument, typed as\n * `ISortedSet<K>` if the BTree implements it, as it does if `V extends undefined`.\n * If `V` cannot be `undefined`, it returns `unknown` instead. Or at least, that\n * was the intention, but TypeScript is acting weird and may return `ISortedSet<K>`\n * even if `V` can't be `undefined` (discussion: btree-typescript issue #14) */\nexport function asSet<K, V>(\n btree: BTree<K, V>,\n): undefined extends V ? ISortedSet<K> : unknown {\n return btree as any;\n}\n\nfunction iterator<T>(\n next: () => IteratorResult<T> = () => ({done: true, value: undefined}),\n): IterableIterator<T> {\n var result: any = {next};\n if (Symbol && Symbol.iterator)\n result[Symbol.iterator] = function () {\n return this;\n };\n return result;\n}\n\n/** Leaf node / base class. **************************************************/\nclass BNode<K, V> {\n // If this is an internal node, _keys[i] is the highest key in children[i].\n keys: K[];\n values: V[];\n // True if this node might be within multiple `BTree`s (or have multiple parents).\n // If so, it must be cloned before being mutated to avoid changing an unrelated tree.\n // This is transitive: if it's true, children are also shared even if `isShared!=true`\n // in those children. (Certain operations will propagate isShared=true to children.)\n isShared: true | undefined;\n get isLeaf() {\n return (this as any).children === undefined;\n }\n\n constructor(keys: K[] = [], values?: V[]) {\n this.keys = keys;\n this.values = values || (undefVals as any[]);\n this.isShared = undefined;\n }\n\n ///////////////////////////////////////////////////////////////////////////\n // Shared methods /////////////////////////////////////////////////////////\n\n maxKey() {\n return this.keys[this.keys.length - 1];\n }\n\n // If key not found, returns i^failXor where i is the insertion index.\n // Callers that don't care whether there was a match will set failXor=0.\n indexOf(key: K, failXor: number, cmp: (a: K, b: K) => number): index {\n const keys = this.keys;\n var lo = 0,\n hi = keys.length,\n mid = hi >> 1;\n while (lo < hi) {\n var c = cmp(keys[mid], key);\n if (c < 0) lo = mid + 1;\n else if (c > 0)\n // key < keys[mid]\n hi = mid;\n else if (c === 0) return mid;\n else {\n // c is NaN or otherwise invalid\n if (key === key)\n // at least the search key is not NaN\n return keys.length;\n else throw new Error('BTree: NaN was used as a key');\n }\n mid = (lo + hi) >> 1;\n }\n return mid ^ failXor;\n\n // Unrolled version: benchmarks show same speed, not worth using\n /*var i = 1, c: number = 0, sum = 0;\n if (keys.length >= 4) {\n i = 3;\n if (keys.length >= 8) {\n i = 7;\n if (keys.length >= 16) {\n i = 15;\n if (keys.length >= 32) {\n i = 31;\n if (keys.length >= 64) {\n i = 127;\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 64 : -64;\n sum += c;\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 32 : -32;\n sum += c;\n }\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 16 : -16;\n sum += c;\n }\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 8 : -8;\n sum += c;\n }\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 4 : -4;\n sum += c;\n }\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 2 : -2;\n sum += c;\n }\n i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 1 : -1;\n c = i < keys.length ? cmp(keys[i], key) : 1;\n sum += c;\n if (c < 0) {\n ++i;\n c = i < keys.length ? cmp(keys[i], key) : 1;\n sum += c;\n }\n if (sum !== sum) {\n if (key === key) // at least the search key is not NaN\n return keys.length ^ failXor;\n else\n throw new Error(\"BTree: NaN was used as a key\");\n }\n return c === 0 ? i : i ^ failXor;*/\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Leaf Node: misc //////////////////////////////////////////////////////////\n\n minKey(): K | undefined {\n return this.keys[0];\n }\n\n minPair(reusedArray: [K, V]): [K, V] | undefined {\n if (this.keys.length === 0) return undefined;\n reusedArray[0] = this.keys[0];\n reusedArray[1] = this.values[0];\n return reusedArray;\n }\n\n maxPair(reusedArray: [K, V]): [K, V] | undefined {\n if (this.keys.length === 0) return undefined;\n const lastIndex = this.keys.length - 1;\n reusedArray[0] = this.keys[lastIndex];\n reusedArray[1] = this.values[lastIndex];\n return reusedArray;\n }\n\n clone(): BNode<K, V> {\n var v = this.values;\n return new BNode<K, V>(\n this.keys.slice(0),\n v === undefVals ? v : v.slice(0),\n );\n }\n\n greedyClone(force?: boolean): BNode<K, V> {\n return this.isShared && !force ? this : this.clone();\n }\n\n get(key: K, defaultValue: V | undefined, tree: BTree<K, V>): V | undefined {\n var i = this.indexOf(key, -1, tree._compare);\n return i < 0 ? defaultValue : this.values[i];\n }\n\n getPairOrNextLower(\n key: K,\n compare: (a: K, b: K) => number,\n inclusive: boolean,\n reusedArray: [K, V],\n ): [K, V] | undefined {\n var i = this.indexOf(key, -1, compare);\n const indexOrLower = i < 0 ? ~i - 1 : inclusive ? i : i - 1;\n if (indexOrLower >= 0) {\n reusedArray[0] = this.keys[indexOrLower];\n reusedArray[1] = this.values[indexOrLower];\n return reusedArray;\n }\n return undefined;\n }\n\n getPairOrNextHigher(\n key: K,\n compare: (a: K, b: K) => number,\n inclusive: boolean,\n reusedArray: [K, V],\n ): [K, V] | undefined {\n var i = this.indexOf(key, -1, compare);\n const indexOrLower = i < 0 ? ~i : inclusive ? i : i + 1;\n const keys = this.keys;\n if (indexOrLower < keys.length) {\n reusedArray[0] = keys[indexOrLower];\n reusedArray[1] = this.values[indexOrLower];\n return reusedArray;\n }\n return undefined;\n }\n\n checkValid(depth: number, _tree: BTree<K, V>, baseIndex: number): number {\n var kL = this.keys.length,\n vL = this.values.length;\n check(\n this.values === undefVals ? kL <= vL : kL === vL,\n 'keys/values length mismatch: depth',\n depth,\n 'with lengths',\n kL,\n vL,\n 'and baseIndex',\n baseIndex,\n );\n // Note: we don't check for \"node too small\" because sometimes a node\n // can legitimately have size 1. This occurs if there is a batch\n // deletion, leaving a node of size 1, and the siblings are full so\n // it can't be merged with adjacent nodes. However, the parent will\n // verify that the average node size is at least half of the maximum.\n check(\n depth == 0 || kL > 0,\n 'empty leaf at depth',\n depth,\n 'and baseIndex',\n baseIndex,\n );\n return kL;\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Leaf Node: set & node splitting //////////////////////////////////////////\n\n set(\n key: K,\n value: V,\n overwrite: boolean | undefined,\n tree: BTree<K, V>,\n ): boolean | BNode<K, V> {\n var i = this.indexOf(key, -1, tree._compare);\n if (i < 0) {\n // key does not exist yet\n i = ~i;\n tree._size++;\n\n if (this.keys.length < tree._maxNodeSize) {\n return this.insertInLeaf(i, key, value, tree);\n } else {\n // This leaf node is full and must split\n var newRightSibling = this.splitOffRightSide(),\n target: BNode<K, V> = this;\n if (i > this.keys.length) {\n i -= this.keys.length;\n target = newRightSibling;\n }\n target.insertInLeaf(i, key, value, tree);\n return newRightSibling;\n }\n } else {\n // Key already exists\n if (overwrite !== false) {\n if (value !== undefined) this.reifyValues();\n // usually this is a no-op, but some users may wish to edit the key\n this.keys[i] = key;\n this.values[i] = value;\n }\n return false;\n }\n }\n\n reifyValues() {\n if (this.values === undefVals)\n return (this.values = this.values.slice(0, this.keys.length));\n return this.values;\n }\n\n insertInLeaf(i: index, key: K, value: V, tree: BTree<K, V>) {\n this.keys.splice(i, 0, key);\n if (this.values === undefVals) {\n while (undefVals.length < tree._maxNodeSize) undefVals.push(undefined);\n if (value === undefined) {\n return true;\n } else {\n this.values = undefVals.slice(0, this.keys.length - 1);\n }\n }\n this.values.splice(i, 0, value);\n return true;\n }\n\n takeFromRight(rhs: BNode<K, V>) {\n // Reminder: parent node must update its copy of key for this node\n // assert: neither node is shared\n // assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)\n var v = this.values;\n if (rhs.values === undefVals) {\n if (v !== undefVals) v.push(undefined as any);\n } else {\n v = this.reifyValues();\n v.push(rhs.values.shift()!);\n }\n this.keys.push(rhs.keys.shift()!);\n }\n\n takeFromLeft(lhs: BNode<K, V>) {\n // Reminder: parent node must update its copy of key for this node\n // assert: neither node is shared\n // assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)\n var v = this.values;\n if (lhs.values === undefVals) {\n if (v !== undefVals) v.unshift(undefined as any);\n } else {\n v = this.reifyValues();\n v.unshift(lhs.values.pop()!);\n }\n this.keys.unshift(lhs.keys.pop()!);\n }\n\n splitOffRightSide(): BNode<K, V> {\n // Reminder: parent node must update its copy of key for this node\n var half = this.keys.length >> 1,\n keys = this.keys.splice(half);\n var values =\n this.values === undefVals ? undefVals : this.values.splice(half);\n return new BNode<K, V>(keys, values);\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Leaf Node: scanning & deletions //////////////////////////////////////////\n\n forRange<R>(\n low: K,\n high: K,\n includeHigh: boolean | undefined,\n editMode: boolean,\n tree: BTree<K, V>,\n count: number,\n onFound?: (k: K, v: V, counter: number) => EditRangeResult<V, R> | void,\n ): EditRangeResult<V, R> | number {\n var cmp = tree._compare;\n var iLow, iHigh;\n if (high === low) {\n if (!includeHigh) return count;\n iHigh = (iLow = this.indexOf(low, -1, cmp)) + 1;\n if (iLow < 0) return count;\n } else {\n iLow = this.indexOf(low, 0, cmp);\n iHigh = this.indexOf(high, -1, cmp);\n if (iHigh < 0) iHigh = ~iHigh;\n else if (includeHigh === true) iHigh++;\n }\n var keys = this.keys,\n values = this.values;\n if (onFound !== undefined) {\n for (var i = iLow; i < iHigh; i++) {\n var key = keys[i];\n var result = onFound(key, values[i], count++);\n if (result !== undefined) {\n if (editMode === true) {\n if (key !== keys[i] || this.isShared === true)\n throw new Error('BTree illegally changed or cloned in editRange');\n if (result.delete) {\n this.keys.splice(i, 1);\n if (this.values !== undefVals) this.values.splice(i, 1);\n tree._size--;\n i--;\n iHigh--;\n } else if (result.hasOwnProperty('value')) {\n values![i] = result.value!;\n }\n }\n if (result.break !== undefined) return result;\n }\n }\n } else count += iHigh - iLow;\n return count;\n }\n\n /** Adds entire contents of right-hand sibling (rhs is left unchanged) */\n mergeSibling(rhs: BNode<K, V>, _: number) {\n this.keys.push.apply(this.keys, rhs.keys);\n if (this.values === undefVals) {\n if (rhs.values === undefVals) return;\n this.values = this.values.slice(0, this.keys.length);\n }\n this.values.push.apply(this.values, rhs.reifyValues());\n }\n}\n\n/** Internal node (non-leaf node) ********************************************/\nclass BNodeInternal<K, V> extends BNode<K, V> {\n // Note: conventionally B+ trees have one fewer key than the number of\n // children, but I find it easier to keep the array lengths equal: each\n // keys[i] caches the value of children[i].maxKey().\n children: BNode<K, V>[];\n\n /**\n * This does not mark `children` as shared, so it is the responsibility of the caller\n * to ensure children are either marked shared, or aren't included in another tree.\n */\n constructor(children: BNode<K, V>[], keys?: K[]) {\n if (!keys) {\n keys = [];\n for (var i = 0; i < children.length; i++) keys[i] = children[i].maxKey();\n }\n super(keys);\n this.children = children;\n }\n\n clone(): BNode<K, V> {\n var children = this.children.slice(0);\n for (var i = 0; i < children.length; i++) children[i].isShared = true;\n return new BNodeInternal<K, V>(children, this.keys.slice(0));\n }\n\n greedyClone(force?: boolean): BNode<K, V> {\n if (this.isShared && !force) return this;\n var nu = new BNodeInternal<K, V>(\n this.children.slice(0),\n this.keys.slice(0),\n );\n for (var i = 0; i < nu.children.length; i++)\n nu.children[i] = nu.children[i].greedyClone(force);\n return nu;\n }\n\n minKey() {\n return this.children[0].minKey();\n }\n\n minPair(reusedArray: [K, V]): [K, V] | undefined {\n return this.children[0].minPair(reusedArray);\n }\n\n maxPair(reusedArray: [K, V]): [K, V] | undefined {\n return this.children[this.children.length - 1].maxPair(reusedArray);\n }\n\n get(key: K, defaultValue: V | undefined, tree: BTree<K, V>): V | undefined {\n var i = this.indexOf(key, 0, tree._compare),\n children = this.children;\n return i < children.length\n ? children[i].get(key, defaultValue, tree)\n : undefined;\n }\n\n getPairOrNextLower(\n key: K,\n compare: (a: K, b: K) => number,\n inclusive: boolean,\n reusedArray: [K, V],\n ): [K, V] | undefined {\n var i = this.indexOf(key, 0, compare),\n children = this.children;\n if (i >= children.length) return this.maxPair(reusedArray);\n const result = children[i].getPairOrNextLower(\n key,\n compare,\n inclusive,\n reusedArray,\n );\n if (result === undefined && i > 0) {\n return children[i - 1].maxPair(reusedArray);\n }\n return result;\n }\n\n getPairOrNextHigher(\n key: K,\n compare: (a: K, b: K) => number,\n inclusive: boolean,\n reusedArray: [K, V],\n ): [K, V] | undefined {\n var i = this.indexOf(key, 0, compare),\n children = this.children,\n length = children.length;\n if (i >= length) return undefined;\n const result = children[i].getPairOrNextHigher(\n key,\n compare,\n inclusive,\n reusedArray,\n );\n if (result === undefined && i < length - 1) {\n return children[i + 1].minPair(reusedArray);\n }\n return result;\n }\n\n checkValid(depth: number, tree: BTree<K, V>, baseIndex: number): number {\n let kL = this.keys.length,\n cL = this.children.length;\n check(\n kL === cL,\n 'keys/children length mismatch: depth',\n depth,\n 'lengths',\n kL,\n cL,\n 'baseIndex',\n baseIndex,\n );\n check(\n kL > 1 || depth > 0,\n 'internal node has length',\n kL,\n 'at depth',\n depth,\n 'baseIndex',\n baseIndex,\n );\n let size = 0,\n c = this.children,\n k = this.keys,\n childSize = 0;\n for (var i = 0; i < cL; i++) {\n size += c[i].checkValid(depth + 1, tree, baseIndex + size);\n childSize += c[i].keys.length;\n check(size >= childSize, 'wtf', baseIndex); // no way this will ever fail\n check(\n i === 0 || c[i - 1].constructor === c[i].constructor,\n 'type mismatch, baseIndex:',\n baseIndex,\n );\n if (c[i].maxKey() != k[i])\n check(\n false,\n 'keys[',\n i,\n '] =',\n k[i],\n 'is wrong, should be ',\n c[i].maxKey(),\n 'at depth',\n depth,\n 'baseIndex',\n baseIndex,\n );\n if (!(i === 0 || tree._compare(k[i - 1], k[i]) < 0))\n check(\n false,\n 'sort violation at depth',\n depth,\n 'index',\n i,\n 'keys',\n k[i - 1],\n k[i],\n );\n }\n // 2020/08: BTree doesn't always avoid grossly undersized nodes,\n // but AFAIK such nodes are pretty harmless, so accept them.\n let toofew = childSize === 0; // childSize < (tree.maxNodeSize >> 1)*cL;\n if (toofew || childSize > tree.maxNodeSize * cL)\n check(\n false,\n toofew ? 'too few' : 'too many',\n 'children (',\n childSize,\n size,\n ') at depth',\n depth,\n 'maxNodeSize:',\n tree.maxNodeSize,\n 'children.length:',\n cL,\n 'baseIndex:',\n baseIndex,\n );\n return size;\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Internal Node: set & node splitting //////////////////////////////////////\n\n set(\n key: K,\n value: V,\n overwrite: boolean | undefined,\n tree: BTree<K, V>,\n ): boolean | BNodeInternal<K, V> {\n var c = this.children,\n max = tree._maxNodeSize,\n cmp = tree._compare;\n var i = Math.min(this.indexOf(key, 0, cmp), c.length - 1),\n child = c[i];\n\n if (child.isShared) c[i] = child = child.clone();\n if (child.keys.length >= max) {\n // child is full; inserting anything else will cause a split.\n // Shifting an item to the left or right sibling may avoid a split.\n // We can do a shift if the adjacent node is not full and if the\n // current key can still be placed in the same node after the shift.\n var other: BNode<K, V>;\n if (\n i > 0 &&\n (other = c[i - 1]).keys.length < max &&\n cmp(child.keys[0], key) < 0\n ) {\n if (other.isShared) c[i - 1] = other = other.clone();\n other.takeFromRight(child);\n this.keys[i - 1] = other.maxKey();\n } else if (\n (other = c[i + 1]) !== undefined &&\n other.keys.length < max &&\n cmp(child.maxKey(), key) < 0\n ) {\n if (other.isShared) c[i + 1] = other = other.clone();\n other.takeFromLeft(child);\n this.keys[i] = c[i].maxKey();\n }\n }\n\n var result = child.set(key, value, overwrite, tree);\n if (result === false) return false;\n this.keys[i] = child.maxKey();\n if (result === true) return true;\n\n // The child has split and `result` is a new right child... does it fit?\n if (this.keys.length < max) {\n // yes\n this.insert(i + 1, result);\n return true;\n } else {\n // no, we must split also\n var newRightSibling = this.splitOffRightSide(),\n target: BNodeInternal<K, V> = this;\n if (cmp(result.maxKey(), this.maxKey()) > 0) {\n target = newRightSibling;\n i -= this.keys.length;\n }\n target.insert(i + 1, result);\n return newRightSibling;\n }\n }\n\n /**\n * Inserts `child` at index `i`.\n * This does not mark `child` as shared, so it is the responsibility of the caller\n * to ensure that either child is marked shared, or it is not included in another tree.\n */\n insert(i: index, child: BNode<K, V>) {\n this.children.splice(i, 0, child);\n this.keys.splice(i, 0, child.maxKey());\n }\n\n /**\n * Split this node.\n * Modifies this to remove the second half of the items, returning a separate node containing them.\n */\n splitOffRightSide() {\n // assert !this.isShared;\n var half = this.children.length >> 1;\n return new BNodeInternal<K, V>(\n this.children.splice(half),\n this.keys.splice(half),\n );\n }\n\n takeFromRight(rhs: BNode<K, V>) {\n // Reminder: parent node must update its copy of key for this node\n // assert: neither node is shared\n // assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)\n this.keys.push(rhs.keys.shift()!);\n this.children.push((rhs as BNodeInternal<K, V>).children.shift()!);\n }\n\n takeFromLeft(lhs: BNode<K, V>) {\n // Reminder: parent node must update its copy of key for this node\n // assert: neither node is shared\n // assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)\n this.keys.unshift(lhs.keys.pop()!);\n this.children.unshift((lhs as BNodeInternal<K, V>).children.pop()!);\n }\n\n /////////////////////////////////////////////////////////////////////////////\n // Internal Node: scanning & deletions //////////////////////////////////////\n\n // Note: `count` is the next value of the third argument to `onFound`.\n // A leaf node's `forRange` function returns a new value for this counter,\n // unless the operation is to stop early.\n forRange<R>(\n low: K,\n high: K,\n includeHigh: boolean | undefined,\n editMode: boolean,\n tree: BTree<K, V>,\n count: number,\n onFound?: (k: K, v: V, counter: number) => EditRangeResult<V, R> | void,\n ): EditRangeResult<V, R> | number {\n var cmp = tree._compare;\n var keys = this.keys,\n children = this.children;\n var iLow = this.indexOf(low, 0, cmp),\n i = iLow;\n var iHigh = Math.min(\n high === low ? iLow : this.indexOf(high, 0, cmp),\n keys.length - 1,\n );\n if (!editMode) {\n // Simple case\n for (; i <= iHigh; i++) {\n var result = children[i].forRange(\n low,\n high,\n includeHigh,\n editMode,\n tree,\n count,\n onFound,\n );\n if (typeof result !== 'number') return result;\n count = result;\n }\n } else if (i <= iHigh) {\n try {\n for (; i <= iHigh; i++) {\n if (children[i].isShared) children[i] = children[i].clone();\n var result = children[i].forRange(\n low,\n high,\n includeHigh,\n editMode,\n tree,\n count,\n onFound,\n );\n // Note: if children[i] is empty then keys[i]=undefined.\n // This is an invalid state, but it is fixed below.\n keys[i] = children[i].maxKey();\n if (typeof result !== 'number') return result;\n count = result;\n }\n } finally {\n // Deletions may have occurred, so look for opportunities to merge nodes.\n var half = tree._maxNodeSize >> 1;\n if (iLow > 0) iLow--;\n for (i = iHigh; i >= iLow; i--) {\n if (children[i].keys.length <= half) {\n if (children[i].keys.length !== 0) {\n this.tryMerge(i, tree._maxNodeSize);\n } else {\n // child is empty! delete it!\n keys.splice(i, 1);\n children.splice(i, 1);\n }\n }\n }\n if (children.length !== 0 && children[0].keys.length === 0)\n check(false, 'emptiness bug');\n }\n }\n return count;\n }\n\n /** Merges child i with child i+1 if their combined size is not too large */\n tryMerge(i: index, maxSize: number): boolean {\n var children = this.children;\n if (i >= 0 && i + 1 < children.length) {\n if (children[i].keys.length + children[i + 1].keys.length <= maxSize) {\n if (children[i].isShared)\n // cloned already UNLESS i is outside scan range\n children[i] = children[i].clone();\n children[i].mergeSibling(children[i + 1], maxSize);\n children.splice(i + 1, 1);\n this.keys.splice(i + 1, 1);\n this.keys[i] = children[i].maxKey();\n return true;\n }\n }\n return false;\n }\n\n /**\n * Move children from `rhs` into this.\n * `rhs` must be part of this tree, and be removed from it after this call\n * (otherwise isShared for its children could be incorrect).\n */\n mergeSibling(rhs: BNode<K, V>, maxNodeSize: number) {\n // assert !this.isShared;\n var oldLength = this.keys.length;\n this.keys.push.apply(this.keys, rhs.keys);\n const rhsChildren = (rhs as any as BNodeInternal<K, V>).children;\n this.children.push.apply(this.children, rhsChildren);\n\n if (rhs.isShared && !this.isShared) {\n // All children of a shared node are implicitly shared, and since their new\n // parent is not shared, they must now be explicitly marked as shared.\n for (var i = 0; i < rhsChildren.length; i++)\n rhsChildren[i].isShared = true;\n }\n\n // If our children are themselves almost empty due to a mass-delete,\n // they may need to be merged too (but only the oldLength-1 and its\n // right sibling should need this).\n this.tryMerge(oldLength - 1, maxNodeSize);\n }\n}\n\n/**\n * A walkable pointer into a BTree for computing efficient diffs between trees with shared data.\n * - A cursor points to either a key/value pair (KVP) or a node (which can be either a leaf or an internal node).\n * As a consequence, a cursor cannot be created for an empty tree.\n * - A cursor can be walked forwards using `step`. A cursor can be compared to another cursor to\n * determine which is ahead in advancement.\n * - A cursor is valid only for the tree it was created from, and only until the first edit made to\n * that tree since the cursor's creation.\n * - A cursor contains a key for the current location, which is the maxKey when the cursor points to a node\n * and a key corresponding to a value when pointing to a leaf.\n * - Leaf is only populated if the cursor points to a KVP. If this is the case, levelIndices.length === internalSpine.length + 1\n * and levelIndices[levelIndices.length - 1] is the index of the value.\n */\ntype DiffCursor<K, V> = {\n height: number;\n internalSpine: BNode<K, V>[][];\n levelIndices: number[];\n leaf: BNode<K, V> | undefined;\n currentKey: K;\n};\n\n// Optimization: this array of `undefined`s is used instead of a normal\n// array of values in nodes where `undefined` is the only value.\n// Its length is extended to max node size on first use; since it can\n// be shared between trees with different maximums, its length can only\n// increase, never decrease. Its type should be undefined[] but strangely\n// TypeScript won't allow the comparison V[] === undefined[]. To prevent\n// users from making this array too large, BTree has a maximum node size.\n//\n// FAQ: undefVals[i] is already undefined, so why increase the array size?\n// Reading outside the bounds of an array is relatively slow because it\n// has the side effect of scanning the prototype chain.\nvar undefVals: any[] = [];\n\nconst Delete = {delete: true},\n DeleteRange = () => Delete;\nconst Break = {break: true};\nconst EmptyLeaf = (function () {\n var n = new BNode<any, any>();\n n.isShared = true;\n return n;\n})();\nconst EmptyArray: any[] = [];\nconst ReusedArray: any[] = []; // assumed thread-local\n\nfunction check(fact: boolean, ...args: any[]) {\n if (!fact) {\n args.unshift('B+ tree'); // at beginning of message\n throw new Error(args.join(' '));\n }\n}\n\n/** A BTree frozen in the empty state. */\nexport const EmptyBTree = (() => {\n let t = new BTree();\n t.freeze();\n return t;\n})();\n", "/**\n * A LookaheadIterator is an iterator that reads ahead one value eagerly and\n * provides access to both the current and next value without having to advance.\n */\nexport class LookaheadIterator<T>\n implements Iterator<[T, ...Array<T | undefined>]>\n{\n readonly #iter: Iterator<T>;\n readonly #buffer: Array<T | undefined>;\n\n #initialized = false;\n\n constructor(iter: Iterator<T>, size: number = 2) {\n this.#iter = iter;\n this.#buffer = new Array(size);\n }\n\n [Symbol.iterator](): Iterator<[T, ...Array<T | undefined>]> {\n return this;\n }\n\n next(): IteratorResult<[T, ...Array<T | undefined>]> {\n if (!this.#initialized) {\n for (let i = 0; i < this.#buffer.length; i++) {\n const r = this.#iter.next();\n this.#buffer[i] = r.done ? undefined : r.value;\n }\n this.#initialized = true;\n } else {\n for (let i = 0; i < this.#buffer.length - 1; i++) {\n this.#buffer[i] = this.#buffer[i + 1];\n }\n const r = this.#iter.next();\n this.#buffer[this.#buffer.length - 1] = r.done ? undefined : r.value;\n }\n\n if (this.#buffer[0] === undefined) {\n return {done: true, value: undefined};\n }\n return {done: false, value: this.#buffer} as IteratorResult<\n [T, ...Array<T | undefined>]\n >;\n }\n\n return(value?: unknown): IteratorResult<[T, ...(T | undefined)[]], unknown> {\n this.#iter.return?.(value);\n return {done: true, value: undefined};\n }\n\n throw(e?: unknown): IteratorResult<[T, ...(T | undefined)[]], unknown> {\n this.#iter.throw?.(e);\n return {done: true, value: undefined};\n }\n}\n", "import {BTree} from '../../../../btree/src/mod.js';\nimport {assert, unreachable} from '../../../../shared/src/asserts.js';\nimport type {\n Condition,\n Ordering,\n OrderPart,\n SimpleCondition,\n} from '../../../../zero-protocol/src/ast.js';\nimport type {Row, Value} from '../../../../zero-protocol/src/data.js';\nimport type {PrimaryKey} from '../../../../zero-protocol/src/primary-key.js';\nimport {assertOrderingIncludesPK} from '../builder/builder.js';\nimport {createPredicate} from '../builder/filter.js';\nimport type {Change} from './change.js';\nimport {\n type Comparator,\n compareValues,\n makeComparator,\n type Node,\n valuesEqual,\n} from './data.js';\nimport {LookaheadIterator} from './lookahead-iterator.js';\nimport type {Constraint, FetchRequest, Input, Output} from './operator.js';\nimport type {SchemaValue, TableSchema} from './schema.js';\nimport type {\n Source,\n SourceChange,\n SourceChangeEdit,\n SourceInput,\n} from './source.js';\nimport type {Stream} from './stream.js';\n\nexport type Overlay = {\n outputIndex: number;\n change: SourceChange;\n};\n\ntype Index = {\n comparator: Comparator;\n data: BTree<Row, undefined>;\n usedBy: Set<Connection>;\n};\n\ntype Connection = {\n input: Input;\n output: Output | undefined;\n sort: Ordering;\n compareRows: Comparator;\n optionalFilters: ((row: Row) => boolean)[];\n};\n\n/**\n * A `MemorySource` is a source that provides data to the pipeline from an\n * in-memory data source.\n *\n * This data is kept in sorted order as downstream pipelines will always expect\n * the data they receive from `pull` to be in sorted order.\n */\nexport class MemorySource implements Source {\n readonly #tableName: string;\n readonly #columns: Record<string, SchemaValue>;\n readonly #primaryKey: PrimaryKey;\n readonly #primaryIndexSort: Ordering;\n readonly #indexes: Map<string, Index> = new Map();\n readonly #connections: Connection[] = [];\n\n #overlay: Overlay | undefined;\n\n constructor(\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n ) {\n this.#tableName = tableName;\n this.#columns = columns;\n this.#primaryKey = primaryKey;\n this.#primaryIndexSort = primaryKey.map(k => [k, 'asc']);\n const comparator = makeBoundComparator(this.#primaryIndexSort);\n this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {\n comparator,\n data: new BTree<Row, undefined>([], comparator),\n usedBy: new Set(),\n });\n assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);\n }\n\n // Mainly for tests.\n getSchemaInfo() {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n #getSchema(connection: Connection): TableSchema {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: connection.sort,\n relationships: {},\n isHidden: false,\n compareRows: connection.compareRows,\n };\n }\n\n connect(\n sort: Ordering,\n optionalFilters?: Condition | undefined,\n ): SourceInput {\n const input: SourceInput = {\n getSchema: () => this.#getSchema(connection),\n fetch: req => this.#fetch(req, connection),\n cleanup: req => this.#cleanup(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n this.#disconnect(input);\n },\n appliedFilters: false,\n };\n\n const predicates: ((row: Row) => boolean)[] = filteredOptionalFilters(\n optionalFilters,\n ).filters.map(c => createPredicate(c));\n\n const connection: Connection = {\n input,\n output: undefined,\n sort,\n compareRows: makeComparator(sort),\n optionalFilters: predicates,\n };\n assertOrderingIncludesPK(sort, this.#primaryKey);\n this.#connections.push(connection);\n return input;\n }\n\n #disconnect(input: Input): void {\n const idx = this.#connections.findIndex(c => c.input === input);\n assert(idx !== -1, 'Connection not found');\n const connection = this.#connections[idx];\n this.#connections.splice(idx, 1);\n\n const primaryIndexKey = JSON.stringify(this.#primaryIndexSort);\n\n for (const [key, index] of this.#indexes) {\n if (key === primaryIndexKey) {\n continue;\n }\n index.usedBy.delete(connection);\n if (index.usedBy.size === 0) {\n this.#indexes.delete(key);\n }\n }\n }\n\n #getPrimaryIndex(): Index {\n const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));\n assert(index, 'Primary index not found');\n return index;\n }\n\n #getOrCreateIndex(sort: Ordering, usedBy: Connection): Index {\n const key = JSON.stringify(sort);\n const index = this.#indexes.get(key);\n // Future optimization could use existing index if it's the same just sorted\n // in reverse of needed.\n if (index) {\n index.usedBy.add(usedBy);\n return index;\n }\n\n const comparator = makeBoundComparator(sort);\n\n // When creating these synchronously becomes a problem, a few options:\n // 1. Allow users to specify needed indexes up front\n // 2. Create indexes in a different thread asynchronously (this would require\n // modifying the BTree to be able to be passed over structured-clone, or using\n // a different library.)\n // 3. We could even theoretically do (2) on multiple threads and then merge the\n // results!\n const data = new BTree<Row, undefined>([], comparator);\n\n // I checked, there's no special path for adding data in bulk faster.\n // The constructor takes an array, but it just calls add/set over and over.\n for (const row of this.#getPrimaryIndex().data.keys()) {\n data.add(row, undefined);\n }\n\n const newIndex = {comparator, data, usedBy: new Set([usedBy])};\n this.#indexes.set(key, newIndex);\n return newIndex;\n }\n\n // For unit testing that we correctly clean up indexes.\n getIndexKeys(): string[] {\n return [...this.#indexes.keys()];\n }\n\n *#fetch(req: FetchRequest, from: Connection): Stream<Node> {\n let overlay: Overlay | undefined;\n\n const callingConnectionNum = this.#connections.indexOf(from);\n assert(callingConnectionNum !== -1, 'Output not found');\n const conn = this.#connections[callingConnectionNum];\n const {sort: requestedSort} = conn;\n\n // If there is a constraint, we need an index sorted by it first.\n const indexSort: OrderPart[] = [];\n if (req.constraint) {\n indexSort.push([req.constraint.key, 'asc']);\n }\n\n // For the special case of constraining by PK, we don't need to worry about\n // any requested sort since there can only be one result. Otherwise we also\n // need the index sorted by the requested sort.\n if (\n this.#primaryKey.length > 1 ||\n req.constraint?.key !== this.#primaryKey[0]\n ) {\n indexSort.push(...requestedSort);\n }\n\n const index = this.#getOrCreateIndex(indexSort, from);\n const {data, comparator} = index;\n\n // When we receive a push, we send it to each output one at a time. Once the\n // push is sent to an output, it should keep being sent until all datastores\n // have received it and the change has been made to the datastore.\n if (this.#overlay) {\n if (callingConnectionNum <= this.#overlay.outputIndex) {\n overlay = this.#overlay;\n }\n }\n\n const matchesConstraint = (row: Row) => {\n if (!req.constraint) {\n return true;\n }\n const {key, value} = req.constraint;\n return valuesEqual(row[key], value);\n };\n\n const matchesFilters = (row: Row) =>\n conn.optionalFilters.every(f => f(row));\n\n const matchesConstraintAndFilters = (row: Row) =>\n matchesConstraint(row) && matchesFilters(row);\n // If there is an overlay for this output, does it match the requested\n // constraints and filters?\n if (overlay) {\n // TODO: This looks wrong given that we can have edit changes in the overlay.\n if (!matchesConstraintAndFilters(overlay.change.row)) {\n overlay = undefined;\n }\n }\n const nextLowerKey = (row: Row | undefined) => {\n if (!row) {\n return undefined;\n }\n let o = overlay;\n if (o) {\n if (comparator(o.change.row, row) >= 0) {\n o = undefined;\n }\n }\n while (row !== undefined) {\n row = data.nextLowerKey(row);\n if (row && matchesConstraintAndFilters(row)) {\n if (o && comparator(o.change.row, row) >= 0) {\n return o.change.row;\n }\n return row;\n }\n }\n return o?.change.row;\n };\n let startAt = req.start?.row;\n if (startAt) {\n if (req.constraint) {\n // There's no problem supporting startAt outside of constraints, but I\n // don't think we have a use case for this \u2013 if we see it, it's probably\n // a bug.\n if (!matchesConstraint(startAt)) {\n assert(false, 'Start row must match constraint');\n }\n }\n if (req.start!.basis === 'before') {\n startAt = nextLowerKey(startAt);\n }\n }\n\n // If there is a constraint, we want to start our scan at the first row that\n // matches the constraint. But because the next OrderPart can be `desc`,\n // it's not true that {[constraintKey]: constraintValue} is the first\n // matching row. Because in that case, the other fields will all be\n // `undefined`, and in Zero `undefined` is always less than any other value.\n // So if the second OrderPart is descending then `undefined` values will\n // actually be the *last* row. We need a way to stay \"start at the first row\n // with this constraint value\". RowBound with the corresponding compareBound\n // comparator accomplishes this. The right thing is probably to teach the\n // btree library to support this concept.\n let scanStart: RowBound | undefined;\n if (req.constraint) {\n scanStart = {};\n for (const [key, dir] of indexSort) {\n if (key === req.constraint.key) {\n scanStart[key] = req.constraint.value;\n } else {\n scanStart[key] = dir === 'asc' ? minValue : maxValue;\n }\n }\n } else {\n scanStart = startAt;\n }\n\n const withOverlay = generateWithOverlay(\n startAt,\n // \uD83D\uDE2C - btree library doesn't support ideas like start \"before\" this\n // key.\n data.keys(scanStart as Row),\n req.constraint,\n overlay,\n comparator,\n );\n\n const withFilters = conn.optionalFilters.length\n ? generateWithFilter(withOverlay, matchesFilters)\n : withOverlay;\n\n yield* generateWithConstraint(\n generateWithStart(withFilters, req, comparator),\n req.constraint,\n );\n }\n\n #cleanup(req: FetchRequest, connection: Connection): Stream<Node> {\n return this.#fetch(req, connection);\n }\n\n push(change: SourceChange): void {\n const primaryIndex = this.#getPrimaryIndex();\n const {data} = primaryIndex;\n\n switch (change.type) {\n case 'add':\n if (data.has(change.row)) {\n throw new Error(`Row already exists: ` + JSON.stringify(change));\n }\n break;\n case 'remove':\n if (!data.has(change.row)) {\n throw new Error(`Row not found: ` + JSON.stringify(change));\n }\n break;\n case 'edit':\n if (!data.has(change.oldRow)) {\n throw new Error(`Row not found: ` + JSON.stringify(change));\n }\n break;\n default:\n unreachable(change);\n }\n\n const outputChange: Change =\n change.type === 'edit'\n ? change\n : {\n type: change.type,\n node: {\n row: change.row,\n relationships: {},\n },\n };\n for (const [outputIndex, {output}] of this.#connections.entries()) {\n if (output) {\n this.#overlay = {outputIndex, change};\n output.push(outputChange);\n }\n }\n this.#overlay = undefined;\n for (const {data} of this.#indexes.values()) {\n switch (change.type) {\n case 'add': {\n const added = data.add(change.row, undefined);\n // must succeed since we checked has() above.\n assert(added);\n break;\n }\n case 'remove': {\n const removed = data.delete(change.row);\n // must succeed since we checked has() above.\n assert(removed);\n break;\n }\n case 'edit': {\n // TODO: We could see if the PK (form the index tree's perspective)\n // changed and if not we could use set.\n\n // We cannot just do `set` with the new value since the `oldRow` might\n // not map to the same entry as the new `row` in the index btree.\n const removed = data.delete(change.oldRow);\n // must succeed since we checked has() above.\n assert(removed);\n data.add(change.row, undefined);\n break;\n }\n default:\n unreachable(change);\n }\n }\n }\n}\n\nfunction* generateWithConstraint(\n it: Stream<Node>,\n constraint: Constraint | undefined,\n) {\n for (const node of it) {\n if (\n constraint &&\n !valuesEqual(node.row[constraint.key], constraint.value)\n ) {\n break;\n }\n yield node;\n }\n}\n\nfunction* generateWithFilter(it: Stream<Node>, filter: (row: Row) => boolean) {\n for (const node of it) {\n if (filter(node.row)) {\n yield node;\n }\n }\n}\n\n/**\n * If the request basis was `before` then the overlay might be the starting point of the stream.\n *\n * This can happen in a case like the following:\n * Store = [1,2,3, 5,6,7]\n * Overlay = [4]\n * Request = fetch starting before 5\n *\n * In this case, the overlay value of `4` should be the starting point of the stream, not `3`.\n */\nexport function* generateWithStart(\n it: Iterator<Node>,\n req: FetchRequest,\n compare: (r1: Row, r2: Row) => number,\n): Stream<Node> {\n // Figure out the start row.\n const cursor = new LookaheadIterator(it, 2);\n\n let started = req.start === undefined ? true : false;\n for (const [curr, next] of cursor) {\n if (!started) {\n assert(req.start);\n if (req.start.basis === 'before') {\n if (next === undefined || compare(next.row, req.start.row) >= 0) {\n started = true;\n }\n } else if (req.start.basis === 'at') {\n if (compare(curr.row, req.start.row) >= 0) {\n started = true;\n }\n } else if (req.start.basis === 'after') {\n if (compare(curr.row, req.start.row) > 0) {\n started = true;\n }\n }\n }\n if (started) {\n yield curr;\n }\n }\n}\n\n/**\n * Takes an iterator and overlay.\n * Splices the overlay into the iterator at the correct position.\n *\n * @param startAt - if there is a lower bound to the stream. If the lower bound of the stream\n * is above the overlay, the overlay will be skipped.\n * @param rows - the stream into which the overlay should be spliced\n * @param constraint - constraint that was applied to the rowIterator and should\n * also be applied to the overlay.\n * @param overlay - the overlay values to splice in\n * @param compare - the comparator to use to find the position for the overlay\n */\nexport function* generateWithOverlay(\n startAt: Row | undefined,\n rows: Iterable<Row>,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n compare: Comparator,\n) {\n const overlays = computeOverlays(startAt, constraint, overlay, compare);\n yield* generateWithOverlayInner(rows, overlays, compare);\n}\n\nfunction computeOverlays(\n startAt: Row | undefined,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n compare: Comparator,\n): [Overlay | undefined, Overlay | undefined] {\n let secondOverlay: Overlay | undefined;\n\n if (\n overlay?.change.type === 'edit' &&\n compare(overlay.change.row, overlay.change.oldRow) !== 0\n ) {\n // Different PK so we split the edit change into a remove and add.\n [overlay, secondOverlay] = splitEditChange(overlay, compare);\n }\n\n if (startAt) {\n overlay = overlayForStartAt(overlay, startAt, compare);\n secondOverlay = overlayForStartAt(secondOverlay, startAt, compare);\n }\n\n if (constraint) {\n overlay = overlayForConstraint(overlay, constraint);\n secondOverlay = overlayForConstraint(secondOverlay, constraint);\n }\n\n if (secondOverlay !== undefined && overlay === undefined) {\n overlay = secondOverlay;\n secondOverlay = undefined;\n }\n\n return [overlay, secondOverlay];\n}\n\nexport {overlayForStartAt as overlayForStartAtForTest};\n\nfunction overlayForStartAt(\n overlay: Overlay | undefined,\n startAt: Row,\n compare: Comparator,\n): Overlay | undefined {\n if (!overlay) {\n return undefined;\n }\n if (compare(overlay.change.row, startAt) < 0) {\n return undefined;\n }\n return overlay;\n}\n\nexport {overlayForConstraint as overlayForConstraintForTest};\n\nfunction overlayForConstraint(\n overlay: Overlay | undefined,\n constraint: Constraint,\n): Overlay | undefined {\n if (!overlay) {\n return undefined;\n }\n\n if (!valuesEqual(overlay.change.row[constraint.key], constraint.value)) {\n return undefined;\n }\n return overlay;\n}\n\nfunction splitEditChange(\n overlay: Overlay,\n compare: Comparator,\n): [Overlay, Overlay] {\n const {oldRow, row} = overlay.change as SourceChangeEdit;\n\n const removeOverlay: Overlay = {\n outputIndex: overlay.outputIndex,\n change: {type: 'remove', row: oldRow},\n };\n const addOverlay: Overlay = {\n outputIndex: overlay.outputIndex,\n change: {type: 'add', row},\n };\n\n const cmp = compare(oldRow, row);\n assert(cmp !== 0, 'We should not split edit change with same PK');\n if (cmp < 0) {\n return [removeOverlay, addOverlay];\n }\n return [addOverlay, removeOverlay];\n}\n\nexport function* generateWithOverlayInner(\n rowIterator: Iterable<Row>,\n overlays: [Overlay | undefined, Overlay | undefined],\n compare: (r1: Row, r2: Row) => number,\n) {\n let [overlay, secondOverlay] = overlays;\n for (const row of rowIterator) {\n if (overlay) {\n if (overlay.change.type === 'add' || overlay.change.type === 'edit') {\n // For edit changes we can only get here if the edit change was not\n // split an the row and the oldRow have the same PK.\n const cmp = compare(overlay.change.row, row);\n if (cmp < 0) {\n yield {row: overlay.change.row, relationships: {}};\n overlay = secondOverlay;\n secondOverlay = undefined;\n }\n }\n\n if (overlay?.change.type === 'remove') {\n const cmp = compare(overlay.change.row, row);\n if (cmp < 0) {\n overlay = secondOverlay;\n secondOverlay = undefined;\n } else if (cmp === 0) {\n overlay = secondOverlay;\n secondOverlay = undefined;\n continue;\n }\n }\n }\n yield {row, relationships: {}};\n }\n\n if (overlay && overlay.change.type === 'add') {\n yield {row: overlay.change.row, relationships: {}};\n }\n}\n\n/**\n * A location to begin scanning an index from. Can either be a specific value\n * or the min or max possible value for the type. This is used to start a scan\n * at the beginning of the rows matching a constraint.\n */\ntype Bound = Value | MinValue | MaxValue;\ntype RowBound = Record<string, Bound>;\nconst minValue = Symbol('min-value');\ntype MinValue = typeof minValue;\nconst maxValue = Symbol('max-value');\ntype MaxValue = typeof maxValue;\n\nfunction makeBoundComparator(sort: Ordering) {\n return (a: RowBound, b: RowBound) => {\n // Hot! Do not use destructuring\n for (const entry of sort) {\n const key = entry[0];\n const cmp = compareBounds(a[key], b[key]);\n if (cmp !== 0) {\n return entry[1] === 'asc' ? cmp : -cmp;\n }\n }\n return 0;\n };\n}\n\nfunction compareBounds(a: Bound, b: Bound): number {\n if (a === b) {\n return 0;\n }\n if (a === minValue) {\n return -1;\n }\n if (b === minValue) {\n return 1;\n }\n if (a === maxValue) {\n return 1;\n }\n if (b === maxValue) {\n return -1;\n }\n return compareValues(a, b);\n}\n\n/**\n * Only returns optional filters if:\n * 1. It's a simple condition\n * 2. It's an `and` condition with only simple conditions inside of it\n * 3. It's an `or` that is a no-op.\n *\n * Otherwise the filters are dropped.\n *\n * This is a short term solution until we update `fetch` to pass\n * the constraints rather than making them static in `connect`.\n *\n * The below way of doing things over-fetches as the optional filters\n * are widened to cover all branches of the pipeline.\n */\nexport function filteredOptionalFilters(\n optionalFilters: Condition | undefined,\n): {filters: SimpleCondition[]; allApplied: boolean} {\n let ret: {\n filters: SimpleCondition[];\n allApplied: boolean;\n } = {\n filters: [],\n allApplied: false,\n };\n\n if (optionalFilters) {\n if (\n optionalFilters.type === 'or' &&\n optionalFilters.conditions.length === 1\n ) {\n optionalFilters = optionalFilters.conditions[0];\n }\n if (optionalFilters.type === 'and') {\n const filters = optionalFilters.conditions.filter(\n c => c.type === 'simple',\n );\n ret = {\n filters,\n allApplied: filters.length === optionalFilters.conditions.length,\n };\n } else if (optionalFilters.type === 'simple') {\n ret = {\n filters: [optionalFilters],\n allApplied: true,\n };\n } else {\n return {filters: [], allApplied: false};\n }\n } else {\n ret.allApplied = true;\n }\n\n return ret;\n}\n", "import {BTree} from '../../../../btree/src/mod.js';\nimport type {JSONValue} from '../../../../shared/src/json.js';\nimport type {Storage} from './operator.js';\nimport type {Stream} from './stream.js';\n\n/**\n * MemoryStorage is a simple in-memory implementation of `Storage` for use\n * on the client and in tests.\n */\nexport class MemoryStorage implements Storage {\n #data: BTree<string, JSONValue> = new BTree();\n\n set(key: string, value: JSONValue) {\n this.#data.add(key, value);\n }\n\n get(key: string, def?: JSONValue): JSONValue | undefined {\n const r = this.#data.get(key);\n if (r !== undefined) {\n return r;\n }\n return def;\n }\n\n del(key: string) {\n this.#data.delete(key);\n }\n\n *scan(options?: {prefix: string}): Stream<[string, JSONValue]> {\n for (const [key, value] of this.#data.entries(options?.prefix)) {\n if (options && !key.startsWith(options.prefix)) {\n return;\n }\n yield [key, value];\n }\n }\n\n cloneData(): Record<string, JSONValue> {\n return structuredClone(Object.fromEntries(this.#data.entries()));\n }\n}\n", "export function reverseString(str: string): string {\n let reversed = '';\n for (let i = str.length - 1; i >= 0; i--) {\n reversed += str[i];\n }\n return reversed;\n}\n", "import {reverseString} from './reverse-string.js';\nimport {h64} from './xxhash.js';\n\n/**\n * xxhash only computes 64-bit values. Run it on the forward and reverse string\n * to get better collision resistance.\n */\nexport function h64WithReverse(str: string): string {\n const forward = h64(str);\n const backward = h64(reverseString(str));\n const full = (forward << 64n) + backward;\n return full.toString(36);\n}\n", "import {h64WithReverse} from '../../../shared/src/h64-with-reverse.js';\nimport * as v from '../../../shared/src/valita.js';\nimport type {Row} from '../../../zero-protocol/src/data.js';\nimport {primaryKeyValueSchema} from '../../../zero-protocol/src/primary-key.js';\nimport type {NormalizedPrimaryKey} from '../../../zql/src/zql/query/normalize-table-schema.js';\n\nexport const CLIENTS_KEY_PREFIX = 'c/';\nexport const DESIRED_QUERIES_KEY_PREFIX = 'd/';\nexport const GOT_QUERIES_KEY_PREFIX = 'g/';\nexport const ENTITIES_KEY_PREFIX = 'e/';\n\nexport function toClientsKey(clientID: string): string {\n return CLIENTS_KEY_PREFIX + clientID;\n}\n\nexport function toDesiredQueriesKey(clientID: string, hash: string): string {\n return DESIRED_QUERIES_KEY_PREFIX + clientID + '/' + hash;\n}\n\nexport function desiredQueriesPrefixForClient(clientID: string): string {\n return DESIRED_QUERIES_KEY_PREFIX + clientID + '/';\n}\n\nexport function toGotQueriesKey(hash: string): string {\n return GOT_QUERIES_KEY_PREFIX + hash;\n}\n\nexport function toPrimaryKeyString(\n tableName: string,\n primaryKey: NormalizedPrimaryKey,\n value: Row,\n): string {\n if (primaryKey.length === 1) {\n return (\n ENTITIES_KEY_PREFIX +\n tableName +\n '/' +\n v.parse(value[primaryKey[0]], primaryKeyValueSchema)\n );\n }\n\n const values = primaryKey.map(k => v.parse(value[k], primaryKeyValueSchema));\n const str = JSON.stringify(values);\n\n const idSegment = h64WithReverse(str);\n return ENTITIES_KEY_PREFIX + tableName + '/' + idSegment;\n}\n", "import type {ExperimentalNoIndexDiff} from '../../../replicache/src/mod.js';\nimport {assert, unreachable} from '../../../shared/src/asserts.js';\nimport type {AST} from '../../../zero-protocol/src/ast.js';\nimport type {Row} from '../../../zero-protocol/src/data.js';\nimport {MemorySource} from '../../../zql/src/zql/ivm/memory-source.js';\nimport {MemoryStorage} from '../../../zql/src/zql/ivm/memory-storage.js';\nimport type {Storage} from '../../../zql/src/zql/ivm/operator.js';\nimport type {Source} from '../../../zql/src/zql/ivm/source.js';\nimport type {\n CommitListener,\n GotCallback,\n QueryDelegate,\n} from '../../../zql/src/zql/query/query-impl.js';\nimport type {TableSchema} from '../../../zql/src/zql/query/schema.js';\nimport {ENTITIES_KEY_PREFIX} from './keys.js';\n\nexport type AddQuery = (\n ast: AST,\n gotCallback?: GotCallback | undefined,\n) => () => void;\n\n/**\n * ZeroContext glues together zql and Replicache. It listens to changes in\n * Replicache data and pushes them into IVM and on tells the server about new\n * queries.\n */\nexport class ZeroContext implements QueryDelegate {\n // It is a bummer to have to maintain separate MemorySources here and copy the\n // data in from the Replicache db. But we want the data to be accessible via\n // pipelines *synchronously* and the core Replicache infra is all async. So\n // that needs to be fixed.\n readonly #sources = new Map<string, MemorySource | undefined>();\n readonly #tables: Record<string, TableSchema>;\n readonly #addQuery: AddQuery;\n readonly #batchViewUpdates: (applyViewUpdates: () => void) => void;\n readonly #commitListeners: Set<CommitListener> = new Set();\n\n readonly staticQueryParameters = undefined;\n\n constructor(\n tables: Record<string, TableSchema>,\n addQuery: AddQuery,\n batchViewUpdates: (applyViewUpdates: () => void) => void,\n ) {\n this.#tables = tables;\n this.#addQuery = addQuery;\n this.#batchViewUpdates = batchViewUpdates;\n }\n\n getSource(name: string): Source | undefined {\n if (this.#sources.has(name)) {\n return this.#sources.get(name);\n }\n\n const schema = this.#tables[name] as TableSchema | undefined;\n const source = schema\n ? new MemorySource(name, schema.columns, schema.primaryKey)\n : undefined;\n this.#sources.set(name, source);\n return source;\n }\n\n addServerQuery(ast: AST, gotCallback?: GotCallback | undefined) {\n return this.#addQuery(ast, gotCallback);\n }\n\n createStorage(): Storage {\n return new MemoryStorage();\n }\n\n onTransactionCommit(cb: CommitListener): () => void {\n this.#commitListeners.add(cb);\n return () => {\n this.#commitListeners.delete(cb);\n };\n }\n\n batchViewUpdates<T>(applyViewUpdates: () => T) {\n let result: T | undefined;\n let viewChangesPerformed = false;\n this.#batchViewUpdates(() => {\n result = applyViewUpdates();\n viewChangesPerformed = true;\n });\n assert(\n viewChangesPerformed,\n 'batchViewUpdates must call applyViewUpdates synchronously.',\n );\n return result as T;\n }\n\n processChanges(changes: ExperimentalNoIndexDiff) {\n try {\n this.batchViewUpdates(() => {\n for (const diff of changes) {\n const {key} = diff;\n assert(key.startsWith(ENTITIES_KEY_PREFIX));\n const slash = key.indexOf('/', ENTITIES_KEY_PREFIX.length);\n const name = key.slice(ENTITIES_KEY_PREFIX.length, slash);\n const source = this.getSource(name);\n if (!source) {\n continue;\n }\n\n switch (diff.op) {\n case 'del':\n assert(typeof diff.oldValue === 'object');\n source.push({\n type: 'remove',\n row: diff.oldValue as Row,\n });\n break;\n case 'add':\n assert(typeof diff.newValue === 'object');\n source.push({\n type: 'add',\n row: diff.newValue as Row,\n });\n break;\n case 'change':\n assert(typeof diff.newValue === 'object');\n assert(typeof diff.oldValue === 'object');\n\n // Edit changes are not yet supported everywhere. For now we only\n // generate them in tests.\n source.push({\n type: 'edit',\n row: diff.newValue as Row,\n oldRow: diff.oldValue as Row,\n });\n\n break;\n default:\n unreachable(diff);\n }\n }\n });\n } finally {\n this.#endTransaction();\n }\n }\n\n #endTransaction() {\n for (const listener of this.#commitListeners) {\n listener();\n }\n }\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.js';\nimport type {MaybePromise} from '../../../shared/src/types.js';\nimport type {Row} from '../../../zero-protocol/src/data.js';\nimport {\n type PrimaryKey,\n type PrimaryKeyValueRecord,\n} from '../../../zero-protocol/src/primary-key.js';\nimport {\n CRUD_MUTATION_NAME,\n type CreateOp,\n type CRUDMutationArg,\n type CRUDOp,\n type CRUDOpKind,\n type DeleteOp,\n type SetOp,\n type UpdateOp,\n} from '../../../zero-protocol/src/push.js';\nimport type {NormalizedPrimaryKey} from '../../../zql/src/zql/query/normalize-table-schema.js';\nimport type {SchemaToRow} from '../../../zql/src/zql/query/query.js';\nimport {toPrimaryKeyString} from './keys.js';\nimport type {NormalizedSchema} from './normalized-schema.js';\nimport type {MutatorDefs, WriteTransaction} from './replicache-types.js';\nimport type {Schema} from './zero.js';\n\nexport type SetValue<\n R extends Row,\n PK extends PrimaryKey,\n> = AsPrimaryKeyValueRecord<Pick<R, PK[number]>> & Omit<R, PK[number]>;\n\nexport type CreateValue<R extends Row, PK extends PrimaryKey> = SetValue<R, PK>;\n\nexport type UpdateValue<\n R extends Row,\n PK extends PrimaryKey,\n> = AsPrimaryKeyValueRecord<Pick<R, PK[number]>> & Partial<Omit<R, PK[number]>>;\n\nexport type DeleteID<\n R extends Row,\n PK extends PrimaryKey,\n> = AsPrimaryKeyValueRecord<Pick<R, PK[number]>>;\n\ntype AsPrimaryKeyValueRecord<R extends Row> = R extends PrimaryKeyValueRecord\n ? R\n : never;\n\n/**\n * This is the type of the generated mutate.<name>.<verb> function.\n */\nexport type RowCRUDMutate<R extends Row, PK extends PrimaryKey> = {\n create: (value: CreateValue<R, PK>) => Promise<void>;\n set: (value: SetValue<R, PK>) => Promise<void>;\n update: (value: UpdateValue<R, PK>) => Promise<void>;\n delete: (id: DeleteID<R, PK>) => Promise<void>;\n};\n\n/**\n * This is the type of the generated mutate.<name> object.\n */\nexport type MakeCRUDMutate<S extends Schema> = BaseCRUDMutate<S> & CRUDBatch<S>;\n\nexport type BaseCRUDMutate<S extends Schema> = {\n [K in keyof S['tables']]: RowCRUDMutate<\n SchemaToRow<S['tables'][K]>,\n S['tables'][K]['primaryKey']\n >;\n};\n\nexport type CRUDBatch<S extends Schema> = <R>(\n body: (m: BaseCRUDMutate<S>) => MaybePromise<R>,\n) => Promise<R>;\n\ntype ZeroCRUDMutate = {\n [CRUD_MUTATION_NAME]: CRUDMutate;\n};\n\n/**\n * This is the zero.mutate object part representing the CRUD operations. If the\n * queries are `issue` and `label`, then this object will have `issue` and\n * `label` properties.\n */\nexport function makeCRUDMutate<const S extends Schema>(\n schema: NormalizedSchema,\n repMutate: ZeroCRUDMutate,\n): MakeCRUDMutate<S> {\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n let inBatch = false;\n\n const mutate = async <R>(body: (m: BaseCRUDMutate<S>) => R): Promise<R> => {\n if (inBatch) {\n throw new Error('Cannot call mutate inside a batch');\n }\n inBatch = true;\n\n try {\n const ops: CRUDOp[] = [];\n const m = {} as Record<string, unknown>;\n for (const name of Object.keys(schema.tables)) {\n m[name] = makeBatchCRUDMutate(name, schema, ops);\n }\n\n const rv = await body(m as BaseCRUDMutate<S>);\n await zeroCRUD({ops});\n return rv;\n } finally {\n inBatch = false;\n }\n };\n\n const assertNotInBatch = (tableName: string, op: CRUDOpKind) => {\n if (inBatch) {\n throw new Error(`Cannot call mutate.${tableName}.${op} inside a batch`);\n }\n };\n\n for (const [name, tableSchema] of Object.entries(schema.tables)) {\n (mutate as unknown as Record<string, RowCRUDMutate<Row, PrimaryKey>>)[\n name\n ] = makeEntityCRUDMutate(\n name,\n tableSchema.primaryKey,\n zeroCRUD,\n assertNotInBatch,\n );\n }\n return mutate as MakeCRUDMutate<S>;\n}\n\n/**\n * Creates the `{create, set, update, delete}` object for use outside a batch.\n */\nfunction makeEntityCRUDMutate<R extends Row, PK extends NormalizedPrimaryKey>(\n tableName: string,\n primaryKey: PK,\n zeroCRUD: CRUDMutate,\n assertNotInBatch: (tableName: string, op: CRUDOpKind) => void,\n): RowCRUDMutate<R, PK> {\n return {\n create: (value: CreateValue<R, PK>) => {\n assertNotInBatch(tableName, 'create');\n const op: CreateOp = {\n op: 'create',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n set: (value: SetValue<R, PK>) => {\n assertNotInBatch(tableName, 'set');\n const op: SetOp = {\n op: 'set',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n update: (value: UpdateValue<R, PK>) => {\n assertNotInBatch(tableName, 'update');\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n delete: (id: DeleteID<R, PK>) => {\n assertNotInBatch(tableName, 'delete');\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n return zeroCRUD({ops: [op]});\n },\n };\n}\n\n/**\n * Creates the `{create, set, update, delete}` object for use inside a batch.\n */\nexport function makeBatchCRUDMutate<\n R extends Row,\n PK extends NormalizedPrimaryKey,\n>(\n tableName: string,\n schema: NormalizedSchema,\n ops: CRUDOp[],\n): RowCRUDMutate<R, PK> {\n const {primaryKey} = schema.tables[tableName];\n return {\n create: (value: CreateValue<R, PK>) => {\n const op: CreateOp = {\n op: 'create',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n set: (value: SetValue<R, PK>) => {\n const op: SetOp = {\n op: 'set',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n update: (value: UpdateValue<R, PK>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n delete: (id: DeleteID<R, PK>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n ops.push(op);\n return promiseVoid;\n },\n };\n}\n\nexport type WithCRUD<MD extends MutatorDefs> = MD & {\n [CRUD_MUTATION_NAME]: CRUDMutator;\n};\n\nexport type CRUDMutate = (crudArg: CRUDMutationArg) => Promise<void>;\n\nexport type CRUDMutator = (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n) => Promise<void>;\n\nexport function makeCRUDMutator(schema: NormalizedSchema): CRUDMutator {\n return async function zeroCRUDMutator(\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n ): Promise<void> {\n for (const op of crudArg.ops) {\n switch (op.op) {\n case 'create':\n await createImpl(tx, op, schema);\n break;\n case 'set':\n await setImpl(tx, op, schema);\n break;\n case 'update':\n await updateImpl(tx, op, schema);\n break;\n case 'delete':\n await deleteImpl(tx, op, schema);\n break;\n }\n }\n };\n}\n\nasync function createImpl(\n tx: WriteTransaction,\n arg: CreateOp,\n schema: NormalizedSchema,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (!(await tx.has(key))) {\n await tx.set(key, arg.value);\n }\n}\n\nasync function setImpl(\n tx: WriteTransaction,\n arg: CreateOp | SetOp,\n schema: NormalizedSchema,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n await tx.set(key, arg.value);\n}\n\nasync function updateImpl(\n tx: WriteTransaction,\n arg: UpdateOp,\n schema: NormalizedSchema,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n const update = arg.value;\n const next = {...(prev as object), ...(update as object)};\n await tx.set(key, next);\n}\n\nasync function deleteImpl(\n tx: WriteTransaction,\n arg: DeleteOp,\n schema: NormalizedSchema,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n await tx.del(key);\n}\n", "// https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html\nconst IPV4_ADDRESS_REGEX =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n// This doesn't ensure a valid ipv6, but any ipv6 hostname will\n// match this regex, and no domain based hostnames will.\nconst IPV6_ADDRESS_HOSTNAME_REGEX = /^\\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\\]$/;\n\nexport const IP_ADDRESS_HOSTNAME_REGEX = new RegExp(\n `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`,\n);\n\nexport function shouldEnableAnalytics(\n server: string | null,\n enableAnalytics = true,\n): boolean {\n if (!enableAnalytics) {\n return false;\n }\n const serverURL = server === null ? null : new URL(server);\n const socketHostname = serverURL?.hostname;\n // If the hostname is undefined, localhost, or an ip address, then\n // this is most likely a test or local development, in which case we\n // do not want to enable analytics.\n return (\n server !== null &&\n socketHostname !== undefined &&\n socketHostname !== 'localhost' &&\n !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname)\n );\n}\n", "import {assert} from '../../../shared/src/asserts.js';\n\nexport type HTTPString = `http${'' | 's'}://${string}`;\n\nexport type WSString = `ws${'' | 's'}://${string}`;\n\nexport function toWSString(url: HTTPString): WSString {\n return ('ws' + url.slice(4)) as WSString;\n}\n\nexport function toHTTPString(url: WSString): HTTPString {\n return ('http' + url.slice(2)) as HTTPString;\n}\n\nexport function assertHTTPString(url: string): asserts url is HTTPString {\n assert(/^https?:\\/\\//.test(url));\n}\n\nexport function assertWSString(url: string): asserts url is WSString {\n assert(/^wss?:\\/\\//.test(url));\n}\n", "import {\n TeeLogSink,\n consoleLogSink,\n type Context,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\nimport {\n DatadogLogSink,\n type DatadogLogSinkOptions,\n} from '../../../datadog/src/mod.js';\nimport {version} from './version.js';\n\nclass LevelFilterLogSink implements LogSink {\n readonly #wrappedLogSink: LogSink;\n readonly #level: LogLevel;\n\n constructor(wrappedLogSink: LogSink, level: LogLevel) {\n this.#wrappedLogSink = wrappedLogSink;\n this.#level = level;\n }\n\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n if (this.#level === 'error' && level !== 'error') {\n return;\n }\n if (this.#level === 'info' && level === 'debug') {\n return;\n }\n this.#wrappedLogSink.log(level, context, ...args);\n }\n\n async flush() {\n await consoleLogSink.flush?.();\n }\n}\n\nconst DATADOG_LOG_LEVEL = 'info';\nconst ZERO_SASS_DOMAIN = '.reflect-server.net';\n\nexport type LogOptions = {\n readonly logLevel: LogLevel;\n readonly logSink: LogSink;\n};\n\nexport function createLogOptions(\n options: {\n consoleLogLevel: LogLevel;\n server: string | null;\n enableAnalytics: boolean;\n },\n createDatadogLogSink: (options: DatadogLogSinkOptions) => LogSink = (\n options: DatadogLogSinkOptions,\n ) => new DatadogLogSink(options),\n): LogOptions {\n const {consoleLogLevel, server, enableAnalytics} = options;\n\n if (!enableAnalytics || server === null) {\n return {\n logLevel: consoleLogLevel,\n logSink: consoleLogSink,\n };\n }\n\n const serverURL = new URL(server);\n const socketHostname = serverURL.hostname;\n const datadogServiceLabel = socketHostname.endsWith(ZERO_SASS_DOMAIN)\n ? socketHostname\n .substring(0, socketHostname.length - ZERO_SASS_DOMAIN.length)\n .toLowerCase()\n : socketHostname;\n const baseURL = new URL('/api/logs/v0/log', server);\n const logLevel = consoleLogLevel === 'debug' ? 'debug' : 'info';\n const logSink = new TeeLogSink([\n new LevelFilterLogSink(consoleLogSink, consoleLogLevel),\n new LevelFilterLogSink(\n createDatadogLogSink({\n service: datadogServiceLabel,\n host: location.host,\n version,\n baseURL,\n }),\n DATADOG_LOG_LEVEL,\n ),\n ]);\n return {\n logLevel,\n logSink,\n };\n}\n", "import {Lock} from '@rocicorp/lock';\nimport type {Context, LogLevel, LogSink} from '@rocicorp/logger';\n\nexport interface DatadogLogSinkOptions {\n apiKey?: string | undefined;\n source?: string | undefined;\n service?: string | undefined;\n host?: string | undefined;\n version?: string | undefined;\n interval?: number | undefined;\n baseURL?: URL | undefined;\n}\n\nconst DD_BASE_URL = new URL(\n 'https://http-intake.logs.datadoghq.com/api/v2/logs',\n);\n\n// https://docs.datadoghq.com/api/latest/logs/\nexport const MAX_LOG_ENTRIES_PER_FLUSH = 1000;\nexport const FORCE_FLUSH_THRESHOLD = 250;\nconst MAX_ENTRY_BYTES = 5 * 1024 * 1024;\nconst MAX_MESSAGE_RETRIES = 2;\n\n// Conservative limit that assumes all chars are encoded as 4 UTF-8 bytes.\n// This makes the actual limit somewhere closer to 1.25 MB, which is still\n// a reasonable amount of log data to send per request.\nexport const MAX_ENTRY_CHARS = MAX_ENTRY_BYTES / 4;\n\nexport class DatadogLogSink implements LogSink {\n #messages: Message[] = [];\n readonly #apiKey: string | undefined;\n readonly #source: string | undefined;\n readonly #service: string | undefined;\n readonly #host: string | undefined;\n readonly #version: string | undefined;\n readonly #interval: number;\n readonly #baseURL: string;\n #timerID: ReturnType<typeof setTimeout> | 0 = 0;\n #flushLock = new Lock();\n\n constructor(options: DatadogLogSinkOptions) {\n const {\n apiKey,\n source,\n service,\n host,\n version,\n interval = 5_000,\n baseURL: baseUrl = DD_BASE_URL,\n } = options;\n\n this.#apiKey = apiKey;\n this.#source = source;\n this.#service = service;\n this.#host = host;\n this.#version = version;\n this.#interval = interval;\n this.#baseURL = baseUrl.toString();\n }\n\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n this.#messages.push(makeMessage(args, context, level));\n if (level === 'error' || this.#messages.length === FORCE_FLUSH_THRESHOLD) {\n // Do not await. Later calls to flush will await as needed.\n void this.flush();\n } else {\n this.#startTimer();\n }\n }\n #startTimer() {\n if (this.#timerID) {\n return;\n }\n\n this.#timerID = setTimeout(() => {\n this.#timerID = 0;\n\n void this.flush();\n }, this.#interval);\n }\n\n flush(): Promise<void> {\n return this.#flushLock.withLock(async () => {\n const {length} = this.#messages;\n if (length === 0) {\n return;\n }\n do {\n const flushTime = Date.now();\n const stringified = [];\n let totalBytes = 0;\n\n for (const m of this.#messages) {\n // As a small perf optimization, we directly mutate\n // the message rather than making a shallow copy.\n // The LOG_SINK_FLUSH_DELAY_ATTRIBUTE will be clobbered by\n // the next flush if this flush fails (which is the desired behavior).\n m.flushDelayMs = flushTime - m.date;\n\n let str = JSON.stringify(m);\n if (str.length > MAX_ENTRY_CHARS) {\n // A single message above the total payload limit will otherwise halt\n // log flushing progress. Drop and replace with a message indicating so.\n m.message = `[Dropped message of length ${str.length}]`;\n str = JSON.stringify(m);\n }\n // Calculate the totalBytes with the newline characters between messages.\n if (str.length + totalBytes + stringified.length > MAX_ENTRY_CHARS) {\n break;\n }\n totalBytes += str.length;\n stringified.push(str);\n\n if (stringified.length === MAX_LOG_ENTRIES_PER_FLUSH) {\n break;\n }\n }\n\n const body = stringified.join('\\n');\n const url = new URL(this.#baseURL);\n if (this.#apiKey !== undefined) {\n url.searchParams.set('dd-api-key', this.#apiKey);\n }\n\n if (this.#source) {\n // Both need to be set for server to treat us as the browser SDK for\n // value 'browser'.\n url.searchParams.set('ddsource', this.#source);\n url.searchParams.set('dd-evp-origin', this.#source);\n }\n\n if (this.#service) {\n url.searchParams.set('service', this.#service);\n }\n\n if (this.#host) {\n url.searchParams.set('host', this.#host);\n }\n\n if (this.#version) {\n url.searchParams.set('ddtags', `version:${this.#version}`);\n }\n\n let ok = false;\n try {\n const response = await fetch(url.toString(), {\n method: 'POST',\n body,\n keepalive: true,\n } as RequestInit);\n\n ok = response.ok;\n if (!ok) {\n // Log to console so that we might catch this in `wrangler tail`.\n console.error(\n 'response',\n response.status,\n response.statusText,\n await response.text,\n );\n }\n } catch (e) {\n // Log to console so that we might catch this in `wrangler tail`.\n console.error('Log flush to datadog failed', e);\n }\n\n if (ok) {\n // Remove messages that were successfully flushed.\n this.#messages.splice(0, stringified.length);\n } else {\n let numWithTooManyRetries = 0;\n for (let i = 0; i < stringified.length; i++) {\n const m = this.#messages[i];\n m.flushRetryCount = (m.flushRetryCount ?? 0) + 1;\n if (m.flushRetryCount > MAX_MESSAGE_RETRIES) {\n numWithTooManyRetries++;\n }\n }\n if (numWithTooManyRetries > 0) {\n console.error(\n `Dropping ${numWithTooManyRetries} datadog log messages which failed to send ${\n MAX_MESSAGE_RETRIES + 1\n } times.`,\n );\n // Remove messages that have failed too many times.\n this.#messages.splice(0, numWithTooManyRetries);\n }\n }\n } while (this.#messages.length >= FORCE_FLUSH_THRESHOLD);\n // If any messages left at this point schedule another flush.\n if (this.#messages.length) {\n this.#startTimer();\n }\n });\n }\n}\n\ntype Message = Context & {\n status: LogLevel;\n date: number;\n message: unknown;\n error?: {origin: 'logger'};\n flushDelayMs?: number;\n flushRetryCount?: number;\n};\n\nfunction flattenMessage(message: unknown): unknown {\n if (Array.isArray(message) && message.length === 1) {\n return flattenMessage(message[0]);\n }\n return message;\n}\n\nfunction convertError(e: Error): {\n name: string;\n message: string;\n stack: string | undefined;\n} {\n return {\n name: e.name,\n message: e.message,\n stack: e.stack,\n };\n}\n\nfunction convertErrors(message: unknown): unknown {\n if (message instanceof Error) {\n return convertError(message);\n }\n if (message instanceof Array) {\n const convertedMessage: unknown[] = [];\n for (const item of message) {\n if (item instanceof Error) {\n convertedMessage.push(convertError(item));\n } else {\n convertedMessage.push(item);\n }\n }\n return convertedMessage;\n }\n return message;\n}\n\nconst LOG_SINK_FLUSH_RETRY_COUNT = 'flushRetryCount';\nconst LOG_SINK_FLUSH_DELAY_ATTRIBUTE = 'flushDelayMs';\n// This code assumes that no context keys will start with\n// @DATADOG_RESERVED_ (a fairly safe assumption).\nconst RESERVED_KEY_PREFIX = '@DATADOG_RESERVED_';\n// See https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#reserved-attributes\n// Note 'msg' and 'date' are not documented.\n// We should avoid using these as context keys. We escape them here\n// because otherwise the impact on the data dog log UI is very confusing\n// (e.g. using 'msg' as a context key results, in the context value\n// replacing the log message.)\nconst RESERVED_KEYS: ReadonlyArray<string> = [\n 'host',\n 'source',\n 'status',\n 'service',\n 'version',\n 'trace_id',\n 'message',\n 'msg', // alias for message\n 'date',\n // The following are attributes reserved by the DataDogLogSink\n // itself (as opposed to DataDog), to report on its own behavior.\n LOG_SINK_FLUSH_DELAY_ATTRIBUTE,\n LOG_SINK_FLUSH_RETRY_COUNT,\n];\n\nfunction makeMessage(\n message: unknown,\n context: Context | undefined,\n logLevel: LogLevel,\n): Message {\n let safeContext = undefined;\n if (context !== undefined) {\n for (const reservedKey of RESERVED_KEYS) {\n if (Object.hasOwn(context, reservedKey)) {\n if (safeContext === undefined) {\n safeContext = {...context};\n }\n safeContext[RESERVED_KEY_PREFIX + reservedKey] =\n safeContext[reservedKey];\n delete safeContext[reservedKey];\n }\n }\n }\n const msg: Message = {\n ...(safeContext ?? context),\n date: Date.now(),\n message: convertErrors(flattenMessage(message)),\n status: logLevel,\n };\n if (logLevel === 'error') {\n msg.error = {origin: 'logger'};\n }\n return msg;\n}\n", "// The env value should be filled in by esbuild.\n\ndeclare const process: {\n env: {\n ['ZERO_VERSION']?: string;\n };\n};\n\n/**\n * The current version of Zero.\n */\nexport const version = process.env.ZERO_VERSION ?? '0.0.0';\n", "import type {LogContext} from '@rocicorp/logger';\nimport type {MaybePromise} from '../../../shared/src/types.js';\nimport type {ErrorKind as ServerErrorKind} from '../../../zero-protocol/src/mod.js';\n\nexport enum MetricName {\n TimeToConnectMs = 'time_to_connect_ms',\n LastConnectError = 'last_connect_error',\n TimeToConnectMsV2 = 'time_to_connect_ms_v2',\n LastConnectErrorV2 = 'last_connect_error_v2',\n TotalTimeToConnectMs = 'total_time_to_connect_ms',\n NotConnected = 'not_connected',\n}\n\n// This value is used to indicate that the client's last connection attempt\n// failed. We don't make this -1 because we want to stack this never connected\n// state in a graph on top of actual connection times, so it should be greater\n// than any other value.\nexport const DID_NOT_CONNECT_VALUE = 100 * 1000;\n\nexport const REPORT_INTERVAL_MS = 5_000;\n\ntype ClientDisconnectReason =\n | 'AbruptClose'\n | 'CleanClose'\n | 'ClientClosed'\n | 'ConnectTimeout'\n | 'UnexpectedBaseCookie'\n | 'PingTimeout'\n | 'Hidden';\n\ntype NotConnectedReason =\n | 'init'\n | 'error'\n | 'hidden'\n | 'hidden_was_init'\n | 'hidden_was_error';\n\nexport type DisconnectReason =\n | {\n server: ServerErrorKind;\n }\n | {\n client: ClientDisconnectReason;\n };\n\nexport function getLastConnectErrorValue(reason: DisconnectReason): string {\n if ('server' in reason) {\n return `server_${camelToSnake(reason.server)}`;\n }\n return `client_${camelToSnake(reason.client)}`;\n}\n\n// camelToSnake is used to convert a protocol ErrorKind into a suitable\n// metric name, eg AuthInvalidated => auth_invalidated. It converts\n// both PascalCase and camelCase to snake_case.\nfunction camelToSnake(s: string): string {\n return s\n .split(/\\.?(?=[A-Z])/)\n .join('_')\n .toLowerCase();\n}\n\ntype MetricsReporter = (metrics: Series[]) => MaybePromise<void>;\n\nexport type MetricManagerOptions = {\n reportIntervalMs: number;\n host: string;\n source: string;\n reporter: MetricsReporter;\n lc: LogContext;\n};\n\n/**\n * MetricManager keeps track of the set of metrics in use and flushes them\n * to a format suitable for reporting.\n */\nexport class MetricManager {\n #reportIntervalMs: number;\n #host: string;\n #reporter: MetricsReporter;\n #lc: LogContext;\n #timerID: ReturnType<typeof setInterval> | null;\n\n constructor(opts: MetricManagerOptions) {\n this.#reportIntervalMs = opts.reportIntervalMs;\n this.#host = opts.host;\n this.#reporter = opts.reporter;\n this.#lc = opts.lc;\n\n this.tags.push(`source:${opts.source}`);\n\n this.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#setNotConnectedReason('init');\n\n this.#timerID = setInterval(() => {\n void this.flush();\n }, this.#reportIntervalMs);\n }\n\n #metrics: Flushable[] = [];\n\n // timeToConnectMs measures the time from the call to connect() to receiving\n // the 'connected' ws message. We record the DID_NOT_CONNECT_VALUE if the previous\n // connection attempt failed for any reason.\n //\n // We set the gauge using #connectStart as follows:\n // - #connectStart is undefined if we are disconnected or connected; it is\n // defined only in the Connecting state, as a number representing the timestamp\n // at which we started connecting.\n // - #connectStart is set to the current time when connect() is called.\n // - When we receive the 'connected' message we record the time to connect and\n // set #connectStart to undefined.\n // - If disconnect() is called with a defined #connectStart then we record\n // DID_NOT_CONNECT_VALUE and set #connectStart to undefined.\n //\n // TODO It's clear after playing with the connection code we should encapsulate\n // the ConnectionState along with its state transitions and possibly behavior.\n // In that world the metric gauge(s) and bookkeeping like #connectStart would\n // be encapsulated with the ConnectionState. This will probably happen as part\n // of https://github.com/rocicorp/reflect-server/issues/255.\n readonly timeToConnectMs = this.#register(\n new Gauge(MetricName.TimeToConnectMs),\n );\n\n // lastConnectError records the last error that occurred when connecting,\n // if any. It is cleared when connecting successfully or when reported, so this\n // state only gets reported if there was a failure during the reporting period and\n // we are still not connected.\n readonly lastConnectError = this.#register(\n new State(\n MetricName.LastConnectError,\n true, // clearOnFlush\n ),\n );\n\n // notConnected records the reason why the client is not currently connected.\n // It is cleared when the client successfully connects.\n readonly #notConnected = this.#register(new State(MetricName.NotConnected));\n\n // The time from the call to connect() to receiving the 'connected' ws message\n // for the current connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect untill there is a\n // connect error, or client reports disconnected and waiting for visible.\n // Should have a value iff _notConnected has no value.\n readonly #timeToConnectMsV2 = this.#register(\n new Gauge(MetricName.TimeToConnectMsV2),\n );\n\n // lastConnectErrorV2 records the last error that occurred when connecting,\n // if any. It is cleared when the client successfully connects or\n // stops trying to connect due to being hidden.\n // Should have a value iff notConnected state is NotConnectedReason.Error.\n readonly #lastConnectErrorV2 = this.#register(\n new State(MetricName.LastConnectErrorV2),\n );\n\n // The total time it took to connect across retries for the current\n // connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect until there is a\n // connect error, or client reports disconnected and waiting for visible.\n // See Zero.#totalToConnectStart for details of how this total is computed.\n // Should have a value iff _notConnected has no value.\n readonly #totalTimeToConnectMs = this.#register(\n new Gauge(MetricName.TotalTimeToConnectMs),\n );\n\n #setNotConnectedReason(reason: NotConnectedReason) {\n this.#notConnected.set(reason);\n }\n\n setConnected(timeToConnectMs: number, totalTimeToConnectMs: number) {\n this.#notConnected.clear();\n this.#lastConnectErrorV2.clear();\n this.#timeToConnectMsV2.set(timeToConnectMs);\n this.#totalTimeToConnectMs.set(totalTimeToConnectMs);\n }\n\n setDisconnectedWaitingForVisible() {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#lastConnectErrorV2.clear();\n let notConnectedReason: NotConnectedReason;\n switch (this.#notConnected.get()) {\n case 'init':\n notConnectedReason = 'hidden_was_init';\n break;\n case 'error':\n notConnectedReason = 'hidden_was_error';\n break;\n default:\n notConnectedReason = 'hidden';\n break;\n }\n this.#setNotConnectedReason(notConnectedReason);\n }\n\n setConnectError(reason: DisconnectReason) {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#setNotConnectedReason('error');\n this.#lastConnectErrorV2.set(getLastConnectErrorValue(reason));\n }\n\n /**\n * Tags to include in all metrics.\n */\n readonly tags: string[] = [];\n\n // Flushes all metrics to an array of time series (plural), one Series\n // per metric.\n async flush() {\n const lc = this.#lc;\n if (this.#timerID === null) {\n lc.error?.('MetricManager.flush() called but already stopped');\n return;\n }\n const allSeries: Series[] = [];\n for (const metric of this.#metrics) {\n const series = metric.flush();\n if (series !== undefined) {\n allSeries.push({\n ...series,\n host: this.#host,\n tags: this.tags,\n });\n }\n }\n if (allSeries.length === 0) {\n lc?.debug?.('No metrics to report');\n return;\n }\n try {\n await this.#reporter(allSeries);\n } catch (e) {\n lc?.error?.(`Error reporting metrics: ${e}`);\n }\n }\n\n stop() {\n if (this.#timerID === null) {\n this.#lc.error?.('MetricManager.stop() called but already stopped');\n return;\n }\n clearInterval(this.#timerID);\n this.#timerID = null;\n }\n\n #register<M extends Flushable>(metric: M) {\n this.#metrics.push(metric);\n return metric;\n }\n}\n\n// These two types are influenced by Datadog's API's needs. We could change what\n// we use internally if necessary, but we'd just have to convert to/from before\n// sending to DD. So for convenience we go with their format.\n\n/** Series is a time series of points for a single metric. */\nexport type Series = {\n host: string;\n metric: string; // We call this 'name' bc 'metric' is overloaded in code.\n points: Point[];\n tags?: string[];\n};\n/**\n * A point is a second-resolution timestamp and a set of values for that\n * timestamp. A point represents exactly one second in time and the values\n * are those recorded for that second. The first element of this array\n * is the timestamp and the second element is an array of values.\n */\nexport type Point = [number, number[]];\n\nfunction makePoint(ts: number, value: number): Point {\n return [ts, [value]];\n}\n\ntype Flushable = {\n flush(): Pick<Series, 'metric' | 'points'> | undefined;\n};\n\n/**\n * Gauge is a metric type that represents a single value that can go up and\n * down. It's typically used to track discrete values or counts eg the number\n * of active users, number of connections, cpu load, etc. A gauge retains\n * its value when flushed.\n *\n * We use a Gauge to sample at the client. If we are interested in tracking\n * a metric value *per client*, the client can note the latest value in\n * a Gauge metric. The metric is periodically reported via Reporter. On the\n * server, we graph the value of the metric rolled up over the periodic\n * reporting period, that is, counted over a span of time equal to the\n * reporting period. The result is ~one point per client per reporting\n * period.\n */\nexport class Gauge implements Flushable {\n readonly #name: string;\n #value: number | undefined = undefined;\n\n constructor(name: string) {\n this.#name = name;\n }\n\n set(value: number) {\n this.#value = value;\n }\n\n get() {\n return this.#value;\n }\n\n clear() {\n this.#value = undefined;\n }\n\n flush() {\n if (this.#value === undefined) {\n return undefined;\n }\n // Gauge reports the timestamp at flush time, not at the point the value was\n // recorded.\n const points = [makePoint(t(), this.#value)];\n return {metric: this.#name, points};\n }\n}\n\nfunction t() {\n return Math.round(Date.now() / 1000);\n}\n\n/**\n * State is a metric type that represents a specific state that the system is\n * in, for example the state of a connection which may be 'open' or 'closed'.\n * The state is given a name/prefix at construction time (eg 'connection') and\n * then can be set to a specific state (eg 'open'). The prefix is prepended to\n * the set state (eg, 'connection_open') and a value of 1 is reported.\n * Unset/cleared states are not reported.\n *\n * Example:\n * const s = new State('connection');\n * s.set('open');\n * s.flush(); // returns {metric: 'connection_open', points: [[now(), [1]]]}\n */\nexport class State implements Flushable {\n readonly #prefix: string;\n readonly #clearOnFlush: boolean;\n #current: string | undefined = undefined;\n\n constructor(prefix: string, clearOnFlush = false) {\n this.#prefix = prefix;\n this.#clearOnFlush = clearOnFlush;\n }\n\n set(state: string) {\n this.#current = state;\n }\n\n get() {\n return this.#current;\n }\n\n clear() {\n this.#current = undefined;\n }\n\n flush() {\n if (this.#current === undefined) {\n return undefined;\n }\n const gauge = new Gauge([this.#prefix, this.#current].join('_'));\n gauge.set(1);\n const series = gauge.flush();\n if (this.#clearOnFlush) {\n this.clear();\n }\n return series;\n }\n}\n", "import {sortedEntries} from '../../../shared/src/sorted-entries.js';\nimport type {Writable} from '../../../shared/src/writable.js';\nimport {\n NormalizedTableSchema,\n normalizeTableSchemaWithCache,\n type TableSchemaCache,\n} from '../../../zql/src/zql/query/normalize-table-schema.js';\nimport type {Schema} from './zero.js';\n\n/**\n * Creates a normalized schema from a schema.\n *\n * A normalized schema has all the keys sorted and the primary key and the\n * primary key columns are checked to be valid.\n */\nexport function normalizeSchema(schema: Schema): NormalizedSchema {\n if (schema instanceof NormalizedSchema) {\n return schema;\n }\n return new NormalizedSchema(schema);\n}\n\nexport class NormalizedSchema {\n readonly version: number;\n readonly tables: {\n readonly [table: string]: NormalizedTableSchema;\n };\n\n constructor(schema: Schema) {\n this.version = schema.version;\n this.tables = normalizeTables(schema.tables);\n }\n}\n\nfunction normalizeTables(tables: Schema['tables']): {\n readonly [table: string]: NormalizedTableSchema;\n} {\n const rv: Writable<{\n readonly [table: string]: NormalizedTableSchema;\n }> = {};\n const tableSchemaCache: TableSchemaCache = new Map();\n for (const [name, table] of sortedEntries(tables)) {\n rv[name] = normalizeTableSchemaWithCache(table, name, tableSchemaCache);\n }\n return rv;\n}\n", "import type {ClientID} from '../../../replicache/src/mod.js';\nimport type {ReplicacheImpl} from '../../../replicache/src/replicache-impl.js';\nimport {must} from '../../../shared/src/must.js';\nimport {hashOfAST} from '../../../zero-protocol/src/ast-hash.js';\nimport {normalizeAST, type AST} from '../../../zero-protocol/src/ast.js';\nimport type {\n ChangeDesiredQueriesMessage,\n QueriesPatchOp,\n} from '../../../zero-protocol/src/mod.js';\nimport type {GotCallback} from '../../../zql/src/zql/query/query-impl.js';\nimport type {ReadTransaction} from '../mod.js';\nimport {desiredQueriesPrefixForClient, GOT_QUERIES_KEY_PREFIX} from './keys.js';\n\ntype QueryHash = string;\n\n/**\n * Tracks what queries the client is currently subscribed to on the server.\n * Sends `changeDesiredQueries` message to server when this changes.\n * Deduplicates requests so that we only listen to a given unique query once.\n */\nexport class QueryManager {\n readonly #clientID: ClientID;\n readonly #send: (change: ChangeDesiredQueriesMessage) => void;\n readonly #queries: Map<\n QueryHash,\n {normalized: AST; count: number; gotCallbacks: GotCallback[]}\n > = new Map();\n readonly #gotQueries: Set<string> = new Set();\n\n constructor(\n clientID: ClientID,\n send: (change: ChangeDesiredQueriesMessage) => void,\n experimentalWatch: InstanceType<typeof ReplicacheImpl>['experimentalWatch'],\n ) {\n this.#clientID = clientID;\n this.#send = send;\n experimentalWatch(\n diff => {\n for (const diffOp of diff) {\n const queryHash = diffOp.key.substring(GOT_QUERIES_KEY_PREFIX.length);\n switch (diffOp.op) {\n case 'add':\n this.#gotQueries.add(queryHash);\n this.#fireGotCallbacks(queryHash, true);\n break;\n case 'del':\n this.#gotQueries.delete(queryHash);\n this.#fireGotCallbacks(queryHash, false);\n break;\n }\n }\n },\n {\n prefix: GOT_QUERIES_KEY_PREFIX,\n initialValuesInFirstDiff: true,\n },\n );\n }\n\n #fireGotCallbacks(queryHash: string, got: boolean) {\n const gotCallbacks = this.#queries.get(queryHash)?.gotCallbacks ?? [];\n for (const gotCallback of gotCallbacks) {\n gotCallback(got);\n }\n }\n\n /**\n * Get the queries that need to be registered with the server.\n *\n * An optional `lastPatch` can be provided. This is the last patch that was\n * sent to the server and may not yet have been acked. If `lastPatch` is provided,\n * this method will return a patch that does not include any events sent in `lastPatch`.\n *\n * This diffing of last patch and current patch is needed since we send\n * a set of queries to the server when we first connect inside of the `sec-protocol` as\n * the `initConnectionMessage`.\n *\n * While we're waiting for the `connected` response to come back from the server,\n * the client may have registered more queries. We need to diff the `initConnectionMessage`\n * queries with the current set of queries to understand what those were.\n */\n async getQueriesPatch(\n tx: ReadTransaction,\n lastPatch?: Map<string, QueriesPatchOp> | undefined,\n ): Promise<Map<string, QueriesPatchOp>> {\n const existingQueryHashes = new Set<string>();\n const prefix = desiredQueriesPrefixForClient(this.#clientID);\n for await (const key of tx.scan({prefix}).keys()) {\n existingQueryHashes.add(key.substring(prefix.length, key.length));\n }\n const patch: Map<string, QueriesPatchOp> = new Map();\n for (const hash of existingQueryHashes) {\n if (!this.#queries.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n for (const [hash, {normalized}] of this.#queries) {\n if (!existingQueryHashes.has(hash)) {\n patch.set(hash, {op: 'put', hash, ast: normalized});\n }\n }\n\n if (lastPatch) {\n // if there are any `puts` in `lastPatch` that are not in `patch` then we need to\n // send a `del` event in `patch`.\n for (const [hash, {op}] of lastPatch) {\n if (op === 'put' && !patch.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n // Remove everything from `patch` that was already sent in `lastPatch`.\n for (const [hash, {op}] of patch) {\n const lastPatchOp = lastPatch.get(hash);\n if (lastPatchOp && lastPatchOp.op === op) {\n patch.delete(hash);\n }\n }\n }\n\n return patch;\n }\n\n add(ast: AST, gotCallback?: GotCallback | undefined): () => void {\n const normalized = normalizeAST(ast);\n const astHash = hashOfAST(normalized);\n let entry = this.#queries.get(astHash);\n if (!entry) {\n entry = {\n normalized,\n count: 1,\n gotCallbacks: gotCallback === undefined ? [] : [gotCallback],\n };\n this.#queries.set(astHash, entry);\n\n this.#send([\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [{op: 'put', hash: astHash, ast: normalized}],\n },\n ]);\n } else {\n ++entry.count;\n if (gotCallback) {\n entry.gotCallbacks.push(gotCallback);\n }\n }\n\n if (gotCallback) {\n queueMicrotask(() => {\n gotCallback(this.#gotQueries.has(astHash));\n });\n }\n\n let removed = false;\n return () => {\n if (removed) {\n return;\n }\n removed = true;\n this.#remove(astHash);\n };\n }\n\n #remove(astHash: string) {\n const entry = must(this.#queries.get(astHash));\n --entry.count;\n if (entry.count === 0) {\n this.#queries.delete(astHash);\n this.#send([\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [{op: 'del', hash: astHash}],\n },\n ]);\n }\n return true;\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\n\nexport const RELOAD_REASON_STORAGE_KEY = '_zeroReloadReason';\n\n// TODO: This should get pushed down into Replicache and used for reloads we\n// do there.\nexport function reloadWithReason(\n lc: LogContext,\n reload: () => void,\n reason: string,\n) {\n if (typeof localStorage === 'undefined') {\n lc.error?.('Zero reloaded the page.', reason);\n } else {\n localStorage[RELOAD_REASON_STORAGE_KEY] = reason;\n }\n reload();\n}\n\nexport function reportReloadReason(lc: LogContext) {\n if (typeof localStorage === 'undefined') {\n return;\n }\n const reason = localStorage[RELOAD_REASON_STORAGE_KEY];\n if (reason) {\n delete localStorage[RELOAD_REASON_STORAGE_KEY];\n lc.error?.('Zero reloaded the page.', reason);\n }\n}\n", "import {ErrorKind} from '../../../zero-protocol/src/mod.js';\n\n/**\n * Represents an error sent by server as part of Zero protocol.\n */\nexport class ServerError<K extends ErrorKind = ErrorKind> extends Error {\n readonly kind: K;\n readonly name = 'ServerError';\n constructor(kind: K, message: string) {\n super(kind + ': ' + message);\n this.kind = kind;\n }\n}\n\nexport function isServerError(ex: unknown): ex is ServerError {\n return ex instanceof ServerError;\n}\n\nexport function isAuthError(\n ex: unknown,\n): ex is\n | ServerError<ErrorKind.AuthInvalidated>\n | ServerError<ErrorKind.Unauthorized> {\n return isServerError(ex) && isAuthErrorKind(ex.kind);\n}\n\nfunction isAuthErrorKind(\n kind: ErrorKind,\n): kind is ErrorKind.AuthInvalidated | ErrorKind.Unauthorized {\n return kind === ErrorKind.AuthInvalidated || kind === ErrorKind.Unauthorized;\n}\n", "import type {HTTPString} from './http-string.js';\n\nfunction validateServerParam(paramName: string, server: string): HTTPString {\n const expectedProtocol = 'http';\n const forExample = () =>\n ` For example: \"${expectedProtocol}s://myapp-myteam.zero.ms/\".`;\n\n if (\n !server.startsWith(`${expectedProtocol}://`) &&\n !server.startsWith(`${expectedProtocol}s://`)\n ) {\n throw new Error(\n `ZeroOptions.${paramName} must use the \"${expectedProtocol}\" or \"${expectedProtocol}s\" scheme.`,\n );\n }\n let url;\n try {\n url = new URL(server);\n } catch {\n throw new Error(\n `ZeroOptions.${paramName} must be a valid URL.${forExample()}`,\n );\n }\n\n const urlString = url.toString();\n\n if (url.pathname !== '/') {\n throw new Error(\n `ZeroOptions.${paramName} must not contain a path component (other than \"/\").${forExample()}`,\n );\n }\n\n for (const [property, invalidEndsWith] of [\n ['search', '?'],\n ['hash', '#'],\n ] as const) {\n if (url[property] || urlString.endsWith(invalidEndsWith)) {\n throw new Error(\n `ZeroOptions.${paramName} must not contain a ${property} component.${forExample()}`,\n );\n }\n }\n\n return urlString as HTTPString;\n}\n\nexport function getServer(\n server: string | undefined | null,\n): HTTPString | null {\n if (server === undefined || server === null) {\n console.warn(\n 'Zero starting up with no server URL. This is supported for unit testing ' +\n 'and prototyping, but no data will be synced.',\n );\n return null;\n }\n return validateServerParam('server', server);\n}\n", "import {Lock} from '@rocicorp/lock';\nimport type {LogContext} from '@rocicorp/logger';\nimport type {\n PatchOperationInternal,\n PokeInternal,\n} from '../../../replicache/src/impl.js';\nimport type {ClientID, PatchOperation} from '../../../replicache/src/mod.js';\nimport type {\n ClientsPatchOp,\n PokeEndBody,\n PokePartBody,\n PokeStartBody,\n QueriesPatchOp,\n RowPatchOp,\n} from '../../../zero-protocol/src/mod.js';\nimport {\n toClientsKey,\n toDesiredQueriesKey,\n toGotQueriesKey,\n toPrimaryKeyString,\n} from './keys.js';\nimport {type NormalizedSchema} from './normalized-schema.js';\n\ntype PokeAccumulator = {\n readonly pokeStart: PokeStartBody;\n readonly parts: PokePartBody[];\n};\n\n/**\n * Handles the multi-part format of zero pokes.\n * As an optimization it also debounces pokes, only poking Replicache with a\n * merged poke at most once per frame (as determined by requestAnimationFrame).\n * The client cannot control how fast the server sends pokes, and it can only\n * update the UI once per frame. This debouncing avoids wastefully\n * computing separate diffs and IVM updates for intermediate states that will\n * never been displayed to the UI.\n */\nexport class PokeHandler {\n readonly #replicachePoke: (poke: PokeInternal) => Promise<void>;\n readonly #onPokeError: () => void;\n readonly #clientID: ClientID;\n readonly #lc: LogContext;\n #receivingPoke: PokeAccumulator | undefined = undefined;\n readonly #pokeBuffer: PokeAccumulator[] = [];\n #pokePlaybackLoopRunning = false;\n #lastRafPerfTimestamp = 0;\n // Serializes calls to this.#replicachePoke otherwise we can cause out of\n // order poke errors.\n readonly #pokeLock = new Lock();\n readonly #schema: NormalizedSchema;\n\n constructor(\n replicachePoke: (poke: PokeInternal) => Promise<void>,\n onPokeError: () => void,\n clientID: ClientID,\n schema: NormalizedSchema,\n lc: LogContext,\n ) {\n this.#replicachePoke = replicachePoke;\n this.#onPokeError = onPokeError;\n this.#clientID = clientID;\n this.#schema = schema;\n this.#lc = lc.withContext('PokeHandler');\n }\n\n handlePokeStart(pokeStart: PokeStartBody) {\n if (this.#receivingPoke) {\n this.#handlePokeError(\n `pokeStart ${JSON.stringify(\n pokeStart,\n )} while still receiving ${JSON.stringify(\n this.#receivingPoke.pokeStart,\n )} `,\n );\n return;\n }\n this.#receivingPoke = {\n pokeStart,\n parts: [],\n };\n }\n\n handlePokePart(pokePart: PokePartBody): number | undefined {\n if (pokePart.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokePart for ${pokePart.pokeID}, when receiving ${this.#receivingPoke\n ?.pokeStart.pokeID}`,\n );\n return;\n }\n this.#receivingPoke.parts.push(pokePart);\n return pokePart.lastMutationIDChanges?.[this.#clientID];\n }\n\n handlePokeEnd(pokeEnd: PokeEndBody) {\n if (pokeEnd.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokeEnd for ${pokeEnd.pokeID}, when receiving ${this.#receivingPoke\n ?.pokeStart.pokeID}`,\n );\n return;\n }\n if (pokeEnd.cancel) {\n this.#receivingPoke = undefined;\n return;\n }\n this.#pokeBuffer.push(this.#receivingPoke);\n this.#receivingPoke = undefined;\n if (!this.#pokePlaybackLoopRunning) {\n this.#startPlaybackLoop();\n }\n }\n\n handleDisconnect(): void {\n this.#lc.debug?.('clearing due to disconnect');\n this.#clear();\n }\n\n #startPlaybackLoop() {\n this.#lc.debug?.('starting playback loop');\n this.#pokePlaybackLoopRunning = true;\n requestAnimationFrame(this.#rafCallback);\n }\n\n #rafCallback = async () => {\n const rafLC = this.#lc.withContext('rafAt', Math.floor(performance.now()));\n if (this.#pokeBuffer.length === 0) {\n rafLC.debug?.('stopping playback loop');\n this.#pokePlaybackLoopRunning = false;\n return;\n }\n requestAnimationFrame(this.#rafCallback);\n const start = performance.now();\n rafLC.debug?.(\n 'raf fired, processing pokes. Since last raf',\n start - this.#lastRafPerfTimestamp,\n );\n this.#lastRafPerfTimestamp = start;\n await this.#processPokesForFrame(rafLC);\n rafLC.debug?.('processing pokes took', performance.now() - start);\n };\n\n #processPokesForFrame(lc: LogContext): Promise<void> {\n return this.#pokeLock.withLock(async () => {\n const now = Date.now();\n lc.debug?.('got poke lock at', now);\n lc.debug?.('merging', this.#pokeBuffer.length);\n try {\n const merged = mergePokes(this.#pokeBuffer, this.#schema);\n this.#pokeBuffer.length = 0;\n if (merged === undefined) {\n lc.debug?.('frame is empty');\n return;\n }\n const start = performance.now();\n lc.debug?.('poking replicache');\n await this.#replicachePoke(merged);\n lc.debug?.('poking replicache took', performance.now() - start);\n } catch (e) {\n this.#handlePokeError(e);\n }\n });\n }\n\n #handlePokeError(e: unknown) {\n if (String(e).includes('unexpected base cookie for poke')) {\n // This can happen if cookie changes due to refresh from idb due\n // to an update arriving to different tabs in the same\n // client group at very different times. Unusual but possible.\n this.#lc.debug?.('clearing due to', e);\n } else {\n this.#lc.error?.('clearing due to unexpected poke error', e);\n }\n this.#clear();\n this.#onPokeError();\n }\n\n #clear() {\n this.#receivingPoke = undefined;\n this.#pokeBuffer.length = 0;\n }\n}\n\nexport function mergePokes(\n pokeBuffer: PokeAccumulator[],\n schema: NormalizedSchema,\n): PokeInternal | undefined {\n if (pokeBuffer.length === 0) {\n return undefined;\n }\n const {baseCookie} = pokeBuffer[0].pokeStart;\n const {cookie} = pokeBuffer[pokeBuffer.length - 1].pokeStart;\n const mergedPatch: PatchOperationInternal[] = [];\n const mergedLastMutationIDChanges: Record<string, number> = {};\n\n let prevPokeStart = undefined;\n for (const pokeAccumulator of pokeBuffer) {\n if (\n prevPokeStart &&\n pokeAccumulator.pokeStart.baseCookie &&\n pokeAccumulator.pokeStart.baseCookie > prevPokeStart.cookie\n ) {\n throw Error(\n `unexpected cookie gap ${JSON.stringify(\n prevPokeStart,\n )} ${JSON.stringify(pokeAccumulator.pokeStart)}`,\n );\n }\n prevPokeStart = pokeAccumulator.pokeStart;\n for (const pokePart of pokeAccumulator.parts) {\n if (pokePart.lastMutationIDChanges) {\n for (const [clientID, lastMutationID] of Object.entries(\n pokePart.lastMutationIDChanges,\n )) {\n mergedLastMutationIDChanges[clientID] = lastMutationID;\n }\n }\n if (pokePart.clientsPatch) {\n mergedPatch.push(\n ...pokePart.clientsPatch.map(clientsPatchOpToReplicachePatchOp),\n );\n }\n if (pokePart.desiredQueriesPatches) {\n for (const [clientID, queriesPatch] of Object.entries(\n pokePart.desiredQueriesPatches,\n )) {\n mergedPatch.push(\n ...queriesPatch.map(op =>\n queryPatchOpToReplicachePatchOp(op, hash =>\n toDesiredQueriesKey(clientID, hash),\n ),\n ),\n );\n }\n }\n if (pokePart.gotQueriesPatch) {\n mergedPatch.push(\n ...pokePart.gotQueriesPatch.map(op =>\n queryPatchOpToReplicachePatchOp(op, toGotQueriesKey),\n ),\n );\n }\n if (pokePart.rowsPatch) {\n mergedPatch.push(\n ...pokePart.rowsPatch.map(p =>\n rowsPatchOpToReplicachePatchOp(p, schema),\n ),\n );\n }\n }\n }\n return {\n baseCookie,\n pullResponse: {\n lastMutationIDChanges: mergedLastMutationIDChanges,\n patch: mergedPatch,\n cookie,\n },\n };\n}\n\nfunction clientsPatchOpToReplicachePatchOp(op: ClientsPatchOp): PatchOperation {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toClientsKey(op.clientID),\n };\n case 'put':\n default:\n return {\n op: 'put',\n key: toClientsKey(op.clientID),\n value: true,\n };\n }\n}\n\nfunction queryPatchOpToReplicachePatchOp(\n op: QueriesPatchOp,\n toKey: (hash: string) => string,\n): PatchOperation {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toKey(op.hash),\n };\n case 'put':\n default:\n return {\n op: 'put',\n key: toKey(op.hash),\n value: op.ast,\n };\n }\n}\n\nfunction rowsPatchOpToReplicachePatchOp(\n op: RowPatchOp,\n schema: NormalizedSchema,\n): PatchOperationInternal {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toPrimaryKeyString(\n op.tableName,\n schema.tables[op.tableName].primaryKey,\n op.id,\n ),\n };\n case 'put':\n return {\n op: 'put',\n key: toPrimaryKeyString(\n op.tableName,\n schema.tables[op.tableName].primaryKey,\n op.value,\n ),\n value: op.value,\n };\n case 'update':\n return {\n op: 'update',\n key: toPrimaryKeyString(\n op.tableName,\n schema.tables[op.tableName].primaryKey,\n op.id,\n ),\n merge: op.merge,\n constrain: op.constrain,\n };\n default:\n throw new Error('to be implemented');\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["v", "path", "v", "v", "v", "v", "v2", "v", "v", "v", "db", "ReadImpl", "WriteImpl", "ReadImpl", "ReadImpl", "WriteImpl", "consoleLogSink", "resolver", "resolver", "resolver", "resolver", "promiseVoid", "resolver", "resolver", "t", "ok", "RWLock", "v", "assert", "v", "path", "toDisplay", "err", "atPath", "t", "assert", "RWLock", "v", "ReadImpl", "WriteImpl", "v", "v", "v", "v", "v", "createChunk", "binarySearch", "v", "getSizeOfEntry", "binarySearch", "array", "entries", "getSizeOfEntry", "splice", "binarySearch", "diff", "value", "greaterThan", "v", "greaterThan", "value", "entries", "createChunk", "chunk", "valueHash", "v", "assert", "assert", "assert", "valueHash", "indexRecords", "baseCookie", "lastMutationID", "clientID", "localMutations", "v", "v", "pusherResult", "beginPullResponse", "newClients", "disableClientGroup", "clientID", "process", "latestGCUpdate", "latestGCUpdate", "mainClientGroupID", "perdagLMID", "perdagBaseSnapshot", "memdagBaseSnapshot", "gatheredChunks", "perdagClientGroupHeadHash", "perdagLmid", "perdagClientGroupBaseSnapshot", "gatheredChunks", "memdagBaseSnapshot", "resolver", "process", "requestIdle", "resolver", "compareUTF8", "greaterThan", "scan", "diff", "diff", "newDiff", "greaterThan", "compareUTF8", "array", "noop", "consoleLogSink", "resolver", "hasClientState", "ok", "pusherResult", "requestID", "beginPullResponse", "clientID", "consoleLogSink", "flattened", "resolver", "compareUTF8", "defined", "val", "compareUTF8", "c", "compareUTF8", "compareUTF8", "v", "v", "change", "cmp", "not", "object", "v", "resolver", "LogContext", "resolver", "putOpSchema", "delOpSchema", "clearOpSchema", "patchOpSchema", "putOpSchema", "delOpSchema", "clearOpSchema", "updateOpSchema", "v", "t", "cmp", "v", "t", "data", "cmp", "diff", "TeeLogSink", "consoleLogSink", "Lock", "version", "ok", "version", "consoleLogSink", "options", "TeeLogSink", "version", "send", "diff", "reload", "Lock", "Lock", "version", "resolver", "LogContext", "diff", "e", "RaceCases"]
|
|
7
|
+
}
|