@rocicorp/zero 0.26.1 → 0.26.2-canary.1
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/_virtual/_@oxc-project_runtime@0.115.0/helpers/usingCtx.js +57 -0
- package/out/_virtual/_rolldown/runtime.js +27 -0
- package/out/analyze-query/src/bin-analyze.js +195 -283
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js +35 -40
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/analyze-query/src/explain-queries.js +11 -13
- package/out/analyze-query/src/explain-queries.js.map +1 -1
- package/out/analyze-query/src/run-ast.js +68 -103
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +105 -153
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/ast-to-zql/src/bin.js +57 -62
- package/out/ast-to-zql/src/bin.js.map +1 -1
- package/out/ast-to-zql/src/format.js +14 -13
- package/out/ast-to-zql/src/format.js.map +1 -1
- package/out/datadog/src/datadog-log-sink.js +148 -213
- package/out/datadog/src/datadog-log-sink.js.map +1 -1
- package/out/otel/src/enabled.js +9 -11
- package/out/otel/src/enabled.js.map +1 -1
- package/out/otel/src/log-options.js +25 -35
- package/out/otel/src/log-options.js.map +1 -1
- package/out/otel/src/maybe-time.js +13 -14
- package/out/otel/src/maybe-time.js.map +1 -1
- package/out/otel/src/span.js +23 -26
- package/out/otel/src/span.js.map +1 -1
- package/out/otel/src/test-log-config.js +11 -10
- package/out/otel/src/test-log-config.js.map +1 -1
- package/out/otel/src/version.js +6 -5
- package/out/otel/src/version.js.map +1 -1
- package/out/replicache/src/async-iterable-to-array.js +8 -9
- package/out/replicache/src/async-iterable-to-array.js.map +1 -1
- package/out/replicache/src/bg-interval.js +28 -35
- package/out/replicache/src/bg-interval.js.map +1 -1
- package/out/replicache/src/btree/diff.js +6 -5
- package/out/replicache/src/btree/diff.js.map +1 -1
- package/out/replicache/src/btree/node.js +281 -372
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/btree/read.js +155 -256
- package/out/replicache/src/btree/read.js.map +1 -1
- package/out/replicache/src/btree/splice.js +60 -80
- package/out/replicache/src/btree/splice.js.map +1 -1
- package/out/replicache/src/btree/write.js +134 -158
- package/out/replicache/src/btree/write.js.map +1 -1
- package/out/replicache/src/call-default-fetch.js +28 -32
- package/out/replicache/src/call-default-fetch.js.map +1 -1
- package/out/replicache/src/config.js +2 -0
- package/out/replicache/src/connection-loop-delegates.js +31 -33
- package/out/replicache/src/connection-loop-delegates.js.map +1 -1
- package/out/replicache/src/connection-loop.js +174 -240
- package/out/replicache/src/connection-loop.js.map +1 -1
- package/out/replicache/src/cookies.js +22 -32
- package/out/replicache/src/cookies.js.map +1 -1
- package/out/replicache/src/dag/chunk.js +44 -50
- package/out/replicache/src/dag/chunk.js.map +1 -1
- package/out/replicache/src/dag/gc.js +94 -114
- package/out/replicache/src/dag/gc.js.map +1 -1
- package/out/replicache/src/dag/key.js +9 -11
- package/out/replicache/src/dag/key.js.map +1 -1
- package/out/replicache/src/dag/lazy-store.js +458 -510
- package/out/replicache/src/dag/lazy-store.js.map +1 -1
- package/out/replicache/src/dag/store-impl.js +147 -178
- package/out/replicache/src/dag/store-impl.js.map +1 -1
- package/out/replicache/src/dag/store.js +19 -22
- package/out/replicache/src/dag/store.js.map +1 -1
- package/out/replicache/src/dag/visitor.js +23 -21
- package/out/replicache/src/dag/visitor.js.map +1 -1
- package/out/replicache/src/db/commit.js +209 -283
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/index.js +79 -122
- package/out/replicache/src/db/index.js.map +1 -1
- package/out/replicache/src/db/read.js +44 -60
- package/out/replicache/src/db/read.js.map +1 -1
- package/out/replicache/src/db/rebase.js +22 -77
- package/out/replicache/src/db/rebase.js.map +1 -1
- package/out/replicache/src/db/write.js +162 -296
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/deleted-clients.js +59 -87
- package/out/replicache/src/deleted-clients.js.map +1 -1
- package/out/replicache/src/error-responses.js +18 -26
- package/out/replicache/src/error-responses.js.map +1 -1
- package/out/replicache/src/expo-sqlite.js +2 -0
- package/out/replicache/src/frozen-json.js +74 -108
- package/out/replicache/src/frozen-json.js.map +1 -1
- package/out/replicache/src/get-default-puller.js +34 -46
- package/out/replicache/src/get-default-puller.js.map +1 -1
- package/out/replicache/src/get-default-pusher.js +25 -33
- package/out/replicache/src/get-default-pusher.js.map +1 -1
- package/out/replicache/src/get-kv-store-provider.js +18 -20
- package/out/replicache/src/get-kv-store-provider.js.map +1 -1
- package/out/replicache/src/hash.js +29 -29
- package/out/replicache/src/hash.js.map +1 -1
- package/out/replicache/src/http-request-info.js +9 -8
- package/out/replicache/src/http-request-info.js.map +1 -1
- package/out/replicache/src/impl.js +2 -0
- package/out/replicache/src/index-defs.js +17 -28
- package/out/replicache/src/index-defs.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +52 -50
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +71 -68
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -1
- package/out/replicache/src/kv/idb-store.js +144 -168
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/mem-store.js +57 -45
- package/out/replicache/src/kv/mem-store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/store.js +56 -62
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/op-sqlite/types.d.ts.map +1 -1
- package/out/replicache/src/kv/op-sqlite/types.js +7 -6
- package/out/replicache/src/kv/op-sqlite/types.js.map +1 -1
- package/out/replicache/src/kv/read-impl.js +26 -25
- package/out/replicache/src/kv/read-impl.js.map +1 -1
- package/out/replicache/src/kv/sqlite-store.js +194 -207
- package/out/replicache/src/kv/sqlite-store.js.map +1 -1
- package/out/replicache/src/kv/throw-if-closed.js +12 -19
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
- package/out/replicache/src/kv/write-impl-base.js +44 -56
- package/out/replicache/src/kv/write-impl-base.js.map +1 -1
- package/out/replicache/src/kv/write-impl.js +22 -26
- package/out/replicache/src/kv/write-impl.js.map +1 -1
- package/out/replicache/src/lazy.js +10 -11
- package/out/replicache/src/lazy.js.map +1 -1
- package/out/replicache/src/log-options.js +14 -7
- package/out/replicache/src/log-options.js.map +1 -1
- package/out/replicache/src/make-idb-name.js +14 -9
- package/out/replicache/src/make-idb-name.js.map +1 -1
- package/out/replicache/src/mutation-recovery.js +12 -0
- package/out/replicache/src/mutation-recovery.js.map +1 -0
- package/out/replicache/src/new-client-channel.js +34 -42
- package/out/replicache/src/new-client-channel.js.map +1 -1
- package/out/replicache/src/on-persist-channel.js +26 -29
- package/out/replicache/src/on-persist-channel.js.map +1 -1
- package/out/replicache/src/op-sqlite.js +2 -0
- package/out/replicache/src/patch-operation.js +27 -36
- package/out/replicache/src/patch-operation.js.map +1 -1
- package/out/replicache/src/pending-mutations.js +14 -12
- package/out/replicache/src/pending-mutations.js.map +1 -1
- package/out/replicache/src/persist/client-gc.js +36 -51
- package/out/replicache/src/persist/client-gc.js.map +1 -1
- package/out/replicache/src/persist/client-group-gc.js +29 -36
- package/out/replicache/src/persist/client-group-gc.js.map +1 -1
- package/out/replicache/src/persist/client-groups.js +80 -154
- package/out/replicache/src/persist/client-groups.js.map +1 -1
- package/out/replicache/src/persist/clients.js +212 -307
- package/out/replicache/src/persist/clients.js.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.js +109 -171
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -1
- package/out/replicache/src/persist/gather-mem-only-visitor.js +23 -24
- package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -1
- package/out/replicache/src/persist/gather-not-cached-visitor.js +35 -33
- package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -1
- package/out/replicache/src/persist/heartbeat.js +31 -41
- package/out/replicache/src/persist/heartbeat.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store-db-name.js +9 -12
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js +78 -97
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -1
- package/out/replicache/src/persist/make-client-id.js +13 -9
- package/out/replicache/src/persist/make-client-id.js.map +1 -1
- package/out/replicache/src/persist/persist.js +113 -174
- package/out/replicache/src/persist/persist.js.map +1 -1
- package/out/replicache/src/persist/refresh.js +94 -183
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/process-scheduler.js +122 -143
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/pusher.js +21 -26
- package/out/replicache/src/pusher.js.map +1 -1
- package/out/replicache/src/replicache-impl.js +844 -1184
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/report-error.js +9 -6
- package/out/replicache/src/report-error.js.map +1 -1
- package/out/replicache/src/request-idle.js +13 -11
- package/out/replicache/src/request-idle.js.map +1 -1
- package/out/replicache/src/scan-iterator.d.ts.map +1 -1
- package/out/replicache/src/scan-iterator.js +108 -135
- package/out/replicache/src/scan-iterator.js.map +1 -1
- package/out/replicache/src/scan-options.js +33 -39
- package/out/replicache/src/scan-options.js.map +1 -1
- package/out/replicache/src/set-interval-with-signal.js +11 -10
- package/out/replicache/src/set-interval-with-signal.js.map +1 -1
- package/out/replicache/src/sqlite.js +2 -0
- package/out/replicache/src/subscriptions.js +222 -338
- package/out/replicache/src/subscriptions.js.map +1 -1
- package/out/replicache/src/sync/diff.js +52 -65
- package/out/replicache/src/sync/diff.js.map +1 -1
- package/out/replicache/src/sync/ids.js +8 -9
- package/out/replicache/src/sync/ids.js.map +1 -1
- package/out/replicache/src/sync/patch.js +34 -45
- package/out/replicache/src/sync/patch.js.map +1 -1
- package/out/replicache/src/sync/pull-error.js +15 -15
- package/out/replicache/src/sync/pull-error.js.map +1 -1
- package/out/replicache/src/sync/pull.js +145 -283
- package/out/replicache/src/sync/pull.js.map +1 -1
- package/out/replicache/src/sync/push.js +64 -79
- package/out/replicache/src/sync/push.js.map +1 -1
- package/out/replicache/src/sync/request-id.js +23 -15
- package/out/replicache/src/sync/request-id.js.map +1 -1
- package/out/replicache/src/sync/sync-head-name.js +6 -5
- package/out/replicache/src/sync/sync-head-name.js.map +1 -1
- package/out/replicache/src/to-error.js +7 -8
- package/out/replicache/src/to-error.js.map +1 -1
- package/out/replicache/src/transaction-closed-error.js +15 -15
- package/out/replicache/src/transaction-closed-error.js.map +1 -1
- package/out/replicache/src/transactions.js +120 -140
- package/out/replicache/src/transactions.js.map +1 -1
- package/out/replicache/src/version.js +9 -5
- package/out/replicache/src/version.js.map +1 -1
- package/out/replicache/src/with-transactions.js +23 -20
- package/out/replicache/src/with-transactions.js.map +1 -1
- package/out/shared/src/abort-error.js +7 -6
- package/out/shared/src/abort-error.js.map +1 -1
- package/out/shared/src/arrays.js +35 -42
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/asserts.js +21 -45
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/bigint-json.js +42 -38
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/binary-search.js +27 -18
- package/out/shared/src/binary-search.js.map +1 -1
- package/out/shared/src/broadcast-channel.js +20 -23
- package/out/shared/src/broadcast-channel.js.map +1 -1
- package/out/shared/src/browser-env.js +11 -17
- package/out/shared/src/browser-env.js.map +1 -1
- package/out/shared/src/btree-set.js +419 -481
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/cache.js +43 -36
- package/out/shared/src/cache.js.map +1 -1
- package/out/shared/src/centroid.js +24 -26
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/config.js +6 -6
- package/out/shared/src/config.js.map +1 -1
- package/out/shared/src/custom-key-map.js +54 -58
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/custom-key-set.js +53 -51
- package/out/shared/src/custom-key-set.js.map +1 -1
- package/out/shared/src/deep-clone.js +30 -41
- package/out/shared/src/deep-clone.js.map +1 -1
- package/out/shared/src/deep-merge.js +25 -24
- package/out/shared/src/deep-merge.js.map +1 -1
- package/out/shared/src/document-visible.js +63 -70
- package/out/shared/src/document-visible.js.map +1 -1
- package/out/shared/src/dotenv.js +7 -3
- package/out/shared/src/dotenv.js.map +1 -1
- package/out/shared/src/error.js +43 -64
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/has-own.js +6 -5
- package/out/shared/src/has-own.js.map +1 -1
- package/out/shared/src/hash.js +15 -14
- package/out/shared/src/hash.js.map +1 -1
- package/out/shared/src/iterables.js +34 -47
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json-schema.js +25 -30
- package/out/shared/src/json-schema.js.map +1 -1
- package/out/shared/src/json.js +90 -129
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/logging-test-utils.js +9 -11
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/logging.js +75 -95
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/must.js +7 -8
- package/out/shared/src/must.js.map +1 -1
- package/out/shared/src/navigator.js +6 -5
- package/out/shared/src/navigator.js.map +1 -1
- package/out/shared/src/object-traversal.js +23 -23
- package/out/shared/src/object-traversal.js.map +1 -1
- package/out/shared/src/objects.js +15 -18
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/options.js +225 -302
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/parse-big-int.js +12 -11
- package/out/shared/src/parse-big-int.js.map +1 -1
- package/out/shared/src/promise-race.js +21 -17
- package/out/shared/src/promise-race.js.map +1 -1
- package/out/shared/src/queue.js +124 -124
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/rand.js +13 -7
- package/out/shared/src/rand.js.map +1 -1
- package/out/shared/src/random-uint64.js +8 -7
- package/out/shared/src/random-uint64.js.map +1 -1
- package/out/shared/src/random-values.js +8 -11
- package/out/shared/src/random-values.js.map +1 -1
- package/out/shared/src/record-proxy.js +68 -57
- package/out/shared/src/record-proxy.js.map +1 -1
- package/out/shared/src/resolved-promises.js +9 -11
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/sentinels.js +9 -12
- package/out/shared/src/sentinels.js.map +1 -1
- package/out/shared/src/set-utils.js +41 -63
- package/out/shared/src/set-utils.js.map +1 -1
- package/out/shared/src/size-of-value.js +55 -51
- package/out/shared/src/size-of-value.js.map +1 -1
- package/out/shared/src/sleep.js +50 -45
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/string-compare.js +8 -11
- package/out/shared/src/string-compare.js.map +1 -1
- package/out/shared/src/subscribable.js +34 -33
- package/out/shared/src/subscribable.js.map +1 -1
- package/out/shared/src/tdigest-schema.js +11 -7
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.js +197 -270
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.js +145 -174
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +238 -468
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts +0 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +149 -194
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +193 -0
- package/out/zero/package.js.map +1 -0
- package/out/zero/src/adapters/drizzle.js +1 -6
- package/out/zero/src/adapters/pg.js +1 -6
- package/out/zero/src/adapters/postgresjs.js +1 -6
- package/out/zero/src/adapters/prisma.js +1 -5
- package/out/zero/src/analyze-query.js +1 -1
- package/out/zero/src/ast-to-zql.js +1 -1
- package/out/zero/src/bindings.js +6 -21
- package/out/zero/src/build-schema.js +5 -1
- package/out/zero/src/build-schema.js.map +1 -1
- package/out/zero/src/change-protocol/v0.js +3 -5
- package/out/zero/src/cli.js +2 -2
- package/out/zero/src/deploy-permissions.js +1 -1
- package/out/zero/src/expo-sqlite.js +2 -4
- package/out/zero/src/op-sqlite.js +2 -4
- package/out/zero/src/pg.js +2 -20
- package/out/zero/src/react-native.js +16 -12
- package/out/zero/src/react-native.js.map +1 -1
- package/out/zero/src/react.js +3 -12
- package/out/zero/src/server/runner/main.js +2 -0
- package/out/zero/src/server.js +2 -17
- package/out/zero/src/solid.js +3 -12
- package/out/zero/src/sqlite.js +2 -6
- package/out/zero/src/transform-query.js +1 -1
- package/out/zero/src/zero-cache-dev.js +124 -151
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.js +9 -6
- package/out/zero/src/zero-out.js.map +1 -1
- package/out/zero/src/zero.js +6 -55
- package/out/zero/src/zqlite.js +2 -7
- package/out/zero-cache/src/auth/auth.js +138 -172
- package/out/zero-cache/src/auth/auth.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.js +25 -33
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +54 -62
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +70 -80
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +284 -432
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.js +31 -45
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.js +81 -83
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/server-context.js +32 -29
- package/out/zero-cache/src/config/server-context.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +753 -833
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +183 -230
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +93 -99
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.js +27 -29
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js +11 -7
- package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +118 -158
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +110 -178
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +82 -151
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/mode-enum.js +8 -9
- package/out/zero-cache/src/db/mode-enum.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy.js +56 -54
- package/out/zero-cache/src/db/pg-copy.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +74 -110
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +19 -36
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/run-transaction.js +19 -20
- package/out/zero-cache/src/db/run-transaction.js.map +1 -1
- package/out/zero-cache/src/db/specs.js +42 -78
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/statements.js +52 -59
- package/out/zero-cache/src/db/statements.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +376 -400
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.js +13 -24
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +89 -99
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +30 -54
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.js +42 -47
- package/out/zero-cache/src/scripts/decommission.js.map +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js +106 -144
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +86 -107
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +306 -440
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +57 -130
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +89 -100
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/logging.js +18 -26
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.js +85 -142
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +16 -13
- package/out/zero-cache/src/server/mutator.js.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js +42 -49
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js +34 -44
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +43 -51
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/priority-op.js +27 -25
- package/out/zero-cache/src/server/priority-op.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js +32 -43
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/server/replicator.js +41 -57
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/main.js +7 -8
- package/out/zero-cache/src/server/runner/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +56 -52
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/runner/runtime.js +26 -32
- package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +22 -27
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.js +79 -148
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +84 -113
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +2 -1
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-urls.js +14 -18
- package/out/zero-cache/src/server/worker-urls.js.map +1 -1
- package/out/zero-cache/src/server/write-worker.js +2 -0
- package/out/zero-cache/src/services/analyze.js +61 -130
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +420 -419
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +111 -114
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-schema.js +80 -148
- package/out/zero-cache/src/services/change-source/common/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +154 -216
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js +11 -14
- package/out/zero-cache/src/services/change-source/pg/backfill-metadata.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +168 -212
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +672 -892
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/decommission.js +19 -23
- package/out/zero-cache/src/services/change-source/pg/decommission.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +258 -411
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +59 -65
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js +218 -247
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput-parser.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js +100 -142
- package/out/zero-cache/src/services/change-source/pg/logical-replication/stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js +17 -19
- package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +88 -98
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/init.js +96 -177
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +69 -107
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +151 -212
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js +22 -53
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js +24 -12
- package/out/zero-cache/src/services/change-source/protocol/current/control.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/data.js +180 -290
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +21 -33
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/json.js +7 -18
- package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/path.js +24 -5
- package/out/zero-cache/src/services/change-source/protocol/current/path.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/status.js +25 -19
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +24 -16
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +51 -46
- package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/mod.js +2 -0
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +165 -171
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +163 -169
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +154 -221
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +340 -299
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +17 -24
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +84 -103
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +49 -43
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/init.js +61 -89
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +20 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +131 -109
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +26 -28
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +434 -513
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +142 -155
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.js +18 -20
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/http-service.js +59 -57
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +182 -214
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +102 -81
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +144 -205
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +10 -14
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +166 -264
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +372 -487
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +483 -592
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +4 -2
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +118 -143
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js +52 -28
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +105 -128
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +2 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +32 -34
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js +101 -133
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js +145 -174
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/constants.js +11 -5
- package/out/zero-cache/src/services/replicator/schema/constants.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +56 -107
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js +81 -66
- package/out/zero-cache/src/services/replicator/schema/table-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts +69 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.js +96 -0
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -0
- package/out/zero-cache/src/services/replicator/write-worker.js +68 -0
- package/out/zero-cache/src/services/replicator/write-worker.js.map +1 -0
- package/out/zero-cache/src/services/run-ast.js +79 -120
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.js +39 -41
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/running-state.js +129 -134
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/statz.js +139 -200
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +46 -49
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +257 -299
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +52 -82
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +85 -107
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +604 -757
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +631 -739
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +60 -40
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +95 -178
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +572 -722
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +246 -257
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +59 -45
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +121 -189
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +138 -263
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +322 -335
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/tracer.js +7 -6
- package/out/zero-cache/src/services/view-syncer/tracer.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js +9 -11
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +1067 -1603
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js +19 -25
- package/out/zero-cache/src/types/error-with-level.js.map +1 -1
- package/out/zero-cache/src/types/http.js +17 -26
- package/out/zero-cache/src/types/http.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js +28 -42
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.js +101 -121
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/names.js +6 -5
- package/out/zero-cache/src/types/names.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.d.ts +1 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js +58 -73
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.js +12 -19
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg.js +144 -218
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.js +95 -90
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.js +32 -27
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.js +42 -30
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/shards.js +36 -45
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.js +20 -9
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/state-version.js +17 -23
- package/out/zero-cache/src/types/state-version.js.map +1 -1
- package/out/zero-cache/src/types/streams.js +234 -270
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/strings.js +10 -13
- package/out/zero-cache/src/types/strings.js.map +1 -1
- package/out/zero-cache/src/types/subscription.js +266 -226
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/url-params.js +30 -39
- package/out/zero-cache/src/types/url-params.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +62 -75
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.js +43 -53
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +42 -43
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +213 -282
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js +22 -21
- package/out/zero-cache/src/workers/mutator.js.map +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts +7 -0
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +92 -97
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +121 -203
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +147 -201
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +178 -187
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/bindings.js +11 -0
- package/out/zero-client/src/client/client-error-kind-enum.js +18 -29
- package/out/zero-client/src/client/client-error-kind-enum.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +291 -346
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-status-enum.js +20 -15
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -1
- package/out/zero-client/src/client/connection.js +92 -110
- package/out/zero-client/src/client/connection.js.map +1 -1
- package/out/zero-client/src/client/context.js +84 -100
- package/out/zero-client/src/client/context.js.map +1 -1
- package/out/zero-client/src/client/crud-impl.js +56 -88
- package/out/zero-client/src/client/crud-impl.js.map +1 -1
- package/out/zero-client/src/client/crud.js +127 -129
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +50 -74
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/delete-clients-manager.js +72 -93
- package/out/zero-client/src/client/delete-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/enable-analytics.js +8 -16
- package/out/zero-client/src/client/enable-analytics.js.map +1 -1
- package/out/zero-client/src/client/error.js +118 -133
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/http-string.js +7 -7
- package/out/zero-client/src/client/http-string.js.map +1 -1
- package/out/zero-client/src/client/inspector/client-group.js +21 -26
- package/out/zero-client/src/client/inspector/client-group.js.map +1 -1
- package/out/zero-client/src/client/inspector/client.js +23 -26
- package/out/zero-client/src/client/inspector/client.js.map +1 -1
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js +72 -73
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +46 -51
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +132 -192
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -1
- package/out/zero-client/src/client/inspector/query.js +72 -77
- package/out/zero-client/src/client/inspector/query.js.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +118 -145
- package/out/zero-client/src/client/ivm-branch.js.map +1 -1
- package/out/zero-client/src/client/keys.js +15 -31
- package/out/zero-client/src/client/keys.js.map +1 -1
- package/out/zero-client/src/client/log-options.js +43 -57
- package/out/zero-client/src/client/log-options.js.map +1 -1
- package/out/zero-client/src/client/make-mutate-property.js +46 -29
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -1
- package/out/zero-client/src/client/make-replicache-mutators.js +80 -96
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -1
- package/out/zero-client/src/client/metric-name-enum.js +11 -15
- package/out/zero-client/src/client/metric-name-enum.js.map +1 -1
- package/out/zero-client/src/client/metrics.js +210 -237
- package/out/zero-client/src/client/metrics.js.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +264 -354
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
- package/out/zero-client/src/client/mutator-proxy.js +122 -151
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -1
- package/out/zero-client/src/client/options.js +7 -10
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/query-manager.js +305 -373
- package/out/zero-client/src/client/query-manager.js.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js +80 -101
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -1
- package/out/zero-client/src/client/server-option.js +30 -59
- package/out/zero-client/src/client/server-option.js.map +1 -1
- package/out/zero-client/src/client/update-needed-reason-type-enum.js +27 -9
- package/out/zero-client/src/client/update-needed-reason-type-enum.js.map +1 -1
- package/out/zero-client/src/client/version.js +9 -5
- package/out/zero-client/src/client/version.js.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +205 -293
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +61 -68
- package/out/zero-client/src/client/zero-rep.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +1367 -1834
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/mod.js +21 -0
- package/out/zero-client/src/util/nanoid.js +13 -18
- package/out/zero-client/src/util/nanoid.js.map +1 -1
- package/out/zero-client/src/util/socket.js +6 -5
- package/out/zero-client/src/util/socket.js.map +1 -1
- package/out/zero-pg/src/mod.js +10 -0
- package/out/zero-protocol/src/analyze-query-result.js +108 -148
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/application-error.js +36 -34
- package/out/zero-protocol/src/application-error.js.map +1 -1
- package/out/zero-protocol/src/ast.js +236 -309
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.js +8 -13
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.js +21 -42
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.js +20 -12
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.js +37 -52
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.js +34 -65
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.js +6 -9
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/delete-clients.js +11 -17
- package/out/zero-protocol/src/delete-clients.js.map +1 -1
- package/out/zero-protocol/src/down.js +11 -23
- package/out/zero-protocol/src/down.js.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.js +24 -41
- package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
- package/out/zero-protocol/src/error-origin-enum.js +8 -9
- package/out/zero-protocol/src/error-origin-enum.js.map +1 -1
- package/out/zero-protocol/src/error-reason-enum.js +12 -17
- package/out/zero-protocol/src/error-reason-enum.js.map +1 -1
- package/out/zero-protocol/src/error.js +76 -152
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +51 -74
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +28 -46
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.js +9 -9
- package/out/zero-protocol/src/mutation-id.js.map +1 -1
- package/out/zero-protocol/src/mutation-type-enum.js +7 -7
- package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +21 -16
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.js +8 -9
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.js +53 -59
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.js +8 -9
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/primary-key.js +9 -19
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +5 -11
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/pull.js +16 -28
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.js +162 -209
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.js +22 -30
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-hash.js +14 -17
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-protocol/src/row-patch.js +23 -30
- package/out/zero-protocol/src/row-patch.js.map +1 -1
- package/out/zero-protocol/src/up.js +11 -22
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/update-auth.js +8 -13
- package/out/zero-protocol/src/update-auth.js.map +1 -1
- package/out/zero-protocol/src/version.js +8 -9
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/bindings.js +12 -0
- package/out/zero-react/src/mod.js +5 -0
- package/out/zero-react/src/use-connection-state.js +14 -11
- package/out/zero-react/src/use-connection-state.js.map +1 -1
- package/out/zero-react/src/use-query.js +283 -281
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-react/src/use-zero-online.js +17 -11
- package/out/zero-react/src/use-zero-online.js.map +1 -1
- package/out/zero-react/src/zero-provider.js +53 -69
- package/out/zero-react/src/zero-provider.js.map +1 -1
- package/out/zero-react/src/zero.js +22 -0
- package/out/zero-schema/src/builder/relationship-builder.js +25 -21
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +51 -79
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +99 -116
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/compiled-permissions.js +21 -25
- package/out/zero-schema/src/compiled-permissions.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js +31 -47
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-schema/src/permissions.js +94 -181
- package/out/zero-schema/src/permissions.js.map +1 -1
- package/out/zero-schema/src/schema-config.js +26 -32
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +79 -76
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +79 -55
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js +66 -40
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/adapters/prisma.d.ts.map +1 -1
- package/out/zero-server/src/adapters/prisma.js +75 -55
- package/out/zero-server/src/adapters/prisma.js.map +1 -1
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +188 -265
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.js +6 -5
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/mod.js +8 -0
- package/out/zero-server/src/pg-query-executor.js +14 -17
- package/out/zero-server/src/pg-query-executor.js.map +1 -1
- package/out/zero-server/src/process-mutations.js +293 -365
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.js +33 -49
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +106 -96
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/schema.js +98 -144
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +54 -69
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/bindings.js +12 -0
- package/out/zero-solid/src/mod.js +5 -0
- package/out/zero-solid/src/solid-view.js +135 -227
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-solid/src/use-connection-state.js +18 -14
- package/out/zero-solid/src/use-connection-state.js.map +1 -1
- package/out/zero-solid/src/use-query.js +55 -100
- package/out/zero-solid/src/use-query.js.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +18 -12
- package/out/zero-solid/src/use-zero-online.js.map +1 -1
- package/out/zero-solid/src/use-zero.js +65 -77
- package/out/zero-solid/src/use-zero.js.map +1 -1
- package/out/zero-solid/src/zero.js +22 -0
- package/out/zero-types/src/format.js +8 -7
- package/out/zero-types/src/format.js.map +1 -1
- package/out/zero-types/src/name-mapper.js +34 -47
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +315 -476
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +69 -74
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/builder/filter.js +116 -140
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/builder/like.js +41 -46
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/error.js +10 -9
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.js +89 -91
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/constraint.js +65 -74
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.js +61 -48
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.js +164 -213
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.js +62 -59
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.js +52 -61
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +91 -96
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.js +22 -26
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.js +41 -35
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +282 -391
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.js +85 -115
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.js +162 -231
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +21 -25
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.js +364 -503
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.js +33 -34
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.js +13 -15
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +267 -270
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.js +91 -104
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/stream.js +10 -10
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.js +422 -569
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +157 -231
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +38 -43
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +166 -255
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/crud.js +35 -34
- package/out/zql/src/mutate/crud.js.map +1 -1
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js +7 -11
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js +67 -71
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.js +26 -25
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-builder.js +134 -239
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.js +222 -212
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-constraint.js +15 -7
- package/out/zql/src/planner/planner-constraint.js.map +1 -1
- package/out/zql/src/planner/planner-debug.js +199 -224
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-fan-in.js +146 -162
- package/out/zql/src/planner/planner-fan-in.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js +62 -74
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-graph.js +302 -334
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.js +255 -240
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.js +10 -6
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-source.js +15 -22
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/planner/planner-terminus.js +28 -28
- package/out/zql/src/planner/planner-terminus.js.map +1 -1
- package/out/zql/src/query/complete-ordering.js +37 -61
- package/out/zql/src/query/complete-ordering.js.map +1 -1
- package/out/zql/src/query/create-builder.js +14 -22
- package/out/zql/src/query/create-builder.js.map +1 -1
- package/out/zql/src/query/error.js +10 -12
- package/out/zql/src/query/error.js.map +1 -1
- package/out/zql/src/query/escape-like.js +6 -5
- package/out/zql/src/query/escape-like.js.map +1 -1
- package/out/zql/src/query/expression.js +138 -157
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +35 -38
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.js +7 -7
- package/out/zql/src/query/metrics-delegate.js.map +1 -1
- package/out/zql/src/query/named.js +52 -51
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +190 -238
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +271 -405
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.js +16 -8
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-registry.js +83 -98
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/query.js +2 -0
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +30 -55
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/static-query.js +7 -14
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/ttl.js +45 -67
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zql/src/query/validate-input.js +23 -20
- package/out/zql/src/query/validate-input.js.map +1 -1
- package/out/zqlite/src/database-storage.js +99 -103
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.js +206 -249
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/explain-queries.js +11 -13
- package/out/zqlite/src/explain-queries.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.js +54 -37
- package/out/zqlite/src/internal/sql-inline.js.map +1 -1
- package/out/zqlite/src/internal/sql.js +17 -15
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/internal/statement-cache.js +117 -92
- package/out/zqlite/src/internal/statement-cache.js.map +1 -1
- package/out/zqlite/src/mod.js +5 -0
- package/out/zqlite/src/query-builder.js +81 -172
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.js +45 -55
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/resolve-scalar-subqueries.js +134 -124
- package/out/zqlite/src/resolve-scalar-subqueries.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +92 -97
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.js +304 -286
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -1
- package/out/zqlite/src/table-source.js +281 -455
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +7 -7
- package/out/replicache/src/db/index-operation-enum.js +0 -7
- package/out/replicache/src/db/index-operation-enum.js.map +0 -1
- package/out/replicache/src/db/meta-type-enum.js +0 -7
- package/out/replicache/src/db/meta-type-enum.js.map +0 -1
- package/out/replicache/src/format-version-enum.js +0 -11
- package/out/replicache/src/format-version-enum.js.map +0 -1
- package/out/replicache/src/http-status-unauthorized.js +0 -5
- package/out/replicache/src/http-status-unauthorized.js.map +0 -1
- package/out/replicache/src/invoke-kind-enum.js +0 -7
- package/out/replicache/src/invoke-kind-enum.js.map +0 -1
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js +0 -9
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js.map +0 -1
- package/out/zero/package.json.js +0 -9
- package/out/zero/package.json.js.map +0 -1
- package/out/zero/src/adapters/drizzle.js.map +0 -1
- package/out/zero/src/adapters/pg.js.map +0 -1
- package/out/zero/src/adapters/postgresjs.js.map +0 -1
- package/out/zero/src/adapters/prisma.js.map +0 -1
- package/out/zero/src/analyze-query.js.map +0 -1
- package/out/zero/src/ast-to-zql.js.map +0 -1
- package/out/zero/src/bindings.js.map +0 -1
- package/out/zero/src/change-protocol/v0.js.map +0 -1
- package/out/zero/src/cli.js.map +0 -1
- package/out/zero/src/deploy-permissions.js.map +0 -1
- package/out/zero/src/expo-sqlite.js.map +0 -1
- package/out/zero/src/op-sqlite.js.map +0 -1
- package/out/zero/src/pg.js.map +0 -1
- package/out/zero/src/react.js.map +0 -1
- package/out/zero/src/server.js.map +0 -1
- package/out/zero/src/solid.js.map +0 -1
- package/out/zero/src/sqlite.js.map +0 -1
- package/out/zero/src/transform-query.js.map +0 -1
- package/out/zero/src/zero.js.map +0 -1
- package/out/zero/src/zqlite.js.map +0 -1
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js +0 -11
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js.map +0 -1
- package/out/zero-cache/src/db/postgres-type-class-enum.js +0 -17
- package/out/zero-cache/src/db/postgres-type-class-enum.js.map +0 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js +0 -9
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +0 -1
|
@@ -1,1209 +1,869 @@
|
|
|
1
|
-
import { Lock } from "@rocicorp/lock";
|
|
2
|
-
import { consoleLogSink } from "@rocicorp/logger";
|
|
3
|
-
import { resolver } from "@rocicorp/resolver";
|
|
4
|
-
import { AbortError } from "../../shared/src/abort-error.js";
|
|
5
1
|
import { assert } from "../../shared/src/asserts.js";
|
|
2
|
+
import { assertCookie } from "./cookies.js";
|
|
3
|
+
import { isClientStateNotFoundResponse, isVersionNotSupportedResponse } from "./error-responses.js";
|
|
4
|
+
import { getDefaultPuller, isDefaultPuller } from "./get-default-puller.js";
|
|
6
5
|
import { getBrowserGlobal } from "../../shared/src/browser-env.js";
|
|
7
|
-
import { getDocumentVisibilityWatcher } from "../../shared/src/document-visible.js";
|
|
8
6
|
import { promiseVoid } from "../../shared/src/resolved-promises.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { StoreImpl } from "./dag/store-impl.js";
|
|
7
|
+
import { deepFreeze } from "./frozen-json.js";
|
|
8
|
+
import { makeIDBName } from "./make-idb-name.js";
|
|
9
|
+
import { AbortError } from "../../shared/src/abort-error.js";
|
|
10
|
+
import { assertHash, emptyHash, newRandomHash } from "./hash.js";
|
|
14
11
|
import { ChunkNotFoundError, mustGetHeadHash } from "./dag/store.js";
|
|
15
|
-
import {
|
|
12
|
+
import { StoreImpl } from "./dag/store-impl.js";
|
|
13
|
+
import { DEFAULT_HEAD_NAME, baseSnapshotFromHash, isLocalMetaDD31 } from "./db/commit.js";
|
|
16
14
|
import { readFromDefaultHead } from "./db/read.js";
|
|
17
|
-
import { rebaseMutationAndCommit } from "./db/rebase.js";
|
|
18
15
|
import { newWriteLocal } from "./db/write.js";
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import { getDefaultPusher, isDefaultPusher } from "./get-default-pusher.js";
|
|
16
|
+
import { withRead, withWrite, withWriteNoImplicitCommit } from "./with-transactions.js";
|
|
17
|
+
import { disableClientGroup } from "./persist/client-groups.js";
|
|
18
|
+
import { makeClientID } from "./persist/make-client-id.js";
|
|
19
|
+
import { ClientStateNotFoundError, hasClientState, initClientV6 } from "./persist/clients.js";
|
|
24
20
|
import { getKVStoreProvider } from "./get-kv-store-provider.js";
|
|
25
|
-
import { newRandomHash, assertHash, emptyHash } from "./hash.js";
|
|
26
|
-
import { httpStatusUnauthorized } from "./http-status-unauthorized.js";
|
|
27
21
|
import { createLogContext } from "./log-options.js";
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
22
|
+
import { IDBDatabasesStore } from "./persist/idb-databases-store.js";
|
|
23
|
+
import { COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, initCollectIDBDatabases } from "./persist/collect-idb-databases.js";
|
|
24
|
+
import { throwIfClosed } from "./transaction-closed-error.js";
|
|
25
|
+
import { getDocumentVisibilityWatcher } from "../../shared/src/document-visible.js";
|
|
26
|
+
import { PullDelegate, PushDelegate } from "./connection-loop-delegates.js";
|
|
27
|
+
import { ConnectionLoop, MAX_DELAY_MS } from "./connection-loop.js";
|
|
28
|
+
import { LazyStore } from "./dag/lazy-store.js";
|
|
29
|
+
import { ReadTransactionImpl, WriteTransactionImpl } from "./transactions.js";
|
|
30
|
+
import { rebaseMutationAndCommit } from "./db/rebase.js";
|
|
31
|
+
import { getDefaultPusher, isDefaultPusher } from "./get-default-pusher.js";
|
|
32
|
+
import { ReportError } from "./report-error.js";
|
|
33
|
+
import { PullError } from "./sync/pull-error.js";
|
|
34
|
+
import { SYNC_HEAD_NAME } from "./sync/sync-head-name.js";
|
|
35
|
+
import { beginPullV1, handlePullResponseV1, maybeEndPull } from "./sync/pull.js";
|
|
36
|
+
import { PushError } from "./pusher.js";
|
|
37
|
+
import { push } from "./sync/push.js";
|
|
38
|
+
import "./mutation-recovery.js";
|
|
33
39
|
import { initNewClientChannel } from "./new-client-channel.js";
|
|
34
40
|
import { initOnPersistChannel } from "./on-persist-channel.js";
|
|
35
41
|
import { pendingMutationsForAPI } from "./pending-mutations.js";
|
|
36
|
-
import { CLIENT_MAX_INACTIVE_TIME,
|
|
42
|
+
import { CLIENT_MAX_INACTIVE_TIME, GC_INTERVAL, initClientGC } from "./persist/client-gc.js";
|
|
37
43
|
import { initClientGroupGC } from "./persist/client-group-gc.js";
|
|
38
|
-
import {
|
|
39
|
-
import { initCollectIDBDatabases, INITIAL_COLLECT_IDB_DELAY, COLLECT_IDB_INTERVAL } from "./persist/collect-idb-databases.js";
|
|
40
|
-
import { startHeartbeats, HEARTBEAT_INTERVAL } from "./persist/heartbeat.js";
|
|
41
|
-
import { IDBDatabasesStore } from "./persist/idb-databases-store.js";
|
|
42
|
-
import { makeClientID } from "./persist/make-client-id.js";
|
|
44
|
+
import { HEARTBEAT_INTERVAL, startHeartbeats } from "./persist/heartbeat.js";
|
|
43
45
|
import { persistDD31 } from "./persist/persist.js";
|
|
44
46
|
import { refresh } from "./persist/refresh.js";
|
|
45
47
|
import { ProcessScheduler } from "./process-scheduler.js";
|
|
46
|
-
import { PushError } from "./pusher.js";
|
|
47
|
-
import { ReportError } from "./report-error.js";
|
|
48
48
|
import { setIntervalWithSignal } from "./set-interval-with-signal.js";
|
|
49
|
-
import {
|
|
50
|
-
import { CookieMismatch, Applied } from "./sync/handle-pull-response-result-type-enum.js";
|
|
51
|
-
import { PullError } from "./sync/pull-error.js";
|
|
49
|
+
import { SubscriptionImpl, SubscriptionsManagerImpl, WatchSubscription } from "./subscriptions.js";
|
|
52
50
|
import { newRequestID } from "./sync/request-id.js";
|
|
53
|
-
import { SYNC_HEAD_NAME } from "./sync/sync-head-name.js";
|
|
54
|
-
import { throwIfClosed } from "./transaction-closed-error.js";
|
|
55
|
-
import { ReadTransactionImpl, WriteTransactionImpl } from "./transactions.js";
|
|
56
51
|
import { version } from "./version.js";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
import { resolver } from "@rocicorp/resolver";
|
|
53
|
+
import { Lock } from "@rocicorp/lock";
|
|
54
|
+
import { consoleLogSink } from "@rocicorp/logger";
|
|
55
|
+
//#region ../replicache/src/replicache-impl.ts
|
|
56
|
+
/**
|
|
57
|
+
* The maximum number of time to call out to getAuth before giving up
|
|
58
|
+
* and throwing an error.
|
|
59
|
+
*/
|
|
60
|
+
var MAX_REAUTH_TRIES = 8;
|
|
61
|
+
var PERSIST_IDLE_TIMEOUT_MS = 1e3;
|
|
62
|
+
var REFRESH_IDLE_TIMEOUT_MS = 1e3;
|
|
63
|
+
var PERSIST_THROTTLE_MS = 500;
|
|
64
|
+
var REFRESH_THROTTLE_MS = 500;
|
|
65
|
+
var LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 100 * 2 ** 20;
|
|
66
|
+
var RECOVER_MUTATIONS_INTERVAL_MS = 300 * 1e3;
|
|
67
|
+
var noop = () => {};
|
|
68
|
+
var updateNeededReasonNewClientGroup = { type: "NewClientGroup" };
|
|
69
|
+
var ReplicacheImpl = class {
|
|
70
|
+
/** The URL to use when doing a pull request. */
|
|
71
|
+
pullURL;
|
|
72
|
+
/** The URL to use when doing a push request. */
|
|
73
|
+
pushURL;
|
|
74
|
+
/** The authorization token used when doing a push request. */
|
|
75
|
+
#auth;
|
|
76
|
+
/** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */
|
|
77
|
+
name;
|
|
78
|
+
#subscriptions;
|
|
79
|
+
#mutationRecovery;
|
|
80
|
+
/**
|
|
81
|
+
* Client groups gets disabled when the server does not know about it.
|
|
82
|
+
* A disabled client group prevents the client from pushing and pulling.
|
|
83
|
+
*/
|
|
84
|
+
isClientGroupDisabled = false;
|
|
85
|
+
#kvStoreProvider;
|
|
86
|
+
lastMutationID = 0;
|
|
87
|
+
/**
|
|
88
|
+
* This is the name Replicache uses for the IndexedDB database where data is
|
|
89
|
+
* stored.
|
|
90
|
+
*/
|
|
91
|
+
get idbName() {
|
|
92
|
+
return makeIDBName(this.name, this.schemaVersion);
|
|
93
|
+
}
|
|
94
|
+
set auth(auth) {
|
|
95
|
+
if (this.#zero) this.#zero.auth = auth;
|
|
96
|
+
this.#auth = auth;
|
|
97
|
+
}
|
|
98
|
+
get auth() {
|
|
99
|
+
return this.#auth;
|
|
100
|
+
}
|
|
101
|
+
/** The schema version of the data understood by this application. */
|
|
102
|
+
schemaVersion;
|
|
103
|
+
get #idbDatabase() {
|
|
104
|
+
return {
|
|
105
|
+
name: this.idbName,
|
|
106
|
+
replicacheName: this.name,
|
|
107
|
+
replicacheFormatVersion: 7,
|
|
108
|
+
schemaVersion: this.schemaVersion
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
#closed = false;
|
|
112
|
+
#online = true;
|
|
113
|
+
#clientID = makeClientID();
|
|
114
|
+
#ready;
|
|
115
|
+
#profileIDPromise;
|
|
116
|
+
#clientGroupIDPromise;
|
|
117
|
+
#mutatorRegistry = {};
|
|
118
|
+
/**
|
|
119
|
+
* The mutators that was registered in the constructor.
|
|
120
|
+
*/
|
|
121
|
+
mutate;
|
|
122
|
+
#pushCounter = 0;
|
|
123
|
+
#pullCounter = 0;
|
|
124
|
+
#pullConnectionLoop;
|
|
125
|
+
#pushConnectionLoop;
|
|
126
|
+
/**
|
|
127
|
+
* The duration between each periodic {@link pull}. Setting this to `null`
|
|
128
|
+
* disables periodic pull completely. Pull will still happen if you call
|
|
129
|
+
* {@link pull} manually.
|
|
130
|
+
*/
|
|
131
|
+
pullInterval;
|
|
132
|
+
/**
|
|
133
|
+
* The delay between when a change is made to Replicache and when Replicache
|
|
134
|
+
* attempts to push that change.
|
|
135
|
+
*/
|
|
136
|
+
pushDelay;
|
|
137
|
+
#requestOptions;
|
|
138
|
+
/**
|
|
139
|
+
* The function to use to pull data from the server.
|
|
140
|
+
*/
|
|
141
|
+
puller;
|
|
142
|
+
/**
|
|
143
|
+
* The function to use to push data to the server.
|
|
144
|
+
*/
|
|
145
|
+
pusher;
|
|
146
|
+
memdag;
|
|
147
|
+
perdag;
|
|
148
|
+
#idbDatabases;
|
|
149
|
+
#lc;
|
|
150
|
+
#zero;
|
|
151
|
+
#closeAbortController = new AbortController();
|
|
152
|
+
#persistLock = new Lock();
|
|
153
|
+
#enableScheduledPersist;
|
|
154
|
+
#enableScheduledRefresh;
|
|
155
|
+
#enableRefresh;
|
|
156
|
+
#enablePullAndPushInOpen;
|
|
157
|
+
#persistScheduler = new ProcessScheduler(() => this.persist(), PERSIST_IDLE_TIMEOUT_MS, PERSIST_THROTTLE_MS, this.#closeAbortController.signal);
|
|
158
|
+
#onPersist;
|
|
159
|
+
#refreshScheduler = new ProcessScheduler(() => this.refresh(), REFRESH_IDLE_TIMEOUT_MS, REFRESH_THROTTLE_MS, this.#closeAbortController.signal);
|
|
160
|
+
/**
|
|
161
|
+
* The options used to control the {@link pull} and push request behavior. This
|
|
162
|
+
* object is live so changes to it will affect the next pull or push call.
|
|
163
|
+
*/
|
|
164
|
+
get requestOptions() {
|
|
165
|
+
return this.#requestOptions;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* `onSync(true)` is called when Replicache transitions from no push or pull
|
|
169
|
+
* happening to at least one happening. `onSync(false)` is called in the
|
|
170
|
+
* opposite case: when Replicache transitions from at least one push or pull
|
|
171
|
+
* happening to none happening.
|
|
172
|
+
*
|
|
173
|
+
* This can be used in a React like app by doing something like the following:
|
|
174
|
+
*
|
|
175
|
+
* ```js
|
|
176
|
+
* const [syncing, setSyncing] = useState(false);
|
|
177
|
+
* useEffect(() => {
|
|
178
|
+
* rep.onSync = setSyncing;
|
|
179
|
+
* }, [rep]);
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
onSync = null;
|
|
183
|
+
/**
|
|
184
|
+
* `onClientStateNotFound` is called when the persistent client has been
|
|
185
|
+
* garbage collected. This can happen if the client has no pending mutations
|
|
186
|
+
* and has not been used for a while.
|
|
187
|
+
*
|
|
188
|
+
* The default behavior is to reload the page (using `location.reload()`). Set
|
|
189
|
+
* this to `null` or provide your own function to prevent the page from
|
|
190
|
+
* reloading automatically.
|
|
191
|
+
*/
|
|
192
|
+
onClientStateNotFound = reload;
|
|
193
|
+
/**
|
|
194
|
+
* `onUpdateNeeded` is called when a code update is needed.
|
|
195
|
+
*
|
|
196
|
+
* A code update can be needed because:
|
|
197
|
+
* - the server no longer supports the {@link pushVersion},
|
|
198
|
+
* {@link pullVersion} or {@link schemaVersion} of the current code.
|
|
199
|
+
* - a new Replicache client has created a new client group, because its code
|
|
200
|
+
* has different mutators, indexes, schema version and/or format version
|
|
201
|
+
* from this Replicache client. This is likely due to the new client having
|
|
202
|
+
* newer code. A code update is needed to be able to locally sync with this
|
|
203
|
+
* new Replicache client (i.e. to sync while offline, the clients can still
|
|
204
|
+
* sync with each other via the server).
|
|
205
|
+
*
|
|
206
|
+
* The default behavior is to reload the page (using `location.reload()`). Set
|
|
207
|
+
* this to `null` or provide your own function to prevent the page from
|
|
208
|
+
* reloading automatically. You may want to provide your own function to
|
|
209
|
+
* display a toast to inform the end user there is a new version of your app
|
|
210
|
+
* available and prompting them to refresh.
|
|
211
|
+
*/
|
|
212
|
+
onUpdateNeeded = reload;
|
|
213
|
+
/**
|
|
214
|
+
* This gets called when we get an HTTP unauthorized (401) response from the
|
|
215
|
+
* push or pull endpoint. Set this to a function that will ask your user to
|
|
216
|
+
* reauthenticate.
|
|
217
|
+
*/
|
|
218
|
+
getAuth = null;
|
|
219
|
+
onPushInvoked = () => void 0;
|
|
220
|
+
onBeginPull = () => void 0;
|
|
221
|
+
onRecoverMutations = (r) => r;
|
|
222
|
+
constructor(options, implOptions = {}) {
|
|
223
|
+
validateOptions(options);
|
|
224
|
+
const { name, logLevel = "info", logSinks = [consoleLogSink], pullURL = "", auth, pushDelay = 10, pushURL = "", schemaVersion = "", pullInterval = 6e4, mutators = {}, requestOptions = {}, puller, pusher, indexes = {}, clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME } = options;
|
|
225
|
+
const { enableMutationRecovery = true, enableScheduledPersist = true, enableScheduledRefresh = true, enableRefresh = () => true, enablePullAndPushInOpen = true, enableClientGroupForking = true, onClientsDeleted = () => promiseVoid } = implOptions;
|
|
226
|
+
this.#zero = implOptions.zero;
|
|
227
|
+
this.#auth = auth ?? "";
|
|
228
|
+
this.pullURL = pullURL;
|
|
229
|
+
this.pushURL = pushURL;
|
|
230
|
+
this.name = name;
|
|
231
|
+
this.schemaVersion = schemaVersion;
|
|
232
|
+
this.pullInterval = pullInterval;
|
|
233
|
+
this.pushDelay = pushDelay;
|
|
234
|
+
this.puller = puller ?? getDefaultPuller(this);
|
|
235
|
+
this.pusher = pusher ?? getDefaultPusher(this);
|
|
236
|
+
this.#enableScheduledPersist = enableScheduledPersist;
|
|
237
|
+
this.#enableScheduledRefresh = enableScheduledRefresh;
|
|
238
|
+
this.#enableRefresh = enableRefresh;
|
|
239
|
+
this.#enablePullAndPushInOpen = enablePullAndPushInOpen;
|
|
240
|
+
this.#lc = createLogContext(logLevel, logSinks, { name });
|
|
241
|
+
this.#lc.debug?.("Constructing Replicache", {
|
|
242
|
+
name,
|
|
243
|
+
"replicache version": version
|
|
244
|
+
});
|
|
245
|
+
this.#subscriptions = new SubscriptionsManagerImpl(this.#queryInternal, this.#lc, this.#closeAbortController.signal);
|
|
246
|
+
const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);
|
|
247
|
+
this.#kvStoreProvider = kvStoreProvider;
|
|
248
|
+
const perKVStore = kvStoreProvider.create(this.idbName);
|
|
249
|
+
this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);
|
|
250
|
+
this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);
|
|
251
|
+
this.memdag = new LazyStore(this.perdag, LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT, newRandomHash, assertHash);
|
|
252
|
+
const readyResolver = resolver();
|
|
253
|
+
this.#ready = readyResolver.promise;
|
|
254
|
+
const { minDelayMs = 30, maxDelayMs = MAX_DELAY_MS } = requestOptions;
|
|
255
|
+
this.#requestOptions = {
|
|
256
|
+
maxDelayMs,
|
|
257
|
+
minDelayMs
|
|
258
|
+
};
|
|
259
|
+
const visibilityWatcher = getDocumentVisibilityWatcher(getBrowserGlobal("document"), 0, this.#closeAbortController.signal);
|
|
260
|
+
this.#pullConnectionLoop = new ConnectionLoop(this.#lc.withContext("PULL"), new PullDelegate(this, () => this.#invokePull()), visibilityWatcher);
|
|
261
|
+
this.#pushConnectionLoop = new ConnectionLoop(this.#lc.withContext("PUSH"), new PushDelegate(this, () => this.#invokePush()));
|
|
262
|
+
this.mutate = this.#registerMutators(mutators);
|
|
263
|
+
const profileIDResolver = resolver();
|
|
264
|
+
this.#profileIDPromise = profileIDResolver.promise;
|
|
265
|
+
const clientGroupIDResolver = resolver();
|
|
266
|
+
this.#clientGroupIDPromise = clientGroupIDResolver.promise;
|
|
267
|
+
this.#onPersist = initOnPersistChannel(this.name, this.#closeAbortController.signal, (persistInfo) => {
|
|
268
|
+
this.#handlePersist(persistInfo);
|
|
269
|
+
});
|
|
270
|
+
this.#open(indexes, enableClientGroupForking, enableMutationRecovery, clientMaxAgeMs, profileIDResolver.resolve, clientGroupIDResolver.resolve, readyResolver.resolve, onClientsDeleted);
|
|
271
|
+
}
|
|
272
|
+
async #open(indexes, enableClientGroupForking, enableMutationRecovery, clientMaxAgeMs, profileIDResolver, resolveClientGroupID, resolveReady, onClientsDeleted) {
|
|
273
|
+
const { clientID } = this;
|
|
274
|
+
await closingInstances.get(this.name);
|
|
275
|
+
await this.#idbDatabases.getProfileID().then(profileIDResolver);
|
|
276
|
+
await this.#idbDatabases.putDatabase(this.#idbDatabase);
|
|
277
|
+
const [client, headHash, , isNewClientGroup] = await initClientV6(clientID, this.#lc, this.perdag, Object.keys(this.#mutatorRegistry), indexes, 7, enableClientGroupForking);
|
|
278
|
+
resolveClientGroupID(client.clientGroupID);
|
|
279
|
+
await withWrite(this.memdag, (write) => write.setHead(DEFAULT_HEAD_NAME, headHash));
|
|
280
|
+
await this.#zero?.init(headHash, this.memdag);
|
|
281
|
+
resolveReady();
|
|
282
|
+
if (this.#enablePullAndPushInOpen) {
|
|
283
|
+
this.pull().catch(noop);
|
|
284
|
+
this.push().catch(noop);
|
|
285
|
+
}
|
|
286
|
+
const { signal } = this.#closeAbortController;
|
|
287
|
+
startHeartbeats(clientID, this.perdag, () => {
|
|
288
|
+
this.#clientStateNotFoundOnClient(clientID);
|
|
289
|
+
}, HEARTBEAT_INTERVAL, this.#lc, signal);
|
|
290
|
+
initClientGC(clientID, this.perdag, clientMaxAgeMs, GC_INTERVAL, onClientsDeleted, this.#lc, signal);
|
|
291
|
+
initCollectIDBDatabases(this.#idbDatabases, this.#kvStoreProvider, COLLECT_IDB_INTERVAL, INITIAL_COLLECT_IDB_DELAY, 2 * clientMaxAgeMs, enableMutationRecovery, onClientsDeleted, this.#lc, signal);
|
|
292
|
+
initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);
|
|
293
|
+
initNewClientChannel(this.name, this.idbName, signal, client.clientGroupID, isNewClientGroup, () => {
|
|
294
|
+
this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);
|
|
295
|
+
}, this.perdag);
|
|
296
|
+
setIntervalWithSignal(() => this.recoverMutations(), RECOVER_MUTATIONS_INTERVAL_MS, signal);
|
|
297
|
+
this.recoverMutations();
|
|
298
|
+
getBrowserGlobal("document")?.addEventListener("visibilitychange", this.#onVisibilityChange);
|
|
299
|
+
}
|
|
300
|
+
#onVisibilityChange = async () => {
|
|
301
|
+
if (this.#closed) return;
|
|
302
|
+
if (getBrowserGlobal("document")?.visibilityState !== "visible") return;
|
|
303
|
+
await this.#checkForClientStateNotFoundAndCallHandler();
|
|
304
|
+
};
|
|
305
|
+
async #checkForClientStateNotFoundAndCallHandler() {
|
|
306
|
+
const { clientID } = this;
|
|
307
|
+
const hasClientState$1 = await withRead(this.perdag, (read) => hasClientState(clientID, read));
|
|
308
|
+
if (!hasClientState$1) this.#clientStateNotFoundOnClient(clientID);
|
|
309
|
+
return !hasClientState$1;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* The browser profile ID for this browser profile. Every instance of Replicache
|
|
313
|
+
* browser-profile-wide shares the same profile ID.
|
|
314
|
+
*/
|
|
315
|
+
get profileID() {
|
|
316
|
+
return this.#profileIDPromise;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* The client ID for this instance of Replicache. Each instance of Replicache
|
|
320
|
+
* gets a unique client ID.
|
|
321
|
+
*/
|
|
322
|
+
get clientID() {
|
|
323
|
+
return this.#clientID;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The client group ID for this instance of Replicache. Instances of
|
|
327
|
+
* Replicache will have the same client group ID if and only if they have
|
|
328
|
+
* the same name, mutators, indexes, schema version, format version, and
|
|
329
|
+
* browser profile.
|
|
330
|
+
*/
|
|
331
|
+
get clientGroupID() {
|
|
332
|
+
return this.#clientGroupIDPromise;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* `onOnlineChange` is called when the {@link online} property changes. See
|
|
336
|
+
* {@link online} for more details.
|
|
337
|
+
*/
|
|
338
|
+
onOnlineChange = null;
|
|
339
|
+
/**
|
|
340
|
+
* A rough heuristic for whether the client is currently online. Note that
|
|
341
|
+
* there is no way to know for certain whether a client is online - the next
|
|
342
|
+
* request can always fail. This property returns true if the last sync attempt succeeded,
|
|
343
|
+
* and false otherwise.
|
|
344
|
+
*/
|
|
345
|
+
get online() {
|
|
346
|
+
return this.#online;
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Whether the Replicache database has been closed. Once Replicache has been
|
|
350
|
+
* closed it no longer syncs and you can no longer read or write data out of
|
|
351
|
+
* it. After it has been closed it is pretty much useless and should not be
|
|
352
|
+
* used any more.
|
|
353
|
+
*/
|
|
354
|
+
get closed() {
|
|
355
|
+
return this.#closed;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Closes this Replicache instance.
|
|
359
|
+
*
|
|
360
|
+
* When closed all subscriptions end and no more read or writes are allowed.
|
|
361
|
+
*/
|
|
362
|
+
async close() {
|
|
363
|
+
this.#closed = true;
|
|
364
|
+
const { promise, resolve } = resolver();
|
|
365
|
+
closingInstances.set(this.name, promise);
|
|
366
|
+
this.#closeAbortController.abort();
|
|
367
|
+
getBrowserGlobal("document")?.removeEventListener("visibilitychange", this.#onVisibilityChange);
|
|
368
|
+
await this.#ready;
|
|
369
|
+
const closingPromises = [
|
|
370
|
+
this.memdag.close(),
|
|
371
|
+
this.perdag.close(),
|
|
372
|
+
this.#idbDatabases.close()
|
|
373
|
+
];
|
|
374
|
+
this.#pullConnectionLoop.close();
|
|
375
|
+
this.#pushConnectionLoop.close();
|
|
376
|
+
this.#subscriptions.clear();
|
|
377
|
+
await Promise.all(closingPromises);
|
|
378
|
+
closingInstances.delete(this.name);
|
|
379
|
+
resolve();
|
|
380
|
+
}
|
|
381
|
+
async maybeEndPull(syncHead, requestID) {
|
|
382
|
+
for (;;) {
|
|
383
|
+
if (this.#closed) return;
|
|
384
|
+
await this.#ready;
|
|
385
|
+
const { clientID } = this;
|
|
386
|
+
const lc = this.#lc.withContext("maybeEndPull").withContext("requestID", requestID);
|
|
387
|
+
const { replayMutations, diffs, oldMainHead, mainHead } = await maybeEndPull(this.memdag, lc, syncHead, clientID, this.#subscriptions, 7);
|
|
388
|
+
if (!replayMutations || replayMutations.length === 0) {
|
|
389
|
+
this.#zero?.advance(oldMainHead, mainHead, diffs.get("") ?? []);
|
|
390
|
+
await this.#subscriptions.fire(diffs);
|
|
391
|
+
this.#schedulePersist();
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
const zeroData = await this.#zero?.getTxData?.(syncHead);
|
|
395
|
+
for (const mutation of replayMutations) {
|
|
396
|
+
if (this.#subscriptions.hasPendingSubscriptionRuns) await Promise.resolve();
|
|
397
|
+
const { meta } = mutation;
|
|
398
|
+
syncHead = await withWriteNoImplicitCommit(this.memdag, (dagWrite) => rebaseMutationAndCommit(mutation, dagWrite, syncHead, SYNC_HEAD_NAME, this.#mutatorRegistry, lc, isLocalMetaDD31(meta) ? meta.clientID : clientID, 7, zeroData));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
#invokePull() {
|
|
403
|
+
if (this.#isPullDisabled()) return Promise.resolve(true);
|
|
404
|
+
return this.#wrapInOnlineCheck(async () => {
|
|
405
|
+
try {
|
|
406
|
+
this.#changeSyncCounters(0, 1);
|
|
407
|
+
const { syncHead, requestID, ok } = await this.beginPull();
|
|
408
|
+
if (!ok) return false;
|
|
409
|
+
if (syncHead !== emptyHash) await this.maybeEndPull(syncHead, requestID);
|
|
410
|
+
} catch (e) {
|
|
411
|
+
throw await this.#convertToClientStateNotFoundError(e);
|
|
412
|
+
} finally {
|
|
413
|
+
this.#changeSyncCounters(0, -1);
|
|
414
|
+
}
|
|
415
|
+
return true;
|
|
416
|
+
}, "Pull");
|
|
417
|
+
}
|
|
418
|
+
#isPullDisabled() {
|
|
419
|
+
return this.isClientGroupDisabled || this.pullURL === "" && isDefaultPuller(this.puller);
|
|
420
|
+
}
|
|
421
|
+
async #wrapInOnlineCheck(f, name) {
|
|
422
|
+
let online = true;
|
|
423
|
+
try {
|
|
424
|
+
return await f();
|
|
425
|
+
} catch (e) {
|
|
426
|
+
if (e instanceof PushError || e instanceof PullError) {
|
|
427
|
+
online = false;
|
|
428
|
+
this.#lc.debug?.(`${name} threw:\n`, e, "\nwith cause:\n", e.causedBy);
|
|
429
|
+
} else if (e instanceof ReportError) this.#lc.error?.(e);
|
|
430
|
+
else this.#lc.info?.(`${name} threw:\n`, e);
|
|
431
|
+
return false;
|
|
432
|
+
} finally {
|
|
433
|
+
if (this.#online !== online) {
|
|
434
|
+
this.#online = online;
|
|
435
|
+
this.onOnlineChange?.(online);
|
|
436
|
+
if (online) this.recoverMutations();
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
async #wrapInReauthRetries(f, verb, lc, preAuth = noop, postAuth = noop) {
|
|
441
|
+
const { clientID } = this;
|
|
442
|
+
let reauthAttempts = 0;
|
|
443
|
+
let lastResult;
|
|
444
|
+
lc = lc.withContext(verb);
|
|
445
|
+
do {
|
|
446
|
+
const requestID = newRequestID(clientID);
|
|
447
|
+
const requestLc = lc.withContext("requestID", requestID);
|
|
448
|
+
const { httpRequestInfo, result } = await f(requestID, requestLc);
|
|
449
|
+
lastResult = result;
|
|
450
|
+
if (!httpRequestInfo) return {
|
|
451
|
+
result,
|
|
452
|
+
authFailure: false
|
|
453
|
+
};
|
|
454
|
+
const { errorMessage, httpStatusCode } = httpRequestInfo;
|
|
455
|
+
if (errorMessage || httpStatusCode !== 200) requestLc.error?.(`Got a non 200 response doing ${verb}: ${httpStatusCode}` + (errorMessage ? `: ${errorMessage}` : ""));
|
|
456
|
+
if (httpStatusCode !== 401) return {
|
|
457
|
+
result,
|
|
458
|
+
authFailure: false
|
|
459
|
+
};
|
|
460
|
+
if (!this.getAuth) return {
|
|
461
|
+
result,
|
|
462
|
+
authFailure: true
|
|
463
|
+
};
|
|
464
|
+
let auth;
|
|
465
|
+
try {
|
|
466
|
+
await preAuth();
|
|
467
|
+
auth = await this.getAuth();
|
|
468
|
+
} finally {
|
|
469
|
+
await postAuth();
|
|
470
|
+
}
|
|
471
|
+
if (auth === null || auth === void 0) return {
|
|
472
|
+
result,
|
|
473
|
+
authFailure: true
|
|
474
|
+
};
|
|
475
|
+
this.auth = auth;
|
|
476
|
+
reauthAttempts++;
|
|
477
|
+
} while (reauthAttempts < MAX_REAUTH_TRIES);
|
|
478
|
+
lc.info?.("Tried to reauthenticate too many times");
|
|
479
|
+
return {
|
|
480
|
+
result: lastResult,
|
|
481
|
+
authFailure: true
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
#isPushDisabled() {
|
|
485
|
+
return this.isClientGroupDisabled || this.pushURL === "" && isDefaultPusher(this.pusher);
|
|
486
|
+
}
|
|
487
|
+
async #invokePush() {
|
|
488
|
+
if (this.#isPushDisabled()) return true;
|
|
489
|
+
await this.#ready;
|
|
490
|
+
const profileID = await this.#profileIDPromise;
|
|
491
|
+
const { clientID } = this;
|
|
492
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
493
|
+
return this.#wrapInOnlineCheck(async () => {
|
|
494
|
+
const { result: pusherResult } = await this.#wrapInReauthRetries(async (requestID, requestLc) => {
|
|
495
|
+
try {
|
|
496
|
+
this.#changeSyncCounters(1, 0);
|
|
497
|
+
const pusherResult = await push(requestID, this.memdag, requestLc, profileID, clientGroupID, clientID, this.pusher, this.schemaVersion, 1);
|
|
498
|
+
return {
|
|
499
|
+
result: pusherResult,
|
|
500
|
+
httpRequestInfo: pusherResult?.httpRequestInfo
|
|
501
|
+
};
|
|
502
|
+
} finally {
|
|
503
|
+
this.#changeSyncCounters(-1, 0);
|
|
504
|
+
}
|
|
505
|
+
}, "push", this.#lc);
|
|
506
|
+
if (pusherResult === void 0) return true;
|
|
507
|
+
const { response, httpRequestInfo } = pusherResult;
|
|
508
|
+
if (isVersionNotSupportedResponse(response)) this.#handleVersionNotSupportedResponse(response);
|
|
509
|
+
else if (isClientStateNotFoundResponse(response)) await this.#clientStateNotFoundOnServer();
|
|
510
|
+
return httpRequestInfo.httpStatusCode === 200;
|
|
511
|
+
}, "Push");
|
|
512
|
+
}
|
|
513
|
+
#handleVersionNotSupportedResponse(response) {
|
|
514
|
+
const reason = { type: response.error };
|
|
515
|
+
if (response.versionType) reason.versionType = response.versionType;
|
|
516
|
+
this.#fireOnUpdateNeeded(reason);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Push pushes pending changes to the {@link pushURL}.
|
|
520
|
+
*
|
|
521
|
+
* You do not usually need to manually call push. If {@link pushDelay} is
|
|
522
|
+
* non-zero (which it is by default) pushes happen automatically shortly after
|
|
523
|
+
* mutations.
|
|
524
|
+
*
|
|
525
|
+
* If the server endpoint fails push will be continuously retried with an
|
|
526
|
+
* exponential backoff.
|
|
527
|
+
*
|
|
528
|
+
* @param [now=false] If true, push will happen immediately and ignore
|
|
529
|
+
* {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the
|
|
530
|
+
* exponential backoff in case of errors.
|
|
531
|
+
* @returns A promise that resolves when the next push completes. In case of
|
|
532
|
+
* errors the first error will reject the returned promise. Subsequent errors
|
|
533
|
+
* will not be reflected in the promise.
|
|
534
|
+
*/
|
|
535
|
+
push({ now = false } = {}) {
|
|
536
|
+
return throwIfError(this.#pushConnectionLoop.send(now));
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Pull pulls changes from the {@link pullURL}. If there are any changes local
|
|
540
|
+
* changes will get replayed on top of the new server state.
|
|
541
|
+
*
|
|
542
|
+
* If the server endpoint fails pull will be continuously retried with an
|
|
543
|
+
* exponential backoff.
|
|
544
|
+
*
|
|
545
|
+
* @param [now=false] If true, pull will happen immediately and ignore
|
|
546
|
+
* {@link RequestOptions.minDelayMs} as well as the exponential backoff in
|
|
547
|
+
* case of errors.
|
|
548
|
+
* @returns A promise that resolves when the next pull completes. In case of
|
|
549
|
+
* errors the first error will reject the returned promise. Subsequent errors
|
|
550
|
+
* will not be reflected in the promise.
|
|
551
|
+
*/
|
|
552
|
+
pull({ now = false } = {}) {
|
|
553
|
+
return throwIfError(this.#pullConnectionLoop.send(now));
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Applies an update from the server to Replicache.
|
|
557
|
+
* Throws an error if cookie does not match. In that case the server thinks
|
|
558
|
+
* this client has a different cookie than it does; the caller should disconnect
|
|
559
|
+
* from the server and re-register, which transmits the cookie the client actually
|
|
560
|
+
* has.
|
|
561
|
+
*
|
|
562
|
+
* @experimental This method is under development and its semantics will change.
|
|
563
|
+
*/
|
|
564
|
+
async poke(poke) {
|
|
565
|
+
await this.#ready;
|
|
566
|
+
const { clientID } = this;
|
|
567
|
+
const requestID = newRequestID(clientID);
|
|
568
|
+
const lc = this.#lc.withContext("handlePullResponse").withContext("requestID", requestID);
|
|
569
|
+
const { pullResponse } = poke;
|
|
570
|
+
if (isVersionNotSupportedResponse(pullResponse)) {
|
|
571
|
+
this.#handleVersionNotSupportedResponse(pullResponse);
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
if (isClientStateNotFoundResponse(pullResponse)) {
|
|
575
|
+
await this.#clientStateNotFoundOnServer();
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
const result = await handlePullResponseV1(lc, this.memdag, deepFreeze(poke.baseCookie), pullResponse, clientID, 7);
|
|
579
|
+
switch (result.type) {
|
|
580
|
+
case 0:
|
|
581
|
+
await this.maybeEndPull(result.syncHead, requestID);
|
|
582
|
+
break;
|
|
583
|
+
case 2: throw new Error("unexpected base cookie for poke: " + JSON.stringify(poke));
|
|
584
|
+
case 1: break;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
async beginPull() {
|
|
588
|
+
await this.#ready;
|
|
589
|
+
const profileID = await this.profileID;
|
|
590
|
+
const { clientID } = this;
|
|
591
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
592
|
+
const { result: { beginPullResponse, requestID } } = await this.#wrapInReauthRetries(async (requestID, requestLc) => {
|
|
593
|
+
const beginPullResponse = await beginPullV1(profileID, clientID, clientGroupID, this.schemaVersion, this.puller, requestID, this.memdag, 7, requestLc);
|
|
594
|
+
return {
|
|
595
|
+
result: {
|
|
596
|
+
beginPullResponse,
|
|
597
|
+
requestID
|
|
598
|
+
},
|
|
599
|
+
httpRequestInfo: beginPullResponse.httpRequestInfo
|
|
600
|
+
};
|
|
601
|
+
}, "pull", this.#lc, () => this.#changeSyncCounters(0, -1), () => this.#changeSyncCounters(0, 1));
|
|
602
|
+
const { pullResponse } = beginPullResponse;
|
|
603
|
+
if (isVersionNotSupportedResponse(pullResponse)) this.#handleVersionNotSupportedResponse(pullResponse);
|
|
604
|
+
else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) await this.#clientStateNotFoundOnServer();
|
|
605
|
+
const { syncHead, httpRequestInfo } = beginPullResponse;
|
|
606
|
+
return {
|
|
607
|
+
requestID,
|
|
608
|
+
syncHead,
|
|
609
|
+
ok: httpRequestInfo.httpStatusCode === 200
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
persist() {
|
|
613
|
+
return this.#persistLock.withLock(async () => {
|
|
614
|
+
const { clientID } = this;
|
|
615
|
+
await this.#ready;
|
|
616
|
+
if (this.#closed) return;
|
|
617
|
+
try {
|
|
618
|
+
await persistDD31(this.#lc, clientID, this.memdag, this.perdag, this.#mutatorRegistry, () => this.#closed, 7, this.#zero?.getTxData);
|
|
619
|
+
} catch (e) {
|
|
620
|
+
if (e instanceof ClientStateNotFoundError) this.#clientStateNotFoundOnClient(clientID);
|
|
621
|
+
else if (this.#closed) this.#lc.debug?.("Exception persisting during close", e);
|
|
622
|
+
else throw e;
|
|
623
|
+
}
|
|
624
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
625
|
+
assert(clientGroupID, "Expected clientGroupID to be defined");
|
|
626
|
+
this.#onPersist({
|
|
627
|
+
clientID,
|
|
628
|
+
clientGroupID
|
|
629
|
+
});
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
async refresh() {
|
|
633
|
+
await this.#ready;
|
|
634
|
+
const { clientID } = this;
|
|
635
|
+
if (this.#closed || !this.#enableRefresh()) return;
|
|
636
|
+
let refreshResult;
|
|
637
|
+
try {
|
|
638
|
+
refreshResult = await refresh(this.#lc, this.memdag, this.perdag, clientID, this.#mutatorRegistry, this.#subscriptions, () => this.closed, 7, this.#zero);
|
|
639
|
+
} catch (e) {
|
|
640
|
+
if (e instanceof ClientStateNotFoundError) this.#clientStateNotFoundOnClient(clientID);
|
|
641
|
+
else if (this.#closed) this.#lc.debug?.("Exception refreshing during close", e);
|
|
642
|
+
else throw e;
|
|
643
|
+
}
|
|
644
|
+
if (refreshResult !== void 0) await this.#subscriptions.fire(refreshResult.diffs);
|
|
645
|
+
}
|
|
646
|
+
#fireOnClientStateNotFound() {
|
|
647
|
+
this.onClientStateNotFound?.();
|
|
648
|
+
}
|
|
649
|
+
#clientStateNotFoundOnClient(clientID) {
|
|
650
|
+
this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);
|
|
651
|
+
this.#fireOnClientStateNotFound();
|
|
652
|
+
}
|
|
653
|
+
async #clientStateNotFoundOnServer() {
|
|
654
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
655
|
+
this.#lc.error?.(`Client state not found on server, clientGroupID: ${clientGroupID}`);
|
|
656
|
+
await this.disableClientGroup();
|
|
657
|
+
this.#fireOnClientStateNotFound();
|
|
658
|
+
}
|
|
659
|
+
async disableClientGroup() {
|
|
660
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
661
|
+
assert(clientGroupID, "Expected clientGroupID to be defined");
|
|
662
|
+
this.isClientGroupDisabled = true;
|
|
663
|
+
await withWrite(this.perdag, (dagWrite) => disableClientGroup(clientGroupID, dagWrite));
|
|
664
|
+
}
|
|
665
|
+
#fireOnUpdateNeeded(reason) {
|
|
666
|
+
this.#lc.debug?.(`Update needed, reason: ${reason}`);
|
|
667
|
+
this.onUpdateNeeded?.(reason);
|
|
668
|
+
}
|
|
669
|
+
async #schedulePersist() {
|
|
670
|
+
if (!this.#enableScheduledPersist) return;
|
|
671
|
+
await this.#schedule("persist", this.#persistScheduler);
|
|
672
|
+
}
|
|
673
|
+
async #handlePersist(persistInfo) {
|
|
674
|
+
this.#lc.debug?.("Handling persist", persistInfo);
|
|
675
|
+
const clientGroupID = await this.#clientGroupIDPromise;
|
|
676
|
+
if (persistInfo.clientGroupID === clientGroupID) this.#scheduleRefresh();
|
|
677
|
+
}
|
|
678
|
+
async #scheduleRefresh() {
|
|
679
|
+
if (!this.#enableScheduledRefresh) return;
|
|
680
|
+
await this.#schedule("refresh from storage", this.#refreshScheduler);
|
|
681
|
+
}
|
|
682
|
+
async #schedule(name, scheduler) {
|
|
683
|
+
try {
|
|
684
|
+
await scheduler.schedule();
|
|
685
|
+
} catch (e) {
|
|
686
|
+
if (e instanceof AbortError) this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);
|
|
687
|
+
else this.#lc.error?.(`Error during ${name}`, e);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Runs a refresh as soon as possible through the refresh scheduler.
|
|
692
|
+
*/
|
|
693
|
+
runRefresh() {
|
|
694
|
+
return this.#refreshScheduler.run();
|
|
695
|
+
}
|
|
696
|
+
#changeSyncCounters(pushDelta, pullDelta) {
|
|
697
|
+
this.#pushCounter += pushDelta;
|
|
698
|
+
this.#pullCounter += pullDelta;
|
|
699
|
+
const delta = pushDelta + pullDelta;
|
|
700
|
+
const counter = this.#pushCounter + this.#pullCounter;
|
|
701
|
+
if (delta === 1 && counter === 1 || counter === 0) {
|
|
702
|
+
const syncing = counter > 0;
|
|
703
|
+
Promise.resolve().then(() => this.onSync?.(syncing));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
/**
|
|
707
|
+
* Subscribe to the result of a {@link query}. The `body` function is
|
|
708
|
+
* evaluated once and its results are returned via `onData`.
|
|
709
|
+
*
|
|
710
|
+
* Thereafter, each time the the result of `body` changes, `onData` is fired
|
|
711
|
+
* again with the new result.
|
|
712
|
+
*
|
|
713
|
+
* `subscribe()` goes to significant effort to avoid extraneous work
|
|
714
|
+
* re-evaluating subscriptions:
|
|
715
|
+
*
|
|
716
|
+
* 1. subscribe tracks the keys that `body` accesses each time it runs. `body`
|
|
717
|
+
* is only re-evaluated when those keys change.
|
|
718
|
+
* 2. subscribe only re-fires `onData` in the case that a result changes by
|
|
719
|
+
* way of the `isEqual` option which defaults to doing a deep JSON value
|
|
720
|
+
* equality check.
|
|
721
|
+
*
|
|
722
|
+
* Because of (1), `body` must be a pure function of the data in Replicache.
|
|
723
|
+
* `body` must not access anything other than the `tx` parameter passed to it.
|
|
724
|
+
*
|
|
725
|
+
* Although subscribe is as efficient as it can be, it is somewhat constrained
|
|
726
|
+
* by the goal of returning an arbitrary computation of the cache. For even
|
|
727
|
+
* better performance (but worse dx), see {@link experimentalWatch}.
|
|
728
|
+
*
|
|
729
|
+
* If an error occurs in the `body` the `onError` function is called if
|
|
730
|
+
* present. Otherwise, the error is logged at log level 'error'.
|
|
731
|
+
*
|
|
732
|
+
* To cancel the subscription, call the returned function.
|
|
733
|
+
*
|
|
734
|
+
* @param body The function to evaluate to get the value to pass into
|
|
735
|
+
* `onData`.
|
|
736
|
+
* @param options Options is either a function or an object. If it is a
|
|
737
|
+
* function it is equivalent to passing it as the `onData` property of an
|
|
738
|
+
* object.
|
|
739
|
+
*/
|
|
740
|
+
subscribe(body, options) {
|
|
741
|
+
if (typeof options === "function") options = { onData: options };
|
|
742
|
+
const { onData, onError, onDone, isEqual } = options;
|
|
743
|
+
return this.#subscriptions.add(new SubscriptionImpl(body, onData, onError, onDone, isEqual));
|
|
744
|
+
}
|
|
745
|
+
experimentalWatch(callback, options) {
|
|
746
|
+
return this.#subscriptions.add(new WatchSubscription(callback, options));
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* Query is used for read transactions. It is recommended to use transactions
|
|
750
|
+
* to ensure you get a consistent view across multiple calls to `get`, `has`
|
|
751
|
+
* and `scan`.
|
|
752
|
+
*/
|
|
753
|
+
query(body) {
|
|
754
|
+
return this.#queryInternal(body);
|
|
755
|
+
}
|
|
756
|
+
get cookie() {
|
|
757
|
+
return this.#ready.then(() => withRead(this.memdag, async (dagRead) => {
|
|
758
|
+
const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);
|
|
759
|
+
if (!mainHeadHash) throw new Error("Internal no main head found");
|
|
760
|
+
const cookie = (await baseSnapshotFromHash(mainHeadHash, dagRead)).meta.cookieJSON;
|
|
761
|
+
assertCookie(cookie);
|
|
762
|
+
return cookie;
|
|
763
|
+
}));
|
|
764
|
+
}
|
|
765
|
+
#queryInternal = async (body) => {
|
|
766
|
+
await this.#ready;
|
|
767
|
+
const { clientID } = this;
|
|
768
|
+
return withRead(this.memdag, async (dagRead) => {
|
|
769
|
+
try {
|
|
770
|
+
return await body(new ReadTransactionImpl(clientID, await readFromDefaultHead(dagRead, 7), this.#lc));
|
|
771
|
+
} catch (ex) {
|
|
772
|
+
throw await this.#convertToClientStateNotFoundError(ex);
|
|
773
|
+
}
|
|
774
|
+
});
|
|
775
|
+
};
|
|
776
|
+
#register(name, mutatorImpl) {
|
|
777
|
+
this.#mutatorRegistry[name] = mutatorImpl;
|
|
778
|
+
return (args) => {
|
|
779
|
+
const trackingData = name === "_zero_crud" ? void 0 : this.#zero?.trackMutation();
|
|
780
|
+
const result = this.#mutate(trackingData, name, mutatorImpl, args, performance.now());
|
|
781
|
+
if (trackingData) return {
|
|
782
|
+
client: result,
|
|
783
|
+
server: trackingData.serverPromise
|
|
784
|
+
};
|
|
785
|
+
return result;
|
|
786
|
+
};
|
|
787
|
+
}
|
|
788
|
+
#registerMutators(regs) {
|
|
789
|
+
const rv = Object.create(null);
|
|
790
|
+
for (const k in regs) rv[k] = this.#register(k, regs[k]);
|
|
791
|
+
return rv;
|
|
792
|
+
}
|
|
793
|
+
async #mutate(trackingData, name, mutatorImpl, args, timestamp) {
|
|
794
|
+
const frozenArgs = deepFreeze(args ?? null);
|
|
795
|
+
if (this.#subscriptions.hasPendingSubscriptionRuns) await Promise.resolve();
|
|
796
|
+
await this.#ready;
|
|
797
|
+
const { clientID } = this;
|
|
798
|
+
return withWriteNoImplicitCommit(this.memdag, async (dagWrite) => {
|
|
799
|
+
try {
|
|
800
|
+
let result;
|
|
801
|
+
let newHead;
|
|
802
|
+
let diffs;
|
|
803
|
+
let headHash;
|
|
804
|
+
try {
|
|
805
|
+
headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);
|
|
806
|
+
const dbWrite = await newWriteLocal(headHash, name, frozenArgs, null, dagWrite, timestamp, clientID, 7);
|
|
807
|
+
const mutationID = await dbWrite.getMutationID();
|
|
808
|
+
const tx = new WriteTransactionImpl(clientID, mutationID, "initial", await this.#zero?.getTxData(headHash, { openLazyRead: dagWrite }), dbWrite, this.#lc);
|
|
809
|
+
if (trackingData) this.#zero?.mutationIDAssigned(trackingData.ephemeralID, mutationID);
|
|
810
|
+
result = await mutatorImpl(tx, args);
|
|
811
|
+
throwIfClosed(dbWrite);
|
|
812
|
+
const lastMutationID = await dbWrite.getMutationID();
|
|
813
|
+
[newHead, diffs] = await dbWrite.commitWithDiffs(DEFAULT_HEAD_NAME, this.#subscriptions);
|
|
814
|
+
this.lastMutationID = lastMutationID;
|
|
815
|
+
} catch (e) {
|
|
816
|
+
if (trackingData) this.#zero?.rejectMutation(trackingData.ephemeralID, e);
|
|
817
|
+
throw e;
|
|
818
|
+
}
|
|
819
|
+
this.#zero?.advance(headHash, newHead, diffs.get("") ?? []);
|
|
820
|
+
this.#pushConnectionLoop.send(false).catch(() => void 0);
|
|
821
|
+
await this.#subscriptions.fire(diffs);
|
|
822
|
+
this.#schedulePersist();
|
|
823
|
+
return result;
|
|
824
|
+
} catch (ex) {
|
|
825
|
+
throw await this.#convertToClientStateNotFoundError(ex);
|
|
826
|
+
}
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
/**
|
|
830
|
+
* In the case we get a ChunkNotFoundError we check if the client got garbage
|
|
831
|
+
* collected and if so change the error to a ClientStateNotFoundError instead
|
|
832
|
+
*/
|
|
833
|
+
async #convertToClientStateNotFoundError(ex) {
|
|
834
|
+
if (ex instanceof ChunkNotFoundError && await this.#checkForClientStateNotFoundAndCallHandler()) return new ClientStateNotFoundError(this.clientID);
|
|
835
|
+
return ex;
|
|
836
|
+
}
|
|
837
|
+
recoverMutations() {}
|
|
838
|
+
/**
|
|
839
|
+
* List of pending mutations. The order of this is from oldest to newest.
|
|
840
|
+
*
|
|
841
|
+
* Gives a list of local mutations that have `mutationID` >
|
|
842
|
+
* `syncHead.mutationID` that exists on the main client group.
|
|
843
|
+
*
|
|
844
|
+
* @experimental This method is experimental and may change in the future.
|
|
845
|
+
*/
|
|
846
|
+
experimentalPendingMutations() {
|
|
847
|
+
return withRead(this.memdag, pendingMutationsForAPI);
|
|
848
|
+
}
|
|
68
849
|
};
|
|
69
|
-
|
|
70
|
-
/** The URL to use when doing a pull request. */
|
|
71
|
-
pullURL;
|
|
72
|
-
/** The URL to use when doing a push request. */
|
|
73
|
-
pushURL;
|
|
74
|
-
/** The authorization token used when doing a push request. */
|
|
75
|
-
#auth;
|
|
76
|
-
/** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */
|
|
77
|
-
name;
|
|
78
|
-
#subscriptions;
|
|
79
|
-
#mutationRecovery;
|
|
80
|
-
/**
|
|
81
|
-
* Client groups gets disabled when the server does not know about it.
|
|
82
|
-
* A disabled client group prevents the client from pushing and pulling.
|
|
83
|
-
*/
|
|
84
|
-
isClientGroupDisabled = false;
|
|
85
|
-
#kvStoreProvider;
|
|
86
|
-
lastMutationID = 0;
|
|
87
|
-
/**
|
|
88
|
-
* This is the name Replicache uses for the IndexedDB database where data is
|
|
89
|
-
* stored.
|
|
90
|
-
*/
|
|
91
|
-
get idbName() {
|
|
92
|
-
return makeIDBName(this.name, this.schemaVersion);
|
|
93
|
-
}
|
|
94
|
-
set auth(auth) {
|
|
95
|
-
if (this.#zero) {
|
|
96
|
-
this.#zero.auth = auth;
|
|
97
|
-
}
|
|
98
|
-
this.#auth = auth;
|
|
99
|
-
}
|
|
100
|
-
get auth() {
|
|
101
|
-
return this.#auth;
|
|
102
|
-
}
|
|
103
|
-
/** The schema version of the data understood by this application. */
|
|
104
|
-
schemaVersion;
|
|
105
|
-
get #idbDatabase() {
|
|
106
|
-
return {
|
|
107
|
-
name: this.idbName,
|
|
108
|
-
replicacheName: this.name,
|
|
109
|
-
replicacheFormatVersion: Latest,
|
|
110
|
-
schemaVersion: this.schemaVersion
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
#closed = false;
|
|
114
|
-
#online = true;
|
|
115
|
-
#clientID = makeClientID();
|
|
116
|
-
#ready;
|
|
117
|
-
#profileIDPromise;
|
|
118
|
-
#clientGroupIDPromise;
|
|
119
|
-
#mutatorRegistry = {};
|
|
120
|
-
/**
|
|
121
|
-
* The mutators that was registered in the constructor.
|
|
122
|
-
*/
|
|
123
|
-
mutate;
|
|
124
|
-
// Number of pushes/pulls at the moment.
|
|
125
|
-
#pushCounter = 0;
|
|
126
|
-
#pullCounter = 0;
|
|
127
|
-
#pullConnectionLoop;
|
|
128
|
-
#pushConnectionLoop;
|
|
129
|
-
/**
|
|
130
|
-
* The duration between each periodic {@link pull}. Setting this to `null`
|
|
131
|
-
* disables periodic pull completely. Pull will still happen if you call
|
|
132
|
-
* {@link pull} manually.
|
|
133
|
-
*/
|
|
134
|
-
pullInterval;
|
|
135
|
-
/**
|
|
136
|
-
* The delay between when a change is made to Replicache and when Replicache
|
|
137
|
-
* attempts to push that change.
|
|
138
|
-
*/
|
|
139
|
-
pushDelay;
|
|
140
|
-
#requestOptions;
|
|
141
|
-
/**
|
|
142
|
-
* The function to use to pull data from the server.
|
|
143
|
-
*/
|
|
144
|
-
puller;
|
|
145
|
-
/**
|
|
146
|
-
* The function to use to push data to the server.
|
|
147
|
-
*/
|
|
148
|
-
pusher;
|
|
149
|
-
memdag;
|
|
150
|
-
perdag;
|
|
151
|
-
#idbDatabases;
|
|
152
|
-
#lc;
|
|
153
|
-
#zero;
|
|
154
|
-
#closeAbortController = new AbortController();
|
|
155
|
-
#persistLock = new Lock();
|
|
156
|
-
#enableScheduledPersist;
|
|
157
|
-
#enableScheduledRefresh;
|
|
158
|
-
#enableRefresh;
|
|
159
|
-
#enablePullAndPushInOpen;
|
|
160
|
-
#persistScheduler = new ProcessScheduler(
|
|
161
|
-
() => this.persist(),
|
|
162
|
-
PERSIST_IDLE_TIMEOUT_MS,
|
|
163
|
-
PERSIST_THROTTLE_MS,
|
|
164
|
-
this.#closeAbortController.signal
|
|
165
|
-
);
|
|
166
|
-
#onPersist;
|
|
167
|
-
#refreshScheduler = new ProcessScheduler(
|
|
168
|
-
() => this.refresh(),
|
|
169
|
-
REFRESH_IDLE_TIMEOUT_MS,
|
|
170
|
-
REFRESH_THROTTLE_MS,
|
|
171
|
-
this.#closeAbortController.signal
|
|
172
|
-
);
|
|
173
|
-
/**
|
|
174
|
-
* The options used to control the {@link pull} and push request behavior. This
|
|
175
|
-
* object is live so changes to it will affect the next pull or push call.
|
|
176
|
-
*/
|
|
177
|
-
get requestOptions() {
|
|
178
|
-
return this.#requestOptions;
|
|
179
|
-
}
|
|
180
|
-
/**
|
|
181
|
-
* `onSync(true)` is called when Replicache transitions from no push or pull
|
|
182
|
-
* happening to at least one happening. `onSync(false)` is called in the
|
|
183
|
-
* opposite case: when Replicache transitions from at least one push or pull
|
|
184
|
-
* happening to none happening.
|
|
185
|
-
*
|
|
186
|
-
* This can be used in a React like app by doing something like the following:
|
|
187
|
-
*
|
|
188
|
-
* ```js
|
|
189
|
-
* const [syncing, setSyncing] = useState(false);
|
|
190
|
-
* useEffect(() => {
|
|
191
|
-
* rep.onSync = setSyncing;
|
|
192
|
-
* }, [rep]);
|
|
193
|
-
* ```
|
|
194
|
-
*/
|
|
195
|
-
onSync = null;
|
|
196
|
-
/**
|
|
197
|
-
* `onClientStateNotFound` is called when the persistent client has been
|
|
198
|
-
* garbage collected. This can happen if the client has no pending mutations
|
|
199
|
-
* and has not been used for a while.
|
|
200
|
-
*
|
|
201
|
-
* The default behavior is to reload the page (using `location.reload()`). Set
|
|
202
|
-
* this to `null` or provide your own function to prevent the page from
|
|
203
|
-
* reloading automatically.
|
|
204
|
-
*/
|
|
205
|
-
onClientStateNotFound = reload;
|
|
206
|
-
/**
|
|
207
|
-
* `onUpdateNeeded` is called when a code update is needed.
|
|
208
|
-
*
|
|
209
|
-
* A code update can be needed because:
|
|
210
|
-
* - the server no longer supports the {@link pushVersion},
|
|
211
|
-
* {@link pullVersion} or {@link schemaVersion} of the current code.
|
|
212
|
-
* - a new Replicache client has created a new client group, because its code
|
|
213
|
-
* has different mutators, indexes, schema version and/or format version
|
|
214
|
-
* from this Replicache client. This is likely due to the new client having
|
|
215
|
-
* newer code. A code update is needed to be able to locally sync with this
|
|
216
|
-
* new Replicache client (i.e. to sync while offline, the clients can still
|
|
217
|
-
* sync with each other via the server).
|
|
218
|
-
*
|
|
219
|
-
* The default behavior is to reload the page (using `location.reload()`). Set
|
|
220
|
-
* this to `null` or provide your own function to prevent the page from
|
|
221
|
-
* reloading automatically. You may want to provide your own function to
|
|
222
|
-
* display a toast to inform the end user there is a new version of your app
|
|
223
|
-
* available and prompting them to refresh.
|
|
224
|
-
*/
|
|
225
|
-
onUpdateNeeded = reload;
|
|
226
|
-
/**
|
|
227
|
-
* This gets called when we get an HTTP unauthorized (401) response from the
|
|
228
|
-
* push or pull endpoint. Set this to a function that will ask your user to
|
|
229
|
-
* reauthenticate.
|
|
230
|
-
*/
|
|
231
|
-
getAuth = null;
|
|
232
|
-
// These three are used for testing
|
|
233
|
-
onPushInvoked = () => void 0;
|
|
234
|
-
onBeginPull = () => void 0;
|
|
235
|
-
onRecoverMutations = (r) => r;
|
|
236
|
-
constructor(options, implOptions = {}) {
|
|
237
|
-
validateOptions(options);
|
|
238
|
-
const {
|
|
239
|
-
name,
|
|
240
|
-
logLevel = "info",
|
|
241
|
-
logSinks = [consoleLogSink],
|
|
242
|
-
pullURL = "",
|
|
243
|
-
auth,
|
|
244
|
-
pushDelay = 10,
|
|
245
|
-
pushURL = "",
|
|
246
|
-
schemaVersion = "",
|
|
247
|
-
pullInterval = 6e4,
|
|
248
|
-
mutators = {},
|
|
249
|
-
requestOptions = {},
|
|
250
|
-
puller,
|
|
251
|
-
pusher,
|
|
252
|
-
indexes = {},
|
|
253
|
-
clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME
|
|
254
|
-
} = options;
|
|
255
|
-
const {
|
|
256
|
-
enableMutationRecovery = true,
|
|
257
|
-
enableScheduledPersist = true,
|
|
258
|
-
enableScheduledRefresh = true,
|
|
259
|
-
enableRefresh = () => true,
|
|
260
|
-
enablePullAndPushInOpen = true,
|
|
261
|
-
enableClientGroupForking = true,
|
|
262
|
-
onClientsDeleted = () => promiseVoid
|
|
263
|
-
} = implOptions;
|
|
264
|
-
this.#zero = implOptions.zero;
|
|
265
|
-
this.#auth = auth ?? "";
|
|
266
|
-
this.pullURL = pullURL;
|
|
267
|
-
this.pushURL = pushURL;
|
|
268
|
-
this.name = name;
|
|
269
|
-
this.schemaVersion = schemaVersion;
|
|
270
|
-
this.pullInterval = pullInterval;
|
|
271
|
-
this.pushDelay = pushDelay;
|
|
272
|
-
this.puller = puller ?? getDefaultPuller(this);
|
|
273
|
-
this.pusher = pusher ?? getDefaultPusher(this);
|
|
274
|
-
this.#enableScheduledPersist = enableScheduledPersist;
|
|
275
|
-
this.#enableScheduledRefresh = enableScheduledRefresh;
|
|
276
|
-
this.#enableRefresh = enableRefresh;
|
|
277
|
-
this.#enablePullAndPushInOpen = enablePullAndPushInOpen;
|
|
278
|
-
this.#lc = createLogContext(logLevel, logSinks, { name });
|
|
279
|
-
this.#lc.debug?.("Constructing Replicache", {
|
|
280
|
-
name,
|
|
281
|
-
"replicache version": version
|
|
282
|
-
});
|
|
283
|
-
this.#subscriptions = new SubscriptionsManagerImpl(
|
|
284
|
-
this.#queryInternal,
|
|
285
|
-
this.#lc,
|
|
286
|
-
this.#closeAbortController.signal
|
|
287
|
-
);
|
|
288
|
-
const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);
|
|
289
|
-
this.#kvStoreProvider = kvStoreProvider;
|
|
290
|
-
const perKVStore = kvStoreProvider.create(this.idbName);
|
|
291
|
-
this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);
|
|
292
|
-
this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);
|
|
293
|
-
this.memdag = new LazyStore(
|
|
294
|
-
this.perdag,
|
|
295
|
-
LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,
|
|
296
|
-
newRandomHash,
|
|
297
|
-
assertHash
|
|
298
|
-
);
|
|
299
|
-
const readyResolver = resolver();
|
|
300
|
-
this.#ready = readyResolver.promise;
|
|
301
|
-
const { minDelayMs = MIN_DELAY_MS, maxDelayMs = MAX_DELAY_MS } = requestOptions;
|
|
302
|
-
this.#requestOptions = { maxDelayMs, minDelayMs };
|
|
303
|
-
const visibilityWatcher = getDocumentVisibilityWatcher(
|
|
304
|
-
getBrowserGlobal("document"),
|
|
305
|
-
0,
|
|
306
|
-
this.#closeAbortController.signal
|
|
307
|
-
);
|
|
308
|
-
this.#pullConnectionLoop = new ConnectionLoop(
|
|
309
|
-
this.#lc.withContext("PULL"),
|
|
310
|
-
new PullDelegate(this, () => this.#invokePull()),
|
|
311
|
-
visibilityWatcher
|
|
312
|
-
);
|
|
313
|
-
this.#pushConnectionLoop = new ConnectionLoop(
|
|
314
|
-
this.#lc.withContext("PUSH"),
|
|
315
|
-
new PushDelegate(this, () => this.#invokePush())
|
|
316
|
-
);
|
|
317
|
-
this.mutate = this.#registerMutators(mutators);
|
|
318
|
-
const profileIDResolver = resolver();
|
|
319
|
-
this.#profileIDPromise = profileIDResolver.promise;
|
|
320
|
-
const clientGroupIDResolver = resolver();
|
|
321
|
-
this.#clientGroupIDPromise = clientGroupIDResolver.promise;
|
|
322
|
-
this.#onPersist = initOnPersistChannel(
|
|
323
|
-
this.name,
|
|
324
|
-
this.#closeAbortController.signal,
|
|
325
|
-
(persistInfo) => {
|
|
326
|
-
void this.#handlePersist(persistInfo);
|
|
327
|
-
}
|
|
328
|
-
);
|
|
329
|
-
void this.#open(
|
|
330
|
-
indexes,
|
|
331
|
-
enableClientGroupForking,
|
|
332
|
-
enableMutationRecovery,
|
|
333
|
-
clientMaxAgeMs,
|
|
334
|
-
profileIDResolver.resolve,
|
|
335
|
-
clientGroupIDResolver.resolve,
|
|
336
|
-
readyResolver.resolve,
|
|
337
|
-
onClientsDeleted
|
|
338
|
-
);
|
|
339
|
-
}
|
|
340
|
-
async #open(indexes, enableClientGroupForking, enableMutationRecovery, clientMaxAgeMs, profileIDResolver, resolveClientGroupID, resolveReady, onClientsDeleted) {
|
|
341
|
-
const { clientID } = this;
|
|
342
|
-
await closingInstances.get(this.name);
|
|
343
|
-
await this.#idbDatabases.getProfileID().then(profileIDResolver);
|
|
344
|
-
await this.#idbDatabases.putDatabase(this.#idbDatabase);
|
|
345
|
-
const [client, headHash, , isNewClientGroup] = await initClientV6(
|
|
346
|
-
clientID,
|
|
347
|
-
this.#lc,
|
|
348
|
-
this.perdag,
|
|
349
|
-
Object.keys(this.#mutatorRegistry),
|
|
350
|
-
indexes,
|
|
351
|
-
Latest,
|
|
352
|
-
enableClientGroupForking
|
|
353
|
-
);
|
|
354
|
-
resolveClientGroupID(client.clientGroupID);
|
|
355
|
-
await withWrite(
|
|
356
|
-
this.memdag,
|
|
357
|
-
(write) => write.setHead(DEFAULT_HEAD_NAME, headHash)
|
|
358
|
-
);
|
|
359
|
-
await this.#zero?.init(headHash, this.memdag);
|
|
360
|
-
resolveReady();
|
|
361
|
-
if (this.#enablePullAndPushInOpen) {
|
|
362
|
-
this.pull().catch(noop);
|
|
363
|
-
this.push().catch(noop);
|
|
364
|
-
}
|
|
365
|
-
const { signal } = this.#closeAbortController;
|
|
366
|
-
startHeartbeats(
|
|
367
|
-
clientID,
|
|
368
|
-
this.perdag,
|
|
369
|
-
() => {
|
|
370
|
-
this.#clientStateNotFoundOnClient(clientID);
|
|
371
|
-
},
|
|
372
|
-
HEARTBEAT_INTERVAL,
|
|
373
|
-
this.#lc,
|
|
374
|
-
signal
|
|
375
|
-
);
|
|
376
|
-
initClientGC(
|
|
377
|
-
clientID,
|
|
378
|
-
this.perdag,
|
|
379
|
-
clientMaxAgeMs,
|
|
380
|
-
GC_INTERVAL,
|
|
381
|
-
onClientsDeleted,
|
|
382
|
-
this.#lc,
|
|
383
|
-
signal
|
|
384
|
-
);
|
|
385
|
-
initCollectIDBDatabases(
|
|
386
|
-
this.#idbDatabases,
|
|
387
|
-
this.#kvStoreProvider,
|
|
388
|
-
COLLECT_IDB_INTERVAL,
|
|
389
|
-
INITIAL_COLLECT_IDB_DELAY,
|
|
390
|
-
2 * clientMaxAgeMs,
|
|
391
|
-
enableMutationRecovery,
|
|
392
|
-
onClientsDeleted,
|
|
393
|
-
this.#lc,
|
|
394
|
-
signal
|
|
395
|
-
);
|
|
396
|
-
initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);
|
|
397
|
-
initNewClientChannel(
|
|
398
|
-
this.name,
|
|
399
|
-
this.idbName,
|
|
400
|
-
signal,
|
|
401
|
-
client.clientGroupID,
|
|
402
|
-
isNewClientGroup,
|
|
403
|
-
() => {
|
|
404
|
-
this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);
|
|
405
|
-
},
|
|
406
|
-
this.perdag
|
|
407
|
-
);
|
|
408
|
-
setIntervalWithSignal(
|
|
409
|
-
() => this.recoverMutations(),
|
|
410
|
-
RECOVER_MUTATIONS_INTERVAL_MS,
|
|
411
|
-
signal
|
|
412
|
-
);
|
|
413
|
-
void this.recoverMutations();
|
|
414
|
-
getBrowserGlobal("document")?.addEventListener(
|
|
415
|
-
"visibilitychange",
|
|
416
|
-
this.#onVisibilityChange
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
#onVisibilityChange = async () => {
|
|
420
|
-
if (this.#closed) {
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
if (getBrowserGlobal("document")?.visibilityState !== "visible") {
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
await this.#checkForClientStateNotFoundAndCallHandler();
|
|
427
|
-
};
|
|
428
|
-
async #checkForClientStateNotFoundAndCallHandler() {
|
|
429
|
-
const { clientID } = this;
|
|
430
|
-
const hasClientState$1 = await withRead(
|
|
431
|
-
this.perdag,
|
|
432
|
-
(read) => hasClientState(clientID, read)
|
|
433
|
-
);
|
|
434
|
-
if (!hasClientState$1) {
|
|
435
|
-
this.#clientStateNotFoundOnClient(clientID);
|
|
436
|
-
}
|
|
437
|
-
return !hasClientState$1;
|
|
438
|
-
}
|
|
439
|
-
/**
|
|
440
|
-
* The browser profile ID for this browser profile. Every instance of Replicache
|
|
441
|
-
* browser-profile-wide shares the same profile ID.
|
|
442
|
-
*/
|
|
443
|
-
get profileID() {
|
|
444
|
-
return this.#profileIDPromise;
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* The client ID for this instance of Replicache. Each instance of Replicache
|
|
448
|
-
* gets a unique client ID.
|
|
449
|
-
*/
|
|
450
|
-
get clientID() {
|
|
451
|
-
return this.#clientID;
|
|
452
|
-
}
|
|
453
|
-
/**
|
|
454
|
-
* The client group ID for this instance of Replicache. Instances of
|
|
455
|
-
* Replicache will have the same client group ID if and only if they have
|
|
456
|
-
* the same name, mutators, indexes, schema version, format version, and
|
|
457
|
-
* browser profile.
|
|
458
|
-
*/
|
|
459
|
-
get clientGroupID() {
|
|
460
|
-
return this.#clientGroupIDPromise;
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* `onOnlineChange` is called when the {@link online} property changes. See
|
|
464
|
-
* {@link online} for more details.
|
|
465
|
-
*/
|
|
466
|
-
onOnlineChange = null;
|
|
467
|
-
/**
|
|
468
|
-
* A rough heuristic for whether the client is currently online. Note that
|
|
469
|
-
* there is no way to know for certain whether a client is online - the next
|
|
470
|
-
* request can always fail. This property returns true if the last sync attempt succeeded,
|
|
471
|
-
* and false otherwise.
|
|
472
|
-
*/
|
|
473
|
-
get online() {
|
|
474
|
-
return this.#online;
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Whether the Replicache database has been closed. Once Replicache has been
|
|
478
|
-
* closed it no longer syncs and you can no longer read or write data out of
|
|
479
|
-
* it. After it has been closed it is pretty much useless and should not be
|
|
480
|
-
* used any more.
|
|
481
|
-
*/
|
|
482
|
-
get closed() {
|
|
483
|
-
return this.#closed;
|
|
484
|
-
}
|
|
485
|
-
/**
|
|
486
|
-
* Closes this Replicache instance.
|
|
487
|
-
*
|
|
488
|
-
* When closed all subscriptions end and no more read or writes are allowed.
|
|
489
|
-
*/
|
|
490
|
-
async close() {
|
|
491
|
-
this.#closed = true;
|
|
492
|
-
const { promise, resolve } = resolver();
|
|
493
|
-
closingInstances.set(this.name, promise);
|
|
494
|
-
this.#closeAbortController.abort();
|
|
495
|
-
getBrowserGlobal("document")?.removeEventListener(
|
|
496
|
-
"visibilitychange",
|
|
497
|
-
this.#onVisibilityChange
|
|
498
|
-
);
|
|
499
|
-
await this.#ready;
|
|
500
|
-
const closingPromises = [
|
|
501
|
-
this.memdag.close(),
|
|
502
|
-
this.perdag.close(),
|
|
503
|
-
this.#idbDatabases.close()
|
|
504
|
-
];
|
|
505
|
-
this.#pullConnectionLoop.close();
|
|
506
|
-
this.#pushConnectionLoop.close();
|
|
507
|
-
this.#subscriptions.clear();
|
|
508
|
-
await Promise.all(closingPromises);
|
|
509
|
-
closingInstances.delete(this.name);
|
|
510
|
-
resolve();
|
|
511
|
-
}
|
|
512
|
-
async maybeEndPull(syncHead, requestID) {
|
|
513
|
-
for (; ; ) {
|
|
514
|
-
if (this.#closed) {
|
|
515
|
-
return;
|
|
516
|
-
}
|
|
517
|
-
await this.#ready;
|
|
518
|
-
const { clientID } = this;
|
|
519
|
-
const lc = this.#lc.withContext("maybeEndPull").withContext("requestID", requestID);
|
|
520
|
-
const { replayMutations, diffs, oldMainHead, mainHead } = await maybeEndPull(
|
|
521
|
-
this.memdag,
|
|
522
|
-
lc,
|
|
523
|
-
syncHead,
|
|
524
|
-
clientID,
|
|
525
|
-
this.#subscriptions,
|
|
526
|
-
Latest
|
|
527
|
-
);
|
|
528
|
-
if (!replayMutations || replayMutations.length === 0) {
|
|
529
|
-
this.#zero?.advance(oldMainHead, mainHead, diffs.get("") ?? []);
|
|
530
|
-
await this.#subscriptions.fire(diffs);
|
|
531
|
-
void this.#schedulePersist();
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
const zeroData = await this.#zero?.getTxData?.(syncHead);
|
|
535
|
-
for (const mutation of replayMutations) {
|
|
536
|
-
if (this.#subscriptions.hasPendingSubscriptionRuns) {
|
|
537
|
-
await Promise.resolve();
|
|
538
|
-
}
|
|
539
|
-
const { meta } = mutation;
|
|
540
|
-
syncHead = await withWriteNoImplicitCommit(
|
|
541
|
-
this.memdag,
|
|
542
|
-
(dagWrite) => rebaseMutationAndCommit(
|
|
543
|
-
mutation,
|
|
544
|
-
dagWrite,
|
|
545
|
-
syncHead,
|
|
546
|
-
SYNC_HEAD_NAME,
|
|
547
|
-
this.#mutatorRegistry,
|
|
548
|
-
lc,
|
|
549
|
-
isLocalMetaDD31(meta) ? meta.clientID : clientID,
|
|
550
|
-
Latest,
|
|
551
|
-
zeroData
|
|
552
|
-
)
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
#invokePull() {
|
|
558
|
-
if (this.#isPullDisabled()) {
|
|
559
|
-
return Promise.resolve(true);
|
|
560
|
-
}
|
|
561
|
-
return this.#wrapInOnlineCheck(async () => {
|
|
562
|
-
try {
|
|
563
|
-
this.#changeSyncCounters(0, 1);
|
|
564
|
-
const { syncHead, requestID, ok } = await this.beginPull();
|
|
565
|
-
if (!ok) {
|
|
566
|
-
return false;
|
|
567
|
-
}
|
|
568
|
-
if (syncHead !== emptyHash) {
|
|
569
|
-
await this.maybeEndPull(syncHead, requestID);
|
|
570
|
-
}
|
|
571
|
-
} catch (e) {
|
|
572
|
-
throw await this.#convertToClientStateNotFoundError(e);
|
|
573
|
-
} finally {
|
|
574
|
-
this.#changeSyncCounters(0, -1);
|
|
575
|
-
}
|
|
576
|
-
return true;
|
|
577
|
-
}, "Pull");
|
|
578
|
-
}
|
|
579
|
-
#isPullDisabled() {
|
|
580
|
-
return this.isClientGroupDisabled || this.pullURL === "" && isDefaultPuller(this.puller);
|
|
581
|
-
}
|
|
582
|
-
async #wrapInOnlineCheck(f, name) {
|
|
583
|
-
let online = true;
|
|
584
|
-
try {
|
|
585
|
-
return await f();
|
|
586
|
-
} catch (e) {
|
|
587
|
-
if (e instanceof PushError || e instanceof PullError) {
|
|
588
|
-
online = false;
|
|
589
|
-
this.#lc.debug?.(`${name} threw:
|
|
590
|
-
`, e, "\nwith cause:\n", e.causedBy);
|
|
591
|
-
} else if (e instanceof ReportError) {
|
|
592
|
-
this.#lc.error?.(e);
|
|
593
|
-
} else {
|
|
594
|
-
this.#lc.info?.(`${name} threw:
|
|
595
|
-
`, e);
|
|
596
|
-
}
|
|
597
|
-
return false;
|
|
598
|
-
} finally {
|
|
599
|
-
if (this.#online !== online) {
|
|
600
|
-
this.#online = online;
|
|
601
|
-
this.onOnlineChange?.(online);
|
|
602
|
-
if (online) {
|
|
603
|
-
void this.recoverMutations();
|
|
604
|
-
}
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
async #wrapInReauthRetries(f, verb, lc, preAuth = noop, postAuth = noop) {
|
|
609
|
-
const { clientID } = this;
|
|
610
|
-
let reauthAttempts = 0;
|
|
611
|
-
let lastResult;
|
|
612
|
-
lc = lc.withContext(verb);
|
|
613
|
-
do {
|
|
614
|
-
const requestID = newRequestID(clientID);
|
|
615
|
-
const requestLc = lc.withContext("requestID", requestID);
|
|
616
|
-
const { httpRequestInfo, result } = await f(requestID, requestLc);
|
|
617
|
-
lastResult = result;
|
|
618
|
-
if (!httpRequestInfo) {
|
|
619
|
-
return {
|
|
620
|
-
result,
|
|
621
|
-
authFailure: false
|
|
622
|
-
};
|
|
623
|
-
}
|
|
624
|
-
const { errorMessage, httpStatusCode } = httpRequestInfo;
|
|
625
|
-
if (errorMessage || httpStatusCode !== 200) {
|
|
626
|
-
requestLc.error?.(
|
|
627
|
-
`Got a non 200 response doing ${verb}: ${httpStatusCode}` + (errorMessage ? `: ${errorMessage}` : "")
|
|
628
|
-
);
|
|
629
|
-
}
|
|
630
|
-
if (httpStatusCode !== httpStatusUnauthorized) {
|
|
631
|
-
return {
|
|
632
|
-
result,
|
|
633
|
-
authFailure: false
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
if (!this.getAuth) {
|
|
637
|
-
return {
|
|
638
|
-
result,
|
|
639
|
-
authFailure: true
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
let auth;
|
|
643
|
-
try {
|
|
644
|
-
await preAuth();
|
|
645
|
-
auth = await this.getAuth();
|
|
646
|
-
} finally {
|
|
647
|
-
await postAuth();
|
|
648
|
-
}
|
|
649
|
-
if (auth === null || auth === void 0) {
|
|
650
|
-
return {
|
|
651
|
-
result,
|
|
652
|
-
authFailure: true
|
|
653
|
-
};
|
|
654
|
-
}
|
|
655
|
-
this.auth = auth;
|
|
656
|
-
reauthAttempts++;
|
|
657
|
-
} while (reauthAttempts < MAX_REAUTH_TRIES);
|
|
658
|
-
lc.info?.("Tried to reauthenticate too many times");
|
|
659
|
-
return {
|
|
660
|
-
result: lastResult,
|
|
661
|
-
authFailure: true
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
|
-
#isPushDisabled() {
|
|
665
|
-
return this.isClientGroupDisabled || this.pushURL === "" && isDefaultPusher(this.pusher);
|
|
666
|
-
}
|
|
667
|
-
async #invokePush() {
|
|
668
|
-
if (this.#isPushDisabled()) {
|
|
669
|
-
return true;
|
|
670
|
-
}
|
|
671
|
-
await this.#ready;
|
|
672
|
-
const profileID = await this.#profileIDPromise;
|
|
673
|
-
const { clientID } = this;
|
|
674
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
675
|
-
return this.#wrapInOnlineCheck(async () => {
|
|
676
|
-
const { result: pusherResult } = await this.#wrapInReauthRetries(
|
|
677
|
-
async (requestID, requestLc) => {
|
|
678
|
-
try {
|
|
679
|
-
this.#changeSyncCounters(1, 0);
|
|
680
|
-
const pusherResult2 = await push(
|
|
681
|
-
requestID,
|
|
682
|
-
this.memdag,
|
|
683
|
-
requestLc,
|
|
684
|
-
profileID,
|
|
685
|
-
clientGroupID,
|
|
686
|
-
clientID,
|
|
687
|
-
this.pusher,
|
|
688
|
-
this.schemaVersion,
|
|
689
|
-
PUSH_VERSION_DD31
|
|
690
|
-
);
|
|
691
|
-
return {
|
|
692
|
-
result: pusherResult2,
|
|
693
|
-
httpRequestInfo: pusherResult2?.httpRequestInfo
|
|
694
|
-
};
|
|
695
|
-
} finally {
|
|
696
|
-
this.#changeSyncCounters(-1, 0);
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
"push",
|
|
700
|
-
this.#lc
|
|
701
|
-
);
|
|
702
|
-
if (pusherResult === void 0) {
|
|
703
|
-
return true;
|
|
704
|
-
}
|
|
705
|
-
const { response, httpRequestInfo } = pusherResult;
|
|
706
|
-
if (isVersionNotSupportedResponse(response)) {
|
|
707
|
-
this.#handleVersionNotSupportedResponse(response);
|
|
708
|
-
} else if (isClientStateNotFoundResponse(response)) {
|
|
709
|
-
await this.#clientStateNotFoundOnServer();
|
|
710
|
-
}
|
|
711
|
-
return httpRequestInfo.httpStatusCode === 200;
|
|
712
|
-
}, "Push");
|
|
713
|
-
}
|
|
714
|
-
#handleVersionNotSupportedResponse(response) {
|
|
715
|
-
const reason = {
|
|
716
|
-
type: response.error
|
|
717
|
-
};
|
|
718
|
-
if (response.versionType) {
|
|
719
|
-
reason.versionType = response.versionType;
|
|
720
|
-
}
|
|
721
|
-
this.#fireOnUpdateNeeded(reason);
|
|
722
|
-
}
|
|
723
|
-
/**
|
|
724
|
-
* Push pushes pending changes to the {@link pushURL}.
|
|
725
|
-
*
|
|
726
|
-
* You do not usually need to manually call push. If {@link pushDelay} is
|
|
727
|
-
* non-zero (which it is by default) pushes happen automatically shortly after
|
|
728
|
-
* mutations.
|
|
729
|
-
*
|
|
730
|
-
* If the server endpoint fails push will be continuously retried with an
|
|
731
|
-
* exponential backoff.
|
|
732
|
-
*
|
|
733
|
-
* @param [now=false] If true, push will happen immediately and ignore
|
|
734
|
-
* {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the
|
|
735
|
-
* exponential backoff in case of errors.
|
|
736
|
-
* @returns A promise that resolves when the next push completes. In case of
|
|
737
|
-
* errors the first error will reject the returned promise. Subsequent errors
|
|
738
|
-
* will not be reflected in the promise.
|
|
739
|
-
*/
|
|
740
|
-
push({ now = false } = {}) {
|
|
741
|
-
return throwIfError(this.#pushConnectionLoop.send(now));
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* Pull pulls changes from the {@link pullURL}. If there are any changes local
|
|
745
|
-
* changes will get replayed on top of the new server state.
|
|
746
|
-
*
|
|
747
|
-
* If the server endpoint fails pull will be continuously retried with an
|
|
748
|
-
* exponential backoff.
|
|
749
|
-
*
|
|
750
|
-
* @param [now=false] If true, pull will happen immediately and ignore
|
|
751
|
-
* {@link RequestOptions.minDelayMs} as well as the exponential backoff in
|
|
752
|
-
* case of errors.
|
|
753
|
-
* @returns A promise that resolves when the next pull completes. In case of
|
|
754
|
-
* errors the first error will reject the returned promise. Subsequent errors
|
|
755
|
-
* will not be reflected in the promise.
|
|
756
|
-
*/
|
|
757
|
-
pull({ now = false } = {}) {
|
|
758
|
-
return throwIfError(this.#pullConnectionLoop.send(now));
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
* Applies an update from the server to Replicache.
|
|
762
|
-
* Throws an error if cookie does not match. In that case the server thinks
|
|
763
|
-
* this client has a different cookie than it does; the caller should disconnect
|
|
764
|
-
* from the server and re-register, which transmits the cookie the client actually
|
|
765
|
-
* has.
|
|
766
|
-
*
|
|
767
|
-
* @experimental This method is under development and its semantics will change.
|
|
768
|
-
*/
|
|
769
|
-
async poke(poke) {
|
|
770
|
-
await this.#ready;
|
|
771
|
-
const { clientID } = this;
|
|
772
|
-
const requestID = newRequestID(clientID);
|
|
773
|
-
const lc = this.#lc.withContext("handlePullResponse").withContext("requestID", requestID);
|
|
774
|
-
const { pullResponse } = poke;
|
|
775
|
-
if (isVersionNotSupportedResponse(pullResponse)) {
|
|
776
|
-
this.#handleVersionNotSupportedResponse(pullResponse);
|
|
777
|
-
return;
|
|
778
|
-
}
|
|
779
|
-
if (isClientStateNotFoundResponse(pullResponse)) {
|
|
780
|
-
await this.#clientStateNotFoundOnServer();
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
const result = await handlePullResponseV1(
|
|
784
|
-
lc,
|
|
785
|
-
this.memdag,
|
|
786
|
-
deepFreeze(poke.baseCookie),
|
|
787
|
-
pullResponse,
|
|
788
|
-
clientID,
|
|
789
|
-
Latest
|
|
790
|
-
);
|
|
791
|
-
switch (result.type) {
|
|
792
|
-
case Applied:
|
|
793
|
-
await this.maybeEndPull(result.syncHead, requestID);
|
|
794
|
-
break;
|
|
795
|
-
case CookieMismatch:
|
|
796
|
-
throw new Error(
|
|
797
|
-
"unexpected base cookie for poke: " + JSON.stringify(poke)
|
|
798
|
-
);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
async beginPull() {
|
|
802
|
-
await this.#ready;
|
|
803
|
-
const profileID = await this.profileID;
|
|
804
|
-
const { clientID } = this;
|
|
805
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
806
|
-
const {
|
|
807
|
-
result: { beginPullResponse, requestID }
|
|
808
|
-
} = await this.#wrapInReauthRetries(
|
|
809
|
-
async (requestID2, requestLc) => {
|
|
810
|
-
const beginPullResponse2 = await beginPullV1(
|
|
811
|
-
profileID,
|
|
812
|
-
clientID,
|
|
813
|
-
clientGroupID,
|
|
814
|
-
this.schemaVersion,
|
|
815
|
-
this.puller,
|
|
816
|
-
requestID2,
|
|
817
|
-
this.memdag,
|
|
818
|
-
Latest,
|
|
819
|
-
requestLc
|
|
820
|
-
);
|
|
821
|
-
return {
|
|
822
|
-
result: { beginPullResponse: beginPullResponse2, requestID: requestID2 },
|
|
823
|
-
httpRequestInfo: beginPullResponse2.httpRequestInfo
|
|
824
|
-
};
|
|
825
|
-
},
|
|
826
|
-
"pull",
|
|
827
|
-
this.#lc,
|
|
828
|
-
() => this.#changeSyncCounters(0, -1),
|
|
829
|
-
() => this.#changeSyncCounters(0, 1)
|
|
830
|
-
);
|
|
831
|
-
const { pullResponse } = beginPullResponse;
|
|
832
|
-
if (isVersionNotSupportedResponse(pullResponse)) {
|
|
833
|
-
this.#handleVersionNotSupportedResponse(pullResponse);
|
|
834
|
-
} else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) {
|
|
835
|
-
await this.#clientStateNotFoundOnServer();
|
|
836
|
-
}
|
|
837
|
-
const { syncHead, httpRequestInfo } = beginPullResponse;
|
|
838
|
-
return { requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200 };
|
|
839
|
-
}
|
|
840
|
-
persist() {
|
|
841
|
-
return this.#persistLock.withLock(async () => {
|
|
842
|
-
const { clientID } = this;
|
|
843
|
-
await this.#ready;
|
|
844
|
-
if (this.#closed) {
|
|
845
|
-
return;
|
|
846
|
-
}
|
|
847
|
-
try {
|
|
848
|
-
await persistDD31(
|
|
849
|
-
this.#lc,
|
|
850
|
-
clientID,
|
|
851
|
-
this.memdag,
|
|
852
|
-
this.perdag,
|
|
853
|
-
this.#mutatorRegistry,
|
|
854
|
-
() => this.#closed,
|
|
855
|
-
Latest,
|
|
856
|
-
this.#zero?.getTxData
|
|
857
|
-
);
|
|
858
|
-
} catch (e) {
|
|
859
|
-
if (e instanceof ClientStateNotFoundError) {
|
|
860
|
-
this.#clientStateNotFoundOnClient(clientID);
|
|
861
|
-
} else if (this.#closed) {
|
|
862
|
-
this.#lc.debug?.("Exception persisting during close", e);
|
|
863
|
-
} else {
|
|
864
|
-
throw e;
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
868
|
-
assert(clientGroupID, "Expected clientGroupID to be defined");
|
|
869
|
-
this.#onPersist({ clientID, clientGroupID });
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
async refresh() {
|
|
873
|
-
await this.#ready;
|
|
874
|
-
const { clientID } = this;
|
|
875
|
-
if (this.#closed || !this.#enableRefresh()) {
|
|
876
|
-
return;
|
|
877
|
-
}
|
|
878
|
-
let refreshResult;
|
|
879
|
-
try {
|
|
880
|
-
refreshResult = await refresh(
|
|
881
|
-
this.#lc,
|
|
882
|
-
this.memdag,
|
|
883
|
-
this.perdag,
|
|
884
|
-
clientID,
|
|
885
|
-
this.#mutatorRegistry,
|
|
886
|
-
this.#subscriptions,
|
|
887
|
-
() => this.closed,
|
|
888
|
-
Latest,
|
|
889
|
-
this.#zero
|
|
890
|
-
);
|
|
891
|
-
} catch (e) {
|
|
892
|
-
if (e instanceof ClientStateNotFoundError) {
|
|
893
|
-
this.#clientStateNotFoundOnClient(clientID);
|
|
894
|
-
} else if (this.#closed) {
|
|
895
|
-
this.#lc.debug?.("Exception refreshing during close", e);
|
|
896
|
-
} else {
|
|
897
|
-
throw e;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
if (refreshResult !== void 0) {
|
|
901
|
-
await this.#subscriptions.fire(refreshResult.diffs);
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
#fireOnClientStateNotFound() {
|
|
905
|
-
this.onClientStateNotFound?.();
|
|
906
|
-
}
|
|
907
|
-
#clientStateNotFoundOnClient(clientID) {
|
|
908
|
-
this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);
|
|
909
|
-
this.#fireOnClientStateNotFound();
|
|
910
|
-
}
|
|
911
|
-
async #clientStateNotFoundOnServer() {
|
|
912
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
913
|
-
this.#lc.error?.(
|
|
914
|
-
`Client state not found on server, clientGroupID: ${clientGroupID}`
|
|
915
|
-
);
|
|
916
|
-
await this.disableClientGroup();
|
|
917
|
-
this.#fireOnClientStateNotFound();
|
|
918
|
-
}
|
|
919
|
-
async disableClientGroup() {
|
|
920
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
921
|
-
assert(clientGroupID, "Expected clientGroupID to be defined");
|
|
922
|
-
this.isClientGroupDisabled = true;
|
|
923
|
-
await withWrite(
|
|
924
|
-
this.perdag,
|
|
925
|
-
(dagWrite) => disableClientGroup(clientGroupID, dagWrite)
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
#fireOnUpdateNeeded(reason) {
|
|
929
|
-
this.#lc.debug?.(`Update needed, reason: ${reason}`);
|
|
930
|
-
this.onUpdateNeeded?.(reason);
|
|
931
|
-
}
|
|
932
|
-
async #schedulePersist() {
|
|
933
|
-
if (!this.#enableScheduledPersist) {
|
|
934
|
-
return;
|
|
935
|
-
}
|
|
936
|
-
await this.#schedule("persist", this.#persistScheduler);
|
|
937
|
-
}
|
|
938
|
-
async #handlePersist(persistInfo) {
|
|
939
|
-
this.#lc.debug?.("Handling persist", persistInfo);
|
|
940
|
-
const clientGroupID = await this.#clientGroupIDPromise;
|
|
941
|
-
if (persistInfo.clientGroupID === clientGroupID) {
|
|
942
|
-
void this.#scheduleRefresh();
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
async #scheduleRefresh() {
|
|
946
|
-
if (!this.#enableScheduledRefresh) {
|
|
947
|
-
return;
|
|
948
|
-
}
|
|
949
|
-
await this.#schedule("refresh from storage", this.#refreshScheduler);
|
|
950
|
-
}
|
|
951
|
-
async #schedule(name, scheduler) {
|
|
952
|
-
try {
|
|
953
|
-
await scheduler.schedule();
|
|
954
|
-
} catch (e) {
|
|
955
|
-
if (e instanceof AbortError) {
|
|
956
|
-
this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);
|
|
957
|
-
} else {
|
|
958
|
-
this.#lc.error?.(`Error during ${name}`, e);
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Runs a refresh as soon as possible through the refresh scheduler.
|
|
964
|
-
*/
|
|
965
|
-
runRefresh() {
|
|
966
|
-
return this.#refreshScheduler.run();
|
|
967
|
-
}
|
|
968
|
-
#changeSyncCounters(pushDelta, pullDelta) {
|
|
969
|
-
this.#pushCounter += pushDelta;
|
|
970
|
-
this.#pullCounter += pullDelta;
|
|
971
|
-
const delta = pushDelta + pullDelta;
|
|
972
|
-
const counter = this.#pushCounter + this.#pullCounter;
|
|
973
|
-
if (delta === 1 && counter === 1 || counter === 0) {
|
|
974
|
-
const syncing = counter > 0;
|
|
975
|
-
void Promise.resolve().then(() => this.onSync?.(syncing));
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
/**
|
|
979
|
-
* Subscribe to the result of a {@link query}. The `body` function is
|
|
980
|
-
* evaluated once and its results are returned via `onData`.
|
|
981
|
-
*
|
|
982
|
-
* Thereafter, each time the the result of `body` changes, `onData` is fired
|
|
983
|
-
* again with the new result.
|
|
984
|
-
*
|
|
985
|
-
* `subscribe()` goes to significant effort to avoid extraneous work
|
|
986
|
-
* re-evaluating subscriptions:
|
|
987
|
-
*
|
|
988
|
-
* 1. subscribe tracks the keys that `body` accesses each time it runs. `body`
|
|
989
|
-
* is only re-evaluated when those keys change.
|
|
990
|
-
* 2. subscribe only re-fires `onData` in the case that a result changes by
|
|
991
|
-
* way of the `isEqual` option which defaults to doing a deep JSON value
|
|
992
|
-
* equality check.
|
|
993
|
-
*
|
|
994
|
-
* Because of (1), `body` must be a pure function of the data in Replicache.
|
|
995
|
-
* `body` must not access anything other than the `tx` parameter passed to it.
|
|
996
|
-
*
|
|
997
|
-
* Although subscribe is as efficient as it can be, it is somewhat constrained
|
|
998
|
-
* by the goal of returning an arbitrary computation of the cache. For even
|
|
999
|
-
* better performance (but worse dx), see {@link experimentalWatch}.
|
|
1000
|
-
*
|
|
1001
|
-
* If an error occurs in the `body` the `onError` function is called if
|
|
1002
|
-
* present. Otherwise, the error is logged at log level 'error'.
|
|
1003
|
-
*
|
|
1004
|
-
* To cancel the subscription, call the returned function.
|
|
1005
|
-
*
|
|
1006
|
-
* @param body The function to evaluate to get the value to pass into
|
|
1007
|
-
* `onData`.
|
|
1008
|
-
* @param options Options is either a function or an object. If it is a
|
|
1009
|
-
* function it is equivalent to passing it as the `onData` property of an
|
|
1010
|
-
* object.
|
|
1011
|
-
*/
|
|
1012
|
-
subscribe(body, options) {
|
|
1013
|
-
if (typeof options === "function") {
|
|
1014
|
-
options = { onData: options };
|
|
1015
|
-
}
|
|
1016
|
-
const { onData, onError, onDone, isEqual } = options;
|
|
1017
|
-
return this.#subscriptions.add(
|
|
1018
|
-
new SubscriptionImpl(body, onData, onError, onDone, isEqual)
|
|
1019
|
-
);
|
|
1020
|
-
}
|
|
1021
|
-
experimentalWatch(callback, options) {
|
|
1022
|
-
return this.#subscriptions.add(
|
|
1023
|
-
new WatchSubscription(callback, options)
|
|
1024
|
-
);
|
|
1025
|
-
}
|
|
1026
|
-
/**
|
|
1027
|
-
* Query is used for read transactions. It is recommended to use transactions
|
|
1028
|
-
* to ensure you get a consistent view across multiple calls to `get`, `has`
|
|
1029
|
-
* and `scan`.
|
|
1030
|
-
*/
|
|
1031
|
-
query(body) {
|
|
1032
|
-
return this.#queryInternal(body);
|
|
1033
|
-
}
|
|
1034
|
-
get cookie() {
|
|
1035
|
-
return this.#ready.then(
|
|
1036
|
-
() => withRead(this.memdag, async (dagRead) => {
|
|
1037
|
-
const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);
|
|
1038
|
-
if (!mainHeadHash) {
|
|
1039
|
-
throw new Error("Internal no main head found");
|
|
1040
|
-
}
|
|
1041
|
-
const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);
|
|
1042
|
-
const baseSnapshotMeta = baseSnapshot.meta;
|
|
1043
|
-
const cookie = baseSnapshotMeta.cookieJSON;
|
|
1044
|
-
assertCookie(cookie);
|
|
1045
|
-
return cookie;
|
|
1046
|
-
})
|
|
1047
|
-
);
|
|
1048
|
-
}
|
|
1049
|
-
#queryInternal = async (body) => {
|
|
1050
|
-
await this.#ready;
|
|
1051
|
-
const { clientID } = this;
|
|
1052
|
-
return withRead(this.memdag, async (dagRead) => {
|
|
1053
|
-
try {
|
|
1054
|
-
const dbRead = await readFromDefaultHead(dagRead, Latest);
|
|
1055
|
-
const tx = new ReadTransactionImpl(clientID, dbRead, this.#lc);
|
|
1056
|
-
return await body(tx);
|
|
1057
|
-
} catch (ex) {
|
|
1058
|
-
throw await this.#convertToClientStateNotFoundError(ex);
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
};
|
|
1062
|
-
#register(name, mutatorImpl) {
|
|
1063
|
-
this.#mutatorRegistry[name] = mutatorImpl;
|
|
1064
|
-
return (args) => {
|
|
1065
|
-
const trackingData = name === "_zero_crud" ? void 0 : this.#zero?.trackMutation();
|
|
1066
|
-
const result = this.#mutate(
|
|
1067
|
-
trackingData,
|
|
1068
|
-
name,
|
|
1069
|
-
mutatorImpl,
|
|
1070
|
-
args,
|
|
1071
|
-
performance.now()
|
|
1072
|
-
);
|
|
1073
|
-
if (trackingData) {
|
|
1074
|
-
return {
|
|
1075
|
-
client: result,
|
|
1076
|
-
server: trackingData.serverPromise
|
|
1077
|
-
};
|
|
1078
|
-
}
|
|
1079
|
-
return result;
|
|
1080
|
-
};
|
|
1081
|
-
}
|
|
1082
|
-
#registerMutators(regs) {
|
|
1083
|
-
const rv = /* @__PURE__ */ Object.create(null);
|
|
1084
|
-
for (const k in regs) {
|
|
1085
|
-
rv[k] = this.#register(k, regs[k]);
|
|
1086
|
-
}
|
|
1087
|
-
return rv;
|
|
1088
|
-
}
|
|
1089
|
-
async #mutate(trackingData, name, mutatorImpl, args, timestamp) {
|
|
1090
|
-
const frozenArgs = deepFreeze(args ?? null);
|
|
1091
|
-
if (this.#subscriptions.hasPendingSubscriptionRuns) {
|
|
1092
|
-
await Promise.resolve();
|
|
1093
|
-
}
|
|
1094
|
-
await this.#ready;
|
|
1095
|
-
const { clientID } = this;
|
|
1096
|
-
return withWriteNoImplicitCommit(this.memdag, async (dagWrite) => {
|
|
1097
|
-
try {
|
|
1098
|
-
let result;
|
|
1099
|
-
let newHead;
|
|
1100
|
-
let diffs;
|
|
1101
|
-
let headHash;
|
|
1102
|
-
try {
|
|
1103
|
-
headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);
|
|
1104
|
-
const originalHash = null;
|
|
1105
|
-
const dbWrite = await newWriteLocal(
|
|
1106
|
-
headHash,
|
|
1107
|
-
name,
|
|
1108
|
-
frozenArgs,
|
|
1109
|
-
originalHash,
|
|
1110
|
-
dagWrite,
|
|
1111
|
-
timestamp,
|
|
1112
|
-
clientID,
|
|
1113
|
-
Latest
|
|
1114
|
-
);
|
|
1115
|
-
const mutationID = await dbWrite.getMutationID();
|
|
1116
|
-
const tx = new WriteTransactionImpl(
|
|
1117
|
-
clientID,
|
|
1118
|
-
mutationID,
|
|
1119
|
-
"initial",
|
|
1120
|
-
await this.#zero?.getTxData(headHash, {
|
|
1121
|
-
openLazyRead: dagWrite
|
|
1122
|
-
}),
|
|
1123
|
-
dbWrite,
|
|
1124
|
-
this.#lc
|
|
1125
|
-
);
|
|
1126
|
-
if (trackingData) {
|
|
1127
|
-
this.#zero?.mutationIDAssigned(
|
|
1128
|
-
trackingData.ephemeralID,
|
|
1129
|
-
mutationID
|
|
1130
|
-
);
|
|
1131
|
-
}
|
|
1132
|
-
result = await mutatorImpl(tx, args);
|
|
1133
|
-
throwIfClosed(dbWrite);
|
|
1134
|
-
const lastMutationID = await dbWrite.getMutationID();
|
|
1135
|
-
[newHead, diffs] = await dbWrite.commitWithDiffs(
|
|
1136
|
-
DEFAULT_HEAD_NAME,
|
|
1137
|
-
this.#subscriptions
|
|
1138
|
-
);
|
|
1139
|
-
this.lastMutationID = lastMutationID;
|
|
1140
|
-
} catch (e) {
|
|
1141
|
-
if (trackingData) {
|
|
1142
|
-
this.#zero?.rejectMutation(trackingData.ephemeralID, e);
|
|
1143
|
-
}
|
|
1144
|
-
throw e;
|
|
1145
|
-
}
|
|
1146
|
-
this.#zero?.advance(headHash, newHead, diffs.get("") ?? []);
|
|
1147
|
-
this.#pushConnectionLoop.send(false).catch(() => void 0);
|
|
1148
|
-
await this.#subscriptions.fire(diffs);
|
|
1149
|
-
void this.#schedulePersist();
|
|
1150
|
-
return result;
|
|
1151
|
-
} catch (ex) {
|
|
1152
|
-
throw await this.#convertToClientStateNotFoundError(ex);
|
|
1153
|
-
}
|
|
1154
|
-
});
|
|
1155
|
-
}
|
|
1156
|
-
/**
|
|
1157
|
-
* In the case we get a ChunkNotFoundError we check if the client got garbage
|
|
1158
|
-
* collected and if so change the error to a ClientStateNotFoundError instead
|
|
1159
|
-
*/
|
|
1160
|
-
async #convertToClientStateNotFoundError(ex) {
|
|
1161
|
-
if (ex instanceof ChunkNotFoundError && await this.#checkForClientStateNotFoundAndCallHandler()) {
|
|
1162
|
-
return new ClientStateNotFoundError(this.clientID);
|
|
1163
|
-
}
|
|
1164
|
-
return ex;
|
|
1165
|
-
}
|
|
1166
|
-
recoverMutations() {
|
|
1167
|
-
}
|
|
1168
|
-
/**
|
|
1169
|
-
* List of pending mutations. The order of this is from oldest to newest.
|
|
1170
|
-
*
|
|
1171
|
-
* Gives a list of local mutations that have `mutationID` >
|
|
1172
|
-
* `syncHead.mutationID` that exists on the main client group.
|
|
1173
|
-
*
|
|
1174
|
-
* @experimental This method is experimental and may change in the future.
|
|
1175
|
-
*/
|
|
1176
|
-
experimentalPendingMutations() {
|
|
1177
|
-
return withRead(this.memdag, pendingMutationsForAPI);
|
|
1178
|
-
}
|
|
1179
|
-
}
|
|
1180
|
-
const closingInstances = /* @__PURE__ */ new Map();
|
|
850
|
+
var closingInstances = /* @__PURE__ */ new Map();
|
|
1181
851
|
async function throwIfError(p) {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
throw res.error;
|
|
1185
|
-
}
|
|
852
|
+
const res = await p;
|
|
853
|
+
if (res) throw res.error;
|
|
1186
854
|
}
|
|
1187
855
|
function reload() {
|
|
1188
|
-
|
|
1189
|
-
location.reload();
|
|
1190
|
-
}
|
|
856
|
+
if (typeof location !== "undefined") location.reload();
|
|
1191
857
|
}
|
|
1192
858
|
function validateOptions(options) {
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
if (typeof clientMaxAgeMs !== "number" || clientMaxAgeMs <= min) {
|
|
1200
|
-
throw new TypeError(
|
|
1201
|
-
`clientAgeMaxMs must be a number larger than ${min}ms`
|
|
1202
|
-
);
|
|
1203
|
-
}
|
|
1204
|
-
}
|
|
859
|
+
const { name, clientMaxAgeMs } = options;
|
|
860
|
+
if (typeof name !== "string" || !name) throw new TypeError("name is required and must be non-empty");
|
|
861
|
+
if (clientMaxAgeMs !== void 0) {
|
|
862
|
+
const min = Math.max(GC_INTERVAL, HEARTBEAT_INTERVAL);
|
|
863
|
+
if (typeof clientMaxAgeMs !== "number" || clientMaxAgeMs <= min) throw new TypeError(`clientAgeMaxMs must be a number larger than ${min}ms`);
|
|
864
|
+
}
|
|
1205
865
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
//# sourceMappingURL=replicache-impl.js.map
|
|
866
|
+
//#endregion
|
|
867
|
+
export { ReplicacheImpl };
|
|
868
|
+
|
|
869
|
+
//# sourceMappingURL=replicache-impl.js.map
|