@rocicorp/zero 0.25.0 → 0.26.0-canary.0
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/analyze-query/src/bin-analyze.js +268 -257
- package/out/analyze-query/src/bin-analyze.js.map +1 -1
- package/out/analyze-query/src/bin-transform.js +31 -23
- package/out/analyze-query/src/bin-transform.js.map +1 -1
- package/out/analyze-query/src/explain-queries.js +13 -16
- package/out/analyze-query/src/explain-queries.js.map +1 -1
- package/out/analyze-query/src/run-ast.d.ts +3 -2
- package/out/analyze-query/src/run-ast.d.ts.map +1 -1
- package/out/analyze-query/src/run-ast.js +82 -74
- package/out/analyze-query/src/run-ast.js.map +1 -1
- package/out/ast-to-zql/src/ast-to-zql.js +146 -180
- package/out/ast-to-zql/src/ast-to-zql.js.map +1 -1
- package/out/ast-to-zql/src/bin.js +51 -54
- package/out/ast-to-zql/src/bin.js.map +1 -1
- package/out/ast-to-zql/src/format.js +15 -14
- package/out/ast-to-zql/src/format.js.map +1 -1
- package/out/datadog/src/datadog-log-sink.js +223 -0
- package/out/datadog/src/datadog-log-sink.js.map +1 -0
- package/out/otel/src/enabled.js +15 -15
- package/out/otel/src/enabled.js.map +1 -1
- package/out/otel/src/log-options.d.ts +1 -1
- package/out/otel/src/log-options.d.ts.map +1 -1
- package/out/otel/src/log-options.js +35 -31
- package/out/otel/src/log-options.js.map +1 -1
- package/out/otel/src/maybe-time.js +14 -11
- package/out/otel/src/maybe-time.js.map +1 -1
- package/out/otel/src/span.js +30 -27
- package/out/otel/src/span.js.map +1 -1
- package/out/otel/src/test-log-config.js +10 -7
- package/out/otel/src/test-log-config.js.map +1 -1
- package/out/otel/src/version.js +5 -2
- package/out/otel/src/version.js.map +1 -1
- package/out/replicache/src/async-iterable-to-array.js +11 -0
- package/out/replicache/src/async-iterable-to-array.js.map +1 -0
- package/out/replicache/src/bg-interval.js +38 -0
- package/out/replicache/src/bg-interval.js.map +1 -0
- package/out/replicache/src/btree/diff.js +8 -0
- package/out/replicache/src/btree/diff.js.map +1 -0
- package/out/replicache/src/btree/node.js +400 -0
- package/out/replicache/src/btree/node.js.map +1 -0
- package/out/replicache/src/btree/read.d.ts +3 -2
- package/out/replicache/src/btree/read.d.ts.map +1 -1
- package/out/replicache/src/btree/read.js +266 -0
- package/out/replicache/src/btree/read.js.map +1 -0
- package/out/replicache/src/btree/splice.js +83 -0
- package/out/replicache/src/btree/splice.js.map +1 -0
- package/out/replicache/src/btree/write.d.ts +1 -1
- package/out/replicache/src/btree/write.d.ts.map +1 -1
- package/out/replicache/src/btree/write.js +163 -0
- package/out/replicache/src/btree/write.js.map +1 -0
- package/out/replicache/src/call-default-fetch.js +34 -0
- package/out/replicache/src/call-default-fetch.js.map +1 -0
- package/out/replicache/src/connection-loop-delegates.js +34 -0
- package/out/replicache/src/connection-loop-delegates.js.map +1 -0
- package/out/replicache/src/connection-loop.js +251 -0
- package/out/replicache/src/connection-loop.js.map +1 -0
- package/out/replicache/src/cookies.js +40 -0
- package/out/replicache/src/cookies.js.map +1 -0
- package/out/replicache/src/dag/chunk.js +59 -0
- package/out/replicache/src/dag/chunk.js.map +1 -0
- package/out/replicache/src/dag/gc.js +117 -0
- package/out/replicache/src/dag/gc.js.map +1 -0
- package/out/replicache/src/dag/key.js +20 -0
- package/out/replicache/src/dag/key.js.map +1 -0
- package/out/replicache/src/dag/lazy-store.d.ts +2 -1
- package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
- package/out/replicache/src/dag/lazy-store.js +515 -0
- package/out/replicache/src/dag/lazy-store.js.map +1 -0
- package/out/replicache/src/dag/store-impl.js +183 -0
- package/out/replicache/src/dag/store-impl.js.map +1 -0
- package/out/replicache/src/dag/store.js +27 -0
- package/out/replicache/src/dag/store.js.map +1 -0
- package/out/replicache/src/dag/visitor.js +22 -0
- package/out/replicache/src/dag/visitor.js.map +1 -0
- package/out/replicache/src/db/commit.js +358 -0
- package/out/replicache/src/db/commit.js.map +1 -0
- package/out/replicache/src/db/index-operation-enum.js +7 -0
- package/out/replicache/src/db/index-operation-enum.js.map +1 -0
- package/out/replicache/src/db/index.js +134 -0
- package/out/replicache/src/db/index.js.map +1 -0
- package/out/replicache/src/db/meta-type-enum.js +7 -0
- package/out/replicache/src/db/meta-type-enum.js.map +1 -0
- package/out/replicache/src/db/read.d.ts +3 -2
- package/out/replicache/src/db/read.d.ts.map +1 -1
- package/out/replicache/src/db/read.js +72 -0
- package/out/replicache/src/db/read.js.map +1 -0
- package/out/replicache/src/db/rebase.d.ts +2 -2
- package/out/replicache/src/db/rebase.d.ts.map +1 -1
- package/out/replicache/src/db/rebase.js +85 -0
- package/out/replicache/src/db/rebase.js.map +1 -0
- package/out/replicache/src/db/write.d.ts +2 -1
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +296 -0
- package/out/replicache/src/db/write.js.map +1 -0
- package/out/replicache/src/deleted-clients.js +104 -0
- package/out/replicache/src/deleted-clients.js.map +1 -0
- package/out/replicache/src/error-responses.js +34 -0
- package/out/replicache/src/error-responses.js.map +1 -0
- package/out/replicache/src/format-version-enum.js +11 -0
- package/out/replicache/src/format-version-enum.js.map +1 -0
- package/out/{chunk-EZM3XBAB.js → replicache/src/frozen-json.js} +8 -75
- package/out/replicache/src/frozen-json.js.map +1 -0
- package/out/replicache/src/get-default-puller.js +61 -0
- package/out/replicache/src/get-default-puller.js.map +1 -0
- package/out/replicache/src/get-default-pusher.js +39 -0
- package/out/replicache/src/get-default-pusher.js.map +1 -0
- package/out/replicache/src/get-kv-store-provider.js +23 -0
- package/out/replicache/src/get-kv-store-provider.js.map +1 -0
- package/out/replicache/src/hash.js +38 -0
- package/out/replicache/src/hash.js.map +1 -0
- package/out/replicache/src/http-request-info.js +10 -0
- package/out/replicache/src/http-request-info.js.map +1 -0
- package/out/replicache/src/http-status-unauthorized.js +5 -0
- package/out/replicache/src/http-status-unauthorized.js.map +1 -0
- package/out/replicache/src/index-defs.js +32 -0
- package/out/replicache/src/index-defs.js.map +1 -0
- package/out/replicache/src/invoke-kind-enum.js +7 -0
- package/out/replicache/src/invoke-kind-enum.js.map +1 -0
- package/out/{chunk-ZZXMKAAG.js → replicache/src/kv/expo-sqlite/store.js} +8 -16
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js +80 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.js.map +1 -0
- package/out/replicache/src/kv/idb-store.js +183 -0
- package/out/replicache/src/kv/idb-store.js.map +1 -0
- package/out/replicache/src/kv/mem-store.js +51 -0
- package/out/replicache/src/kv/mem-store.js.map +1 -0
- package/out/{op-sqlite.js → replicache/src/kv/op-sqlite/store.js} +7 -18
- package/out/replicache/src/kv/op-sqlite/store.js.map +1 -0
- package/out/replicache/src/kv/op-sqlite/types.js +6 -0
- package/out/replicache/src/kv/op-sqlite/types.js.map +1 -0
- package/out/replicache/src/kv/read-impl.js +27 -0
- package/out/replicache/src/kv/read-impl.js.map +1 -0
- package/out/replicache/src/kv/sqlite-store.d.ts.map +1 -1
- package/out/{chunk-ECUMGQGC.js → replicache/src/kv/sqlite-store.js} +27 -21
- package/out/replicache/src/kv/sqlite-store.js.map +1 -0
- package/out/{chunk-ASRS2LFV.js → replicache/src/kv/throw-if-closed.js} +4 -6
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -0
- package/out/replicache/src/kv/write-impl-base.js +57 -0
- package/out/replicache/src/kv/write-impl-base.js.map +1 -0
- package/out/replicache/src/kv/write-impl.js +30 -0
- package/out/replicache/src/kv/write-impl.js.map +1 -0
- package/out/replicache/src/lazy.js +13 -0
- package/out/replicache/src/lazy.js.map +1 -0
- package/out/replicache/src/log-options.js +9 -0
- package/out/replicache/src/log-options.js.map +1 -0
- package/out/replicache/src/make-idb-name.js +13 -0
- package/out/replicache/src/make-idb-name.js.map +1 -0
- package/out/replicache/src/new-client-channel.js +51 -0
- package/out/replicache/src/new-client-channel.js.map +1 -0
- package/out/replicache/src/on-persist-channel.js +36 -0
- package/out/replicache/src/on-persist-channel.js.map +1 -0
- package/out/replicache/src/patch-operation.js +42 -0
- package/out/replicache/src/patch-operation.js.map +1 -0
- package/out/replicache/src/pending-mutations.js +16 -0
- package/out/replicache/src/pending-mutations.js.map +1 -0
- package/out/replicache/src/persist/client-gc.js +58 -0
- package/out/replicache/src/persist/client-gc.js.map +1 -0
- package/out/replicache/src/persist/client-group-gc.js +43 -0
- package/out/replicache/src/persist/client-group-gc.js.map +1 -0
- package/out/replicache/src/persist/client-groups.js +184 -0
- package/out/replicache/src/persist/client-groups.js.map +1 -0
- package/out/replicache/src/persist/clients.d.ts +3 -2
- package/out/replicache/src/persist/clients.d.ts.map +1 -1
- package/out/replicache/src/persist/clients.js +353 -0
- package/out/replicache/src/persist/clients.js.map +1 -0
- package/out/replicache/src/persist/collect-idb-databases.js +188 -0
- package/out/replicache/src/persist/collect-idb-databases.js.map +1 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.js +27 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.js.map +1 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.js +37 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.js.map +1 -0
- package/out/replicache/src/persist/heartbeat.js +48 -0
- package/out/replicache/src/persist/heartbeat.js.map +1 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.js +14 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.js.map +1 -0
- package/out/replicache/src/persist/idb-databases-store.d.ts +1 -0
- package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -1
- package/out/replicache/src/persist/idb-databases-store.js +103 -0
- package/out/replicache/src/persist/idb-databases-store.js.map +1 -0
- package/out/replicache/src/persist/make-client-id.js +12 -0
- package/out/replicache/src/persist/make-client-id.js.map +1 -0
- package/out/replicache/src/persist/persist.d.ts +2 -2
- package/out/replicache/src/persist/persist.d.ts.map +1 -1
- package/out/replicache/src/persist/persist.js +183 -0
- package/out/replicache/src/persist/persist.js.map +1 -0
- package/out/replicache/src/persist/refresh.d.ts +4 -3
- package/out/replicache/src/persist/refresh.d.ts.map +1 -1
- package/out/replicache/src/persist/refresh.js +198 -0
- package/out/replicache/src/persist/refresh.js.map +1 -0
- package/out/replicache/src/process-scheduler.js +96 -0
- package/out/replicache/src/process-scheduler.js.map +1 -0
- package/out/replicache/src/pusher.js +33 -0
- package/out/replicache/src/pusher.js.map +1 -0
- package/out/replicache/src/replicache-impl.d.ts +1 -1
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +1200 -0
- package/out/replicache/src/replicache-impl.js.map +1 -0
- package/out/replicache/src/replicache-options.d.ts +3 -2
- package/out/replicache/src/replicache-options.d.ts.map +1 -1
- package/out/replicache/src/report-error.js +6 -0
- package/out/replicache/src/report-error.js.map +1 -0
- package/out/replicache/src/request-idle.js +13 -0
- package/out/replicache/src/request-idle.js.map +1 -0
- package/out/replicache/src/scan-iterator.js +146 -0
- package/out/replicache/src/scan-iterator.js.map +1 -0
- package/out/replicache/src/scan-options.js +45 -0
- package/out/replicache/src/scan-options.js.map +1 -0
- package/out/replicache/src/set-interval-with-signal.js +12 -0
- package/out/replicache/src/set-interval-with-signal.js.map +1 -0
- package/out/replicache/src/subscriptions.js +355 -0
- package/out/replicache/src/subscriptions.js.map +1 -0
- package/out/replicache/src/sync/diff.d.ts +3 -2
- package/out/replicache/src/sync/diff.d.ts.map +1 -1
- package/out/replicache/src/sync/diff.js +72 -0
- package/out/replicache/src/sync/diff.js.map +1 -0
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js +9 -0
- package/out/replicache/src/sync/handle-pull-response-result-type-enum.js.map +1 -0
- package/out/replicache/src/sync/ids.js +9 -0
- package/out/replicache/src/sync/ids.js.map +1 -0
- package/out/replicache/src/sync/patch.js +49 -0
- package/out/replicache/src/sync/patch.js.map +1 -0
- package/out/replicache/src/sync/pull-error.js +16 -0
- package/out/replicache/src/sync/pull-error.js.map +1 -0
- package/out/replicache/src/sync/pull.d.ts +3 -2
- package/out/replicache/src/sync/pull.d.ts.map +1 -1
- package/out/replicache/src/sync/pull.js +301 -0
- package/out/replicache/src/sync/pull.js.map +1 -0
- package/out/replicache/src/sync/push.js +88 -0
- package/out/replicache/src/sync/push.js.map +1 -0
- package/out/replicache/src/sync/request-id.js +20 -0
- package/out/replicache/src/sync/request-id.js.map +1 -0
- package/out/replicache/src/sync/sync-head-name.js +5 -0
- package/out/replicache/src/sync/sync-head-name.js.map +1 -0
- package/out/replicache/src/to-error.js +10 -0
- package/out/replicache/src/to-error.js.map +1 -0
- package/out/replicache/src/transaction-closed-error.js +19 -0
- package/out/replicache/src/transaction-closed-error.js.map +1 -0
- package/out/replicache/src/transactions.js +152 -0
- package/out/replicache/src/transactions.js.map +1 -0
- package/out/replicache/src/version.js +5 -0
- package/out/replicache/src/version.js.map +1 -0
- package/out/replicache/src/with-transactions.js +28 -0
- package/out/replicache/src/with-transactions.js.map +1 -0
- package/out/shared/src/abort-error.js +6 -3
- package/out/shared/src/abort-error.js.map +1 -1
- package/out/shared/src/arrays.js +45 -43
- package/out/shared/src/arrays.js.map +1 -1
- package/out/shared/src/asserts.js +64 -68
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/bigint-json.js +38 -42
- package/out/shared/src/bigint-json.js.map +1 -1
- package/out/shared/src/binary-search.js +18 -29
- package/out/shared/src/binary-search.js.map +1 -1
- package/out/shared/src/broadcast-channel.js +24 -0
- package/out/shared/src/broadcast-channel.js.map +1 -0
- package/out/shared/src/browser-env.js +25 -0
- package/out/shared/src/browser-env.js.map +1 -0
- package/out/shared/src/btree-set.js +464 -507
- package/out/shared/src/btree-set.js.map +1 -1
- package/out/shared/src/cache.js +34 -38
- package/out/shared/src/cache.js.map +1 -1
- package/out/shared/src/centroid.js +24 -24
- package/out/shared/src/centroid.js.map +1 -1
- package/out/shared/src/config.js +6 -3
- package/out/shared/src/config.js.map +1 -1
- package/out/shared/src/custom-key-map.js +58 -64
- package/out/shared/src/custom-key-map.js.map +1 -1
- package/out/shared/src/custom-key-set.js +51 -57
- package/out/shared/src/custom-key-set.js.map +1 -1
- package/out/shared/src/deep-clone.js +46 -0
- package/out/shared/src/deep-clone.js.map +1 -0
- package/out/shared/src/deep-merge.d.ts +26 -4
- package/out/shared/src/deep-merge.d.ts.map +1 -1
- package/out/shared/src/deep-merge.js +28 -0
- package/out/shared/src/deep-merge.js.map +1 -0
- package/out/shared/src/document-visible.js +74 -0
- package/out/shared/src/document-visible.js.map +1 -0
- package/out/shared/src/dotenv.js +5 -7
- package/out/shared/src/dotenv.js.map +1 -1
- package/out/shared/src/error.js +57 -56
- package/out/shared/src/error.js.map +1 -1
- package/out/shared/src/has-own.js +5 -3
- 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.d.ts +0 -1
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js +44 -80
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/json-schema.js +30 -33
- package/out/shared/src/json-schema.js.map +1 -1
- package/out/shared/src/json.js +128 -143
- package/out/shared/src/json.js.map +1 -1
- package/out/shared/src/logging-test-utils.js +12 -19
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/logging.d.ts.map +1 -1
- package/out/shared/src/logging.js +99 -83
- package/out/shared/src/logging.js.map +1 -1
- package/out/shared/src/must.js +9 -7
- package/out/shared/src/must.js.map +1 -1
- package/out/shared/src/navigator.js +5 -0
- package/out/shared/src/navigator.js.map +1 -0
- package/out/shared/src/object-traversal.d.ts +19 -0
- package/out/shared/src/object-traversal.d.ts.map +1 -0
- package/out/shared/src/object-traversal.js +27 -0
- package/out/shared/src/object-traversal.js.map +1 -0
- package/out/shared/src/objects.js +21 -22
- package/out/shared/src/objects.js.map +1 -1
- package/out/shared/src/options-types.d.ts +113 -0
- package/out/shared/src/options-types.d.ts.map +1 -0
- package/out/shared/src/options.d.ts +4 -111
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +289 -318
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/parse-big-int.js +12 -10
- package/out/shared/src/parse-big-int.js.map +1 -1
- package/out/shared/src/promise-race.js +20 -0
- package/out/shared/src/promise-race.js.map +1 -0
- package/out/shared/src/queue.js +119 -122
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/rand.js +8 -10
- package/out/shared/src/rand.js.map +1 -1
- package/out/shared/src/random-uint64.js +9 -0
- package/out/shared/src/random-uint64.js.map +1 -0
- package/out/shared/src/random-values.js +13 -0
- package/out/shared/src/random-values.js.map +1 -0
- package/out/shared/src/record-proxy.d.ts +13 -0
- package/out/shared/src/record-proxy.d.ts.map +1 -0
- package/out/shared/src/record-proxy.js +59 -0
- package/out/shared/src/record-proxy.js.map +1 -0
- package/out/shared/src/resolved-promises.js +12 -9
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/sentinels.js +13 -6
- package/out/shared/src/sentinels.js.map +1 -1
- package/out/shared/src/set-utils.js +63 -62
- package/out/shared/src/set-utils.js.map +1 -1
- package/out/shared/src/size-of-value.js +58 -0
- package/out/shared/src/size-of-value.js.map +1 -0
- package/out/shared/src/sleep.js +45 -53
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/string-compare.js +12 -9
- package/out/shared/src/string-compare.js.map +1 -1
- package/out/shared/src/subscribable.js +34 -0
- package/out/shared/src/subscribable.js.map +1 -0
- package/out/shared/src/tdigest-schema.js +7 -7
- package/out/shared/src/tdigest-schema.js.map +1 -1
- package/out/shared/src/tdigest.js +247 -271
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/shared/src/valita.js +195 -207
- package/out/shared/src/valita.js.map +1 -1
- package/out/z2s/src/compiler.d.ts +2 -2
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +439 -310
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +186 -218
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.json.js +9 -0
- package/out/zero/package.json.js.map +1 -0
- package/out/zero/src/adapters/drizzle.d.ts +1 -1
- package/out/zero/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero/src/adapters/drizzle.js +8 -2
- package/out/zero/src/adapters/drizzle.js.map +1 -1
- package/out/zero/src/adapters/pg.js +7 -2
- package/out/zero/src/adapters/pg.js.map +1 -1
- package/out/zero/src/adapters/postgresjs.js +7 -2
- package/out/zero/src/adapters/postgresjs.js.map +1 -1
- package/out/zero/src/analyze-query.js +1 -1
- package/out/zero/src/analyze-query.js.map +1 -1
- package/out/zero/src/ast-to-zql.js +1 -1
- package/out/zero/src/ast-to-zql.js.map +1 -1
- package/out/zero/src/bindings.d.ts +2 -0
- package/out/zero/src/bindings.d.ts.map +1 -0
- package/out/zero/src/bindings.js +27 -0
- package/out/zero/src/bindings.js.map +1 -0
- package/out/zero/src/build-schema.js +3 -5
- package/out/zero/src/build-schema.js.map +1 -1
- package/out/zero/src/change-protocol/v0.js +5 -3
- package/out/zero/src/change-protocol/v0.js.map +1 -1
- package/out/zero/src/cli.js +2 -2
- package/out/zero/src/cli.js.map +1 -1
- package/out/zero/src/deploy-permissions.js +1 -1
- package/out/zero/src/deploy-permissions.js.map +1 -1
- package/out/zero/src/expo-sqlite.js +5 -0
- package/out/zero/src/expo-sqlite.js.map +1 -0
- package/out/zero/src/op-sqlite.js +5 -0
- package/out/zero/src/op-sqlite.js.map +1 -0
- package/out/zero/src/pg.js +31 -3
- package/out/zero/src/pg.js.map +1 -1
- package/out/zero/src/react-native.js +13 -0
- package/out/zero/src/react-native.js.map +1 -0
- package/out/zero/src/react.js +15 -0
- package/out/zero/src/react.js.map +1 -0
- package/out/zero/src/server.js +27 -3
- package/out/zero/src/server.js.map +1 -1
- package/out/zero/src/solid.js +15 -0
- package/out/zero/src/solid.js.map +1 -0
- package/out/zero/src/sqlite.js +7 -0
- package/out/zero/src/sqlite.js.map +1 -0
- package/out/zero/src/transform-query.js +1 -1
- package/out/zero/src/transform-query.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js +138 -104
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero/src/zero-out.js +6 -6
- package/out/zero/src/zero-out.js.map +1 -1
- package/out/zero/src/zero.js +71 -0
- package/out/zero/src/zero.js.map +1 -0
- package/out/zero/src/zqlite.js +11 -3
- package/out/zero/src/zqlite.js.map +1 -1
- package/out/zero-cache/src/auth/jwt.d.ts +3 -0
- package/out/zero-cache/src/auth/jwt.d.ts.map +1 -1
- package/out/zero-cache/src/auth/jwt.js +33 -38
- package/out/zero-cache/src/auth/jwt.js.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.d.ts +1 -1
- package/out/zero-cache/src/auth/load-permissions.d.ts.map +1 -1
- package/out/zero-cache/src/auth/load-permissions.js +61 -45
- package/out/zero-cache/src/auth/load-permissions.js.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.d.ts +1 -1
- package/out/zero-cache/src/auth/read-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/read-authorizer.js +79 -91
- package/out/zero-cache/src/auth/read-authorizer.js.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.d.ts +4 -3
- package/out/zero-cache/src/auth/write-authorizer.d.ts.map +1 -1
- package/out/zero-cache/src/auth/write-authorizer.js +395 -328
- package/out/zero-cache/src/auth/write-authorizer.js.map +1 -1
- package/out/zero-cache/src/config/network.js +42 -45
- package/out/zero-cache/src/config/network.js.map +1 -1
- package/out/zero-cache/src/config/normalize.js +86 -83
- package/out/zero-cache/src/config/normalize.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +63 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +743 -682
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +5 -5
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +170 -162
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts +10 -3
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +101 -109
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.js +32 -36
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/delete-lite-db.js +9 -6
- package/out/zero-cache/src/db/delete-lite-db.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +150 -174
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js +170 -165
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +157 -137
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/mode-enum.d.ts +2 -0
- package/out/zero-cache/src/db/mode-enum.d.ts.map +1 -1
- package/out/zero-cache/src/db/mode-enum.js +9 -3
- package/out/zero-cache/src/db/mode-enum.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy.js +51 -90
- package/out/zero-cache/src/db/pg-copy.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts +10 -0
- package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +116 -97
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js +27 -39
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js +11 -6
- package/out/zero-cache/src/db/postgres-replica-identity-enum.js.map +1 -1
- package/out/zero-cache/src/db/postgres-type-class-enum.js +17 -9
- package/out/zero-cache/src/db/postgres-type-class-enum.js.map +1 -1
- package/out/zero-cache/src/db/specs.d.ts +1 -7
- package/out/zero-cache/src/db/specs.d.ts.map +1 -1
- package/out/zero-cache/src/db/specs.js +66 -40
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/statements.d.ts +1 -1
- package/out/zero-cache/src/db/statements.d.ts.map +1 -1
- package/out/zero-cache/src/db/statements.js +59 -52
- package/out/zero-cache/src/db/statements.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts +1 -1
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +372 -501
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/db/warmup.js +25 -12
- package/out/zero-cache/src/db/warmup.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +71 -82
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/observability/metrics.js +54 -32
- package/out/zero-cache/src/observability/metrics.js.map +1 -1
- package/out/zero-cache/src/scripts/decommission.js +47 -43
- package/out/zero-cache/src/scripts/decommission.js.map +1 -1
- package/out/zero-cache/src/scripts/deploy-permissions.js +132 -119
- package/out/zero-cache/src/scripts/deploy-permissions.js.map +1 -1
- package/out/zero-cache/src/scripts/permissions.d.ts +1 -1
- package/out/zero-cache/src/scripts/permissions.d.ts.map +1 -1
- package/out/zero-cache/src/scripts/permissions.js +106 -100
- package/out/zero-cache/src/scripts/permissions.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts +10 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +426 -366
- 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 +99 -64
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +112 -109
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/logging.d.ts +1 -1
- package/out/zero-cache/src/server/logging.d.ts.map +1 -1
- package/out/zero-cache/src/server/logging.js +26 -19
- package/out/zero-cache/src/server/logging.js.map +1 -1
- package/out/zero-cache/src/server/main.d.ts.map +1 -1
- package/out/zero-cache/src/server/main.js +137 -120
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/mutator.js +19 -0
- package/out/zero-cache/src/server/mutator.js.map +1 -0
- package/out/zero-cache/src/server/otel-diag-logger.d.ts +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-diag-logger.js +48 -71
- package/out/zero-cache/src/server/otel-diag-logger.js.map +1 -1
- package/out/zero-cache/src/server/otel-log-sink.js +40 -41
- package/out/zero-cache/src/server/otel-log-sink.js.map +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts +1 -1
- package/out/zero-cache/src/server/otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/otel-start.js +53 -68
- package/out/zero-cache/src/server/otel-start.js.map +1 -1
- package/out/zero-cache/src/server/reaper.js +34 -26
- package/out/zero-cache/src/server/reaper.js.map +1 -1
- package/out/zero-cache/src/server/replicator.js +53 -31
- package/out/zero-cache/src/server/replicator.js.map +1 -1
- package/out/zero-cache/src/server/runner/main.js +6 -4
- package/out/zero-cache/src/server/runner/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +46 -50
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/server/runner/runtime.js +33 -32
- package/out/zero-cache/src/server/runner/runtime.js.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/runner/zero-dispatcher.js +28 -22
- package/out/zero-cache/src/server/runner/zero-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +130 -63
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.d.ts.map +1 -1
- package/out/zero-cache/src/server/worker-dispatcher.js +112 -106
- package/out/zero-cache/src/server/worker-dispatcher.js.map +1 -1
- package/out/zero-cache/src/server/worker-urls.d.ts +7 -0
- package/out/zero-cache/src/server/worker-urls.d.ts.map +1 -0
- package/out/zero-cache/src/server/worker-urls.js +21 -0
- package/out/zero-cache/src/server/worker-urls.js.map +1 -0
- package/out/zero-cache/src/services/analyze.d.ts +4 -9
- package/out/zero-cache/src/services/analyze.d.ts.map +1 -1
- package/out/zero-cache/src/services/analyze.js +118 -121
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts +10 -3
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/column-metadata.js +154 -144
- package/out/zero-cache/src/services/change-source/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +197 -171
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js +11 -3
- package/out/zero-cache/src/services/change-source/custom/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +622 -623
- 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 +24 -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.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +327 -284
- 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.d.ts +2 -3
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +61 -69
- 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 +247 -257
- 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 +127 -119
- 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 +20 -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.d.ts +5 -5
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +96 -119
- 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 +138 -117
- package/out/zero-cache/src/services/change-source/pg/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +2 -2
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/published.js +70 -76
- package/out/zero-cache/src/services/change-source/pg/schema/published.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/shard.js +199 -188
- 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 +53 -38
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js +11 -3
- package/out/zero-cache/src/services/change-source/pg/sync-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/control.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/control.js +13 -19
- 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 +143 -116
- package/out/zero-cache/src/services/change-source/protocol/current/data.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +2 -0
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.js +29 -19
- 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.d.ts +8 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.js +19 -0
- package/out/zero-cache/src/services/change-source/protocol/current/json.js.map +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current/path.js +5 -20
- 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 +12 -13
- package/out/zero-cache/src/services/change-source/protocol/current/status.js.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current/upstream.js +5 -4
- 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.d.ts +1 -0
- package/out/zero-cache/src/services/change-source/protocol/current.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/protocol/current.js +38 -7
- package/out/zero-cache/src/services/change-source/protocol/current.js.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js +67 -37
- package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +139 -157
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +11 -4
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +208 -157
- 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 +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 +242 -349
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +5 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +24 -22
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js +9 -4
- package/out/zero-cache/src/services/change-streamer/error-type-enum.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/forwarder.js +53 -57
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts +16 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js +48 -0
- package/out/zero-cache/src/services/change-streamer/replica-monitor.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.js +82 -68
- 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 +2 -2
- 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 +93 -78
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts +58 -0
- package/out/zero-cache/src/services/change-streamer/snapshot.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot.js +28 -18
- package/out/zero-cache/src/services/change-streamer/snapshot.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +3 -2
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +308 -353
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +3 -2
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +85 -87
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/heapz.js +21 -25
- package/out/zero-cache/src/services/heapz.js.map +1 -1
- package/out/zero-cache/src/services/http-service.d.ts +5 -5
- package/out/zero-cache/src/services/http-service.d.ts.map +1 -1
- package/out/zero-cache/src/services/http-service.js +57 -59
- package/out/zero-cache/src/services/http-service.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts +1 -1
- package/out/zero-cache/src/services/life-cycle.d.ts.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +216 -255
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +76 -130
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts +1 -1
- package/out/zero-cache/src/services/litestream/commands.d.ts.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +202 -154
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/error.js +11 -6
- package/out/zero-cache/src/services/mutagen/error.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +2 -1
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +271 -267
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +202 -2
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +354 -348
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/change-processor.js +483 -497
- package/out/zero-cache/src/services/replicator/change-processor.js.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/incremental-sync.js +97 -97
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -1
- package/out/zero-cache/src/services/replicator/notifier.js +28 -52
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -0
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +113 -83
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replicator.js +33 -26
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js +74 -86
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/constants.js +5 -7
- package/out/zero-cache/src/services/replicator/schema/constants.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +2 -2
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +70 -74
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -1
- package/out/zero-cache/src/services/run-ast.d.ts +9 -3
- package/out/zero-cache/src/services/run-ast.d.ts.map +1 -1
- package/out/zero-cache/src/services/run-ast.js +91 -78
- package/out/zero-cache/src/services/run-ast.js.map +1 -1
- package/out/zero-cache/src/services/runner.d.ts +1 -1
- package/out/zero-cache/src/services/runner.d.ts.map +1 -1
- package/out/zero-cache/src/services/runner.js +40 -40
- package/out/zero-cache/src/services/runner.js.map +1 -1
- package/out/zero-cache/src/services/running-state.d.ts +1 -1
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -1
- package/out/zero-cache/src/services/running-state.js +122 -119
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/statz.js +184 -162
- package/out/zero-cache/src/services/statz.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/active-users-gauge.js +56 -42
- 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 +307 -298
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +80 -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.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js +110 -96
- package/out/zero-cache/src/services/view-syncer/cvr-purger.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +6 -5
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +676 -611
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +4 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +643 -694
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +38 -60
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/inspect-handler.js +175 -85
- 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 +23 -22
- 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 +584 -461
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +229 -277
- 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.d.ts +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +79 -131
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/init.js +207 -131
- package/out/zero-cache/src/services/view-syncer/schema/init.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +4 -4
- package/out/zero-cache/src/services/view-syncer/schema/types.js +265 -257
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +5 -5
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +309 -337
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js +13 -7
- package/out/zero-cache/src/services/view-syncer/ttl-clock.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +5 -4
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +1514 -1311
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js +30 -21
- package/out/zero-cache/src/types/error-with-level.js.map +1 -1
- package/out/zero-cache/src/types/http.js +27 -14
- package/out/zero-cache/src/types/http.js.map +1 -1
- package/out/zero-cache/src/types/lexi-version.js +46 -31
- package/out/zero-cache/src/types/lexi-version.js.map +1 -1
- package/out/zero-cache/src/types/lite.js +118 -125
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/names.js +6 -3
- package/out/zero-cache/src/types/names.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.js +74 -68
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.js +17 -72
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/pg.d.ts +1 -1
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +213 -233
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +2 -2
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js +95 -143
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/profiler.js +29 -30
- package/out/zero-cache/src/types/profiler.js.map +1 -1
- package/out/zero-cache/src/types/row-key.js +30 -68
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/schema-versions.js +25 -19
- package/out/zero-cache/src/types/schema-versions.js.map +1 -1
- package/out/zero-cache/src/types/shards.js +50 -36
- package/out/zero-cache/src/types/shards.js.map +1 -1
- package/out/zero-cache/src/types/sql.js +9 -13
- package/out/zero-cache/src/types/sql.js.map +1 -1
- package/out/zero-cache/src/types/streams.js +245 -254
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/strings.js +14 -11
- package/out/zero-cache/src/types/strings.js.map +1 -1
- package/out/zero-cache/src/types/subscription.js +200 -259
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/url-params.js +35 -30
- package/out/zero-cache/src/types/url-params.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +5 -4
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +68 -76
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.js +56 -59
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connect-params.d.ts +1 -0
- package/out/zero-cache/src/workers/connect-params.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connect-params.js +46 -40
- package/out/zero-cache/src/workers/connect-params.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +282 -243
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js +24 -0
- package/out/zero-cache/src/workers/mutator.js.map +1 -0
- package/out/zero-cache/src/workers/replicator.d.ts +1 -1
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -1
- package/out/zero-cache/src/workers/replicator.js +103 -106
- package/out/zero-cache/src/workers/replicator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +181 -147
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts +3 -3
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +192 -169
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +199 -0
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -0
- package/out/zero-client/src/client/bindings.d.ts +13 -0
- package/out/zero-client/src/client/bindings.d.ts.map +1 -0
- package/out/zero-client/src/client/client-error-kind-enum.d.ts +12 -12
- package/out/zero-client/src/client/client-error-kind-enum.d.ts.map +1 -1
- package/out/zero-client/src/client/client-error-kind-enum.js +29 -0
- package/out/zero-client/src/client/client-error-kind-enum.js.map +1 -0
- package/out/zero-client/src/client/connection-manager.d.ts +20 -40
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +310 -0
- package/out/zero-client/src/client/connection-manager.js.map +1 -0
- package/out/zero-client/src/client/connection-status-enum.js +15 -0
- package/out/zero-client/src/client/connection-status-enum.js.map +1 -0
- package/out/zero-client/src/client/connection.d.ts +48 -5
- package/out/zero-client/src/client/connection.d.ts.map +1 -1
- package/out/zero-client/src/client/connection.js +110 -0
- package/out/zero-client/src/client/connection.js.map +1 -0
- package/out/zero-client/src/client/context.d.ts +9 -10
- package/out/zero-client/src/client/context.d.ts.map +1 -1
- package/out/zero-client/src/client/context.js +104 -0
- package/out/zero-client/src/client/context.js.map +1 -0
- package/out/zero-client/src/client/crud-impl.d.ts +11 -0
- package/out/zero-client/src/client/crud-impl.d.ts.map +1 -0
- package/out/zero-client/src/client/crud-impl.js +102 -0
- package/out/zero-client/src/client/crud-impl.js.map +1 -0
- package/out/zero-client/src/client/crud.d.ts +17 -47
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/crud.js +143 -0
- package/out/zero-client/src/client/crud.js.map +1 -0
- package/out/zero-client/src/client/custom.d.ts +52 -25
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +87 -0
- package/out/zero-client/src/client/custom.js.map +1 -0
- package/out/zero-client/src/client/delete-clients-manager.d.ts +2 -2
- package/out/zero-client/src/client/delete-clients-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/delete-clients-manager.js +98 -0
- package/out/zero-client/src/client/delete-clients-manager.js.map +1 -0
- package/out/zero-client/src/client/enable-analytics.js +18 -0
- package/out/zero-client/src/client/enable-analytics.js.map +1 -0
- package/out/zero-client/src/client/error.d.ts +30 -12
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js +148 -0
- package/out/zero-client/src/client/error.js.map +1 -0
- package/out/zero-client/src/client/http-string.js +11 -0
- package/out/zero-client/src/client/http-string.js.map +1 -0
- package/out/zero-client/src/client/inspector/client-group.js +27 -0
- package/out/zero-client/src/client/inspector/client-group.js.map +1 -0
- package/out/zero-client/src/client/inspector/client.js +28 -0
- package/out/zero-client/src/client/inspector/client.js.map +1 -0
- package/out/zero-client/src/client/inspector/html-dialog-prompt.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js +77 -0
- package/out/zero-client/src/client/inspector/html-dialog-prompt.js.map +1 -0
- package/out/zero-client/src/client/inspector/inspector.d.ts +8 -3
- package/out/zero-client/src/client/inspector/inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/inspector.js +54 -0
- package/out/zero-client/src/client/inspector/inspector.js.map +1 -0
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts +4 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/lazy-inspector.js +243 -0
- package/out/zero-client/src/client/inspector/lazy-inspector.js.map +1 -0
- package/out/zero-client/src/client/inspector/query.d.ts.map +1 -1
- package/out/zero-client/src/client/inspector/query.js +82 -0
- package/out/zero-client/src/client/inspector/query.js.map +1 -0
- package/out/zero-client/src/client/ivm-branch.d.ts +4 -4
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/ivm-branch.js +156 -0
- package/out/zero-client/src/client/ivm-branch.js.map +1 -0
- package/out/zero-client/src/client/keys.js +45 -0
- package/out/zero-client/src/client/keys.js.map +1 -0
- package/out/zero-client/src/client/log-options.js +60 -0
- package/out/zero-client/src/client/log-options.js.map +1 -0
- package/out/zero-client/src/client/make-mutate-property.d.ts +40 -0
- package/out/zero-client/src/client/make-mutate-property.d.ts.map +1 -0
- package/out/zero-client/src/client/make-mutate-property.js +33 -0
- package/out/zero-client/src/client/make-mutate-property.js.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts +34 -0
- package/out/zero-client/src/client/make-replicache-mutators.d.ts.map +1 -0
- package/out/zero-client/src/client/make-replicache-mutators.js +108 -0
- package/out/zero-client/src/client/make-replicache-mutators.js.map +1 -0
- package/out/zero-client/src/client/metric-name-enum.js +15 -0
- package/out/zero-client/src/client/metric-name-enum.js.map +1 -0
- package/out/zero-client/src/client/metrics.d.ts +2 -2
- package/out/zero-client/src/client/metrics.d.ts.map +1 -1
- package/out/zero-client/src/client/metrics.js +249 -0
- package/out/zero-client/src/client/metrics.js.map +1 -0
- package/out/zero-client/src/client/mutation-tracker.d.ts +12 -4
- package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +363 -0
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -0
- package/out/zero-client/src/client/mutator-proxy.d.ts +16 -0
- package/out/zero-client/src/client/mutator-proxy.d.ts.map +1 -0
- package/out/zero-client/src/client/mutator-proxy.js +143 -0
- package/out/zero-client/src/client/mutator-proxy.js.map +1 -0
- package/out/zero-client/src/client/options.d.ts +70 -10
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js +11 -0
- package/out/zero-client/src/client/options.js.map +1 -0
- package/out/zero-client/src/client/query-manager.d.ts +9 -2
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.js +377 -0
- package/out/zero-client/src/client/query-manager.js.map +1 -0
- package/out/zero-client/src/client/reload-error-handler.d.ts +4 -4
- package/out/zero-client/src/client/reload-error-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/reload-error-handler.js +114 -0
- package/out/zero-client/src/client/reload-error-handler.js.map +1 -0
- package/out/zero-client/src/client/server-option.js +64 -0
- package/out/zero-client/src/client/server-option.js.map +1 -0
- package/out/zero-client/src/client/update-needed-reason-type-enum.js +9 -0
- package/out/zero-client/src/client/update-needed-reason-type-enum.js.map +1 -0
- package/out/zero-client/src/client/version.js +5 -0
- package/out/zero-client/src/client/version.js.map +1 -0
- package/out/zero-client/src/client/zero-poke-handler.d.ts +4 -4
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +303 -0
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -0
- package/out/zero-client/src/client/zero-rep.d.ts +3 -2
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.js +72 -0
- package/out/zero-client/src/client/zero-rep.js.map +1 -0
- package/out/zero-client/src/client/zero.d.ts +119 -28
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +1800 -0
- package/out/zero-client/src/client/zero.js.map +1 -0
- package/out/zero-client/src/mod.d.ts +23 -20
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-client/src/types/query-result.d.ts +5 -4
- package/out/zero-client/src/types/query-result.d.ts.map +1 -1
- package/out/zero-client/src/util/nanoid.js +21 -0
- package/out/zero-client/src/util/nanoid.js.map +1 -0
- package/out/zero-client/src/util/socket.js +7 -0
- package/out/zero-client/src/util/socket.js.map +1 -0
- package/out/zero-events/src/status.d.ts +1 -1
- package/out/zero-events/src/status.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.d.ts +238 -1
- package/out/zero-protocol/src/analyze-query-result.d.ts.map +1 -1
- package/out/zero-protocol/src/analyze-query-result.js +159 -24
- package/out/zero-protocol/src/analyze-query-result.js.map +1 -1
- package/out/zero-protocol/src/application-error.d.ts +2 -8
- package/out/zero-protocol/src/application-error.d.ts.map +1 -1
- package/out/zero-protocol/src/application-error.js +35 -34
- package/out/zero-protocol/src/application-error.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +2 -2
- package/out/zero-protocol/src/ast.js +296 -277
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.d.ts +2 -2
- package/out/zero-protocol/src/change-desired-queries.js +11 -7
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.d.ts +2 -2
- package/out/zero-protocol/src/client-schema.d.ts.map +1 -1
- package/out/zero-protocol/src/client-schema.js +40 -26
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.js +11 -18
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +4 -4
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +50 -51
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.d.ts +4 -4
- package/out/zero-protocol/src/custom-queries.js +61 -39
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.js +9 -4
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/delete-clients.js +16 -9
- package/out/zero-protocol/src/delete-clients.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +107 -7
- package/out/zero-protocol/src/down.d.ts.map +1 -1
- package/out/zero-protocol/src/down.js +20 -4
- package/out/zero-protocol/src/down.js.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.js +41 -23
- package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
- package/out/zero-protocol/src/error-origin-enum.js +9 -4
- package/out/zero-protocol/src/error-origin-enum.js.map +1 -1
- package/out/zero-protocol/src/error-reason-enum.js +17 -8
- package/out/zero-protocol/src/error-reason-enum.js.map +1 -1
- package/out/zero-protocol/src/error.d.ts +17 -17
- package/out/zero-protocol/src/error.js +151 -89
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/inspect-down.d.ts +321 -21
- package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +72 -54
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.d.ts +10 -6
- package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +39 -26
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.js +9 -5
- package/out/zero-protocol/src/mutation-id.js.map +1 -1
- package/out/zero-protocol/src/mutation-type-enum.js +7 -3
- package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +16 -17
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.js +9 -4
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.js +55 -72
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.js +9 -4
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/primary-key.js +19 -5
- package/out/zero-protocol/src/primary-key.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +2 -2
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +7 -58
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/pull.js +26 -19
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +4 -4
- package/out/zero-protocol/src/push.js +179 -176
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.d.ts +3 -3
- package/out/zero-protocol/src/queries-patch.js +29 -22
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-hash.js +18 -14
- package/out/zero-protocol/src/query-hash.js.map +1 -1
- package/out/zero-protocol/src/row-patch.js +29 -20
- package/out/zero-protocol/src/row-patch.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +6 -5
- package/out/zero-protocol/src/up.d.ts.map +1 -1
- package/out/zero-protocol/src/up.js +18 -4
- package/out/zero-protocol/src/up.js.map +1 -1
- package/out/zero-protocol/src/version.js +9 -4
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/bindings.d.ts +2 -0
- package/out/zero-react/src/bindings.d.ts.map +1 -0
- package/out/zero-react/src/mod.d.ts +2 -13
- package/out/zero-react/src/mod.d.ts.map +1 -1
- package/out/zero-react/src/use-connection-state.d.ts +9 -0
- package/out/zero-react/src/use-connection-state.d.ts.map +1 -0
- package/out/zero-react/src/use-connection-state.js +14 -0
- package/out/zero-react/src/use-connection-state.js.map +1 -0
- package/out/zero-react/src/use-query.d.ts +5 -9
- package/out/zero-react/src/use-query.d.ts.map +1 -1
- package/out/zero-react/src/use-query.js +289 -0
- package/out/zero-react/src/use-query.js.map +1 -0
- package/out/zero-react/src/use-zero-online.d.ts +1 -1
- package/out/zero-react/src/use-zero-online.js +14 -0
- package/out/zero-react/src/use-zero-online.js.map +1 -0
- package/out/zero-react/src/zero-provider.d.ts +19 -10
- package/out/zero-react/src/zero-provider.d.ts.map +1 -1
- package/out/zero-react/src/zero-provider.js +77 -0
- package/out/zero-react/src/zero-provider.js.map +1 -0
- package/out/zero-react/src/zero.d.ts +2 -0
- package/out/zero-react/src/zero.d.ts.map +1 -0
- package/out/zero-schema/src/builder/relationship-builder.js +22 -19
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.d.ts +1 -3
- package/out/zero-schema/src/builder/schema-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/schema-builder.js +81 -71
- package/out/zero-schema/src/builder/schema-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +117 -116
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/compiled-permissions.d.ts +22 -2
- package/out/zero-schema/src/compiled-permissions.d.ts.map +1 -1
- package/out/zero-schema/src/compiled-permissions.js +24 -19
- package/out/zero-schema/src/compiled-permissions.js.map +1 -1
- package/out/zero-schema/src/name-mapper.js +43 -38
- package/out/zero-schema/src/name-mapper.js.map +1 -1
- package/out/zero-schema/src/permissions.d.ts +12 -9
- package/out/zero-schema/src/permissions.d.ts.map +1 -1
- package/out/zero-schema/src/permissions.js +193 -0
- package/out/zero-schema/src/permissions.js.map +1 -0
- package/out/zero-schema/src/schema-config.d.ts +1 -6
- package/out/zero-schema/src/schema-config.d.ts.map +1 -1
- package/out/zero-schema/src/schema-config.js +35 -51
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-server/src/adapters/drizzle.d.ts +2 -2
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js +84 -97
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts +8 -2
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js +54 -74
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts +7 -2
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js +40 -54
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/custom.d.ts +48 -19
- package/out/zero-server/src/custom.d.ts.map +1 -1
- package/out/zero-server/src/custom.js +278 -106
- package/out/zero-server/src/custom.js.map +1 -1
- package/out/zero-server/src/logging.js +7 -4
- package/out/zero-server/src/logging.js.map +1 -1
- package/out/zero-server/src/mod.d.ts +1 -1
- package/out/zero-server/src/mod.d.ts.map +1 -1
- package/out/zero-server/src/pg-query-executor.d.ts +11 -0
- package/out/zero-server/src/pg-query-executor.d.ts.map +1 -0
- package/out/zero-server/src/pg-query-executor.js +20 -0
- package/out/zero-server/src/pg-query-executor.js.map +1 -0
- package/out/zero-server/src/process-mutations.d.ts +13 -13
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js +328 -272
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/push-processor.d.ts +5 -3
- package/out/zero-server/src/push-processor.d.ts.map +1 -1
- package/out/zero-server/src/push-processor.js +50 -32
- package/out/zero-server/src/push-processor.js.map +1 -1
- package/out/zero-server/src/queries/process-queries.d.ts +76 -3
- package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
- package/out/zero-server/src/queries/process-queries.js +104 -93
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-server/src/schema.d.ts +2 -2
- package/out/zero-server/src/schema.d.ts.map +1 -1
- package/out/zero-server/src/schema.js +136 -124
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts +9 -6
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js +56 -51
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/bindings.d.ts +2 -0
- package/out/zero-solid/src/bindings.d.ts.map +1 -0
- package/out/zero-solid/src/mod.d.ts +1 -9
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +3 -5
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/{solid.js → zero-solid/src/solid-view.js} +47 -196
- package/out/zero-solid/src/solid-view.js.map +1 -0
- package/out/zero-solid/src/{use-zero-connection-state.d.ts → use-connection-state.d.ts} +3 -3
- package/out/zero-solid/src/use-connection-state.d.ts.map +1 -0
- package/out/zero-solid/src/use-connection-state.js +17 -0
- package/out/zero-solid/src/use-connection-state.js.map +1 -0
- package/out/zero-solid/src/use-query.d.ts +4 -7
- package/out/zero-solid/src/use-query.d.ts.map +1 -1
- package/out/zero-solid/src/use-query.js +92 -0
- package/out/zero-solid/src/use-query.js.map +1 -0
- package/out/zero-solid/src/use-zero-online.d.ts +1 -1
- package/out/zero-solid/src/use-zero-online.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero-online.js +15 -0
- package/out/zero-solid/src/use-zero-online.js.map +1 -0
- package/out/zero-solid/src/use-zero.d.ts +22 -11
- package/out/zero-solid/src/use-zero.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero.js +86 -0
- package/out/zero-solid/src/use-zero.js.map +1 -0
- package/out/zero-solid/src/zero.d.ts +2 -0
- package/out/zero-solid/src/zero.d.ts.map +1 -0
- package/out/zero-types/src/default-types.d.ts +38 -0
- package/out/zero-types/src/default-types.d.ts.map +1 -0
- package/out/zero-types/src/format.js +7 -4
- package/out/zero-types/src/format.js.map +1 -1
- package/out/zero-types/src/name-mapper.js +43 -40
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zero-types/src/schema.d.ts +4 -4
- package/out/zero-types/src/server-schema.d.ts.map +1 -0
- package/out/zql/src/builder/builder.d.ts +10 -2
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +474 -427
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/debug-delegate.d.ts +4 -0
- package/out/zql/src/builder/debug-delegate.d.ts.map +1 -1
- package/out/zql/src/builder/debug-delegate.js +68 -47
- package/out/zql/src/builder/debug-delegate.js.map +1 -1
- package/out/zql/src/builder/filter.js +132 -138
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/builder/like.js +44 -51
- package/out/zql/src/builder/like.js.map +1 -1
- package/out/zql/src/error.d.ts +5 -0
- package/out/zql/src/error.d.ts.map +1 -1
- package/out/zql/src/error.js +9 -6
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/array-view.d.ts +2 -2
- package/out/zql/src/ivm/array-view.d.ts.map +1 -1
- package/out/zql/src/ivm/array-view.js +89 -92
- package/out/zql/src/ivm/array-view.js.map +1 -1
- package/out/zql/src/ivm/constraint.js +74 -127
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts +7 -2
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js +53 -87
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/exists.d.ts +6 -4
- package/out/zql/src/ivm/exists.d.ts.map +1 -1
- package/out/zql/src/ivm/exists.js +206 -244
- package/out/zql/src/ivm/exists.js.map +1 -1
- package/out/zql/src/ivm/fan-in.d.ts +5 -3
- package/out/zql/src/ivm/fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-in.js +58 -52
- package/out/zql/src/ivm/fan-in.js.map +1 -1
- package/out/zql/src/ivm/fan-out.d.ts +4 -2
- package/out/zql/src/ivm/fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/fan-out.js +56 -48
- package/out/zql/src/ivm/fan-out.js.map +1 -1
- package/out/zql/src/ivm/filter-operators.d.ts +13 -11
- package/out/zql/src/ivm/filter-operators.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-operators.js +91 -88
- package/out/zql/src/ivm/filter-operators.js.map +1 -1
- package/out/zql/src/ivm/filter-push.d.ts +2 -1
- package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-push.js +27 -24
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/filter.d.ts +4 -2
- package/out/zql/src/ivm/filter.d.ts.map +1 -1
- package/out/zql/src/ivm/filter.js +36 -32
- package/out/zql/src/ivm/filter.js.map +1 -1
- package/out/zql/src/ivm/flipped-join.d.ts +1 -2
- package/out/zql/src/ivm/flipped-join.d.ts.map +1 -1
- package/out/zql/src/ivm/flipped-join.js +372 -325
- package/out/zql/src/ivm/flipped-join.js.map +1 -1
- package/out/zql/src/ivm/join-utils.d.ts +9 -2
- package/out/zql/src/ivm/join-utils.d.ts.map +1 -1
- package/out/zql/src/ivm/join-utils.js +104 -78
- package/out/zql/src/ivm/join-utils.js.map +1 -1
- package/out/zql/src/ivm/join.d.ts +3 -16
- package/out/zql/src/ivm/join.d.ts.map +1 -1
- package/out/zql/src/ivm/join.js +225 -211
- package/out/zql/src/ivm/join.js.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -1
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js +26 -24
- package/out/zql/src/ivm/maybe-split-and-push-edit-change.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +9 -8
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +484 -491
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/memory-storage.js +32 -31
- package/out/zql/src/ivm/memory-storage.js.map +1 -1
- package/out/zql/src/ivm/operator.d.ts +15 -12
- package/out/zql/src/ivm/operator.d.ts.map +1 -1
- package/out/zql/src/ivm/operator.js +16 -9
- package/out/zql/src/ivm/operator.js.map +1 -1
- package/out/zql/src/ivm/push-accumulated.d.ts +2 -2
- package/out/zql/src/ivm/push-accumulated.d.ts.map +1 -1
- package/out/zql/src/ivm/push-accumulated.js +236 -305
- package/out/zql/src/ivm/push-accumulated.js.map +1 -1
- package/out/zql/src/ivm/skip.d.ts +2 -3
- package/out/zql/src/ivm/skip.d.ts.map +1 -1
- package/out/zql/src/ivm/skip.js +95 -106
- package/out/zql/src/ivm/skip.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +18 -8
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.d.ts +2 -0
- package/out/zql/src/ivm/stream.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js +12 -17
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/take.d.ts +2 -3
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js +525 -451
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +4 -4
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +213 -132
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/union-fan-out.d.ts +2 -3
- package/out/zql/src/ivm/union-fan-out.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-out.js +43 -45
- package/out/zql/src/ivm/union-fan-out.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +247 -217
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/ivm/view.d.ts +3 -2
- package/out/zql/src/ivm/view.d.ts.map +1 -1
- package/out/zql/src/mutate/crud.d.ts +116 -0
- package/out/zql/src/mutate/crud.d.ts.map +1 -0
- package/out/zql/src/mutate/crud.js +41 -0
- package/out/zql/src/mutate/crud.js.map +1 -0
- package/out/zql/src/mutate/custom.d.ts +39 -63
- package/out/zql/src/mutate/custom.d.ts.map +1 -1
- package/out/zql/src/mutate/custom.js +12 -8
- package/out/zql/src/mutate/custom.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts +112 -0
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator-registry.js +88 -0
- package/out/zql/src/mutate/mutator-registry.js.map +1 -0
- package/out/zql/src/mutate/mutator.d.ts +94 -0
- package/out/zql/src/mutate/mutator.d.ts.map +1 -0
- package/out/zql/src/mutate/mutator.js +34 -0
- package/out/zql/src/mutate/mutator.js.map +1 -0
- package/out/zql/src/planner/planner-builder.d.ts +2 -1
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -1
- package/out/zql/src/planner/planner-builder.js +239 -148
- package/out/zql/src/planner/planner-builder.js.map +1 -1
- package/out/zql/src/planner/planner-connection.d.ts +14 -15
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -1
- package/out/zql/src/planner/planner-connection.js +205 -247
- package/out/zql/src/planner/planner-connection.js.map +1 -1
- package/out/zql/src/planner/planner-constraint.js +8 -11
- package/out/zql/src/planner/planner-constraint.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts +39 -44
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js +227 -161
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-fan-in.d.ts.map +1 -1
- package/out/zql/src/planner/planner-fan-in.js +157 -159
- package/out/zql/src/planner/planner-fan-in.js.map +1 -1
- package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -1
- package/out/zql/src/planner/planner-fan-out.js +73 -59
- package/out/zql/src/planner/planner-fan-out.js.map +1 -1
- package/out/zql/src/planner/planner-graph.d.ts +10 -9
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -1
- package/out/zql/src/planner/planner-graph.js +323 -357
- package/out/zql/src/planner/planner-graph.js.map +1 -1
- package/out/zql/src/planner/planner-join.d.ts +7 -3
- package/out/zql/src/planner/planner-join.d.ts.map +1 -1
- package/out/zql/src/planner/planner-join.js +239 -322
- package/out/zql/src/planner/planner-join.js.map +1 -1
- package/out/zql/src/planner/planner-node.d.ts +6 -1
- package/out/zql/src/planner/planner-node.d.ts.map +1 -1
- package/out/zql/src/planner/planner-node.js +8 -2
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-source.js +23 -12
- package/out/zql/src/planner/planner-source.js.map +1 -1
- package/out/zql/src/planner/planner-terminus.js +28 -27
- package/out/zql/src/planner/planner-terminus.js.map +1 -1
- package/out/zql/src/query/complete-ordering.d.ts +5 -0
- package/out/zql/src/query/complete-ordering.d.ts.map +1 -0
- package/out/zql/src/query/complete-ordering.js +71 -0
- package/out/zql/src/query/complete-ordering.js.map +1 -0
- package/out/zql/src/query/create-builder.d.ts +10 -0
- package/out/zql/src/query/create-builder.d.ts.map +1 -0
- package/out/zql/src/query/create-builder.js +32 -0
- package/out/zql/src/query/create-builder.js.map +1 -0
- package/out/zql/src/query/error.js +12 -8
- package/out/zql/src/query/error.js.map +1 -1
- package/out/zql/src/query/escape-like.js +7 -0
- package/out/zql/src/query/escape-like.js.map +1 -0
- package/out/zql/src/query/expression.d.ts +5 -5
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js +153 -151
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/measure-push-operator.d.ts +2 -3
- package/out/zql/src/query/measure-push-operator.d.ts.map +1 -1
- package/out/zql/src/query/measure-push-operator.js +39 -35
- package/out/zql/src/query/measure-push-operator.js.map +1 -1
- package/out/zql/src/query/metrics-delegate.js +9 -5
- package/out/zql/src/query/metrics-delegate.js.map +1 -1
- package/out/zql/src/query/named.d.ts +21 -12
- package/out/zql/src/query/named.d.ts.map +1 -1
- package/out/zql/src/query/named.js +46 -64
- package/out/zql/src/query/named.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +120 -0
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -0
- package/out/zql/src/query/query-delegate-base.js +250 -0
- package/out/zql/src/query/query-delegate-base.js.map +1 -0
- package/out/zql/src/query/query-delegate.d.ts +27 -4
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +30 -52
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +393 -459
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query-internals.d.ts +68 -0
- package/out/zql/src/query/query-internals.d.ts.map +1 -0
- package/out/zql/src/query/query-internals.js +11 -0
- package/out/zql/src/query/query-internals.js.map +1 -0
- package/out/zql/src/query/query-registry.d.ts +239 -0
- package/out/zql/src/query/query-registry.d.ts.map +1 -0
- package/out/zql/src/query/query-registry.js +121 -0
- package/out/zql/src/query/query-registry.js.map +1 -0
- package/out/zql/src/query/query.d.ts +65 -242
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts +22 -0
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -0
- package/out/zql/src/query/runnable-query-impl.js +60 -0
- package/out/zql/src/query/runnable-query-impl.js.map +1 -0
- package/out/zql/src/query/schema-query.d.ts +7 -0
- package/out/zql/src/query/schema-query.d.ts.map +1 -0
- package/out/zql/src/query/static-query.d.ts +3 -25
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.js +18 -32
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/ttl.js +69 -62
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zql/src/query/validate-input.d.ts +15 -0
- package/out/zql/src/query/validate-input.d.ts.map +1 -0
- package/out/zql/src/query/validate-input.js +24 -0
- package/out/zql/src/query/validate-input.js.map +1 -0
- package/out/zqlite/src/database-storage.d.ts +1 -1
- package/out/zqlite/src/database-storage.d.ts.map +1 -1
- package/out/zqlite/src/database-storage.js +99 -102
- package/out/zqlite/src/database-storage.js.map +1 -1
- package/out/zqlite/src/db.d.ts +2 -1
- package/out/zqlite/src/db.d.ts.map +1 -1
- package/out/zqlite/src/db.js +241 -192
- package/out/zqlite/src/db.js.map +1 -1
- package/out/zqlite/src/explain-queries.js +13 -16
- package/out/zqlite/src/explain-queries.js.map +1 -1
- package/out/zqlite/src/internal/sql-inline.d.ts +13 -0
- package/out/zqlite/src/internal/sql-inline.d.ts.map +1 -0
- package/out/zqlite/src/internal/sql-inline.js +45 -0
- package/out/zqlite/src/internal/sql-inline.js.map +1 -0
- package/out/zqlite/src/internal/sql.js +15 -10
- package/out/zqlite/src/internal/sql.js.map +1 -1
- package/out/zqlite/src/internal/statement-cache.js +86 -110
- package/out/zqlite/src/internal/statement-cache.js.map +1 -1
- package/out/zqlite/src/query-builder.js +172 -143
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts +5 -19
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js +56 -70
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.js +97 -121
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -1
- package/out/zqlite/src/sqlite-stat-fanout.d.ts +121 -0
- package/out/zqlite/src/sqlite-stat-fanout.d.ts.map +1 -0
- package/out/zqlite/src/sqlite-stat-fanout.js +301 -0
- package/out/zqlite/src/sqlite-stat-fanout.js.map +1 -0
- package/out/zqlite/src/table-source.d.ts +18 -6
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +443 -311
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +32 -29
- package/out/chunk-424PT5DM.js +0 -23
- package/out/chunk-424PT5DM.js.map +0 -7
- package/out/chunk-AFADJQ2O.js +0 -1
- package/out/chunk-AFADJQ2O.js.map +0 -7
- package/out/chunk-ASRS2LFV.js.map +0 -7
- package/out/chunk-ECUMGQGC.js.map +0 -7
- package/out/chunk-EZM3XBAB.js.map +0 -7
- package/out/chunk-QZSBDHTA.js +0 -18337
- package/out/chunk-QZSBDHTA.js.map +0 -7
- package/out/chunk-TJFNGO7E.js +0 -4126
- package/out/chunk-TJFNGO7E.js.map +0 -7
- package/out/chunk-VZOYWIRW.js +0 -30
- package/out/chunk-VZOYWIRW.js.map +0 -7
- package/out/chunk-YTVU4GOY.js +0 -372
- package/out/chunk-YTVU4GOY.js.map +0 -7
- package/out/chunk-ZZXMKAAG.js.map +0 -7
- package/out/expo-sqlite.js +0 -11
- package/out/expo-sqlite.js.map +0 -7
- package/out/inspector-IU2HG74I.js +0 -43
- package/out/inspector-IU2HG74I.js.map +0 -7
- package/out/lazy-inspector-OXIFYSSQ.js +0 -574
- package/out/lazy-inspector-OXIFYSSQ.js.map +0 -7
- package/out/op-sqlite.js.map +0 -7
- package/out/react-native.js +0 -25
- package/out/react-native.js.map +0 -7
- package/out/react.js +0 -479
- package/out/react.js.map +0 -7
- package/out/shared/src/enum.js +0 -2
- package/out/shared/src/enum.js.map +0 -1
- package/out/shared/src/expand.js +0 -2
- package/out/shared/src/expand.js.map +0 -1
- package/out/shared/src/immutable.js +0 -2
- package/out/shared/src/immutable.js.map +0 -1
- package/out/shared/src/types.js +0 -2
- package/out/shared/src/types.js.map +0 -1
- package/out/shared/src/writable.js +0 -2
- package/out/shared/src/writable.js.map +0 -1
- package/out/solid.js.map +0 -7
- package/out/sqlite.js +0 -15
- package/out/sqlite.js.map +0 -7
- package/out/zero/package.json +0 -194
- package/out/zero/src/server/change-streamer.js +0 -2
- package/out/zero/src/server/change-streamer.js.map +0 -1
- package/out/zero/src/server/main.js +0 -2
- package/out/zero/src/server/main.js.map +0 -1
- package/out/zero/src/server/reaper.js +0 -2
- package/out/zero/src/server/reaper.js.map +0 -1
- package/out/zero/src/server/replicator.js +0 -2
- package/out/zero/src/server/replicator.js.map +0 -1
- package/out/zero/src/server/runner/main.js +0 -2
- package/out/zero/src/server/runner/main.js.map +0 -1
- package/out/zero/src/server/syncer.js +0 -2
- package/out/zero/src/server/syncer.js.map +0 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput.types.js +0 -4
- package/out/zero-cache/src/services/change-source/pg/logical-replication/pgoutput.types.js.map +0 -1
- package/out/zero-cache/src/services/change-source/protocol/mod.js +0 -5
- package/out/zero-cache/src/services/change-source/protocol/mod.js.map +0 -1
- package/out/zero-cache/src/services/service.js +0 -2
- package/out/zero-cache/src/services/service.js.map +0 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.d.ts +0 -32
- package/out/zero-cache/src/services/view-syncer/key-columns.d.ts.map +0 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.js +0 -75
- package/out/zero-cache/src/services/view-syncer/key-columns.js.map +0 -1
- package/out/zero-cache/src/types/satisfies.js +0 -2
- package/out/zero-cache/src/types/satisfies.js.map +0 -1
- package/out/zero-client/src/client/on-error.d.ts +0 -15
- package/out/zero-client/src/client/on-error.d.ts.map +0 -1
- package/out/zero-client/src/client/zero-log-context.d.ts +0 -7
- package/out/zero-client/src/client/zero-log-context.d.ts.map +0 -1
- package/out/zero-events/src/index.js +0 -2
- package/out/zero-events/src/index.js.map +0 -1
- package/out/zero-events/src/json.js +0 -2
- package/out/zero-events/src/json.js.map +0 -1
- package/out/zero-events/src/status.js +0 -3
- package/out/zero-events/src/status.js.map +0 -1
- package/out/zero-pg/src/mod.js +0 -6
- package/out/zero-pg/src/mod.js.map +0 -1
- package/out/zero-protocol/src/error-kind.js +0 -3
- package/out/zero-protocol/src/error-kind.js.map +0 -1
- package/out/zero-protocol/src/error-origin.js +0 -3
- package/out/zero-protocol/src/error-origin.js.map +0 -1
- package/out/zero-protocol/src/error-reason.js +0 -3
- package/out/zero-protocol/src/error-reason.js.map +0 -1
- package/out/zero-react/src/components/inspector.d.ts +0 -8
- package/out/zero-react/src/components/inspector.d.ts.map +0 -1
- package/out/zero-react/src/components/mark-icon.d.ts +0 -3
- package/out/zero-react/src/components/mark-icon.d.ts.map +0 -1
- package/out/zero-react/src/components/zero-inspector.d.ts +0 -7
- package/out/zero-react/src/components/zero-inspector.d.ts.map +0 -1
- package/out/zero-react/src/use-zero-connection-state.d.ts +0 -9
- package/out/zero-react/src/use-zero-connection-state.d.ts.map +0 -1
- package/out/zero-schema/src/server-schema.d.ts.map +0 -1
- package/out/zero-schema/src/server-schema.js +0 -2
- package/out/zero-schema/src/server-schema.js.map +0 -1
- package/out/zero-schema/src/table-schema.js +0 -7
- package/out/zero-schema/src/table-schema.js.map +0 -1
- package/out/zero-server/src/mod.js +0 -9
- package/out/zero-server/src/mod.js.map +0 -1
- package/out/zero-server/src/query.d.ts +0 -22
- package/out/zero-server/src/query.d.ts.map +0 -1
- package/out/zero-server/src/query.js +0 -61
- package/out/zero-server/src/query.js.map +0 -1
- package/out/zero-solid/src/use-zero-connection-state.d.ts.map +0 -1
- package/out/zero-types/src/schema-value.js +0 -2
- package/out/zero-types/src/schema-value.js.map +0 -1
- package/out/zero-types/src/schema.js +0 -2
- package/out/zero-types/src/schema.js.map +0 -1
- package/out/zero.js +0 -81
- package/out/zero.js.map +0 -7
- package/out/zql/src/ivm/change.js +0 -2
- package/out/zql/src/ivm/change.js.map +0 -1
- package/out/zql/src/ivm/default-format.js +0 -2
- package/out/zql/src/ivm/default-format.js.map +0 -1
- package/out/zql/src/ivm/schema.js +0 -2
- package/out/zql/src/ivm/schema.js.map +0 -1
- package/out/zql/src/ivm/source.js +0 -2
- package/out/zql/src/ivm/source.js.map +0 -1
- package/out/zql/src/ivm/view.js +0 -2
- package/out/zql/src/ivm/view.js.map +0 -1
- package/out/zql/src/query/query-delegate.js +0 -2
- package/out/zql/src/query/query-delegate.js.map +0 -1
- package/out/zql/src/query/query.js +0 -9
- package/out/zql/src/query/query.js.map +0 -1
- package/out/zql/src/query/typed-view.js +0 -2
- package/out/zql/src/query/typed-view.js.map +0 -1
- package/out/zqlite/src/mod.js +0 -5
- package/out/zqlite/src/mod.js.map +0 -1
- /package/out/{zero-schema → zero-types}/src/server-schema.d.ts +0 -0
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../replicache/src/call-default-fetch.ts", "../../replicache/src/error-responses.ts", "../../replicache/src/http-request-info.ts", "../../replicache/src/patch-operation.ts", "../../replicache/src/get-default-puller.ts", "../../replicache/src/kv/idb-store.ts", "../../shared/src/browser-env.ts", "../../shared/src/resolved-promises.ts", "../../replicache/src/kv/write-impl-base.ts", "../../replicache/src/make-idb-name.ts", "../../shared/src/abort-error.ts", "../../shared/src/sleep.ts", "../../replicache/src/bg-interval.ts", "../../replicache/src/dag/gc.ts", "../../replicache/src/dag/key.ts", "../../replicache/src/dag/store-impl.ts", "../../replicache/src/deleted-clients.ts", "../../shared/src/navigator.ts", "../../replicache/src/kv/mem-store.ts", "../../replicache/src/kv/read-impl.ts", "../../replicache/src/kv/write-impl.ts", "../../replicache/src/kv/idb-store-with-mem-fallback.ts", "../../replicache/src/get-kv-store-provider.ts", "../../replicache/src/log-options.ts", "../../replicache/src/persist/idb-databases-store-db-name.ts", "../../replicache/src/persist/idb-databases-store.ts", "../../replicache/src/persist/collect-idb-databases.ts", "../../replicache/src/transaction-closed-error.ts", "../../shared/src/error.ts", "../../zero-protocol/src/application-error.ts", "../../zero-protocol/src/error-kind-enum.ts", "../../zero-protocol/src/error-origin-enum.ts", "../../zero-protocol/src/error-reason-enum.ts", "../../zero-protocol/src/mutation-id.ts", "../../zero-protocol/src/error.ts", "../../zero-protocol/src/custom-queries.ts", "../../zero-schema/src/builder/table-builder.ts", "../../zero-protocol/src/client-schema.ts", "../../zero-schema/src/builder/schema-builder.ts", "../../zql/src/ivm/data.ts", "../../zql/src/ivm/view-apply-change.ts", "../../zero-client/src/client/client-error-kind-enum.ts", "../../zero-client/src/client/connection-status-enum.ts", "../../zero-client/src/client/error.ts", "../../zero-client/src/client/update-needed-reason-type-enum.ts", "../../zero-client/src/client/zero.ts", "../../replicache/src/replicache-impl.ts", "../../shared/src/document-visible.ts", "../../replicache/src/connection-loop-delegates.ts", "../../replicache/src/connection-loop.ts", "../../replicache/src/dag/lazy-store.ts", "../../replicache/src/transactions.ts", "../../replicache/src/scan-iterator.ts", "../../replicache/src/scan-options.ts", "../../replicache/src/db/rebase.ts", "../../replicache/src/get-default-pusher.ts", "../../replicache/src/http-status-unauthorized.ts", "../../replicache/src/report-error.ts", "../../replicache/src/to-error.ts", "../../replicache/src/sync/handle-pull-response-result-type-enum.ts", "../../replicache/src/sync/patch.ts", "../../replicache/src/sync/pull-error.ts", "../../replicache/src/sync/sync-head-name.ts", "../../replicache/src/sync/pull.ts", "../../replicache/src/pusher.ts", "../../replicache/src/sync/push.ts", "../../replicache/src/mutation-recovery.ts", "../../shared/src/broadcast-channel.ts", "../../replicache/src/new-client-channel.ts", "../../replicache/src/on-persist-channel.ts", "../../replicache/src/pending-mutations.ts", "../../replicache/src/persist/client-gc.ts", "../../replicache/src/persist/client-group-gc.ts", "../../replicache/src/persist/heartbeat.ts", "../../replicache/src/dag/visitor.ts", "../../replicache/src/persist/gather-mem-only-visitor.ts", "../../replicache/src/persist/persist.ts", "../../replicache/src/persist/gather-not-cached-visitor.ts", "../../replicache/src/persist/refresh.ts", "../../replicache/src/process-scheduler.ts", "../../replicache/src/request-idle.ts", "../../replicache/src/set-interval-with-signal.ts", "../../replicache/src/subscriptions.ts", "../../replicache/src/invoke-kind-enum.ts", "../../replicache/src/sync/request-id.ts", "../../replicache/src/version.ts", "../../shared/src/promise-race.ts", "../../shared/src/sentinels.ts", "../../zero-protocol/src/delete-clients.ts", "../../zero-protocol/src/queries-patch.ts", "../../zero-protocol/src/connect.ts", "../../zero-protocol/src/mutation-type-enum.ts", "../../zero-protocol/src/push.ts", "../../zero-protocol/src/mutations-patch.ts", "../../zero-protocol/src/row-patch.ts", "../../zero-protocol/src/version.ts", "../../zero-protocol/src/poke.ts", "../../zero-protocol/src/pong.ts", "../../zero-protocol/src/pull.ts", "../../zero-protocol/src/down.ts", "../../zero-protocol/src/protocol-version.ts", "../../zero-types/src/name-mapper.ts", "../../zero-schema/src/name-mapper.ts", "../../zql/src/mutate/custom.ts", "../../zql/src/query/metrics-delegate.ts", "../../zql/src/query/query-impl.ts", "../../zero-protocol/src/query-hash.ts", "../../zql/src/ivm/filter-operators.ts", "../../zql/src/ivm/operator.ts", "../../zql/src/ivm/stream.ts", "../../zql/src/ivm/exists.ts", "../../zql/src/ivm/push-accumulated.ts", "../../zql/src/ivm/fan-in.ts", "../../zql/src/ivm/fan-out.ts", "../../zql/src/ivm/maybe-split-and-push-edit-change.ts", "../../zql/src/ivm/filter-push.ts", "../../zql/src/ivm/filter.ts", "../../zql/src/ivm/constraint.ts", "../../zql/src/ivm/join-utils.ts", "../../zql/src/ivm/flipped-join.ts", "../../zql/src/ivm/join.ts", "../../zql/src/ivm/skip.ts", "../../zql/src/ivm/take.ts", "../../zql/src/ivm/union-fan-in.ts", "../../zql/src/ivm/union-fan-out.ts", "../../zql/src/planner/planner-fan-in.ts", "../../zql/src/planner/planner-fan-out.ts", "../../zql/src/planner/planner-constraint.ts", "../../zql/src/planner/planner-connection.ts", "../../zql/src/planner/planner-source.ts", "../../zql/src/planner/planner-graph.ts", "../../zql/src/planner/planner-join.ts", "../../zql/src/planner/planner-terminus.ts", "../../zql/src/planner/planner-builder.ts", "../../zql/src/query/expression.ts", "../../zql/src/builder/like.ts", "../../zql/src/builder/filter.ts", "../../zql/src/builder/builder.ts", "../../zql/src/error.ts", "../../zql/src/ivm/array-view.ts", "../../zero-types/src/format.ts", "../../zql/src/query/query.ts", "../../zero-client/src/util/socket.ts", "../../zero-client/src/client/active-clients-manager.ts", "../../zero-client/src/client/connection-manager.ts", "../../shared/src/subscribable.ts", "../../zero-client/src/client/connection.ts", "../../zql/src/ivm/memory-storage.ts", "../../shared/src/btree-set.ts", "../../zql/src/query/measure-push-operator.ts", "../../zql/src/ivm/memory-source.ts", "../../zero-client/src/client/ivm-branch.ts", "../../zero-client/src/client/context.ts", "../../zero-client/src/client/crud.ts", "../../zero-client/src/client/custom.ts", "../../zero-client/src/client/delete-clients-manager.ts", "../../zero-client/src/client/enable-analytics.ts", "../../zero-client/src/client/http-string.ts", "../../zero-client/src/client/log-options.ts", "../../datadog/src/datadog-log-sink.ts", "../../zero-client/src/client/version.ts", "../../zero-client/src/client/metric-name-enum.ts", "../../zero-client/src/client/metrics.ts", "../../zero-client/src/client/mutation-tracker.ts", "../../zero-client/src/client/query-manager.ts", "../../zero-client/src/client/options.ts", "../../zero-client/src/client/reload-error-handler.ts", "../../zero-client/src/client/server-option.ts", "../../zero-client/src/client/zero-log-context.ts", "../../zero-client/src/client/zero-poke-handler.ts", "../../zero-client/src/client/zero-rep.ts"],
|
|
4
|
-
"sourcesContent": ["import type {HTTPRequestInfo} from './http-request-info.ts';\n\n/**\n * Helper function for {@link getDefaultPuller} and {@link getDefaultPusher}.\n */\nexport async function callDefaultFetch<Body>(\n url: string,\n auth: string,\n requestID: string,\n requestBody: Body,\n): Promise<readonly [Response | undefined, HTTPRequestInfo]> {\n const init = {\n headers: {\n 'Content-type': 'application/json',\n 'Authorization': auth,\n 'X-Replicache-RequestID': requestID,\n },\n body: JSON.stringify(requestBody),\n method: 'POST',\n };\n const request = new Request(url, init);\n const response = await fetch(request);\n const httpStatusCode = response.status;\n if (httpStatusCode !== 200) {\n return [\n undefined,\n {\n httpStatusCode,\n errorMessage: await response.text(),\n },\n ];\n }\n return [\n response,\n {\n httpStatusCode,\n errorMessage: '',\n },\n ];\n}\n", "import {assert} from '../../shared/src/asserts.ts';\n\nfunction isError(obj: unknown, type: string): boolean {\n return (\n typeof obj === 'object' &&\n obj !== null &&\n (obj as {error: unknown}).error === type\n );\n}\n\ntype ErrorResponse = {error: string};\n\nexport function isErrorResponse(obj: object): obj is ErrorResponse {\n return typeof (obj as {error: unknown}).error === 'string';\n}\n\n/**\n * In certain scenarios the server can signal that it does not know about the\n * client. For example, the server might have lost all of its state (this might\n * happen during the development of the server).\n */\nexport type ClientStateNotFoundResponse = {\n error: 'ClientStateNotFound';\n};\n\nexport function isClientStateNotFoundResponse(\n v: unknown,\n): v is ClientStateNotFoundResponse {\n return isError(v, 'ClientStateNotFound');\n}\n\n/**\n * The server endpoint may respond with a `VersionNotSupported` error if it does\n * not know how to handle the pull, push or schema version.\n */\nexport type VersionNotSupportedResponse = {\n error: 'VersionNotSupported';\n versionType?: 'pull' | 'push' | 'schema' | undefined;\n};\n\nexport function isVersionNotSupportedResponse(\n v: unknown,\n): v is VersionNotSupportedResponse {\n if (!isError(v, 'VersionNotSupported')) {\n return false;\n }\n\n const {versionType} = v as Record<string, unknown>;\n switch (versionType) {\n case undefined:\n case 'pull':\n case 'push':\n case 'schema':\n return true;\n }\n\n return false;\n}\n\nexport function assertVersionNotSupportedResponse(\n v: unknown,\n): asserts v is VersionNotSupportedResponse {\n assert(isVersionNotSupportedResponse(v));\n}\n", "import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\n\nexport function assertHTTPRequestInfo(\n v: unknown,\n): asserts v is HTTPRequestInfo {\n assertObject(v);\n assertNumber(v.httpStatusCode);\n assertString(v.errorMessage);\n}\n\nexport type HTTPRequestInfo = {\n httpStatusCode: number;\n errorMessage: string;\n};\n", "import {\n assertArray,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\nimport {\n type ReadonlyJSONObject,\n type ReadonlyJSONValue,\n assertJSONObject,\n assertJSONValue,\n} from '../../shared/src/json.ts';\n\nexport type PatchOperationInternal =\n | {\n readonly op: 'put';\n readonly key: string;\n readonly value: ReadonlyJSONValue;\n }\n | {\n readonly op: 'update';\n readonly key: string;\n readonly merge?: ReadonlyJSONObject | undefined;\n readonly constrain?: readonly string[] | undefined;\n }\n | {\n readonly op: 'del';\n readonly key: string;\n }\n | {\n readonly op: 'clear';\n };\n\n/**\n * This type describes the patch field in a {@link PullResponse} and it is used\n * to describe how to update the Replicache key-value store.\n */\nexport type PatchOperation =\n | {\n readonly op: 'put';\n readonly key: string;\n readonly value: ReadonlyJSONValue;\n }\n | {\n readonly op: 'del';\n readonly key: string;\n }\n | {\n readonly op: 'clear';\n };\n\nexport function assertPatchOperations(\n p: unknown,\n): asserts p is PatchOperationInternal[] {\n assertArray(p);\n for (const item of p) {\n assertPatchOperation(item);\n }\n}\n\nfunction assertPatchOperation(p: unknown): asserts p is PatchOperationInternal {\n assertObject(p);\n switch (p.op) {\n case 'put':\n assertString(p.key);\n assertJSONValue(p.value);\n break;\n case 'update':\n assertString(p.key);\n if (p.merge !== undefined) {\n assertJSONObject(p.merge);\n }\n if (p.constrain !== undefined) {\n assertArray(p.constrain);\n for (const key of p.constrain) {\n assertString(key);\n }\n }\n break;\n case 'del':\n assertString(p.key);\n break;\n case 'clear':\n break;\n default:\n throw new Error(\n `unknown patch op \\`${p.op}\\`, expected one of \\`put\\`, \\`del\\`, \\`clear\\``,\n );\n }\n}\n", "import {\n assertNumber,\n assertObject,\n assertString,\n} from '../../shared/src/asserts.ts';\nimport {callDefaultFetch} from './call-default-fetch.ts';\nimport {assertCookie} from './cookies.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport {assertHTTPRequestInfo} from './http-request-info.ts';\nimport {assertPatchOperations} from './patch-operation.ts';\nimport type {\n PullResponseV1,\n Puller,\n PullerResult,\n PullerResultV1,\n} from './puller.ts';\nimport type {PullRequest} from './sync/pull.ts';\n\n/**\n * This creates a default puller which uses HTTP POST to send the pull request.\n */\nexport function getDefaultPuller(rep: {pullURL: string; auth: string}): Puller {\n async function puller(\n requestBody: PullRequest,\n requestID: string,\n ): Promise<PullerResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pullURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n return {\n response: await response.json(),\n httpRequestInfo,\n };\n }\n\n defaultPullers.add(puller);\n return puller;\n}\n\nconst defaultPullers = new WeakSet();\n\nexport function isDefaultPuller(puller: Puller): boolean {\n return defaultPullers.has(puller);\n}\n\nexport function assertPullResponseV1(v: unknown): asserts v is PullResponseV1 {\n assertObject(v);\n if (isClientStateNotFoundResponse(v) || isVersionNotSupportedResponse(v)) {\n return;\n }\n if (v.cookie !== undefined) {\n assertCookie(v.cookie);\n }\n assertLastMutationIDChanges(v.lastMutationIDChanges);\n assertPatchOperations(v.patch);\n}\n\nfunction assertLastMutationIDChanges(\n lastMutationIDChanges: unknown,\n): asserts lastMutationIDChanges is Record<string, number> {\n assertObject(lastMutationIDChanges);\n for (const [key, value] of Object.entries(lastMutationIDChanges)) {\n assertString(key);\n assertNumber(value);\n }\n}\n\nexport function assertPullerResultV1(v: unknown): asserts v is PullerResultV1 {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPullResponseV1(v.response);\n }\n}\n", "import {resolver} from '@rocicorp/resolver';\nimport {assertNotNull} from '../../../shared/src/asserts.ts';\nimport {mustGetBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {\n storeIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\nimport {WriteImplBase, deleteSentinel} from './write-impl-base.ts';\n\nconst RELAXED = {durability: 'relaxed'} as const;\nconst OBJECT_STORE = 'chunks';\n\nexport class IDBStore implements Store {\n #db: Promise<IDBDatabase>;\n #closed = false;\n #idbDeleted = false;\n\n constructor(name: string) {\n this.#db = openDatabase(name);\n }\n\n read(): Promise<Read> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(readImpl);\n }\n\n write(): Promise<Write> {\n if (this.#closed) {\n return storeIsClosedRejection();\n }\n return this.#withReopen(writeImpl);\n }\n\n async close(): Promise<void> {\n if (!this.#idbDeleted) {\n const db = await this.#db;\n db.close();\n }\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n async #withReopen<R>(fn: (db: IDBDatabase) => R): Promise<R> {\n // Tries to reopen an IndexedDB, and rejects if the database needs\n // upgrading (is missing for whatever reason).\n const reopenExistingDB = async (name: string): Promise<IDBDatabase> => {\n const {promise, resolve, reject} = resolver<IDBDatabase>();\n const req = indexedDB.open(name);\n\n req.onupgradeneeded = () => {\n const tx = req.transaction;\n assertNotNull(tx);\n tx.abort();\n this.#idbDeleted = true;\n reject(\n new IDBNotFoundError(\n `Expected IndexedDB not found: ${name}. This likely means that the user deleted IndexedDB instances while the app was running. This is non-fatal. The app will continue running in memory until reload.`,\n ),\n );\n };\n\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n\n const db = await promise;\n db.onversionchange = () => db.close();\n return db;\n };\n\n // We abstract on `readImpl` to work around an issue in Safari. Safari does\n // not allow any microtask between a transaction is created until it is\n // first used. We used to use `await read()` here instead of `await\n // this._db` but then there is a microtask between the creation of the\n // transaction and the return of this function. By doing `await this._db`\n // here we only await the db and no await is involved with the transaction.\n // See https://github.com/jakearchibald/idb-keyval/commit/1af0a00b1a70a678d2f9cf5e74c55a22e57324c5#r55989916\n const db = await this.#db;\n\n try {\n return fn(db);\n } catch (e: unknown) {\n if (!this.#closed && e instanceof DOMException) {\n if (e.name === 'InvalidStateError') {\n this.#db = reopenExistingDB(db.name);\n const reopened = await this.#db;\n return fn(reopened);\n } else if (e.name === 'NotFoundError') {\n // This edge-case can happen if the db has been deleted and the\n // user/developer has DevTools open in certain browsers.\n // See discussion at https://github.com/rocicorp/replicache-internal/pull/216\n this.#idbDeleted = true;\n mustGetBrowserGlobal('indexedDB').deleteDatabase(db.name);\n throw new IDBNotFoundError(\n `Expected IndexedDB ${db.name} missing object store. Deleting db. This is non-fatal, the app will continue working in memory until it is reloaded.`,\n );\n }\n }\n throw e;\n }\n }\n}\n\nclass ReadImpl implements Read {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n this.#tx = tx;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).count(key);\n req.onsuccess = () => resolve(req.result > 0);\n req.onerror = () => reject(req.error);\n });\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n return new Promise((resolve, reject) => {\n const req = objectStore(this.#tx).get(key);\n req.onsuccess = () => resolve(deepFreezeAllowUndefined(req.result));\n req.onerror = () => reject(req.error);\n });\n }\n\n release(): void {\n this.#closed = true;\n // Do nothing. We rely on IDB locking.\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nclass WriteImpl extends WriteImplBase {\n readonly #tx: IDBTransaction;\n #closed = false;\n\n constructor(tx: IDBTransaction) {\n super(new ReadImpl(tx));\n this.#tx = tx;\n }\n\n commit(): Promise<void> {\n if (this.#closed) {\n return transactionIsClosedRejection();\n }\n if (this._pending.size === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n const tx = this.#tx;\n const store = objectStore(tx);\n for (const [key, val] of this._pending) {\n if (val === deleteSentinel) {\n store.delete(key);\n } else {\n store.put(val, key);\n }\n }\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n\n release(): void {\n // We rely on IDB locking so no need to do anything here.\n this.#closed = true;\n super.release();\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n\nfunction writeImpl(db: IDBDatabase): Write {\n const tx = db.transaction(OBJECT_STORE, 'readwrite', RELAXED);\n return new WriteImpl(tx);\n}\n\nfunction readImpl(db: IDBDatabase): Read {\n const tx = db.transaction(OBJECT_STORE, 'readonly');\n return new ReadImpl(tx);\n}\n\nfunction objectStore(tx: IDBTransaction): IDBObjectStore {\n return tx.objectStore(OBJECT_STORE);\n}\n\nfunction openDatabase(name: string): Promise<IDBDatabase> {\n const idb = mustGetBrowserGlobal('indexedDB');\n return new Promise((resolve, reject) => {\n const req = idb.open(name);\n req.onupgradeneeded = () => {\n req.result.createObjectStore(OBJECT_STORE);\n };\n req.onsuccess = () => {\n const db = req.result;\n // Another tab/process wants to modify the db, so release it.\n db.onversionchange = () => db.close();\n resolve(db);\n };\n req.onerror = () => reject(req.error);\n });\n}\n\n/**\n * This error is thrown when we detect that the IndexedDB has been removed. This\n * does not normally happen but can happen during development if the user has\n * DevTools open and deletes the IndexedDB from there.\n */\nexport class IDBNotFoundError extends Error {\n name = 'IDBNotFoundError';\n}\n", "// Helpers for some objects from the browser environment. These are wrapped in\n// functions because Replicache runs in environments that do not have these\n// objects (such as Web Workers, Deno etc).\n\ntype GlobalThis = typeof globalThis;\n\nconst overrides = new Map<keyof GlobalThis, GlobalThis[keyof GlobalThis]>();\n\nexport function overrideBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n value: GlobalThis[T],\n) {\n overrides.set(name, value);\n}\n\nexport function clearBrowserOverrides() {\n overrides.clear();\n}\n\nexport function getBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n if (overrides.has(name)) {\n return overrides.get(name);\n }\n return globalThis[name];\n}\n\n/**\n * Returns the global method with the given name, bound to the global object.\n * This is important because some methods (e.g. `requestAnimationFrame`) are not\n * bound to the global object by default.\n *\n * If you end up using {@linkcode getBrowserGlobal} instead in a case like this:\n *\n * ```js\n * this.#raf = getBrowserGlobal('requestAnimationFrame') ?? rafFallback;\n * ...\n * this.#raf(() => ...);\n * ```\n *\n * You will end up with `Uncaught TypeError: Illegal invocation` because `this`\n * is not bound to the global object\n */\nexport function getBrowserGlobalMethod<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] | undefined {\n return getBrowserGlobal(name)?.bind(globalThis);\n}\n\nexport function mustGetBrowserGlobal<T extends keyof GlobalThis>(\n name: T,\n): GlobalThis[T] {\n const r = getBrowserGlobal(name);\n if (r === undefined) {\n throw new Error(\n `Unsupported JavaScript environment: Could not find ${name}.`,\n );\n }\n return r;\n}\n", "export const promiseTrue = Promise.resolve(true as const);\nexport const promiseFalse = Promise.resolve(false as const);\nexport const promiseUndefined = Promise.resolve(undefined);\nexport const promiseVoid = Promise.resolve();\n\n/**\n * A promise that never resolves.\n */\nexport const promiseNever = new Promise<never>(() => {});\n", "import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {\n promiseFalse,\n promiseTrue,\n promiseVoid,\n} from '../../../shared/src/resolved-promises.ts';\nimport {\n type FrozenJSONValue,\n deepFreeze,\n deepFreezeAllowUndefined,\n} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {\n maybeTransactionIsClosedRejection,\n transactionIsClosedRejection,\n} from './throw-if-closed.ts';\n\nexport const deleteSentinel = Symbol();\ntype DeleteSentinel = typeof deleteSentinel;\n\nexport class WriteImplBase {\n protected readonly _pending: Map<string, FrozenJSONValue | DeleteSentinel> =\n new Map();\n readonly #read: Read;\n\n constructor(read: Read) {\n this.#read = read;\n }\n\n has(key: string): Promise<boolean> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n switch (this._pending.get(key)) {\n case undefined:\n return this.#read.has(key);\n case deleteSentinel:\n return promiseFalse;\n default:\n return promiseTrue;\n }\n }\n\n async get(key: string): Promise<FrozenJSONValue | undefined> {\n if (this.#read.closed) {\n return transactionIsClosedRejection();\n }\n const v = this._pending.get(key);\n switch (v) {\n case deleteSentinel:\n return undefined;\n case undefined: {\n const v = await this.#read.get(key);\n return deepFreezeAllowUndefined(v);\n }\n default:\n return v;\n }\n }\n\n put(key: string, value: ReadonlyJSONValue) {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deepFreeze(value)), promiseVoid)\n );\n }\n\n del(key: string): Promise<void> {\n return (\n maybeTransactionIsClosedRejection(this.#read) ??\n (this._pending.set(key, deleteSentinel), promiseVoid)\n );\n }\n\n release(): void {\n this.#read.release();\n }\n\n get closed(): boolean {\n return this.#read.closed;\n }\n}\n", "import * as FormatVersion from './format-version-enum.ts';\n\n/**\n * Returns the name of the IDB database that will be used for a particular Replicache instance.\n * @param name The name of the Replicache instance (i.e., the `name` field of `ReplicacheOptions`).\n * @param schemaVersion The schema version of the database (i.e., the `schemaVersion` field of `ReplicacheOptions`).\n * @returns\n */\n\nexport function makeIDBName(name: string, schemaVersion?: string): string {\n return makeIDBNameInternal(name, schemaVersion, FormatVersion.Latest);\n}\n\nfunction makeIDBNameInternal(\n name: string,\n schemaVersion: string | undefined,\n formatVersion: number,\n): string {\n const n = `rep:${name}:${formatVersion}`;\n return schemaVersion ? `${n}:${schemaVersion}` : n;\n}\n\nexport {makeIDBNameInternal as makeIDBNameForTesting};\n", "export class AbortError extends Error {\n name = 'AbortError';\n}\n", "import {resolver} from '@rocicorp/resolver';\nimport {AbortError} from './abort-error.ts';\n\nconst promiseVoid = Promise.resolve();\nconst promiseNever = new Promise<void>(() => undefined);\n\n/**\n * Creates a promise that resolves after `ms` milliseconds. Note that if you\n * pass in `0` no `setTimeout` is used and the promise resolves immediately. In\n * other words no macro task is used in that case.\n *\n * Pass in an AbortSignal to clear the timeout.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n const newAbortError = () => new AbortError('Aborted');\n\n if (signal?.aborted) {\n return Promise.reject(newAbortError());\n }\n\n if (ms === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n let handleAbort: () => void;\n if (signal) {\n handleAbort = () => {\n clearTimeout(id);\n reject(newAbortError());\n };\n signal.addEventListener('abort', handleAbort, {once: true});\n }\n\n const id = setTimeout(() => {\n resolve();\n signal?.removeEventListener('abort', handleAbort);\n }, ms);\n });\n}\n\n/**\n * Returns a pair of promises. The first promise resolves after `ms` milliseconds\n * unless the AbortSignal is aborted. The second promise resolves when the AbortSignal\n * is aborted.\n */\nexport function sleepWithAbort(\n ms: number,\n signal: AbortSignal,\n): [ok: Promise<void>, aborted: Promise<void>] {\n if (ms === 0) {\n return [promiseVoid, promiseNever];\n }\n\n const {promise: abortedPromise, resolve: abortedResolve} = resolver<void>();\n\n const sleepPromise = new Promise<void>(resolve => {\n const handleAbort = () => {\n clearTimeout(id);\n abortedResolve();\n };\n\n const id = setTimeout(() => {\n resolve();\n signal.removeEventListener('abort', handleAbort);\n }, ms);\n\n signal.addEventListener('abort', handleAbort, {once: true});\n });\n\n return [sleepPromise, abortedPromise];\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\n\nexport function initBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n void runBgIntervalProcess(processName, process, delayMs, lc, signal);\n}\n\nasync function runBgIntervalProcess(\n processName: string,\n process: () => Promise<unknown>,\n delayMs: () => number,\n lc: LogContext,\n signal: AbortSignal,\n): Promise<void> {\n if (signal.aborted) {\n return;\n }\n lc = lc.withContext('bgIntervalProcess', processName);\n lc.debug?.('Starting');\n while (!signal.aborted) {\n try {\n await sleep(delayMs(), signal);\n } catch (e) {\n if (!(e instanceof AbortError)) {\n throw e;\n }\n }\n if (!signal.aborted) {\n lc.debug?.('Running');\n try {\n await process();\n } catch (e) {\n if (signal.aborted) {\n lc.debug?.('Error running most likely due to close.', e);\n } else {\n lc.error?.('Error running.', e);\n }\n }\n }\n }\n lc.debug?.('Stopping');\n}\n", "import {assert, assertNumber} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {skipGCAsserts} from '../config.ts';\nimport {type Hash, emptyHash} from '../hash.ts';\n\nexport type HeadChange = {\n new: Hash | undefined;\n old: Hash | undefined;\n};\n\ntype LoadedRefCountPromises = Map<Hash, Promise<number>>;\n\nexport interface RefCountUpdatesDelegate {\n getRefCount: (hash: Hash) => MaybePromise<number | undefined>;\n getRefs: (hash: Hash) => MaybePromise<readonly Hash[] | undefined>;\n /**\n * Should be implemented if the store lazily loads refs, returning whether\n * or not the chunks refs have already been counted (i.e. are reflected\n * in `getRefCount`).\n *\n * If defined then:\n * - `getRefs` should return undefined for refs that have not been loaded,\n * but should never return undefined for hashes in `putChunks`.\n * - it is assumed that chunks in `putChunks` may have been reachable before\n * the write, but may not have been counted. This method is used to\n * determine if they have been counted or not. If they have not been\n * counted, and are reachable with the write applied, the returned\n * ref count updates will include updates for counting them.\n *\n * If undefined then:\n * - `getRefs` should never return undefined\n * - it is assumed that the refs of any chunks which were reachable before\n * the write are already counted\n */\n areRefsCounted?: (hash: Hash) => boolean;\n}\n\n/**\n * Computes how ref counts should be updated when a dag write is committed.\n * Does not modify the dag store.\n * @param headChanges Heads that were changed by the dag write.\n * @param putChunks Chunks that were put by the dag write.\n * @param delegate Delegate used for getting ref information from the dag store.\n * @returns Map from chunk Hash to changed ref counts. Chunks with a new ref\n * count of 0 should be deleted. All hashes in `putChunks` will have an entry\n * (which will be zero if the newly put chunk is not reachable from any head).\n */\nexport function computeRefCountUpdates(\n headChanges: Iterable<HeadChange>,\n putChunks: ReadonlySet<Hash>,\n delegate: RefCountUpdatesDelegate,\n): Promise<Map<Hash, number>> {\n return new RefCountUpdates(headChanges, putChunks, delegate).compute();\n}\n\nclass RefCountUpdates {\n readonly #newHeads: Hash[];\n readonly #oldHeads: Hash[];\n readonly #putChunks: ReadonlySet<Hash>;\n readonly #delegate: RefCountUpdatesDelegate;\n readonly #refsCounted: Set<Hash> | null;\n readonly #refCountUpdates: Map<Hash, number>;\n readonly #loadedRefCountPromises: LoadedRefCountPromises;\n readonly #isLazyDelegate: boolean;\n\n constructor(\n headChanges: Iterable<HeadChange>,\n putChunks: ReadonlySet<Hash>,\n delegate: RefCountUpdatesDelegate,\n ) {\n const newHeads: Hash[] = [];\n const oldHeads: Hash[] = [];\n for (const changedHead of headChanges) {\n if (changedHead.old !== changedHead.new) {\n changedHead.old && oldHeads.push(changedHead.old);\n changedHead.new && newHeads.push(changedHead.new);\n }\n }\n this.#newHeads = newHeads;\n this.#oldHeads = oldHeads;\n this.#putChunks = putChunks;\n this.#delegate = delegate;\n this.#refCountUpdates = new Map();\n // This map is used to ensure we do not load the ref count key more than once.\n // Once it is loaded we only operate on a cache of the ref counts.\n this.#loadedRefCountPromises = new Map();\n this.#isLazyDelegate = delegate.areRefsCounted !== undefined;\n this.#refsCounted = this.#isLazyDelegate ? new Set() : null;\n }\n\n async compute(): Promise<Map<Hash, number>> {\n for (const n of this.#newHeads) {\n await this.#changeRefCount(n, 1);\n }\n\n // Now go through the put chunks to ensure each has an entry in\n // refCountUpdates (zero for new chunks which are not reachable from\n // newHeads).\n await Promise.all(\n Array.from(this.#putChunks.values(), hash =>\n this.#ensureRefCountLoaded(hash),\n ),\n );\n\n if (this.#isLazyDelegate) {\n assert(this.#delegate.areRefsCounted);\n assert(this.#refsCounted);\n let refCountsUpdated;\n do {\n refCountsUpdated = false;\n for (const hash of this.#putChunks.values()) {\n if (\n !this.#delegate.areRefsCounted(hash) &&\n !this.#refsCounted.has(hash) &&\n this.#refCountUpdates.get(hash) !== 0\n ) {\n await this.#updateRefsCounts(hash, 1);\n refCountsUpdated = true;\n break;\n }\n }\n } while (refCountsUpdated);\n }\n\n for (const o of this.#oldHeads) {\n await this.#changeRefCount(o, -1);\n }\n\n if (!skipGCAsserts) {\n for (const [hash, update] of this.#refCountUpdates) {\n assert(\n update >= 0,\n `ref count update must be non-negative. ${hash}:${update}`,\n );\n }\n }\n\n return this.#refCountUpdates;\n }\n\n async #changeRefCount(hash: Hash, delta: number): Promise<void> {\n // First make sure that we have the ref count in the cache. This is async\n // because it might need to load the ref count from the store (via the delegate).\n //\n // Once we have loaded the ref count all the updates to it are sync to\n // prevent race conditions.\n await this.#ensureRefCountLoaded(hash);\n if (this.#updateRefCount(hash, delta)) {\n await this.#updateRefsCounts(hash, delta);\n }\n }\n\n async #updateRefsCounts(hash: Hash, delta: number) {\n if (hash === emptyHash) {\n return;\n }\n const refs = await this.#delegate.getRefs(hash);\n if (!skipGCAsserts) {\n assert(\n refs || (this.#isLazyDelegate && !this.#putChunks.has(hash)),\n 'refs must be defined',\n );\n }\n\n if (refs !== undefined) {\n this.#refsCounted?.add(hash);\n const ps = refs.map(ref => this.#changeRefCount(ref, delta));\n await Promise.all(ps);\n }\n }\n\n #ensureRefCountLoaded(hash: Hash): Promise<number> {\n // Only get the ref count once.\n let p = this.#loadedRefCountPromises.get(hash);\n if (p === undefined) {\n p = (async () => {\n const value = (await this.#delegate.getRefCount(hash)) || 0;\n this.#refCountUpdates.set(hash, value);\n return value;\n })();\n this.#loadedRefCountPromises.set(hash, p);\n }\n return p;\n }\n\n #updateRefCount(hash: Hash, delta: number): boolean {\n const oldCount = this.#refCountUpdates.get(hash);\n assertNumber(oldCount);\n this.#refCountUpdates.set(hash, oldCount + delta);\n return (oldCount === 0 && delta === 1) || (oldCount === 1 && delta === -1);\n }\n}\n", "import {type Hash, parse as parseHash} from '../hash.ts';\nimport * as KeyType from './key-type-enum.ts';\n\nexport function chunkDataKey(hash: Hash): string {\n return `c/${hash}/d`;\n}\n\nexport function chunkMetaKey(hash: Hash): string {\n return `c/${hash}/m`;\n}\n\nexport function chunkRefCountKey(hash: Hash): string {\n return `c/${hash}/r`;\n}\n\nexport function headKey(name: string): string {\n return `h/${name}`;\n}\n\nexport type Key =\n | {\n type: KeyType.ChunkData;\n hash: Hash;\n }\n | {\n type: KeyType.ChunkMeta;\n hash: Hash;\n }\n | {\n type: KeyType.ChunkRefCount;\n hash: Hash;\n }\n | {\n type: KeyType.Head;\n name: string;\n };\n\nexport function parse(key: string): Key {\n const invalidKey = () => new Error(`Invalid key. Got \"${key}\"`);\n const hash = () => parseHash(key.substring(2, key.length - 2));\n\n // '/'\n if (key.charCodeAt(1) === 47) {\n switch (key.charCodeAt(0)) {\n // c\n case 99: {\n if (key.length < 4 || key.charCodeAt(key.length - 2) !== 47) {\n throw invalidKey();\n }\n switch (key.charCodeAt(key.length - 1)) {\n case 100: // d\n return {\n type: KeyType.ChunkData,\n hash: hash(),\n };\n case 109: // m\n return {\n type: KeyType.ChunkMeta,\n hash: hash(),\n };\n case 114: // r\n return {\n type: KeyType.ChunkRefCount,\n hash: hash(),\n };\n }\n break;\n }\n case 104: // h\n return {\n type: KeyType.Head,\n name: key.substring(2),\n };\n }\n }\n throw invalidKey();\n}\n", "import {assertNumber} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {type Hash, assertHash} from '../hash.ts';\nimport type {\n Read as KVRead,\n Store as KVStore,\n Write as KVWrite,\n} from '../kv/store.ts';\nimport {\n Chunk,\n type ChunkHasher,\n type Refs,\n assertRefs,\n createChunk,\n} from './chunk.ts';\nimport {type RefCountUpdatesDelegate, computeRefCountUpdates} from './gc.ts';\nimport {chunkDataKey, chunkMetaKey, chunkRefCountKey, headKey} from './key.ts';\nimport {type Read, type Store, type Write, mustGetChunk} from './store.ts';\n\nexport class StoreImpl implements Store {\n readonly #kv: KVStore;\n readonly #chunkHasher: ChunkHasher;\n readonly #assertValidHash: (hash: Hash) => void;\n\n constructor(\n kv: KVStore,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n this.#kv = kv;\n this.#chunkHasher = chunkHasher;\n this.#assertValidHash = assertValidHash;\n }\n\n async read(): Promise<Read> {\n return new ReadImpl(await this.#kv.read(), this.#assertValidHash);\n }\n\n async write(): Promise<Write> {\n return new WriteImpl(\n await this.#kv.write(),\n this.#chunkHasher,\n this.#assertValidHash,\n );\n }\n\n close(): Promise<void> {\n return this.#kv.close();\n }\n}\n\nexport class ReadImpl implements Read {\n protected readonly _tx: KVRead;\n readonly assertValidHash: (hash: Hash) => void;\n\n constructor(kv: KVRead, assertValidHash: (hash: Hash) => void) {\n this._tx = kv;\n this.assertValidHash = assertValidHash;\n }\n\n hasChunk(hash: Hash): Promise<boolean> {\n return this._tx.has(chunkDataKey(hash));\n }\n\n async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const data = await this._tx.get(chunkDataKey(hash));\n if (data === undefined) {\n return undefined;\n }\n\n const refsVal = await this._tx.get(chunkMetaKey(hash));\n let refs: Refs;\n if (refsVal !== undefined) {\n assertRefs(refsVal);\n refs = refsVal;\n } else {\n refs = [];\n }\n return new Chunk(hash, data, refs);\n }\n\n mustGetChunk(hash: Hash): Promise<Chunk> {\n return mustGetChunk(this, hash);\n }\n\n async getHead(name: string): Promise<Hash | undefined> {\n const data = await this._tx.get(headKey(name));\n if (data === undefined) {\n return undefined;\n }\n assertHash(data);\n return data;\n }\n\n release(): void {\n this._tx.release();\n }\n\n get closed(): boolean {\n return this._tx.closed;\n }\n}\n\ntype HeadChange = {\n new: Hash | undefined;\n old: Hash | undefined;\n};\n\nexport class WriteImpl\n extends ReadImpl\n implements Write, RefCountUpdatesDelegate\n{\n declare protected readonly _tx: KVWrite;\n readonly #chunkHasher: ChunkHasher;\n\n readonly #putChunks = new Set<Hash>();\n readonly #changedHeads = new Map<string, HeadChange>();\n\n constructor(\n kvw: KVWrite,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n super(kvw, assertValidHash);\n this.#chunkHasher = chunkHasher;\n }\n\n createChunk = <V>(data: V, refs: Refs): Chunk<V> =>\n createChunk(data, refs, this.#chunkHasher);\n\n get kvWrite(): KVWrite {\n return this._tx;\n }\n\n async putChunk(c: Chunk): Promise<void> {\n const {hash, data, meta} = c;\n // We never want to write temp hashes to the underlying store.\n this.assertValidHash(hash);\n const key = chunkDataKey(hash);\n // Commit contains InternalValue and Hash which are opaque types.\n const p1 = this._tx.put(key, data as ReadonlyJSONValue);\n let p2;\n if (meta.length > 0) {\n for (const h of meta) {\n this.assertValidHash(h);\n }\n p2 = this._tx.put(chunkMetaKey(hash), meta);\n }\n this.#putChunks.add(hash);\n await p1;\n await p2;\n }\n\n setHead(name: string, hash: Hash): Promise<void> {\n return this.#setHead(name, hash);\n }\n\n removeHead(name: string): Promise<void> {\n return this.#setHead(name, undefined);\n }\n\n async #setHead(name: string, hash: Hash | undefined): Promise<void> {\n const oldHash = await this.getHead(name);\n const hk = headKey(name);\n\n let p1: Promise<void>;\n if (hash === undefined) {\n p1 = this._tx.del(hk);\n } else {\n p1 = this._tx.put(hk, hash);\n }\n\n const v = this.#changedHeads.get(name);\n if (v === undefined) {\n this.#changedHeads.set(name, {new: hash, old: oldHash});\n } else {\n // Keep old if existing\n v.new = hash;\n }\n\n await p1;\n }\n\n async commit(): Promise<void> {\n const refCountUpdates = await computeRefCountUpdates(\n this.#changedHeads.values(),\n this.#putChunks,\n this,\n );\n await this.#applyRefCountUpdates(refCountUpdates);\n await this._tx.commit();\n }\n\n async getRefCount(hash: Hash): Promise<number | undefined> {\n const value = await this._tx.get(chunkRefCountKey(hash));\n if (value === undefined) {\n return undefined;\n }\n assertNumber(value);\n if (value < 0 || value > 0xffff || value !== (value | 0)) {\n throw new Error(\n `Invalid ref count ${value}. We expect the value to be a Uint16`,\n );\n }\n return value;\n }\n\n async getRefs(hash: Hash): Promise<readonly Hash[]> {\n const meta = await this._tx.get(chunkMetaKey(hash));\n if (meta === undefined) {\n return [];\n }\n assertRefs(meta);\n return meta;\n }\n\n async #applyRefCountUpdates(refCountCache: Map<Hash, number>): Promise<void> {\n const ps: Promise<void>[] = [];\n for (const [hash, count] of refCountCache) {\n if (count === 0) {\n ps.push(this.#removeAllRelatedKeys(hash));\n } else {\n const refCountKey = chunkRefCountKey(hash);\n ps.push(this._tx.put(refCountKey, count));\n }\n }\n await Promise.all(ps);\n }\n\n async #removeAllRelatedKeys(hash: Hash): Promise<void> {\n await Promise.all([\n this._tx.del(chunkDataKey(hash)),\n this._tx.del(chunkMetaKey(hash)),\n this._tx.del(chunkRefCountKey(hash)),\n ]);\n\n this.#putChunks.delete(hash);\n }\n\n release(): void {\n this._tx.release();\n }\n}\n", "import {stringCompare} from '../../shared/src/string-compare.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport type {Read, Write} from './dag/store.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getClients, setClients} from './persist/clients.ts';\nimport {\n clientGroupIDSchema,\n clientIDSchema,\n type ClientGroupID,\n type ClientID,\n} from './sync/ids.ts';\n\n/**\n * We keep track of deleted clients in the {@linkcode DELETED_CLIENTS_HEAD_NAME}\n * head.\n */\nexport const DELETED_CLIENTS_HEAD_NAME = 'deleted-clients-v2';\n\ntype ClientIDPair = {\n clientGroupID: ClientGroupID;\n clientID: ClientID;\n};\n\nexport type DeletedClients = readonly Readonly<ClientIDPair>[];\n\nexport type WritableDeletedClients = ClientIDPair[];\n\nexport const deletedClientsSchema: v.Type<DeletedClients> = v.readonlyArray(\n v.readonlyObject({\n clientGroupID: clientGroupIDSchema,\n clientID: clientIDSchema,\n }),\n);\n\nfunction compare(a: ClientIDPair, b: ClientIDPair): number {\n const cg = stringCompare(a.clientGroupID, b.clientGroupID);\n if (cg !== 0) {\n return cg;\n }\n return stringCompare(a.clientID, b.clientID);\n}\n\nexport function normalizeDeletedClients(\n deletedClients: DeletedClients,\n): DeletedClients {\n // dedupe\n return [...deletedClients]\n .sort(compare)\n .filter(\n (item, index) =>\n index === 0 ||\n compare(item, [...deletedClients].sort(compare)[index - 1]) !== 0,\n );\n}\n\nexport function mergeDeletedClients(\n a: DeletedClients,\n b: DeletedClients,\n): DeletedClients {\n const merged: WritableDeletedClients = [];\n a = normalizeDeletedClients(a);\n b = normalizeDeletedClients(b);\n for (let i = 0, j = 0; i < a.length || j < b.length; ) {\n if (i < a.length && (j >= b.length || compare(a[i], b[j]) < 0)) {\n merged.push(a[i]);\n i++;\n } else if (j < b.length && (i >= a.length || compare(b[j], a[i]) < 0)) {\n merged.push(b[j]);\n j++;\n } else {\n // equal\n merged.push(a[i]);\n i++;\n j++;\n }\n }\n return merged;\n}\n\nexport function removeFromDeletedClients(\n old: DeletedClients,\n toRemove: DeletedClients,\n): DeletedClients {\n old = normalizeDeletedClients(old);\n toRemove = normalizeDeletedClients(toRemove);\n const result: WritableDeletedClients = [];\n for (let i = 0, j = 0; i < old.length; ) {\n if (j >= toRemove.length || compare(old[i], toRemove[j]) < 0) {\n result.push(old[i]);\n i++;\n } else if (j < toRemove.length && compare(old[i], toRemove[j]) === 0) {\n // equal, skip\n i++;\n j++;\n } else {\n // old[i] > toRemove[j]\n j++;\n }\n }\n return result;\n}\n\nexport async function setDeletedClients(\n dagWrite: Write,\n deletedClients: DeletedClients,\n): Promise<DeletedClients> {\n // sort and dedupe\n\n const data = normalizeDeletedClients(deletedClients);\n\n const chunkData = deepFreeze(data);\n const chunk = dagWrite.createChunk(chunkData, []);\n await dagWrite.putChunk(chunk);\n await dagWrite.setHead(DELETED_CLIENTS_HEAD_NAME, chunk.hash);\n return data;\n}\n\nexport async function getDeletedClients(\n dagRead: Read,\n): Promise<DeletedClients> {\n const hash = await dagRead.getHead(DELETED_CLIENTS_HEAD_NAME);\n if (hash === undefined) {\n return [];\n }\n const chunk = await dagRead.mustGetChunk(hash);\n\n const res = v.test(chunk.data, deletedClientsSchema);\n if (!res.ok) {\n // If not ok then we ignore this. It might be in the old format but we do\n // not know the clientGroupID of the old clients.\n return [];\n }\n\n return res.value;\n}\n\n/**\n * Adds deleted clients to the {@linkcode DELETED_CLIENTS_HEAD_NAME} head.\n * @returns the new list of deleted clients (sorted and deduped).\n */\nexport async function addDeletedClients(\n dagWrite: Write,\n deletedClientsToAdd: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n\n return setDeletedClients(\n dagWrite,\n mergeDeletedClients(oldDeletedClients, deletedClientsToAdd),\n );\n}\n\nexport async function removeDeletedClients(\n dagWrite: Write,\n deletedClientsToRemove: DeletedClients,\n): Promise<DeletedClients> {\n const oldDeletedClients = await getDeletedClients(dagWrite);\n return setDeletedClients(\n dagWrite,\n removeFromDeletedClients(oldDeletedClients, deletedClientsToRemove),\n );\n}\n\nexport async function confirmDeletedClients(\n dagWrite: Write,\n deletedClientIds: readonly ClientID[],\n deletedClientGroupIds: readonly ClientGroupID[],\n): Promise<DeletedClients> {\n const deletedClientIDSet = new Set(deletedClientIds);\n const deletedClientGroupIDSet = new Set(deletedClientGroupIds);\n const oldDeletedClients = await getDeletedClients(dagWrite);\n const clients = new Map(await getClients(dagWrite));\n for (const clientID of deletedClientIds) {\n clients.delete(clientID);\n }\n for (const clientGroupID of deletedClientGroupIds) {\n for (const [clientID, client] of clients) {\n if (client.clientGroupID === clientGroupID) {\n clients.delete(clientID);\n }\n }\n }\n\n await setClients(clients, dagWrite);\n\n return setDeletedClients(\n dagWrite,\n oldDeletedClients.filter(\n ({clientGroupID, clientID}) =>\n !deletedClientGroupIDSet.has(clientGroupID) &&\n !deletedClientIDSet.has(clientID),\n ),\n );\n}\n\n/**\n * Sorts and dedupes the given array.\n */\nexport function normalize<T>(arr: readonly T[]): T[] {\n return [...new Set(arr)].sort();\n}\n", "type Navigator = {\n onLine: boolean;\n userAgent: string;\n // add more as needed\n};\n\nconst localNavigator: Navigator | undefined =\n typeof navigator !== 'undefined' ? navigator : undefined;\n\nexport {localNavigator as navigator};\n", "import {RWLock} from '@rocicorp/lock';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Read, Store, Write} from './store.ts';\nimport {throwIfStoreClosed} from './throw-if-closed.ts';\nimport {WriteImpl} from './write-impl.ts';\n\ntype StorageMap = Map<string, FrozenJSONValue>;\n\ntype Value = {readonly lock: RWLock; readonly map: StorageMap};\n\nconst stores = new Map<string, Value>();\n\nexport function clearAllNamedMemStoresForTesting(): void {\n stores.clear();\n}\n\nexport function dropMemStore(name: string): Promise<void> {\n stores.delete(name);\n return promiseVoid;\n}\n\nexport function hasMemStore(name: string): boolean {\n return stores.has(name);\n}\n\n/**\n * A named in-memory Store implementation.\n *\n * Two (or more) named memory stores with the same name will share the same\n * underlying storage. They will also share the same read/write locks, so that\n * only one write transaction can be running at the same time.\n *\n * @experimental This class is experimental and might be removed or changed\n * in the future without following semver versioning. Please be cautious.\n */\nexport class MemStore implements Store {\n readonly #map: StorageMap;\n readonly #rwLock: RWLock;\n #closed = false;\n\n constructor(name: string) {\n const entry = stores.get(name);\n let lock: RWLock;\n let map: StorageMap;\n if (entry) {\n ({lock, map} = entry);\n } else {\n lock = new RWLock();\n map = new Map();\n stores.set(name, {lock, map});\n }\n this.#rwLock = lock;\n this.#map = map;\n }\n\n async read(): Promise<Read> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.read();\n return new ReadImpl(this.#map, release);\n }\n\n async write(): Promise<Write> {\n throwIfStoreClosed(this);\n const release = await this.#rwLock.write();\n return new WriteImpl(this.#map, release);\n }\n\n close(): Promise<void> {\n this.#closed = true;\n return promiseVoid;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n}\n", "import type {FrozenJSONValue} from '../frozen-json.ts';\nimport type {Read} from './store.ts';\nimport {maybeTransactionIsClosedRejection} from './throw-if-closed.ts';\n\nexport class ReadImpl implements Read {\n readonly #map: Map<string, FrozenJSONValue>;\n readonly #release: () => void;\n #closed = false;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n this.#map = map;\n this.#release = release;\n }\n\n release() {\n this.#release();\n this.#closed = true;\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n has(key: string): Promise<boolean> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.has(key))\n );\n }\n\n get(key: string): Promise<FrozenJSONValue | undefined> {\n return (\n maybeTransactionIsClosedRejection(this) ??\n Promise.resolve(this.#map.get(key))\n );\n }\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {ReadImpl} from './read-impl.ts';\nimport type {Write} from './store.ts';\nimport {transactionIsClosedRejection} from './throw-if-closed.ts';\nimport {deleteSentinel, WriteImplBase} from './write-impl-base.ts';\n\nexport class WriteImpl extends WriteImplBase implements Write {\n readonly #map: Map<string, FrozenJSONValue>;\n\n constructor(map: Map<string, FrozenJSONValue>, release: () => void) {\n super(new ReadImpl(map, release));\n this.#map = map;\n }\n\n commit(): Promise<void> {\n if (this.closed) {\n return transactionIsClosedRejection();\n }\n\n // HOT. Do not allocate entry tuple and destructure.\n this._pending.forEach((value, key) => {\n if (value === deleteSentinel) {\n this.#map.delete(key);\n } else {\n this.#map.set(key, value);\n }\n });\n this._pending.clear();\n this.release();\n return promiseVoid;\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {navigator} from '../../../shared/src/navigator.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {IDBStore} from './idb-store.ts';\nimport {MemStore, dropMemStore} from './mem-store.ts';\nimport type {Read, Store, Write} from './store.ts';\n\n/**\n * This store uses an {@link IDBStore} by default. If the {@link IDBStore} fails\n * to open the DB with an exception that matches\n * {@link isFirefoxPrivateBrowsingError} we switch out the implementation to use\n * a {@link MemStore} instead.\n *\n * The reason this is relatively complicated is that when {@link IDBStore} is\n * created, it calls `openDatabase` synchronously, but that returns a `Promise`\n * that will reject in the case of Firefox private browsing. We don't await this\n * promise until we call `read` or `write` so we cannot do the switch until\n * then.\n */\n\nexport class IDBStoreWithMemFallback implements Store {\n readonly #lc: LogContext;\n readonly #name: string;\n #store: Store;\n constructor(lc: LogContext, name: string) {\n this.#lc = lc;\n this.#name = name;\n this.#store = new IDBStore(name);\n }\n\n read(): Promise<Read> {\n return this.#withBrainTransplant(s => s.read());\n }\n\n write(): Promise<Write> {\n return this.#withBrainTransplant(s => s.write());\n }\n\n async #withBrainTransplant<T extends Read>(\n f: (store: Store) => Promise<T>,\n ): Promise<T> {\n try {\n return await f(this.#store);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n // It is possible that we end up with multiple pending read/write and\n // they all reject. Make sure we only replace the implementation once.\n if (this.#store instanceof IDBStore) {\n this.#lc.info?.(\n 'Switching to MemStore because of Firefox private browsing error',\n );\n this.#store = new MemStore(this.#name);\n }\n return f(this.#store);\n }\n throw e;\n }\n }\n\n close(): Promise<void> {\n return this.#store.close();\n }\n\n get closed(): boolean {\n return this.#store.closed;\n }\n}\n\nfunction isFirefoxPrivateBrowsingError(e: unknown): e is DOMException {\n return (\n isFirefox() &&\n e instanceof DOMException &&\n e.name === 'InvalidStateError' &&\n e.message ===\n 'A mutation operation was attempted on a database that did not allow mutations.'\n );\n}\n\nfunction isFirefox(): boolean {\n return navigator?.userAgent?.includes('Firefox') ?? false;\n}\n\nexport function newIDBStoreWithMemFallback(\n lc: LogContext,\n name: string,\n): Store {\n if (isFirefox()) {\n return new IDBStoreWithMemFallback(lc, name);\n }\n return new IDBStore(name);\n}\n\nexport function dropIDBStoreWithMemFallback(name: string): Promise<void> {\n if (!isFirefox()) {\n return dropIDBStore(name);\n }\n try {\n return dropIDBStore(name);\n } catch (e) {\n if (isFirefoxPrivateBrowsingError(e)) {\n return dropMemStore(name);\n }\n }\n return promiseVoid;\n}\n\nfunction dropIDBStore(name: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = () => resolve();\n req.onerror = () => reject(req.error);\n });\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {\n dropIDBStoreWithMemFallback,\n newIDBStoreWithMemFallback,\n} from './kv/idb-store-with-mem-fallback.ts';\nimport {dropMemStore, MemStore} from './kv/mem-store.ts';\nimport type {StoreProvider} from './kv/store.ts';\n\nexport function getKVStoreProvider(\n lc: LogContext,\n kvStore: 'mem' | 'idb' | StoreProvider | undefined,\n): StoreProvider {\n switch (kvStore) {\n case 'idb':\n case undefined:\n return {\n create: name => newIDBStoreWithMemFallback(lc, name),\n drop: dropIDBStoreWithMemFallback,\n };\n case 'mem':\n return {\n create: name => new MemStore(name),\n drop: name => dropMemStore(name),\n };\n default:\n return kvStore;\n }\n}\n", "import {\n consoleLogSink,\n LogContext,\n TeeLogSink,\n type Context,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\n\n/**\n * Creates a LogContext\n * @param logLevel The log level to use. Default is `'info'`.\n * @param logSinks Destination for logs. Default is `[consoleLogSink]`.\n * @param context Optional: Additional information that can be associated with logs.\n * @returns A LogContext instance configured with the provided options.\n */\nexport function createLogContext(\n logLevel: LogLevel = 'info',\n logSinks: LogSink[] = [consoleLogSink],\n context?: Context,\n): LogContext {\n const logSink =\n logSinks.length === 1 ? logSinks[0] : new TeeLogSink(logSinks);\n return new LogContext(logLevel, context, logSink);\n}\n", "import {randomUint64} from '../../../shared/src/random-uint64.ts';\nimport {dropIDBStoreWithMemFallback} from '../kv/idb-store-with-mem-fallback.ts';\n\nconst IDB_DATABASES_VERSION = 0;\nconst IDB_DATABASES_DB_NAME = 'replicache-dbs-v' + IDB_DATABASES_VERSION;\n\nlet testNamespace = '';\n\n/** Namespace db name in test to isolate tests' indexeddb state. */\nexport function setupForTest(): void {\n testNamespace = randomUint64().toString(36);\n}\n\nexport function teardownForTest(): Promise<void> {\n const idbDatabasesDBName = getIDBDatabasesDBName();\n testNamespace = '';\n return dropIDBStoreWithMemFallback(idbDatabasesDBName);\n}\n\nexport function getIDBDatabasesDBName(): string {\n return testNamespace + IDB_DATABASES_DB_NAME;\n}\n", "import {\n assert,\n assertNumber,\n assertObject,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport {deepFreeze} from '../frozen-json.ts';\nimport type {CreateStore, Read, Store} from '../kv/store.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {getIDBDatabasesDBName} from './idb-databases-store-db-name.ts';\nimport {makeClientID} from './make-client-id.ts';\n\nconst DBS_KEY = 'dbs';\nconst PROFILE_ID_KEY = 'profileId';\n\n// TODO: make an opaque type\nexport type IndexedDBName = string;\n\nexport type IndexedDBDatabase = {\n readonly name: IndexedDBName;\n readonly replicacheName: string;\n readonly replicacheFormatVersion: number;\n readonly schemaVersion: string;\n readonly lastOpenedTimestampMS?: number;\n};\n\nexport type IndexedDBDatabaseRecord = {\n readonly [name: IndexedDBName]: IndexedDBDatabase;\n};\n\nfunction assertIndexedDBDatabaseRecord(\n value: unknown,\n): asserts value is IndexedDBDatabaseRecord {\n assertObject(value);\n for (const [name, db] of Object.entries(value)) {\n assertString(name);\n assertIndexedDBDatabase(db);\n assert(name === db.name);\n }\n}\n\nfunction assertIndexedDBDatabase(\n value: unknown,\n): asserts value is IndexedDBDatabase {\n assertObject(value);\n assertString(value.name);\n assertString(value.replicacheName);\n assertNumber(value.replicacheFormatVersion);\n assertString(value.schemaVersion);\n if (value.lastOpenedTimestampMS !== undefined) {\n assertNumber(value.lastOpenedTimestampMS);\n }\n}\n\nexport class IDBDatabasesStore {\n readonly #kvStore: Store;\n\n constructor(createKVStore: CreateStore) {\n this.#kvStore = createKVStore(getIDBDatabasesDBName());\n }\n\n putDatabase(db: IndexedDBDatabase): Promise<IndexedDBDatabaseRecord> {\n return this.#putDatabase({...db, lastOpenedTimestampMS: Date.now()});\n }\n\n putDatabaseForTesting(\n db: IndexedDBDatabase,\n ): Promise<IndexedDBDatabaseRecord> {\n return this.#putDatabase(db);\n }\n\n #putDatabase(db: IndexedDBDatabase): Promise<IndexedDBDatabaseRecord> {\n return withWrite(this.#kvStore, async write => {\n const oldDbRecord = await getDatabases(write);\n const dbRecord = {\n ...oldDbRecord,\n [db.name]: db,\n };\n await write.put(DBS_KEY, dbRecord);\n return dbRecord;\n });\n }\n\n clearDatabases(): Promise<void> {\n return withWrite(this.#kvStore, write => write.del(DBS_KEY));\n }\n\n deleteDatabases(names: Iterable<IndexedDBName>): Promise<void> {\n return withWrite(this.#kvStore, async write => {\n const oldDbRecord = await getDatabases(write);\n const dbRecord = {\n ...oldDbRecord,\n };\n for (const name of names) {\n delete dbRecord[name];\n }\n await write.put(DBS_KEY, dbRecord);\n });\n }\n\n getDatabases(): Promise<IndexedDBDatabaseRecord> {\n return withRead(this.#kvStore, getDatabases);\n }\n\n close(): Promise<void> {\n return this.#kvStore.close();\n }\n\n getProfileID(): Promise<string> {\n return withWrite(this.#kvStore, async write => {\n let profileId = await write.get(PROFILE_ID_KEY);\n if (profileId === undefined) {\n // Profile id is 'p' followed by a random number.\n profileId = `p${makeClientID()}`;\n await write.put(PROFILE_ID_KEY, profileId);\n }\n assertString(profileId);\n return profileId;\n });\n }\n}\n\nasync function getDatabases(read: Read): Promise<IndexedDBDatabaseRecord> {\n let dbRecord = await read.get(DBS_KEY);\n if (!dbRecord) {\n dbRecord = deepFreeze({});\n }\n assertIndexedDBDatabaseRecord(dbRecord);\n return dbRecord;\n}\n", "import type {LogContext, LogLevel, LogSink} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport {StoreImpl} from '../dag/store-impl.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n getDeletedClients,\n mergeDeletedClients,\n normalizeDeletedClients,\n type DeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {getKVStoreProvider} from '../get-kv-store-provider.ts';\nimport {assertHash, newRandomHash} from '../hash.ts';\nimport {IDBStore} from '../kv/idb-store.ts';\nimport type {DropStore, StoreProvider} from '../kv/store.ts';\nimport {createLogContext} from '../log-options.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n} from './client-groups.ts';\nimport type {OnClientsDeleted} from './clients.ts';\nimport {getClients} from './clients.ts';\nimport type {IndexedDBDatabase} from './idb-databases-store.ts';\nimport {IDBDatabasesStore} from './idb-databases-store.ts';\n\n/**\n * How frequently to try to collect\n */\nexport const COLLECT_IDB_INTERVAL = 12 * 60 * 60 * 1000; // 12 hours\n\n/**\n * We delay the initial collection to prevent doing it at startup.\n */\nexport const INITIAL_COLLECT_IDB_DELAY = 5 * 60 * 1000; // 5 minutes\n\nexport function initCollectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n collectInterval: number,\n initialCollectDelay: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n let initial = true;\n initBgIntervalProcess(\n 'CollectIDBDatabases',\n async () => {\n await collectIDBDatabases(\n idbDatabasesStore,\n Date.now(),\n maxAge,\n kvDropStore,\n enableMutationRecovery,\n onClientsDeleted,\n );\n },\n () => {\n if (initial) {\n initial = false;\n return initialCollectDelay;\n }\n return collectInterval;\n },\n lc,\n signal,\n );\n}\n\n/**\n * Collects IDB databases that are no longer needed.\n */\nexport async function collectIDBDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n now: number,\n maxAge: number,\n kvDropStore: DropStore,\n enableMutationRecovery: boolean,\n onClientsDeleted: OnClientsDeleted,\n newDagStore = defaultNewDagStore,\n): Promise<void> {\n const databases = await idbDatabasesStore.getDatabases();\n\n const dbs = Object.values(databases);\n const collectResults = await Promise.all(\n dbs.map(\n async db =>\n [\n db.name,\n await gatherDatabaseInfoForCollect(\n db,\n now,\n maxAge,\n enableMutationRecovery,\n newDagStore,\n ),\n ] as const,\n ),\n );\n\n const dbNamesToRemove: string[] = [];\n const dbNamesToKeep: string[] = [];\n const deletedClientsToRemove: WritableDeletedClients = [];\n for (const [dbName, [canCollect, deletedClients]] of collectResults) {\n if (canCollect) {\n dbNamesToRemove.push(dbName);\n deletedClientsToRemove.push(...deletedClients);\n } else {\n dbNamesToKeep.push(dbName);\n }\n }\n\n const {errors} = await dropDatabases(\n idbDatabasesStore,\n dbNamesToRemove,\n kvDropStore,\n );\n if (errors.length) {\n throw errors[0];\n }\n\n if (deletedClientsToRemove.length > 0) {\n // Add the deleted clients to all the dbs that survived the collection.\n let allDeletedClients: DeletedClients = deletedClientsToRemove;\n for (const name of dbNamesToKeep) {\n await withWrite(newDagStore(name), async dagWrite => {\n const newDeletedClients = await addDeletedClients(\n dagWrite,\n deletedClientsToRemove,\n );\n\n allDeletedClients = mergeDeletedClients(\n allDeletedClients,\n newDeletedClients,\n );\n });\n }\n // normalize and dedupe\n const normalizedDeletedClients = normalizeDeletedClients(allDeletedClients);\n\n // Call the callback with the normalized deleted clients\n await onClientsDeleted(normalizedDeletedClients);\n }\n}\n\nasync function dropDatabaseInternal(\n name: string,\n idbDatabasesStore: IDBDatabasesStore,\n kvDropStore: DropStore,\n) {\n await kvDropStore(name);\n await idbDatabasesStore.deleteDatabases([name]);\n}\n\nasync function dropDatabases(\n idbDatabasesStore: IDBDatabasesStore,\n namesToRemove: string[],\n kvDropStore: DropStore,\n): Promise<{dropped: string[]; errors: unknown[]}> {\n // Try to remove the databases in parallel. Don't let a single reject fail the\n // other ones. We will check for failures afterwards.\n const dropStoreResults = await Promise.allSettled(\n namesToRemove.map(async name => {\n await dropDatabaseInternal(name, idbDatabasesStore, kvDropStore);\n return name;\n }),\n );\n\n const dropped: string[] = [];\n const errors: unknown[] = [];\n for (const result of dropStoreResults) {\n if (result.status === 'fulfilled') {\n dropped.push(result.value);\n } else {\n errors.push(result.reason);\n }\n }\n\n return {dropped, errors};\n}\n\nfunction defaultNewDagStore(name: string): Store {\n const perKvStore = new IDBStore(name);\n return new StoreImpl(perKvStore, newRandomHash, assertHash);\n}\n\n/**\n * If the database is older than maxAge and there are no pending mutations we\n * return `true` and an array of the deleted clients in that db. If the database is\n * too new or there are pending mutations we return `[false]`.\n */\nfunction gatherDatabaseInfoForCollect(\n db: IndexedDBDatabase,\n now: number,\n maxAge: number,\n enableMutationRecovery: boolean,\n newDagStore: typeof defaultNewDagStore,\n): MaybePromise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n if (db.replicacheFormatVersion > FormatVersion.Latest) {\n return [false];\n }\n\n // 0 is used in testing\n assert(db.lastOpenedTimestampMS !== undefined);\n\n // - For DD31 we can delete the database if it is older than maxAge and\n // there are no pending mutations.\n if (now - db.lastOpenedTimestampMS < maxAge) {\n return [false];\n }\n // If increase the format version we need to decide how to deal with this\n // logic.\n assert(\n db.replicacheFormatVersion === FormatVersion.DD31 ||\n db.replicacheFormatVersion === FormatVersion.V6 ||\n db.replicacheFormatVersion === FormatVersion.V7,\n );\n return canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery,\n newDagStore(db.name),\n );\n}\n\n/**\n * Options for `dropDatabase` and `dropAllDatabases`.\n */\nexport type DropDatabaseOptions = {\n /**\n * Allows providing a custom implementation of the underlying storage layer.\n * Default is `'idb'`.\n */\n kvStore?: 'idb' | 'mem' | StoreProvider | undefined;\n /**\n * Determines how much logging to do. When this is set to `'debug'`,\n * Replicache will also log `'info'` and `'error'` messages. When set to\n * `'info'` we log `'info'` and `'error'` but not `'debug'`. When set to\n * `'error'` we only log `'error'` messages.\n * Default is `'info'`.\n */\n logLevel?: LogLevel | undefined;\n /**\n * Enables custom handling of logs.\n *\n * By default logs are logged to the console. If you would like logs to be\n * sent elsewhere (e.g. to a cloud logging service like DataDog) you can\n * provide an array of {@link LogSink}s. Logs at or above\n * {@link DropDatabaseOptions.logLevel} are sent to each of these {@link LogSink}s.\n * If you would still like logs to go to the console, include\n * `consoleLogSink` in the array.\n *\n * ```ts\n * logSinks: [consoleLogSink, myCloudLogSink],\n * ```\n * Default is `[consoleLogSink]`.\n */\n logSinks?: LogSink[] | undefined;\n};\n\n/**\n * Drops the specified database.\n * @param dbName The name of the database to drop.\n * @param opts Options for dropping the database.\n */\nexport async function dropDatabase(dbName: string, opts?: DropDatabaseOptions) {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropDatabase: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n await dropDatabaseInternal(\n dbName,\n new IDBDatabasesStore(kvStoreProvider.create),\n kvStoreProvider.drop,\n );\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n */\nexport async function dropAllDatabases(opts?: DropDatabaseOptions): Promise<{\n dropped: string[];\n errors: unknown[];\n}> {\n const logContext = createLogContext(opts?.logLevel, opts?.logSinks, {\n dropAllDatabases: undefined,\n });\n const kvStoreProvider = getKVStoreProvider(logContext, opts?.kvStore);\n const store = new IDBDatabasesStore(kvStoreProvider.create);\n const databases = await store.getDatabases();\n const dbNames = Object.values(databases).map(db => db.name);\n return dropDatabases(store, dbNames, kvStoreProvider.drop);\n}\n\n/**\n * Deletes all IndexedDB data associated with Replicache.\n *\n * Returns an object with the names of the successfully dropped databases\n * and any errors encountered while dropping.\n *\n * @deprecated Use `dropAllDatabases` instead.\n */\nexport function deleteAllReplicacheData(opts?: DropDatabaseOptions) {\n return dropAllDatabases(opts);\n}\n\n/**\n * If there are pending mutations in any of the clients in this db we return\n * `[false]`. Otherwise we return `true` and an array of the deleted clients to\n * remove.\n */\nfunction canDatabaseBeCollectedAndGetDeletedClientIDs(\n enableMutationRecovery: boolean,\n perdag: Store,\n): Promise<\n [canCollect: false] | [canCollect: true, deletedClients: DeletedClients]\n> {\n return withRead(perdag, async read => {\n // If mutation recovery is disabled we do not care if there are pending\n // mutations when we decide if we can collect the database.\n if (enableMutationRecovery) {\n const clientGroups = await getClientGroups(read);\n for (const clientGroup of clientGroups.values()) {\n if (clientGroupHasPendingMutations(clientGroup)) {\n return [false];\n }\n }\n }\n\n const clients = await getClients(read);\n const existingDeletedClients = await getDeletedClients(read);\n const deletedClients: WritableDeletedClients = [...existingDeletedClients];\n\n // Add all current clients to the deleted clients list\n for (const [clientID, client] of clients) {\n deletedClients.push({\n clientID,\n clientGroupID: client.clientGroupID,\n });\n }\n\n // The normalization (deduping and sorting) will be done when storing\n return [true, deletedClients];\n });\n}\n", "/**\n * This error is thrown when you try to call methods on a closed transaction.\n */\nexport class TransactionClosedError extends Error {\n constructor() {\n super('Transaction is closed');\n }\n}\n\nexport type Closed = {closed: boolean};\n\nexport function throwIfClosed(tx: Closed): void {\n if (tx.closed) {\n throw new TransactionClosedError();\n }\n}\n\nexport function rejectIfClosed(tx: Closed): undefined | Promise<never> {\n return tx.closed ? Promise.reject(new TransactionClosedError()) : undefined;\n}\n", "import {jsonSchema} from './json-schema.ts';\nimport type {ReadonlyJSONValue} from './json.ts';\n\nexport function getErrorMessage(error: unknown): string {\n return getErrorMessageInternal(error, new Set());\n}\n\nfunction getErrorMessageInternal(error: unknown, seen: Set<unknown>): string {\n if (typeof error === 'string') {\n return error;\n }\n\n if (typeof error === 'object' && error !== null) {\n if (seen.has(error)) {\n return 'Circular error reference detected while extracting the error message.';\n }\n seen.add(error);\n }\n\n if (error instanceof Error) {\n if (error.message) {\n return error.message;\n }\n\n if ('cause' in error) {\n const cause = (error as {cause?: unknown}).cause;\n if (cause !== undefined) {\n const causeMessage = getErrorMessageInternal(cause, seen);\n if (causeMessage) {\n return causeMessage;\n }\n }\n }\n }\n\n if (\n typeof error === 'object' &&\n error !== null &&\n 'message' in error &&\n typeof (error as {message: unknown}).message === 'string'\n ) {\n const message = (error as {message: string}).message;\n if (message) {\n return message;\n }\n }\n\n try {\n const json = jsonSchema.parse(error);\n return `Parsed message: ${JSON.stringify(json)}`;\n } catch (_e) {}\n\n return `Unknown error of type ${typeof error} was thrown and the message could not be determined. See cause for details.`;\n}\n\nexport function getErrorDetails(error: unknown): ReadonlyJSONValue | undefined {\n if (error instanceof Error) {\n if ('details' in error) {\n try {\n return jsonSchema.parse(error?.details);\n } catch (_e) {}\n }\n\n if (error.name && error.name !== 'Error') {\n return {name: error.name};\n }\n\n return undefined;\n }\n\n if (typeof error === 'object' && error !== null && 'details' in error) {\n try {\n return jsonSchema.parse((error as {details: ReadonlyJSONValue})?.details);\n } catch (_e) {}\n }\n\n try {\n return jsonSchema.parse(error);\n } catch (_e) {}\n\n return undefined;\n}\n", "import {getErrorDetails, getErrorMessage} from '../../shared/src/error.ts';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\n\n/**\n * Options accepted by {@link ApplicationError}.\n *\n * Use these when you need to attach additional context to an error that will\n * be sent back to the client.\n *\n * @property details Structured data forwarded to the client alongside the\n * error. Values must be JSON-serializable so they can safely cross the network\n * boundary.\n * @property cause Optional underlying error that triggered this application\n * error. This is surfaced through the standard `cause` property for debugging\n * on the server.\n */\nexport interface ApplicationErrorOptions<\n T extends ReadonlyJSONValue | undefined,\n> {\n details?: T;\n cause?: unknown;\n}\n\n/**\n * Error type that application code can throw to surface structured metadata back to\n * the client.\n *\n * Use this when you want to return a descriptive message along with the\n * JSON-serializable `details`.\n */\nexport class ApplicationError<\n const T extends ReadonlyJSONValue | undefined = undefined,\n> extends Error {\n /**\n * This maps onto errors for transform and push app-level failures.\n */\n readonly #details: T;\n\n constructor(\n message: string,\n options?: ApplicationErrorOptions<T> | undefined,\n ) {\n super(message, {cause: options?.cause});\n this.name = 'ApplicationError';\n this.#details = options?.details ?? (undefined as T);\n }\n\n get details(): T {\n return this.#details;\n }\n}\n\nexport function isApplicationError(error: unknown): error is ApplicationError {\n return error instanceof ApplicationError;\n}\n\nexport function wrapWithApplicationError<\n T extends ReadonlyJSONValue | undefined = ReadonlyJSONValue | undefined,\n>(error: unknown): ApplicationError<T> {\n if (isApplicationError(error)) {\n return error as ApplicationError<T>;\n }\n\n const message = getErrorMessage(error);\n const details = getErrorDetails(error);\n\n return new ApplicationError<T>(message, {\n cause: error,\n details: details as T,\n });\n}\n", "// Note: Metric names depend on these values,\n// so if you add or change on here a corresponding dashboard\n// change will likely be needed.\n\nexport const AuthInvalidated = 'AuthInvalidated';\nexport const ClientNotFound = 'ClientNotFound';\nexport const InvalidConnectionRequest = 'InvalidConnectionRequest';\nexport const InvalidConnectionRequestBaseCookie =\n 'InvalidConnectionRequestBaseCookie';\nexport const InvalidConnectionRequestLastMutationID =\n 'InvalidConnectionRequestLastMutationID';\nexport const InvalidConnectionRequestClientDeleted =\n 'InvalidConnectionRequestClientDeleted';\nexport const InvalidMessage = 'InvalidMessage';\nexport const InvalidPush = 'InvalidPush';\nexport const PushFailed = 'PushFailed';\nexport const MutationFailed = 'MutationFailed';\nexport const MutationRateLimited = 'MutationRateLimited';\nexport const Rebalance = 'Rebalance';\nexport const Rehome = 'Rehome';\nexport const TransformFailed = 'TransformFailed';\nexport const Unauthorized = 'Unauthorized';\nexport const VersionNotSupported = 'VersionNotSupported';\nexport const SchemaVersionNotSupported = 'SchemaVersionNotSupported';\nexport const ServerOverloaded = 'ServerOverloaded';\nexport const Internal = 'Internal';\n\n/**\n * The app rejected the client's auth token (used in CRUD mutators).\n * @deprecated auth errors are now represented as ['error', { ... }] messages\n */\nexport type AuthInvalidated = typeof AuthInvalidated;\n/**\n * zero-cache no longer has CVR state for the client.\n */\nexport type ClientNotFound = typeof ClientNotFound;\n/**\n * Handshake metadata is invalid or incomplete.\n */\nexport type InvalidConnectionRequest = typeof InvalidConnectionRequest;\n/**\n * Client's base cookie is ahead of the replica snapshot.\n */\nexport type InvalidConnectionRequestBaseCookie =\n typeof InvalidConnectionRequestBaseCookie;\n/**\n * Client's last mutation ID is ahead of the replica.\n */\nexport type InvalidConnectionRequestLastMutationID =\n typeof InvalidConnectionRequestLastMutationID;\n/**\n * The server deleted the client.\n */\nexport type InvalidConnectionRequestClientDeleted =\n typeof InvalidConnectionRequestClientDeleted;\n/**\n * Upstream message failed schema validation or JSON parsing.\n */\nexport type InvalidMessage = typeof InvalidMessage;\n/**\n * Push payload could not be applied (version mismatch, out-of-order mutation).\n */\nexport type InvalidPush = typeof InvalidPush;\n/**\n * Push failed during processing.\n */\nexport type PushFailed = typeof PushFailed;\n/**\n * Transform failed during processing.\n */\nexport type TransformFailed = typeof TransformFailed;\n/**\n * CRUD mutator failure.\n * @deprecated\n */\nexport type MutationFailed = typeof MutationFailed;\n/**\n * CRUD mutator rate limit.\n * @deprecated\n */\nexport type MutationRateLimited = typeof MutationRateLimited;\n/**\n * Cache is rebalancing ownership.\n */\nexport type Rebalance = typeof Rebalance;\n/**\n * Replica ownership moved.\n */\nexport type Rehome = typeof Rehome;\n/**\n * JWT validation failure (used in CRUD mutators).\n * @deprecated\n */\nexport type Unauthorized = typeof Unauthorized;\n/**\n * Client requested unsupported protocol version.\n */\nexport type VersionNotSupported = typeof VersionNotSupported;\n/**\n * Client schema hash or version is outside zero-cache window.\n */\nexport type SchemaVersionNotSupported = typeof SchemaVersionNotSupported;\n/**\n * zero-cache is overloaded.\n */\nexport type ServerOverloaded = typeof ServerOverloaded;\n/**\n * Unhandled zero-cache exception.\n */\nexport type Internal = typeof Internal;\n", "export const Client = 'client';\nexport const Server = 'server';\nexport const ZeroCache = 'zeroCache';\n\nexport type Client = typeof Client;\nexport type Server = typeof Server;\nexport type ZeroCache = typeof ZeroCache;\n", "export const Database = 'database';\nexport const Parse = 'parse';\nexport const OutOfOrderMutation = 'oooMutation';\nexport const UnsupportedPushVersion = 'unsupportedPushVersion';\nexport const Internal = 'internal';\nexport const HTTP = 'http';\nexport const Timeout = 'timeout';\n\nexport type Database = typeof Database;\nexport type Parse = typeof Parse;\nexport type OutOfOrderMutation = typeof OutOfOrderMutation;\nexport type UnsupportedPushVersion = typeof UnsupportedPushVersion;\nexport type Internal = typeof Internal;\nexport type HTTP = typeof HTTP;\nexport type Timeout = typeof Timeout;\n", "import * as v from '../../shared/src/valita.ts';\n\nexport const mutationIDSchema = v.object({\n id: v.number(),\n clientID: v.string(),\n});\n\nexport type MutationID = v.Infer<typeof mutationIDSchema>;\n", "import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {mutationIDSchema} from './mutation-id.ts';\nimport {ErrorKind} from './error-kind.ts';\nimport {ErrorOrigin} from './error-origin.ts';\nimport {ErrorReason} from './error-reason.ts';\n\nconst basicErrorKindSchema = v.literalUnion(\n ErrorKind.AuthInvalidated,\n ErrorKind.ClientNotFound,\n ErrorKind.InvalidConnectionRequest,\n ErrorKind.InvalidConnectionRequestBaseCookie,\n ErrorKind.InvalidConnectionRequestLastMutationID,\n ErrorKind.InvalidConnectionRequestClientDeleted,\n ErrorKind.InvalidMessage,\n ErrorKind.InvalidPush,\n ErrorKind.MutationRateLimited,\n ErrorKind.MutationFailed,\n ErrorKind.Unauthorized,\n ErrorKind.VersionNotSupported,\n ErrorKind.SchemaVersionNotSupported,\n ErrorKind.Internal,\n);\n\nconst basicErrorBodySchema = v.object({\n kind: basicErrorKindSchema,\n message: v.string(),\n // this is optional for backwards compatibility\n origin: v.literalUnion(ErrorOrigin.Server, ErrorOrigin.ZeroCache).optional(),\n});\n\nconst backoffErrorKindSchema = v.literalUnion(\n ErrorKind.Rebalance,\n ErrorKind.Rehome,\n ErrorKind.ServerOverloaded,\n);\n\nconst backoffBodySchema = v.object({\n kind: backoffErrorKindSchema,\n message: v.string(),\n minBackoffMs: v.number().optional(),\n maxBackoffMs: v.number().optional(),\n // Query parameters to send in the next reconnect. In the event of\n // a conflict, these will be overridden by the parameters used by\n // the client; it is the responsibility of the server to avoid\n // parameter name conflicts.\n //\n // The parameters will only be added to the immediately following\n // reconnect, and not after that.\n reconnectParams: v.record(v.string()).optional(),\n origin: v.literal(ErrorOrigin.ZeroCache).optional(),\n});\n\nconst pushFailedErrorKindSchema = v.literal(ErrorKind.PushFailed);\nconst transformFailedErrorKindSchema = v.literal(ErrorKind.TransformFailed);\n\nexport const errorKindSchema: v.Type<ErrorKind> = v.union(\n basicErrorKindSchema,\n backoffErrorKindSchema,\n pushFailedErrorKindSchema,\n transformFailedErrorKindSchema,\n);\n\nconst pushFailedBaseSchema = v.object({\n kind: pushFailedErrorKindSchema,\n details: jsonSchema.optional(),\n /**\n * The mutationIDs of the mutations that failed to process.\n * This can be a subset of the mutationIDs in the request.\n */\n mutationIDs: v.array(mutationIDSchema),\n message: v.string(),\n});\n\nexport const pushFailedBodySchema = v.union(\n pushFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.Server),\n reason: v.literalUnion(\n ErrorReason.Database,\n ErrorReason.Parse,\n ErrorReason.OutOfOrderMutation,\n ErrorReason.UnsupportedPushVersion,\n ErrorReason.Internal,\n ),\n }),\n pushFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.ZeroCache),\n reason: v.literal(ErrorReason.HTTP),\n status: v.number(),\n bodyPreview: v.string().optional(),\n }),\n pushFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.ZeroCache),\n reason: v.literalUnion(\n ErrorReason.Timeout,\n ErrorReason.Parse,\n ErrorReason.Internal,\n ),\n }),\n);\n\nconst transformFailedBaseSchema = v.object({\n kind: transformFailedErrorKindSchema,\n details: jsonSchema.optional(),\n /**\n * The queryIDs of the queries that failed to transform.\n */\n queryIDs: v.array(v.string()),\n message: v.string(),\n});\n\nexport const transformFailedBodySchema = v.union(\n transformFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.Server),\n reason: v.literalUnion(\n ErrorReason.Database,\n ErrorReason.Parse,\n ErrorReason.Internal,\n ),\n }),\n transformFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.ZeroCache),\n reason: v.literal(ErrorReason.HTTP),\n status: v.number(),\n bodyPreview: v.string().optional(),\n }),\n transformFailedBaseSchema.extend({\n origin: v.literal(ErrorOrigin.ZeroCache),\n reason: v.literalUnion(\n ErrorReason.Timeout,\n ErrorReason.Parse,\n ErrorReason.Internal,\n ),\n }),\n);\n\nexport const errorBodySchema = v.union(\n basicErrorBodySchema,\n backoffBodySchema,\n pushFailedBodySchema,\n transformFailedBodySchema,\n);\n\nexport type BackoffBody = v.Infer<typeof backoffBodySchema>;\nexport type PushFailedBody = v.Infer<typeof pushFailedBodySchema>;\nexport type TransformFailedBody = v.Infer<typeof transformFailedBodySchema>;\nexport type ErrorBody = v.Infer<typeof errorBodySchema>;\n\nexport const errorMessageSchema: v.Type<ErrorMessage> = v.tuple([\n v.literal('error'),\n errorBodySchema,\n]);\n\nexport type ErrorMessage = ['error', ErrorBody];\n\n/**\n * Represents an error used across zero-client, zero-cache, and zero-server.\n */\nexport class ProtocolError<\n const T extends ErrorBody = ErrorBody,\n> extends Error {\n readonly errorBody: T;\n\n constructor(errorBody: T, options?: ErrorOptions) {\n super(errorBody.message, options);\n this.name = 'ProtocolError';\n this.errorBody = errorBody;\n }\n\n get kind(): T['kind'] {\n return this.errorBody.kind;\n }\n}\n\nexport function isProtocolError(error: unknown): error is ProtocolError {\n return error instanceof ProtocolError;\n}\n", "import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {astSchema} from './ast.ts';\nimport {transformFailedBodySchema} from './error.ts';\n\nexport const transformRequestBodySchema = v.array(\n v.object({\n id: v.string(),\n name: v.string(),\n args: v.readonly(v.array(jsonSchema)),\n }),\n);\nexport type TransformRequestBody = v.Infer<typeof transformRequestBodySchema>;\n\nexport const transformedQuerySchema = v.object({\n id: v.string(),\n name: v.string(),\n ast: astSchema,\n});\n\nexport const appErroredQuerySchema = v.object({\n error: v.literal('app'),\n id: v.string(),\n name: v.string(),\n // optional for backwards compatibility\n message: v.string().optional(),\n details: jsonSchema.optional(),\n});\nexport const parseErroredQuerySchema = v.object({\n error: v.literal('parse'),\n id: v.string(),\n name: v.string(),\n message: v.string(),\n details: jsonSchema.optional(),\n});\nexport const erroredQuerySchema = v.union(\n appErroredQuerySchema,\n parseErroredQuerySchema,\n);\nexport type ErroredQuery = v.Infer<typeof erroredQuerySchema>;\n\nexport const transformResponseBodySchema = v.array(\n v.union(transformedQuerySchema, erroredQuerySchema),\n);\nexport type TransformResponseBody = v.Infer<typeof transformResponseBodySchema>;\n\nexport const transformRequestMessageSchema = v.tuple([\n v.literal('transform'),\n transformRequestBodySchema,\n]);\nexport type TransformRequestMessage = v.Infer<\n typeof transformRequestMessageSchema\n>;\nexport const transformErrorMessageSchema = v.tuple([\n v.literal('transformError'),\n v.array(erroredQuerySchema),\n]);\nexport type TransformErrorMessage = v.Infer<typeof transformErrorMessageSchema>;\n\nconst transformFailedMessageSchema = v.tuple([\n v.literal('transformFailed'),\n transformFailedBodySchema,\n]);\nconst transformOkMessageSchema = v.tuple([\n v.literal('transformed'),\n transformResponseBodySchema,\n]);\n\nexport const transformResponseMessageSchema = v.union(\n transformOkMessageSchema,\n transformFailedMessageSchema,\n);\nexport type TransformResponseMessage = v.Infer<\n typeof transformResponseMessageSchema\n>;\n", "import type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue, TableSchema} from '../table-schema.ts';\n\n/* oxlint-disable @typescript-eslint/no-explicit-any */\nexport function table<TName extends string>(name: TName) {\n return new TableBuilder({\n name,\n columns: {},\n primaryKey: [] as any as PrimaryKey,\n });\n}\n\nexport function string<T extends string = string>() {\n return new ColumnBuilder({\n type: 'string',\n optional: false,\n customType: null as unknown as T,\n });\n}\n\nexport function number<T extends number = number>() {\n return new ColumnBuilder({\n type: 'number',\n optional: false,\n customType: null as unknown as T,\n });\n}\n\nexport function boolean<T extends boolean = boolean>() {\n return new ColumnBuilder({\n type: 'boolean',\n optional: false,\n customType: null as unknown as T,\n });\n}\n\nexport function json<T extends ReadonlyJSONValue = ReadonlyJSONValue>() {\n return new ColumnBuilder({\n type: 'json',\n optional: false,\n customType: null as unknown as T,\n });\n}\n\nexport function enumeration<T extends string>() {\n return new ColumnBuilder({\n type: 'string',\n optional: false,\n customType: null as unknown as T,\n });\n}\n\nexport const column = {\n string,\n number,\n boolean,\n json,\n enumeration,\n};\n\nexport class TableBuilder<TShape extends TableSchema> {\n readonly #schema: TShape;\n constructor(schema: TShape) {\n this.#schema = schema;\n }\n\n from<ServerName extends string>(serverName: ServerName) {\n return new TableBuilder<TShape>({\n ...this.#schema,\n // Strip the \"public.\" schema if specified, as tables in the upstream\n // \"public\" schema are created without the schema prefix on the replica.\n // See liteTableName() in zero-cache/src/types/names.ts\n serverName: serverName.startsWith('public.')\n ? serverName.substring('public.'.length)\n : serverName,\n });\n }\n\n columns<const TColumns extends Record<string, ColumnBuilder<SchemaValue>>>(\n columns: TColumns,\n ): TableBuilderWithColumns<{\n name: TShape['name'];\n columns: {[K in keyof TColumns]: TColumns[K]['schema']};\n primaryKey: TShape['primaryKey'];\n }> {\n const columnSchemas = Object.fromEntries(\n Object.entries(columns).map(([k, v]) => [k, v.schema]),\n ) as {[K in keyof TColumns]: TColumns[K]['schema']};\n return new TableBuilderWithColumns({\n ...this.#schema,\n columns: columnSchemas,\n }) as any;\n }\n}\n\nexport class TableBuilderWithColumns<TShape extends TableSchema> {\n readonly #schema: TShape;\n\n constructor(schema: TShape) {\n this.#schema = schema;\n }\n\n primaryKey<TPKColNames extends (keyof TShape['columns'])[]>(\n ...pkColumnNames: TPKColNames\n ) {\n return new TableBuilderWithColumns({\n ...this.#schema,\n primaryKey: pkColumnNames,\n });\n }\n\n get schema() {\n return this.#schema;\n }\n\n build() {\n // We can probably get the type system to throw an error if primaryKey is not called\n // before passing the schema to createSchema\n // Till then --\n if (this.#schema.primaryKey.length === 0) {\n throw new Error(`Table \"${this.#schema.name}\" is missing a primary key`);\n }\n const names = new Set<string>();\n for (const [col, {serverName}] of Object.entries(this.#schema.columns)) {\n const name = serverName ?? col;\n if (names.has(name)) {\n throw new Error(\n `Table \"${\n this.#schema.name\n }\" has multiple columns referencing \"${name}\"`,\n );\n }\n names.add(name);\n }\n return this.#schema;\n }\n}\n\nclass ColumnBuilder<TShape extends SchemaValue<any>> {\n readonly #schema: TShape;\n constructor(schema: TShape) {\n this.#schema = schema;\n }\n\n from<ServerName extends string>(serverName: ServerName) {\n return new ColumnBuilder<TShape & {serverName: string}>({\n ...this.#schema,\n serverName,\n });\n }\n\n optional(): ColumnBuilder<Omit<TShape, 'optional'> & {optional: true}> {\n return new ColumnBuilder({\n ...this.#schema,\n optional: true,\n });\n }\n\n get schema() {\n return this.#schema;\n }\n}\n\nexport type {ColumnBuilder};\n", "import {must} from '../../shared/src/must.ts';\nimport {mapAllEntries} from '../../shared/src/objects.ts';\nimport * as v from '../../shared/src/valita.ts';\n\nexport type ValueType = 'string' | 'number' | 'boolean' | 'null' | 'json';\n\nexport const valueTypeSchema: v.Type<ValueType> = v.literalUnion(\n 'string',\n 'number',\n 'boolean',\n 'null',\n 'json',\n);\n\nexport const columnSchemaSchema = v.object({\n type: valueTypeSchema,\n});\n\nexport type ColumnSchema = v.Infer<typeof columnSchemaSchema>;\n\nexport const tableSchemaSchema = v.object({\n columns: v.record(columnSchemaSchema),\n // TODO: Make this non-optional when bumping the\n // MIN_SERVER_SUPPORTED_SYNC_PROTOCOL to 30+.\n primaryKey: v.array(v.string()).optional(),\n});\n\nexport type TableSchema = v.Infer<typeof tableSchemaSchema>;\n\nexport const clientSchemaSchema = v.object({\n tables: v.record(tableSchemaSchema),\n});\n\nexport type ClientSchema = v.Infer<typeof clientSchemaSchema>;\n\nconst keyCmp = ([a]: [a: string, _: unknown], [b]: [b: string, _: unknown]) =>\n a < b ? -1 : a > b ? 1 : 0;\n\n/**\n * Returns a normalized schema (with the tables and columns sorted)\n * suitable for hashing.\n */\nexport function normalizeClientSchema(schema: ClientSchema): ClientSchema {\n return {\n tables: mapAllEntries(schema.tables, tables =>\n tables.sort(keyCmp).map(([name, table]) => [\n name,\n {\n columns: mapAllEntries(table.columns, e => e.sort(keyCmp)),\n primaryKey: must(\n table.primaryKey,\n `new clients always specify a primaryKey`,\n ).sort(),\n },\n ]),\n ),\n };\n}\n", "/* oxlint-disable @typescript-eslint/no-explicit-any */\nimport {h64} from '../../../shared/src/hash.ts';\nimport {mapEntries} from '../../../shared/src/objects.ts';\nimport {\n normalizeClientSchema,\n type ClientSchema,\n} from '../../../zero-protocol/src/client-schema.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {Relationship, TableSchema} from '../table-schema.ts';\nimport type {Relationships} from './relationship-builder.ts';\nimport {type TableBuilderWithColumns} from './table-builder.ts';\n\nexport type {Schema};\n\n/**\n * Note: the keys of the `tables` and `relationships` parameters do not matter.\n * You can assign them to any value you like. E.g.,\n *\n * ```ts\n * createSchema({rsdfgafg: table('users')...}, {sdfd: relationships(users, ...)})\n * ```\n */\nexport function createSchema<\n const TTables extends readonly TableBuilderWithColumns<TableSchema>[],\n const TRelationships extends readonly Relationships[],\n const TEnableLegacyQueries extends boolean | undefined,\n const TEnableLegacyMutators extends boolean | undefined,\n>(options: {\n readonly tables: TTables;\n readonly relationships?: TRelationships | undefined;\n /** @see Schema.enableLegacyQueries */\n readonly enableLegacyQueries?: TEnableLegacyQueries | undefined;\n /** @see Schema.enableLegacyMutators */\n readonly enableLegacyMutators?: TEnableLegacyMutators | undefined;\n}): {\n tables: {\n readonly [K in TTables[number]['schema']['name']]: Extract<\n TTables[number]['schema'],\n {name: K}\n >;\n };\n relationships: {\n readonly [K in TRelationships[number]['name']]: Extract<\n TRelationships[number],\n {name: K}\n >['relationships'];\n };\n enableLegacyQueries: TEnableLegacyQueries;\n enableLegacyMutators: TEnableLegacyMutators;\n} {\n const retTables: Record<string, TableSchema> = {};\n const retRelationships: Record<string, Record<string, Relationship>> = {};\n const serverNames = new Set<string>();\n\n options.tables.forEach(table => {\n const {serverName = table.schema.name} = table.schema;\n if (serverNames.has(serverName)) {\n throw new Error(`Multiple tables reference the name \"${serverName}\"`);\n }\n serverNames.add(serverName);\n if (retTables[table.schema.name]) {\n throw new Error(\n `Table \"${table.schema.name}\" is defined more than once in the schema`,\n );\n }\n retTables[table.schema.name] = table.build();\n });\n options.relationships?.forEach(relationships => {\n if (retRelationships[relationships.name]) {\n throw new Error(\n `Relationships for table \"${relationships.name}\" are defined more than once in the schema`,\n );\n }\n retRelationships[relationships.name] = relationships.relationships;\n checkRelationship(\n relationships.relationships,\n relationships.name,\n retTables,\n );\n });\n\n return {\n tables: retTables,\n relationships: retRelationships,\n enableLegacyQueries: options.enableLegacyQueries,\n enableLegacyMutators: options.enableLegacyMutators,\n } as any;\n}\n\nfunction checkRelationship(\n relationships: Record<string, Relationship>,\n tableName: string,\n tables: Record<string, TableSchema>,\n) {\n // TS should be able to check this for us but something is preventing it from happening.\n Object.entries(relationships).forEach(([name, rel]) => {\n let source = tables[tableName];\n if (source.columns[name] !== undefined) {\n throw new Error(\n `Relationship \"${tableName}\".\"${name}\" cannot have the same name as the column \"${name}\" on the the table \"${source.name}\"`,\n );\n }\n rel.forEach(connection => {\n if (!tables[connection.destSchema]) {\n throw new Error(\n `For relationship \"${tableName}\".\"${name}\", destination table \"${connection.destSchema}\" is missing in the schema`,\n );\n }\n if (!source.columns[connection.sourceField[0]]) {\n throw new Error(\n `For relationship \"${tableName}\".\"${name}\", the source field \"${connection.sourceField[0]}\" is missing in the table schema \"${source.name}\"`,\n );\n }\n source = tables[connection.destSchema];\n });\n });\n}\n\nexport function clientSchemaFrom(schema: Schema): {\n clientSchema: ClientSchema;\n hash: string;\n} {\n const client = {\n tables: mapEntries(\n schema.tables,\n (name, {serverName, columns, primaryKey}) => [\n serverName ?? name,\n {\n columns: mapEntries(columns, (name, {serverName, type}) => [\n serverName ?? name,\n {type},\n ]),\n primaryKey: primaryKey.map(k => columns[k].serverName ?? k),\n },\n ],\n ),\n } satisfies ClientSchema;\n const clientSchema = normalizeClientSchema(client);\n const hash = h64(JSON.stringify(clientSchema)).toString(36);\n return {clientSchema, hash};\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {\n assertBoolean,\n assertNumber,\n assertString,\n} from '../../../shared/src/asserts.ts';\nimport type {Ordering} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * A row flowing through the pipeline, plus its relationships.\n * Relationships are generated lazily as read.\n */\nexport type Node = {\n row: Row;\n relationships: Record<string, () => Stream<Node>>;\n};\n\n/**\n * Compare two values. The values must be of the same type. This function\n * throws at runtime if the types differ.\n *\n * Note, this function considers `null === null` and\n * `undefined === undefined`. This is different than SQL. In join code,\n * null must be treated separately.\n *\n * See: https://github.com/rocicorp/mono/pull/2116/files#r1704811479\n *\n * @returns < 0 if a < b, 0 if a === b, > 0 if a > b\n */\nexport function compareValues(a: Value, b: Value): number {\n a = normalizeUndefined(a);\n b = normalizeUndefined(b);\n\n if (a === b) {\n return 0;\n }\n if (a === null) {\n return -1;\n }\n if (b === null) {\n return 1;\n }\n if (typeof a === 'boolean') {\n assertBoolean(b);\n return a ? 1 : -1;\n }\n if (typeof a === 'number') {\n assertNumber(b);\n return a - b;\n }\n if (typeof a === 'string') {\n assertString(b);\n // We compare all strings in Zero as UTF-8. This is the default on SQLite\n // and we need to match it. See:\n // https://blog.replicache.dev/blog/replicache-11-adventures-in-text-encoding.\n //\n // TODO: We could change this since SQLite supports UTF-16. Microbenchmark\n // to see if there's a big win.\n //\n // https://www.sqlite.org/c3ref/create_collation.html\n return compareUTF8(a, b);\n }\n throw new Error(`Unsupported type: ${a}`);\n}\n\nexport type NormalizedValue = Exclude<Value, undefined>;\n\n/**\n * We allow undefined to be passed for the convenience of developers, but we\n * treat it equivalently to null. It's better for perf to not create an copy\n * of input values, so we just normalize at use when necessary.\n */\nexport function normalizeUndefined(v: Value): NormalizedValue {\n return v ?? null;\n}\n\nexport type Comparator = (r1: Row, r2: Row) => number;\n\nexport function makeComparator(order: Ordering, reverse?: boolean): Comparator {\n return (a, b) => {\n // Skip destructuring here since it is hot code.\n for (const ord of order) {\n const field = ord[0];\n const comp = compareValues(a[field], b[field]);\n if (comp !== 0) {\n const result = ord[1] === 'asc' ? comp : -comp;\n return reverse ? -result : result;\n }\n }\n return 0;\n };\n}\n\n/**\n * Determine if two values are equal. Note that unlike compareValues() above,\n * this function treats `null` as unequal to itself (and same for `undefined`).\n * This is required to make joins work correctly, but may not be the right\n * semantic for your application.\n */\nexport function valuesEqual(a: Value, b: Value): boolean {\n // oxlint-disable-next-line eqeqeq\n if (a == null || b == null) {\n return false;\n }\n return a === b;\n}\n\nexport function drainStreams(node: Node) {\n for (const stream of Object.values(node.relationships)) {\n for (const node of stream()) {\n drainStreams(node);\n }\n }\n}\n", "import {\n assert,\n assertArray,\n assertNumber,\n unreachable,\n} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {drainStreams, type Comparator, type Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Entry, Format} from './view.ts';\n\nexport const refCountSymbol = Symbol('rc');\nexport const idSymbol = Symbol('id');\n\ntype MetaEntry = Writable<Entry> & {\n [refCountSymbol]: number;\n [idSymbol]?: string | undefined;\n};\ntype MetaEntryList = MetaEntry[];\n\n/**\n * `applyChange` does not consume the `relationships` of `ChildChange#node`,\n * `EditChange#node` and `EditChange#oldNode`. The `ViewChange` type\n * documents and enforces this via the type system.\n */\nexport type ViewChange =\n | AddViewChange\n | RemoveViewChange\n | ChildViewChange\n | EditViewChange;\n\nexport type RowOnlyNode = {row: Row};\n\nexport type AddViewChange = {\n type: 'add';\n node: Node;\n};\n\nexport type RemoveViewChange = {\n type: 'remove';\n node: Node;\n};\n\ntype ChildViewChange = {\n type: 'child';\n node: RowOnlyNode;\n child: {\n relationshipName: string;\n change: ViewChange;\n };\n};\n\ntype EditViewChange = {\n type: 'edit';\n node: RowOnlyNode;\n oldNode: RowOnlyNode;\n};\n\n/**\n * This is a subset of WeakMap but restricted to what we need.\n * @deprecated Not used anymore. This will be removed in the future.\n */\nexport interface RefCountMap {\n get(entry: Entry): number | undefined;\n set(entry: Entry, refCount: number): void;\n delete(entry: Entry): boolean;\n}\n\nexport function applyChange(\n parentEntry: Entry,\n change: ViewChange,\n schema: SourceSchema,\n relationship: string,\n format: Format,\n withIDs = false,\n): void {\n if (schema.isHidden) {\n switch (change.type) {\n case 'add':\n case 'remove':\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n const childSchema = must(schema.relationships[relationship]);\n for (const node of children()) {\n applyChange(\n parentEntry,\n {type: change.type, node},\n childSchema,\n relationship,\n format,\n withIDs,\n );\n }\n }\n return;\n case 'edit':\n // If hidden at this level it means that the hidden row was changed. If\n // the row was changed in such a way that it would change the\n // relationships then the edit would have been split into remove and\n // add.\n return;\n case 'child': {\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n applyChange(\n parentEntry,\n change.child.change,\n childSchema,\n relationship,\n format,\n withIDs,\n );\n return;\n }\n default:\n unreachable(change);\n }\n }\n\n const {singular, relationships: childFormats} = format;\n switch (change.type) {\n case 'add': {\n let newEntry: MetaEntry | undefined;\n\n if (singular) {\n const oldEntry = parentEntry[relationship] as MetaEntry | undefined;\n if (oldEntry !== undefined) {\n assert(\n schema.compareRows(oldEntry, change.node.row) === 0,\n `Singular relationship '${relationship}' should not have multiple rows. You may need to declare this relationship with the \\`many\\` helper instead of the \\`one\\` helper in your schema.`,\n );\n // adding same again.\n oldEntry[refCountSymbol]++;\n } else {\n newEntry = makeNewMetaEntry(change.node.row, schema, withIDs, 1);\n\n (parentEntry as Writable<Entry>)[relationship] = newEntry;\n }\n } else {\n newEntry = add(\n change.node.row,\n getChildEntryList(parentEntry, relationship),\n schema,\n withIDs,\n );\n }\n\n if (newEntry) {\n for (const [relationship, children] of Object.entries(\n change.node.relationships,\n )) {\n // TODO: Is there a flag to make TypeScript complain that dictionary access might be undefined?\n const childSchema = must(schema.relationships[relationship]);\n const childFormat = childFormats[relationship];\n if (childFormat === undefined) {\n continue;\n }\n\n const newView = childFormat.singular\n ? undefined\n : ([] as MetaEntryList);\n newEntry[relationship] = newView;\n\n for (const node of children()) {\n applyChange(\n newEntry,\n {type: 'add', node},\n childSchema,\n relationship,\n childFormat,\n withIDs,\n );\n }\n }\n }\n break;\n }\n case 'remove': {\n if (singular) {\n const oldEntry = parentEntry[relationship] as MetaEntry | undefined;\n assert(oldEntry !== undefined, 'node does not exist');\n const rc = oldEntry[refCountSymbol];\n if (rc === 1) {\n (parentEntry as Writable<Entry>)[relationship] = undefined;\n }\n oldEntry[refCountSymbol]--;\n } else {\n removeAndUpdateRefCount(\n getChildEntryList(parentEntry, relationship),\n change.node.row,\n schema.compareRows,\n );\n }\n // Needed to ensure cleanup of operator state is fully done.\n drainStreams(change.node);\n break;\n }\n case 'child': {\n let existing: MetaEntry;\n if (singular) {\n existing = getSingularEntry(parentEntry, relationship);\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n existing = view[pos];\n }\n\n const childSchema = must(\n schema.relationships[change.child.relationshipName],\n );\n const childFormat = format.relationships[change.child.relationshipName];\n if (childFormat !== undefined) {\n applyChange(\n existing,\n change.child.change,\n childSchema,\n change.child.relationshipName,\n childFormat,\n withIDs,\n );\n }\n break;\n }\n case 'edit': {\n if (singular) {\n const existing = parentEntry[relationship];\n assertMetaEntry(existing);\n applyEdit(existing, change, schema, withIDs);\n } else {\n const view = getChildEntryList(parentEntry, relationship);\n // The position of the row in the list may have changed due to the edit.\n if (schema.compareRows(change.oldNode.row, change.node.row) !== 0) {\n const {pos: oldPos, found: oldFound} = binarySearch(\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n assert(oldFound, 'old node does not exist');\n const oldEntry = view[oldPos];\n const {pos, found} = binarySearch(\n view,\n change.node.row,\n schema.compareRows,\n );\n // A special case:\n // when refCount is 1 (so the row is being moved\n // without leaving a placeholder behind), and the new pos is\n // the same as the old, or directly after the old (so after the remove\n // of the old it would be in the same pos):\n // the row does not need to be moved, it can just be edited in place.\n if (\n oldEntry[refCountSymbol] === 1 &&\n (pos === oldPos || pos - 1 === oldPos)\n ) {\n applyEdit(oldEntry, change, schema, withIDs);\n } else {\n // Move the row. If the row has > 1 ref count, an edit should\n // be received for each ref count. On the first edit, the original\n // row is moved, the edit is applied to it and its ref count is set\n // to 1. A shallow copy of the row is left at the old pos for\n // processing of the remaining edit, and the copy's ref count\n // is decremented. As each edit is received the ref count of the\n // copy is decrement, and the ref count of the row at the new\n // position is incremented. When the copy's ref count goes to 0,\n // it is removed.\n oldEntry[refCountSymbol]--;\n let adjustedPos = pos;\n if (oldEntry[refCountSymbol] === 0) {\n view.splice(oldPos, 1);\n adjustedPos = oldPos < pos ? pos - 1 : pos;\n }\n\n let entryToEdit;\n if (found) {\n entryToEdit = view[adjustedPos];\n } else {\n view.splice(adjustedPos, 0, oldEntry);\n entryToEdit = oldEntry;\n if (oldEntry[refCountSymbol] > 0) {\n const oldEntryCopy = {...oldEntry};\n view[oldPos] = oldEntryCopy;\n }\n }\n entryToEdit[refCountSymbol]++;\n applyEdit(entryToEdit, change, schema, withIDs);\n }\n } else {\n // Position could not have changed, so simply edit in place.\n const {pos, found} = binarySearch(\n view,\n change.oldNode.row,\n schema.compareRows,\n );\n assert(found, 'node does not exist');\n applyEdit(view[pos], change, schema, withIDs);\n }\n }\n\n break;\n }\n default:\n unreachable(change);\n }\n}\n\nfunction applyEdit(\n existing: MetaEntry,\n change: EditViewChange,\n schema: SourceSchema,\n withIDs: boolean,\n) {\n Object.assign(existing, change.node.row);\n if (withIDs) {\n existing[idSymbol] = makeID(change.node.row, schema);\n }\n}\n\nfunction add(\n row: Row,\n view: MetaEntryList,\n schema: SourceSchema,\n withIDs: boolean,\n): MetaEntry | undefined {\n const {pos, found} = binarySearch(view, row, schema.compareRows);\n\n if (found) {\n view[pos][refCountSymbol]++;\n return undefined;\n }\n const newEntry = makeNewMetaEntry(row, schema, withIDs, 1);\n view.splice(pos, 0, newEntry);\n return newEntry;\n}\n\nfunction removeAndUpdateRefCount(\n view: MetaEntryList,\n row: Row,\n compareRows: Comparator,\n): MetaEntry {\n const {pos, found} = binarySearch(view, row, compareRows);\n assert(found, 'node does not exist');\n const oldEntry = view[pos];\n const rc = oldEntry[refCountSymbol];\n if (rc === 1) {\n view.splice(pos, 1);\n }\n oldEntry[refCountSymbol]--;\n\n return oldEntry;\n}\n\n// TODO: Do not return an object. It puts unnecessary pressure on the GC.\nfunction binarySearch(\n view: MetaEntryList,\n target: Row,\n comparator: Comparator,\n) {\n let low = 0;\n let high = view.length - 1;\n while (low <= high) {\n const mid = (low + high) >>> 1;\n const comparison = comparator(view[mid] as Row, target as Row);\n if (comparison < 0) {\n low = mid + 1;\n } else if (comparison > 0) {\n high = mid - 1;\n } else {\n return {pos: mid, found: true};\n }\n }\n return {pos: low, found: false};\n}\n\nfunction getChildEntryList(\n parentEntry: Entry,\n relationship: string,\n): MetaEntryList {\n const view = parentEntry[relationship];\n assertArray(view);\n return view as MetaEntryList;\n}\n\nfunction assertMetaEntry(v: unknown): asserts v is MetaEntry {\n assertNumber((v as Partial<MetaEntry>)[refCountSymbol]);\n}\n\nfunction getSingularEntry(parentEntry: Entry, relationship: string): MetaEntry {\n const e = parentEntry[relationship];\n assertNumber((e as Partial<MetaEntry>)[refCountSymbol]);\n return e as MetaEntry;\n}\n\nfunction makeNewMetaEntry(\n row: Row,\n schema: SourceSchema,\n withIDs: boolean,\n rc: number,\n): MetaEntry {\n if (withIDs) {\n return {...row, [refCountSymbol]: rc, [idSymbol]: makeID(row, schema)};\n }\n return {...row, [refCountSymbol]: rc};\n}\nfunction makeID(row: Row, schema: SourceSchema) {\n // optimization for case of non-compound primary key\n if (schema.primaryKey.length === 1) {\n return JSON.stringify(row[schema.primaryKey[0]]);\n }\n return JSON.stringify(schema.primaryKey.map(k => row[k]));\n}\n", "export const AbruptClose = 'AbruptClose';\nexport const CleanClose = 'CleanClose';\nexport const ClientClosed = 'ClientClosed';\nexport const ConnectTimeout = 'ConnectTimeout';\nexport const DisconnectTimeout = 'DisconnectTimeout';\nexport const UnexpectedBaseCookie = 'UnexpectedBaseCookie';\nexport const PingTimeout = 'PingTimeout';\nexport const PullTimeout = 'PullTimeout';\nexport const Hidden = 'Hidden';\nexport const NoSocketOrigin = 'NoSocketOrigin';\nexport const InvalidMessage = 'InvalidMessage';\nexport const UserDisconnect = 'UserDisconnect';\nexport const Internal = 'Internal';\n\nexport type AbruptClose = typeof AbruptClose;\nexport type CleanClose = typeof CleanClose;\nexport type ClientClosed = typeof ClientClosed;\nexport type ConnectTimeout = typeof ConnectTimeout;\nexport type DisconnectTimeout = typeof DisconnectTimeout;\nexport type UnexpectedBaseCookie = typeof UnexpectedBaseCookie;\nexport type PingTimeout = typeof PingTimeout;\nexport type PullTimeout = typeof PullTimeout;\nexport type Hidden = typeof Hidden;\nexport type NoSocketOrigin = typeof NoSocketOrigin;\nexport type InvalidMessage = typeof InvalidMessage;\nexport type UserDisconnect = typeof UserDisconnect;\nexport type Internal = typeof Internal;\n", "export const Disconnected = 'disconnected';\nexport const Connecting = 'connecting';\nexport const Connected = 'connected';\nexport const NeedsAuth = 'needs-auth';\nexport const Error = 'error';\nexport const Closed = 'closed';\n\nexport type Disconnected = typeof Disconnected;\nexport type Connecting = typeof Connecting;\nexport type Connected = typeof Connected;\nexport type NeedsAuth = typeof NeedsAuth;\nexport type Error = typeof Error;\nexport type Closed = typeof Closed;\n", "import {unreachable} from '../../../shared/src/asserts.ts';\nimport type {Expand} from '../../../shared/src/expand.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {\n type BackoffBody,\n type ErrorBody,\n isProtocolError,\n ProtocolError,\n type PushFailedBody,\n type TransformFailedBody,\n} from '../../../zero-protocol/src/error.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {ConnectionStatus} from './connection-status.ts';\n\nexport type ZeroError = ProtocolError<ErrorBody> | ClientError;\nexport type ZeroErrorBody = Expand<ErrorBody | ClientErrorBody>;\nexport type ZeroErrorKind = Expand<ErrorKind | ClientErrorKind>;\nexport type AuthError = ProtocolError<NeedsAuthReason>;\n\nexport type NeedsAuthReason = Expand<\n | (ErrorBody & {\n kind: ErrorKind.AuthInvalidated | ErrorKind.Unauthorized;\n })\n | (Extract<PushFailedBody, {reason: ErrorReason.HTTP}> & {status: 401 | 403})\n | (Extract<TransformFailedBody, {reason: ErrorReason.HTTP}> & {\n status: 401 | 403;\n })\n>;\n\nexport type ClientErrorBody = {\n kind: ClientErrorKind;\n origin: typeof ErrorOrigin.Client;\n message: string;\n};\n\n/**\n * Represents an error encountered by the client.\n */\nexport class ClientError<\n const T extends Omit<ClientErrorBody, 'origin'> = Omit<\n ClientErrorBody,\n 'origin'\n >,\n> extends Error {\n readonly errorBody: {origin: typeof ErrorOrigin.Client} & T;\n\n constructor(errorBody: T, options?: ErrorOptions) {\n super(errorBody.message, options);\n this.name = 'ClientError';\n this.errorBody = {...errorBody, origin: ErrorOrigin.Client};\n }\n\n get kind(): T['kind'] {\n return this.errorBody.kind;\n }\n}\n\nexport function isServerError(ex: unknown): ex is ProtocolError<ErrorBody> {\n return (\n isProtocolError(ex) &&\n (ex.errorBody.origin === ErrorOrigin.Server ||\n ex.errorBody.origin === ErrorOrigin.ZeroCache)\n );\n}\n\nexport function isAuthError(ex: unknown): ex is AuthError {\n if (isServerError(ex)) {\n if (\n ex.kind === ErrorKind.AuthInvalidated ||\n ex.kind === ErrorKind.Unauthorized\n ) {\n return true;\n }\n if (\n (ex.errorBody.kind === ErrorKind.PushFailed ||\n ex.errorBody.kind === ErrorKind.TransformFailed) &&\n ex.errorBody.reason === ErrorReason.HTTP &&\n (ex.errorBody.status === 401 || ex.errorBody.status === 403)\n ) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function getBackoffParams(error: ZeroError): BackoffBody | undefined {\n if (isServerError(error)) {\n switch (error.errorBody.kind) {\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return error.errorBody;\n }\n }\n return undefined;\n}\n\nexport function isClientError(ex: unknown): ex is ClientError<ClientErrorBody> {\n return (\n ex instanceof ClientError && ex.errorBody.origin === ErrorOrigin.Client\n );\n}\n\nexport const NO_STATUS_TRANSITION = 'NO_STATUS_TRANSITION';\n\nexport type ErrorConnectionTransition =\n | {status: typeof NO_STATUS_TRANSITION; reason: ZeroError}\n | {status: ConnectionStatus.NeedsAuth; reason: AuthError}\n | {status: ConnectionStatus.Error; reason: ZeroError}\n | {status: ConnectionStatus.Disconnected; reason: ZeroError}\n | {status: ConnectionStatus.Closed; reason: ZeroError};\n\n/**\n * Returns the status to transition to, or null if the error\n * indicates that the connection should continue in the current state.\n */\nexport function getErrorConnectionTransition(\n ex: unknown,\n): ErrorConnectionTransition {\n // Handle auth errors by transitioning to needs-auth state\n if (isAuthError(ex)) {\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex,\n } as const;\n }\n\n if (isClientError(ex)) {\n switch (ex.kind) {\n // Connecting errors that should continue in the current state\n case ClientErrorKind.AbruptClose:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.ConnectTimeout:\n case ClientErrorKind.PingTimeout:\n case ClientErrorKind.PullTimeout:\n case ClientErrorKind.Hidden:\n case ClientErrorKind.NoSocketOrigin:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Fatal errors that should transition to error state\n case ClientErrorKind.UnexpectedBaseCookie:\n case ClientErrorKind.Internal:\n case ClientErrorKind.InvalidMessage:\n case ClientErrorKind.UserDisconnect:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Disconnected error (this should already result in a disconnected state)\n case ClientErrorKind.DisconnectTimeout:\n return {status: ConnectionStatus.Disconnected, reason: ex} as const;\n\n // Closed error (this should already result in a closed state)\n case ClientErrorKind.ClientClosed:\n return {status: ConnectionStatus.Closed, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n if (isServerError(ex)) {\n switch (ex.kind) {\n // Errors that should transition to error state\n case ErrorKind.ClientNotFound:\n case ErrorKind.InvalidConnectionRequest:\n case ErrorKind.InvalidConnectionRequestBaseCookie:\n case ErrorKind.InvalidConnectionRequestLastMutationID:\n case ErrorKind.InvalidConnectionRequestClientDeleted:\n case ErrorKind.InvalidMessage:\n case ErrorKind.InvalidPush:\n case ErrorKind.VersionNotSupported:\n case ErrorKind.SchemaVersionNotSupported:\n case ErrorKind.Internal:\n // PushFailed and TransformFailed can be auth errors (401/403)\n // or other errors - handle non-auth cases here\n case ErrorKind.PushFailed:\n case ErrorKind.TransformFailed:\n return {status: ConnectionStatus.Error, reason: ex} as const;\n\n // Errors that should continue with backoff/retry\n case ErrorKind.Rebalance:\n case ErrorKind.Rehome:\n case ErrorKind.ServerOverloaded:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n // Auth errors are handled above by isAuthError check\n case ErrorKind.AuthInvalidated:\n case ErrorKind.Unauthorized:\n return {\n status: ConnectionStatus.NeedsAuth,\n reason: ex as AuthError,\n } as const;\n\n // Mutation-specific errors don't affect connection state\n case ErrorKind.MutationRateLimited:\n case ErrorKind.MutationFailed:\n return {status: NO_STATUS_TRANSITION, reason: ex} as const;\n\n default:\n unreachable(ex.kind);\n }\n }\n\n // we default to error state if we don't know what to do\n // this is a catch-all for unexpected errors\n return {\n status: ConnectionStatus.Error,\n reason: new ClientError({\n kind: ClientErrorKind.Internal,\n message:\n 'Unexpected internal error: ' +\n (ex instanceof Error\n ? ex.message\n : typeof ex === 'string'\n ? ex\n : String(ex ?? 'Unknown error')),\n }),\n } as const;\n}\n", "/**\n * There is a new client group due to a another tab loading new code which\n * cannot sync locally with this tab until it updates to the new code. This tab\n * can still sync with the zero-cache.\n */\nexport const NewClientGroup = 'NewClientGroup';\nexport type NewClientGroup = typeof NewClientGroup;\n\n/**\n * This client was unable to connect to the zero-cache because it is using a\n * protocol version that the zero-cache does not support.\n */\nexport const VersionNotSupported = 'VersionNotSupported';\nexport type VersionNotSupported = typeof VersionNotSupported;\n\n/**\n * This client was unable to connect to the zero-cache because it is using a\n * schema version (see {@codelink Schema}) that the zero-cache does not support.\n */\nexport const SchemaVersionNotSupported = 'SchemaVersionNotSupported';\nexport type SchemaVersionNotSupported = typeof SchemaVersionNotSupported;\n", "import {type LogLevel, type LogSink} from '@rocicorp/logger';\nimport {type Resolver, resolver} from '@rocicorp/resolver';\nimport {type DeletedClients} from '../../../replicache/src/deleted-clients.ts';\nimport {\n ReplicacheImpl,\n type ReplicacheImplOptions,\n} from '../../../replicache/src/impl.ts';\nimport {dropDatabase} from '../../../replicache/src/persist/collect-idb-databases.ts';\nimport type {Puller, PullerResult} from '../../../replicache/src/puller.ts';\nimport type {Pusher, PusherResult} from '../../../replicache/src/pusher.ts';\nimport type {ReplicacheOptions} from '../../../replicache/src/replicache-options.ts';\nimport type {\n ClientGroupID,\n ClientID,\n} from '../../../replicache/src/sync/ids.ts';\nimport type {PullRequest} from '../../../replicache/src/sync/pull.ts';\nimport type {PushRequest} from '../../../replicache/src/sync/push.ts';\nimport type {\n MutatorDefs,\n MutatorReturn,\n UpdateNeededReason as ReplicacheUpdateNeededReason,\n} from '../../../replicache/src/types.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {\n getBrowserGlobal,\n mustGetBrowserGlobal,\n} from '../../../shared/src/browser-env.ts';\nimport type {DeepMerge} from '../../../shared/src/deep-merge.ts';\nimport {getDocumentVisibilityWatcher} from '../../../shared/src/document-visible.ts';\nimport {h64} from '../../../shared/src/hash.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {navigator} from '../../../shared/src/navigator.ts';\nimport {promiseRace} from '../../../shared/src/promise-race.ts';\nimport {emptyFunction} from '../../../shared/src/sentinels.ts';\nimport {sleep, sleepWithAbort} from '../../../shared/src/sleep.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport {type ClientSchema} from '../../../zero-protocol/src/client-schema.ts';\nimport type {ConnectedMessage} from '../../../zero-protocol/src/connect.ts';\nimport {encodeSecProtocols} from '../../../zero-protocol/src/connect.ts';\nimport type {DeleteClientsBody} from '../../../zero-protocol/src/delete-clients.ts';\nimport type {Downstream} from '../../../zero-protocol/src/down.ts';\nimport {downstreamSchema} from '../../../zero-protocol/src/down.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {\n ProtocolError,\n type ErrorMessage,\n} from '../../../zero-protocol/src/error.ts';\nimport * as MutationType from '../../../zero-protocol/src/mutation-type-enum.ts';\nimport type {PingMessage} from '../../../zero-protocol/src/ping.ts';\nimport type {\n PokeEndMessage,\n PokePartMessage,\n PokeStartMessage,\n} from '../../../zero-protocol/src/poke.ts';\nimport {PROTOCOL_VERSION} from '../../../zero-protocol/src/protocol-version.ts';\nimport type {\n PullRequestMessage,\n PullResponseBody,\n PullResponseMessage,\n} from '../../../zero-protocol/src/pull.ts';\nimport type {\n CRUDMutation,\n CRUDMutationArg,\n CustomMutation,\n MutationID,\n PushMessage,\n} from '../../../zero-protocol/src/push.ts';\nimport {CRUD_MUTATION_NAME, mapCRUD} from '../../../zero-protocol/src/push.ts';\nimport type {UpQueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport type {Upstream} from '../../../zero-protocol/src/up.ts';\nimport type {NullableVersion} from '../../../zero-protocol/src/version.ts';\nimport {nullableVersionSchema} from '../../../zero-protocol/src/version.ts';\nimport {\n type Schema,\n clientSchemaFrom,\n} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {\n type NameMapper,\n clientToServer,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {ViewFactory} from '../../../zql/src/ivm/view.ts';\nimport {customMutatorKey} from '../../../zql/src/mutate/custom.ts';\nimport {\n type ClientMetricMap,\n type MetricMap,\n isClientMetric,\n} from '../../../zql/src/query/metrics-delegate.ts';\nimport type {QueryDelegate} from '../../../zql/src/query/query-delegate.ts';\nimport {\n type AnyQuery,\n materialize,\n newQuery,\n} from '../../../zql/src/query/query-impl.ts';\nimport {\n type HumanReadable,\n type MaterializeOptions,\n type PreloadOptions,\n type Query,\n type QueryRowType,\n type QueryTable,\n type RunOptions,\n delegateSymbol,\n} from '../../../zql/src/query/query.ts';\nimport type {TypedView} from '../../../zql/src/query/typed-view.ts';\nimport {nanoid} from '../util/nanoid.ts';\nimport {send} from '../util/socket.ts';\nimport {ActiveClientsManager} from './active-clients-manager.ts';\nimport {\n ConnectionManager,\n throwIfConnectionError,\n type ConnectionState,\n} from './connection-manager.ts';\nimport {type Connection, ConnectionImpl} from './connection.ts';\nimport {ZeroContext} from './context.ts';\nimport {\n type BatchMutator,\n type CRUDMutator,\n type DBMutator,\n type WithCRUD,\n makeCRUDMutate,\n makeCRUDMutator,\n} from './crud.ts';\nimport type {\n CustomMutatorDefs,\n CustomMutatorImpl,\n MakeCustomMutatorInterfaces,\n} from './custom.ts';\nimport {makeReplicacheMutator} from './custom.ts';\nimport {DeleteClientsManager} from './delete-clients-manager.ts';\nimport {shouldEnableAnalytics} from './enable-analytics.ts';\nimport {\n type HTTPString,\n type WSString,\n appendPath,\n toWSString,\n} from './http-string.ts';\nimport {Inspector} from './inspector/inspector.ts';\nimport {IVMSourceBranch} from './ivm-branch.ts';\nimport {type LogOptions, createLogOptions} from './log-options.ts';\nimport {\n DID_NOT_CONNECT_VALUE,\n MetricManager,\n REPORT_INTERVAL_MS,\n type Series,\n getLastConnectErrorValue,\n shouldReportConnectError,\n} from './metrics.ts';\nimport {MutationTracker} from './mutation-tracker.ts';\nimport type {OnErrorParameters} from './on-error.ts';\nimport type {UpdateNeededReason, ZeroOptions} from './options.ts';\nimport {QueryManager} from './query-manager.ts';\nimport {\n reloadScheduled,\n reloadWithReason,\n reportReloadReason,\n resetBackoff,\n} from './reload-error-handler.ts';\nimport {\n ClientError,\n getBackoffParams,\n getErrorConnectionTransition,\n isAuthError,\n isClientError,\n isServerError,\n NO_STATUS_TRANSITION,\n type ZeroError,\n} from './error.ts';\nimport {getServer} from './server-option.ts';\nimport {version} from './version.ts';\nimport {ZeroLogContext} from './zero-log-context.ts';\nimport {PokeHandler} from './zero-poke-handler.ts';\nimport {\n fromReplicacheAuthToken,\n toReplicacheAuthToken,\n ZeroRep,\n} from './zero-rep.ts';\nimport {ConnectionStatus} from './connection-status.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\n\nexport type NoRelations = Record<string, never>;\n\nexport type MakeEntityQueriesFromSchema<S extends Schema> = {\n readonly [K in keyof S['tables'] & string]: Query<S, K>;\n};\n\ndeclare const TESTING: boolean;\n\nexport type TestingContext = {\n puller: Puller;\n pusher: Pusher;\n setReload: (r: () => void) => void;\n logOptions: LogOptions;\n connectStart: () => number | undefined;\n socketResolver: () => Resolver<WebSocket>;\n connectionManager: () => ConnectionManager;\n};\n\nexport const exposedToTestingSymbol = Symbol();\nexport const createLogOptionsSymbol = Symbol();\n\ninterface TestZero {\n [exposedToTestingSymbol]?: TestingContext;\n [createLogOptionsSymbol]?: (options: {\n consoleLogLevel: LogLevel;\n server: string | null;\n }) => LogOptions;\n}\n\nfunction asTestZero<S extends Schema, MD extends CustomMutatorDefs | undefined>(\n z: Zero<S, MD>,\n): TestZero {\n return z as TestZero;\n}\n\nexport const RUN_LOOP_INTERVAL_MS = 5_000;\n\n/**\n * How frequently we should ping the server to keep the connection alive.\n */\nexport const PING_INTERVAL_MS = 5_000;\n\n/**\n * The amount of time we wait for a pong before we consider the ping timed out.\n */\nexport const PING_TIMEOUT_MS = 5_000;\n\n/**\n * The amount of time we wait for a pull response before we consider a pull\n * request timed out.\n */\nexport const PULL_TIMEOUT_MS = 5_000;\n\nexport const DEFAULT_DISCONNECT_HIDDEN_DELAY_MS = 5_000;\n\n/**\n * The amount of time we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n *\n * Default to 5 minutes.\n */\nexport const DEFAULT_DISCONNECT_TIMEOUT_MS = 5 * 60 * 1_000;\n\n/**\n * The amount of time we wait for a connection to be established before we\n * consider it timed out.\n */\nexport const CONNECT_TIMEOUT_MS = 10_000;\n\nconst CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY = 6;\n\nconst NULL_LAST_MUTATION_ID_SENT = {clientID: '', id: -1} as const;\n\nconst DEFAULT_QUERY_CHANGE_THROTTLE_MS = 10;\n\nfunction convertOnUpdateNeededReason(\n reason: ReplicacheUpdateNeededReason,\n): UpdateNeededReason {\n return {type: reason.type};\n}\n\nfunction updateNeededReloadReasonMessage(reason: UpdateNeededReason) {\n const {type} = reason;\n let reasonMsg = '';\n switch (type) {\n case 'NewClientGroup':\n reasonMsg =\n \"This client could not sync with a newer client. This is probably due to another tab loading a newer incompatible version of the app's code.\";\n break;\n case 'VersionNotSupported':\n reasonMsg =\n \"The server no longer supports this client's protocol version.\";\n break;\n case 'SchemaVersionNotSupported':\n reasonMsg = 'Client and server schemas incompatible.';\n break;\n default:\n unreachable(type);\n }\n if (reason.message) {\n reasonMsg += ' ' + reason.message;\n }\n return reasonMsg;\n}\n\nconst serverAheadReloadReason = `Server reported that client is ahead of server. This probably happened because the server is in development mode and restarted. Currently when this happens, the dev server loses its state and on reconnect sees the client as ahead. If you see this in other cases, it may be a bug in Zero.`;\n\nfunction onClientStateNotFoundServerReason(serverErrMsg: string) {\n return `Server could not find state needed to synchronize this client. ${serverErrMsg}`;\n}\nconst ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT =\n 'The local persistent state needed to synchronize this client has been garbage collected.';\n\n// Keep in sync with packages/replicache/src/replicache-options.ts\nexport interface ReplicacheInternalAPI {\n lastMutationID(): number;\n}\n\nconst internalReplicacheImplMap = new WeakMap<object, ReplicacheImpl>();\n\nexport function getInternalReplicacheImplForTesting(\n z: object,\n): ReplicacheImpl<MutatorDefs> {\n assert(TESTING);\n return must(internalReplicacheImplMap.get(z));\n}\n\nconst CLOSE_CODE_NORMAL = 1000;\nconst CLOSE_CODE_GOING_AWAY = 1001;\ntype CloseCode = typeof CLOSE_CODE_NORMAL | typeof CLOSE_CODE_GOING_AWAY;\n\nexport class Zero<\n const S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n> {\n readonly version = version;\n\n readonly #rep: ReplicacheImpl<WithCRUD<MutatorDefs>>;\n readonly #server: HTTPString | null;\n readonly userID: string;\n readonly storageKey: string;\n\n readonly #lc: ZeroLogContext;\n readonly #logOptions: LogOptions;\n readonly #enableAnalytics: boolean;\n readonly #clientSchema: ClientSchema;\n\n readonly #pokeHandler: PokeHandler;\n readonly #queryManager: QueryManager;\n readonly #ivmMain: IVMSourceBranch;\n readonly #clientToServer: NameMapper;\n readonly #deleteClientsManager: DeleteClientsManager;\n readonly #mutationTracker: MutationTracker;\n\n /**\n * The queries we sent when inside the sec-protocol header when establishing a connection.\n * More queries could be registered while we're waiting for the 'connected' message\n * to come back from the server. To understand what queries we need to send\n * to the server, we diff the `initConnectionQueries` with the current set of desired queries.\n *\n * If this is set to `undefined` that means no queries were sent inside the `sec-protocol` header\n * and an `initConnection` message must be sent to the server after receiving the `connected` message.\n */\n #initConnectionQueries: Map<string, UpQueriesPatchOp> | undefined;\n\n /**\n * We try to send the deleted clients and (client groups) as part of the\n * sec-protocol header. If we can't because the header would get too large we\n * keep track of the deleted clients and send them after the connection is\n * established.\n */\n #deletedClients: DeleteClientsBody | undefined;\n\n #lastMutationIDSent: {clientID: string; id: number} =\n NULL_LAST_MUTATION_ID_SENT;\n\n #onPong: () => void = () => undefined;\n\n readonly #onlineManager: OnlineManager;\n\n readonly #onUpdateNeeded: (reason: UpdateNeededReason) => void;\n readonly #onClientStateNotFound: (reason?: string) => void;\n // Last cookie used to initiate a connection\n #connectCookie: NullableVersion = null;\n // Total number of sockets successfully connected by this client\n #connectedCount = 0;\n // Number of messages received over currently connected socket. Reset\n // on disconnect.\n #messageCount = 0;\n #connectedAt = 0;\n // Reset on successful connection.\n #connectErrorCount = 0;\n\n #abortPingTimeout = () => {\n // intentionally empty\n };\n\n readonly #zeroContext: ZeroContext;\n readonly queryDelegate: QueryDelegate;\n\n #pendingPullsByRequestID: Map<string, Resolver<PullResponseBody>> = new Map();\n #lastMutationIDReceived = 0;\n\n #socket: WebSocket | undefined = undefined;\n #socketResolver = resolver<WebSocket>();\n /**\n * Utility promise that resolves when the socket transitions to connected.\n * It rejects if we hit an error or timeout before the connected message.\n * Used by push/pull helpers to queue work until the connection is usable.\n */\n #connectResolver = resolver<void>();\n\n #closeAbortController = new AbortController();\n\n readonly #visibilityWatcher;\n\n readonly #connectionManager: ConnectionManager;\n readonly #connection: Connection;\n #unsubscribeConnectionState: (() => void) | undefined = undefined;\n readonly #activeClientsManager: Promise<ActiveClientsManager>;\n #inspector: Inspector | undefined;\n\n #connectStart: number | undefined = undefined;\n // Set on connect attempt if currently undefined.\n // Reset to undefined when\n // 1. client stops trying to connect because it is hidden\n // 2. client encounters a connect error and canary request indicates\n // the client is offline\n // 2. client successfully connects\n #totalToConnectStart: number | undefined = undefined;\n\n readonly #options: ZeroOptions<S, MD>;\n\n readonly query: MakeEntityQueriesFromSchema<S>;\n\n // TODO: Metrics needs to be rethought entirely as we're not going to\n // send metrics to customer server.\n #metrics: MetricManager;\n\n // Store as field to allow test subclass to override. Web API doesn't allow\n // overwriting location fields for security reasons.\n #reload = () => getBrowserGlobal('location')?.reload();\n\n /**\n * Constructs a new Zero client.\n */\n constructor(options: ZeroOptions<S, MD>) {\n const {\n userID,\n storageKey,\n onOnlineChange,\n onUpdateNeeded,\n onClientStateNotFound,\n hiddenTabDisconnectDelay = DEFAULT_DISCONNECT_HIDDEN_DELAY_MS,\n schema,\n batchViewUpdates = applyViewUpdates => applyViewUpdates(),\n maxRecentQueries = 0,\n slowMaterializeThreshold = 5_000,\n } = options as ZeroOptions<S, MD>;\n if (!userID) {\n throw new ClientError({\n kind: ClientErrorKind.Internal,\n message: 'ZeroOptions.userID must not be empty.',\n });\n }\n const server = getServer(options.server);\n this.#enableAnalytics = shouldEnableAnalytics(\n server,\n false /*options.enableAnalytics,*/, // Reenable analytics\n );\n\n let {kvStore = 'idb'} = options as ZeroOptions<S, MD>;\n if (kvStore === 'idb') {\n if (!getBrowserGlobal('indexedDB')) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'IndexedDB is not supported in this environment. Falling back to memory storage.',\n );\n kvStore = 'mem';\n }\n }\n\n if (hiddenTabDisconnectDelay < 0) {\n throw new ClientError({\n kind: ClientErrorKind.Internal,\n message: 'ZeroOptions.hiddenTabDisconnectDelay must not be negative.',\n });\n }\n\n this.#onlineManager = new OnlineManager();\n\n if (onOnlineChange) {\n this.#onlineManager.subscribe(onOnlineChange);\n }\n\n this.#options = options;\n\n this.#logOptions = this.#createLogOptions({\n consoleLogLevel: options.logLevel ?? 'warn',\n server: null, //server, // Reenable remote logging\n enableAnalytics: this.#enableAnalytics,\n });\n const logOptions = this.#logOptions;\n\n this.#connectionManager = new ConnectionManager({\n disconnectTimeoutMs: DEFAULT_DISCONNECT_TIMEOUT_MS,\n });\n const syncOnlineState = (state: ConnectionState) => {\n this.#onlineManager.setOnline(state.name === ConnectionStatus.Connected);\n };\n syncOnlineState(this.#connectionManager.state);\n this.#unsubscribeConnectionState =\n this.#connectionManager.subscribe(syncOnlineState);\n\n const {enableLegacyMutators = true, enableLegacyQueries = true} = schema;\n\n const replicacheMutators: MutatorDefs & {\n [CRUD_MUTATION_NAME]: CRUDMutator;\n } = {\n [CRUD_MUTATION_NAME]: enableLegacyMutators\n ? makeCRUDMutator(schema)\n : () =>\n Promise.reject(\n new ClientError({\n kind: ClientErrorKind.Internal,\n message: 'Zero CRUD mutators are not enabled.',\n }),\n ),\n };\n this.#ivmMain = new IVMSourceBranch(schema.tables);\n\n function assertUnique(key: string) {\n assert(\n replicacheMutators[key] === undefined,\n `A mutator, or mutator namespace, has already been defined for ${key}`,\n );\n }\n\n // We create a special log sink that calls onError if defined instead of\n // logging error messages.\n const {onError} = options;\n const sink = logOptions.logSink;\n const logSink: LogSink<OnErrorParameters> = {\n log(level, context, ...args) {\n if (level === 'error' && onError) {\n onError(...(args as OnErrorParameters));\n } else {\n sink.log(level, context, ...args);\n }\n },\n async flush() {\n await sink.flush?.();\n },\n };\n\n const lc = new ZeroLogContext(logOptions.logLevel, {}, logSink);\n\n this.#mutationTracker = new MutationTracker(\n lc,\n (upTo: MutationID) => this.#send(['ackMutationResponses', upTo]),\n error => {\n this.#disconnect(lc, error);\n },\n );\n if (options.mutators) {\n for (const [namespaceOrKey, mutatorOrMutators] of Object.entries(\n options.mutators,\n )) {\n if (typeof mutatorOrMutators === 'function') {\n const key = namespaceOrKey as string;\n assertUnique(key);\n replicacheMutators[key] = makeReplicacheMutator(\n lc,\n mutatorOrMutators,\n schema,\n // Replicache expects mutators to only be able to return JSON\n // but Zero wraps the return with: `{server?: Promise<MutationResult>, client?: T}`\n ) as () => MutatorReturn;\n continue;\n }\n if (typeof mutatorOrMutators === 'object') {\n for (const [name, mutator] of Object.entries(mutatorOrMutators)) {\n const key = customMutatorKey(\n namespaceOrKey as string,\n name as string,\n );\n assertUnique(key);\n replicacheMutators[key] = makeReplicacheMutator(\n lc,\n mutator as CustomMutatorImpl<S>,\n schema,\n ) as () => MutatorReturn;\n }\n continue;\n }\n unreachable(mutatorOrMutators);\n }\n }\n\n this.storageKey = storageKey ?? '';\n\n const {clientSchema, hash} = clientSchemaFrom(schema);\n this.#clientSchema = clientSchema;\n\n // Create a hash that includes storage key, URL configuration, and query parameters\n const nameKey = JSON.stringify({\n storageKey: this.storageKey,\n mutateUrl: options.mutateURL ?? '',\n queryUrl: options.getQueriesURL ?? '',\n });\n const hashedKey = h64(nameKey).toString(36);\n\n const replicacheOptions: ReplicacheOptions<WithCRUD<MutatorDefs>> = {\n // The schema stored in IDB is dependent upon both the ClientSchema\n // and the AST schema (i.e. PROTOCOL_VERSION).\n schemaVersion: `${PROTOCOL_VERSION}.${hash}`,\n logLevel: logOptions.logLevel,\n logSinks: [logOptions.logSink],\n mutators: replicacheMutators,\n name: `zero-${userID}-${hashedKey}`,\n pusher: (req, reqID) => this.#pusher(req, reqID),\n puller: (req, reqID) => this.#puller(req, reqID),\n pushDelay: 0,\n requestOptions: {\n maxDelayMs: 0,\n minDelayMs: 0,\n },\n licenseKey: 'zero-client-static-key',\n kvStore,\n };\n\n this.#zeroContext = new ZeroContext(\n lc,\n this.#ivmMain,\n (ast, ttl, gotCallback) => {\n if (enableLegacyQueries) {\n return this.#queryManager.addLegacy(ast, ttl, gotCallback);\n }\n // legacy queries are client side only. Do not track with the server\n return emptyFunction;\n },\n (ast, customQueryID, ttl, gotCallback) =>\n this.#queryManager.addCustom(ast, customQueryID, ttl, gotCallback),\n (ast, ttl) => {\n if (enableLegacyQueries) {\n this.#queryManager.updateLegacy(ast, ttl);\n }\n },\n (customQueryID, ttl) =>\n this.#queryManager.updateCustom(customQueryID, ttl),\n () => this.#queryManager.flushBatch(),\n batchViewUpdates,\n this.#addMetric,\n assertValidRunOptions,\n );\n this.queryDelegate = this.#zeroContext;\n\n const replicacheImplOptions: ReplicacheImplOptions = {\n enableClientGroupForking: false,\n enableMutationRecovery: false,\n enablePullAndPushInOpen: false, // Zero calls push in its connection management code\n onClientsDeleted: deletedClients =>\n this.#deleteClientsManager.onClientsDeleted(deletedClients),\n zero: new ZeroRep(\n this.#zeroContext,\n this.#ivmMain,\n options.mutators !== undefined,\n this.#mutationTracker,\n ),\n };\n\n const rep = new ReplicacheImpl(replicacheOptions, replicacheImplOptions);\n this.#rep = rep;\n\n if (TESTING) {\n internalReplicacheImplMap.set(this, rep);\n }\n this.#server = server;\n this.userID = userID;\n this.#lc = lc.withContext('clientID', rep.clientID);\n this.#connection = new ConnectionImpl(\n this.#connectionManager,\n this.#lc,\n auth => this.#setAuth(auth),\n );\n this.#mutationTracker.setClientIDAndWatch(\n rep.clientID,\n rep.experimentalWatch.bind(rep),\n );\n\n this.#activeClientsManager = makeActiveClientsManager(\n rep.clientGroupID,\n this.clientID,\n this.#closeAbortController.signal,\n (clientID: ClientID, clientGroupID: ClientGroupID) =>\n this.#deleteClientsManager.onClientsDeleted([\n {clientGroupID, clientID},\n ]),\n );\n\n const onUpdateNeededCallback = (reason: UpdateNeededReason) => {\n if (onUpdateNeeded) {\n onUpdateNeeded(reason);\n } else {\n reloadWithReason(\n this.#lc,\n this.#reload,\n reason.type,\n updateNeededReloadReasonMessage(reason),\n );\n }\n };\n this.#onUpdateNeeded = onUpdateNeededCallback;\n this.#rep.onUpdateNeeded = reason => {\n onUpdateNeededCallback(convertOnUpdateNeededReason(reason));\n };\n\n const onClientStateNotFoundCallback =\n onClientStateNotFound ??\n ((reason?: string) => {\n reloadWithReason(\n this.#lc,\n this.#reload,\n ErrorKind.ClientNotFound,\n reason ?? ON_CLIENT_STATE_NOT_FOUND_REASON_CLIENT,\n );\n });\n this.#onClientStateNotFound = onClientStateNotFoundCallback;\n this.#rep.onClientStateNotFound = onClientStateNotFoundCallback;\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const {mutate, mutateBatch} = makeCRUDMutate<S>(schema, rep.mutate) as any;\n\n if (options.mutators) {\n for (const [namespaceOrKey, mutatorsOrMutator] of Object.entries(\n options.mutators,\n )) {\n if (typeof mutatorsOrMutator === 'function') {\n mutate[namespaceOrKey] = must(rep.mutate[namespaceOrKey as string]);\n continue;\n }\n\n let existing = mutate[namespaceOrKey];\n if (existing === undefined) {\n existing = {};\n mutate[namespaceOrKey] = existing;\n }\n\n for (const name of Object.keys(mutatorsOrMutator)) {\n existing[name] = must(\n rep.mutate[customMutatorKey(namespaceOrKey, name)],\n );\n }\n }\n }\n\n this.mutate = mutate;\n this.mutateBatch = mutateBatch;\n\n this.#queryManager = new QueryManager(\n this.#lc,\n this.#mutationTracker,\n rep.clientID,\n schema.tables,\n msg => this.#send(msg),\n rep.experimentalWatch.bind(rep),\n maxRecentQueries,\n options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS,\n slowMaterializeThreshold,\n (error: ZeroError) => {\n this.#disconnect(lc, error);\n },\n );\n this.#clientToServer = clientToServer(schema.tables);\n\n this.#deleteClientsManager = new DeleteClientsManager(\n msg => this.#send(msg),\n rep.perdag,\n this.#lc,\n this.#rep.clientGroupID,\n );\n\n this.query = this.#registerQueries(schema);\n\n reportReloadReason(this.#lc);\n\n this.#metrics = new MetricManager({\n reportIntervalMs: REPORT_INTERVAL_MS,\n host: getBrowserGlobal('location')?.host ?? '',\n source: 'client',\n reporter: this.#enableAnalytics\n ? allSeries => this.#reportMetrics(allSeries)\n : () => Promise.resolve(),\n lc: this.#lc,\n });\n this.#metrics.tags.push(`version:${this.version}`);\n\n this.#pokeHandler = new PokeHandler(\n poke => this.#rep.poke(poke),\n () => this.#onPokeError(),\n rep.clientID,\n schema,\n this.#lc,\n this.#mutationTracker,\n );\n\n this.#visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n hiddenTabDisconnectDelay,\n this.#closeAbortController.signal,\n );\n\n void this.#runLoop();\n\n this.#expose();\n\n if (TESTING) {\n asTestZero(this)[exposedToTestingSymbol] = {\n puller: this.#puller,\n pusher: this.#pusher,\n setReload: (r: () => void) => {\n this.#reload = r;\n },\n logOptions: this.#logOptions,\n connectStart: () => this.#connectStart,\n socketResolver: () => this.#socketResolver,\n connectionManager: () => this.#connectionManager,\n };\n }\n }\n\n #expose() {\n // Expose the Zero instance to the global scope.\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const g = globalThis as any;\n if (g.__zero === undefined) {\n g.__zero = this;\n } else if (g.__zero instanceof Zero) {\n const prev = g.__zero;\n g.__zero = {\n [prev.clientID]: prev,\n [this.clientID]: this,\n };\n } else {\n g.__zero[this.clientID] = this;\n }\n }\n\n #unexpose() {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const g = globalThis as any;\n assert(g.__zero !== undefined);\n if (g.__zero instanceof Zero) {\n assert(g.__zero === this);\n delete g.__zero;\n } else {\n delete g.__zero[this.clientID];\n if (Object.entries(g.__zero).length === 1) {\n g.__zero = Object.values(g.__zero)[0];\n }\n }\n }\n\n #send(msg: Upstream): void {\n if (\n this.#socket &&\n this.#connectionManager.is(ConnectionStatus.Connected)\n ) {\n send(this.#socket, msg);\n }\n }\n\n #createLogOptions(options: {\n consoleLogLevel: LogLevel;\n server: HTTPString | null;\n enableAnalytics: boolean;\n }): LogOptions {\n if (TESTING) {\n const testZero = asTestZero(this);\n if (testZero[createLogOptionsSymbol]) {\n return testZero[createLogOptionsSymbol](options);\n }\n }\n return createLogOptions(options);\n }\n\n preload(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n query: Query<S, keyof S['tables'] & string, any>,\n options?: PreloadOptions,\n ) {\n return query[delegateSymbol](this.#zeroContext).preload(options);\n }\n\n run<Q>(\n query: Q,\n runOptions?: RunOptions,\n ): Promise<HumanReadable<QueryRowType<Q>>> {\n return (query as AnyQuery)\n [delegateSymbol](this.#zeroContext)\n .run(runOptions) as Promise<HumanReadable<QueryRowType<Q>>>;\n }\n\n materialize<Q>(\n query: Q,\n options?: MaterializeOptions,\n ): TypedView<HumanReadable<QueryRowType<Q>>>;\n materialize<T, Q>(\n query: Q,\n factory: ViewFactory<S, QueryTable<Q>, QueryRowType<Q>, T>,\n options?: MaterializeOptions,\n ): T;\n materialize<T, Q>(\n query: Q,\n factoryOrOptions?:\n | ViewFactory<S, QueryTable<Q>, QueryRowType<Q>, T>\n | MaterializeOptions,\n maybeOptions?: MaterializeOptions,\n ) {\n return materialize(\n query,\n this.#zeroContext,\n factoryOrOptions,\n maybeOptions,\n );\n }\n\n /**\n * The server URL that this Zero instance is configured with.\n */\n get server(): HTTPString | null {\n return this.#server;\n }\n\n /**\n * The name of the IndexedDB database in which the data of this\n * instance of Zero is stored.\n */\n get idbName(): string {\n return this.#rep.idbName;\n }\n\n /**\n * The schema version of the data understood by this application.\n * See [[ZeroOptions.schemaVersion]].\n */\n get schemaVersion(): string {\n return this.#rep.schemaVersion;\n }\n\n /**\n * The schema passed into Zero when it was constructed.\n *\n * This can be paired with the inspector API to explore the client cache for\n * debugging or tooling. The inspector exposes the raw key/value map as well\n * as the per-table rows that back `zero.query[tableName].run()`.\n *\n * ```ts\n * const inspector = __zero.inspector;\n * const client = inspector.client;\n *\n * console.log('client map:', await client.map());\n *\n * for (const tableName of Object.keys(__zero.schema.tables)) {\n * console.table(await client.rows(tableName));\n * }\n * ```\n */\n get schema(): S {\n return this.#options.schema;\n }\n\n /**\n * The client ID for this instance of Zero. Each instance\n * gets a unique client ID.\n */\n get clientID(): ClientID {\n return this.#rep.clientID;\n }\n\n get clientGroupID(): Promise<ClientGroupID> {\n return this.#rep.clientGroupID;\n }\n\n /**\n * Provides simple \"CRUD\" mutations for the tables in the schema.\n *\n * Each table has `create`, `set`, `update`, and `delete` methods.\n *\n * ```ts\n * await zero.mutate.issue.create({id: '1', title: 'First issue', priority: 'high'});\n * await zero.mutate.comment.create({id: '1', text: 'First comment', issueID: '1'});\n * ```\n *\n * The `update` methods support partials. Unspecified or `undefined` fields\n * are left unchanged:\n *\n * ```ts\n * // Priority left unchanged.\n * await zero.mutate.issue.update({id: '1', title: 'Updated title'});\n * ```\n */\n readonly mutate: MD extends CustomMutatorDefs\n ? S['enableLegacyMutators'] extends false\n ? MakeCustomMutatorInterfaces<S, MD>\n : DeepMerge<DBMutator<S>, MakeCustomMutatorInterfaces<S, MD>>\n : DBMutator<S>;\n\n /**\n * Provides a way to batch multiple CRUD mutations together:\n *\n * ```ts\n * await zero.mutateBatch(m => {\n * await m.issue.create({id: '1', title: 'First issue'});\n * await m.comment.create({id: '1', text: 'First comment', issueID: '1'});\n * });\n * ```\n *\n * Batch sends all mutations in a single transaction. If one fails, all are\n * rolled back together. Batch can also be more efficient than making many\n * individual mutations.\n *\n * `mutateBatch` is not allowed inside another `mutateBatch` call. Doing so\n * will throw an error.\n */\n readonly mutateBatch: BatchMutator<S>;\n\n /**\n * The connection API for managing Zero's connection lifecycle.\n *\n * Use this to monitor connection state and manually control connections.\n *\n * @example\n * ```ts\n * // Subscribe to connection state changes\n * z.connection.state.subscribe(state => {\n * console.log('Connection state:', state.name);\n * });\n *\n * // Manually resume connection from error state\n * await z.connection.connect();\n * ```\n */\n get connection(): Connection {\n return this.#connection;\n }\n\n /**\n * Whether this Zero instance has been closed.\n *\n * Once a Zero instance has been closed it no longer syncs, you can no\n * longer query or mutate data with it, and its query views stop updating.\n */\n get closed(): boolean {\n return this.#connectionManager.is(ConnectionStatus.Closed);\n }\n\n /**\n * Closes this Zero instance.\n *\n * Once a Zero instance has been closed it no longer syncs, you can no\n * longer query or mutate data with it, and its query views stop updating.\n */\n async close(): Promise<void> {\n const lc = this.#lc.withContext('close');\n\n try {\n if (this.closed) {\n lc.debug?.('close() called on already closed instance');\n return;\n }\n\n lc.debug?.('Closing Zero instance. Stack:', new Error().stack);\n\n this.#unsubscribeConnectionState?.();\n this.#unsubscribeConnectionState = undefined;\n this.#onlineManager.cleanup();\n\n if (!this.#connectionManager.is(ConnectionStatus.Disconnected)) {\n this.#disconnect(\n lc,\n new ClientError({\n kind: ClientErrorKind.ClientClosed,\n message: 'Zero instance closed by user',\n }),\n CLOSE_CODE_NORMAL,\n );\n }\n lc.debug?.('Aborting closeAbortController due to close()');\n this.#closeAbortController.abort();\n this.#metrics.stop();\n const ret = await this.#rep.close();\n this.#unexpose();\n return ret;\n } catch (e) {\n lc.error?.('Error closing Zero instance', e);\n throw e;\n } finally {\n this.#connectionManager.closed();\n }\n }\n\n #onMessage = (e: MessageEvent<string>) => {\n const lc = this.#lc;\n lc.debug?.('received message', e.data);\n if (this.closed) {\n lc.debug?.('ignoring message because already closed');\n return;\n }\n\n let downMessage: Downstream;\n const {data} = e;\n try {\n downMessage = valita.parse(\n JSON.parse(data),\n downstreamSchema,\n 'passthrough',\n );\n } catch (e) {\n const invalidMessageError = new ClientError({\n kind: ClientErrorKind.InvalidMessage,\n message: `Invalid message received from server: ${e instanceof Error ? e.message + '. ' : ''}${data}`,\n });\n this.#disconnect(lc, invalidMessageError);\n return;\n }\n this.#messageCount++;\n const msgType = downMessage[0];\n switch (msgType) {\n case 'connected':\n return this.#handleConnectedMessage(lc, downMessage);\n\n case 'error':\n return this.#handleErrorMessage(lc, downMessage);\n\n case 'pong':\n // Receiving a pong means that the connection is healthy, as the\n // initial schema / versioning negotiations would produce an error\n // before a ping-pong timeout.\n resetBackoff();\n return this.#onPong();\n\n case 'pokeStart':\n return this.#handlePokeStart(lc, downMessage);\n\n case 'pokePart':\n if (downMessage[1].rowsPatch) {\n // Receiving row data indicates that the client is in a good state\n // and can reset the reload backoff state.\n resetBackoff();\n }\n return this.#handlePokePart(lc, downMessage);\n\n case 'pokeEnd':\n return this.#handlePokeEnd(lc, downMessage);\n\n case 'pull':\n return this.#handlePullResponse(lc, downMessage);\n\n case 'deleteClients':\n return this.#deleteClientsManager.clientsDeletedOnServer(\n downMessage[1],\n );\n\n case 'pushResponse':\n return this.#mutationTracker.processPushResponse(downMessage[1]);\n\n case 'transformError':\n this.#queryManager.handleTransformErrors(downMessage[1]);\n break;\n\n case 'inspect':\n // ignore at this layer.\n break;\n\n default: {\n const invalidMessageError = new ClientError({\n kind: ClientErrorKind.InvalidMessage,\n message: `Invalid message received from server: ${data}`,\n });\n this.#disconnect(lc, invalidMessageError);\n return;\n }\n }\n };\n\n #onOpen = () => {\n const l = addWebSocketIDFromSocketToLogContext(this.#socket!, this.#lc);\n if (this.#connectStart === undefined) {\n l.error?.('Got open event but connect start time is undefined.');\n } else {\n const now = Date.now();\n const timeToOpenMs = now - this.#connectStart;\n l.info?.('Got socket open event', {\n navigatorOnline: navigator?.onLine,\n timeToOpenMs,\n });\n }\n };\n\n #onClose = (e: CloseEvent) => {\n const lc = addWebSocketIDFromSocketToLogContext(this.#socket!, this.#lc);\n const {code, reason, wasClean} = e;\n if (code <= 1001) {\n lc.info?.('Got socket close event', {code, reason, wasClean});\n } else {\n lc.error?.('Got unexpected socket close event', {\n code,\n reason,\n wasClean,\n });\n }\n\n const closeError = new ClientError(\n wasClean\n ? {\n kind: ClientErrorKind.CleanClose,\n message: 'WebSocket connection closed cleanly',\n }\n : {\n kind: ClientErrorKind.AbruptClose,\n message: 'WebSocket connection closed abruptly',\n },\n );\n this.#connectResolver.reject(closeError);\n this.#disconnect(lc, closeError);\n };\n\n // An error on the connection is fatal for the connection.\n async #handleErrorMessage(\n lc: ZeroLogContext,\n downMessage: ErrorMessage,\n ): Promise<void> {\n const [, {kind, message}] = downMessage;\n\n // Rate limit errors are not fatal to the connection.\n // We really don't want to disconnect and reconnect a rate limited user as\n // it'll use more resources on the server\n if (kind === ErrorKind.MutationRateLimited) {\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n lc.error?.(kind, 'Mutation rate limited', {message});\n return;\n }\n\n lc.info?.(`${kind}: ${message}}`);\n const error = new ProtocolError(downMessage[1]);\n lc.error?.(`${error.kind}:\\n\\n${error.errorBody.message}`, error);\n\n lc.debug?.('Rejecting connect resolver due to error', error);\n this.#connectResolver.reject(error);\n this.#disconnect(lc, error);\n\n if (kind === ErrorKind.VersionNotSupported) {\n this.#onUpdateNeeded({type: kind, message});\n } else if (kind === ErrorKind.SchemaVersionNotSupported) {\n await this.#rep.disableClientGroup();\n this.#onUpdateNeeded({\n type: 'SchemaVersionNotSupported',\n message,\n });\n } else if (kind === ErrorKind.ClientNotFound) {\n await this.#rep.disableClientGroup();\n this.#onClientStateNotFound?.(onClientStateNotFoundServerReason(message));\n } else if (\n kind === ErrorKind.InvalidConnectionRequestLastMutationID ||\n kind === ErrorKind.InvalidConnectionRequestBaseCookie\n ) {\n await dropDatabase(this.#rep.idbName);\n reloadWithReason(lc, this.#reload, kind, serverAheadReloadReason);\n }\n }\n\n async #handleConnectedMessage(\n lc: ZeroLogContext,\n connectedMessage: ConnectedMessage,\n ): Promise<void> {\n const now = Date.now();\n const [, connectBody] = connectedMessage;\n lc = addWebSocketIDToLogContext(connectBody.wsid, lc);\n\n if (this.#connectedCount === 0) {\n this.#checkConnectivity('firstConnect');\n } else if (this.#connectErrorCount > 0) {\n this.#checkConnectivity('connectAfterError');\n }\n this.#connectedCount++;\n this.#connectedAt = now;\n this.#metrics.lastConnectError.clear();\n const proceedingConnectErrorCount = this.#connectErrorCount;\n this.#connectErrorCount = 0;\n\n let timeToConnectMs: number | undefined;\n let connectMsgLatencyMs: number | undefined;\n if (this.#connectStart === undefined) {\n lc.error?.('Got connected message but connect start time is undefined.');\n } else {\n timeToConnectMs = now - this.#connectStart;\n this.#metrics.timeToConnectMs.set(timeToConnectMs);\n connectMsgLatencyMs =\n connectBody.timestamp !== undefined\n ? now - connectBody.timestamp\n : undefined;\n this.#connectStart = undefined;\n }\n let totalTimeToConnectMs: number | undefined;\n if (this.#totalToConnectStart === undefined) {\n lc.error?.(\n 'Got connected message but total to connect start time is undefined.',\n );\n } else {\n totalTimeToConnectMs = now - this.#totalToConnectStart;\n this.#totalToConnectStart = undefined;\n }\n\n this.#metrics.setConnected(timeToConnectMs ?? 0, totalTimeToConnectMs ?? 0);\n\n lc.info?.('Connected', {\n navigatorOnline: navigator?.onLine,\n timeToConnectMs,\n totalTimeToConnectMs,\n connectMsgLatencyMs,\n connectedCount: this.#connectedCount,\n proceedingConnectErrorCount,\n });\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n\n lc.debug?.('Resolving connect resolver');\n const socket = must(this.#socket);\n const queriesPatch = await this.#rep.query(tx =>\n this.#queryManager.getQueriesPatch(tx, this.#initConnectionQueries),\n );\n\n const hasDeletedClients = () =>\n skipEmptyArray(this.#deletedClients?.clientIDs) ||\n skipEmptyArray(this.#deletedClients?.clientGroupIDs);\n\n const maybeSendDeletedClients = () => {\n if (hasDeletedClients()) {\n send(socket, ['deleteClients', this.#deletedClients!]);\n this.#deletedClients = undefined;\n }\n };\n\n if (queriesPatch.size > 0 && this.#initConnectionQueries !== undefined) {\n maybeSendDeletedClients();\n send(socket, [\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [...queriesPatch.values()],\n },\n ]);\n } else if (this.#initConnectionQueries === undefined) {\n // if #initConnectionQueries was undefined that means we never\n // sent `initConnection` to the server inside the sec-protocol header.\n const clientSchema = this.#clientSchema;\n send(socket, [\n 'initConnection',\n {\n desiredQueriesPatch: [...queriesPatch.values()],\n deleted: skipEmptyDeletedClients(this.#deletedClients),\n // The clientSchema only needs to be sent for the very first request.\n // Henceforth it is stored with the CVR and verified automatically.\n ...(this.#connectCookie === null ? {clientSchema} : {}),\n userPushURL: this.#options.mutateURL,\n userQueryURL: this.#options.getQueriesURL,\n },\n ]);\n this.#deletedClients = undefined;\n }\n this.#initConnectionQueries = undefined;\n\n maybeSendDeletedClients();\n\n this.#connectionManager.connected();\n this.#connectResolver.resolve();\n }\n\n /**\n * Starts a new connection. This will create the WebSocket that does the HTTP\n * request to the server.\n *\n * {@link #connect} will throw an assertion error if the\n * {@link #connectionManager} status is not {@link ConnectionState.Disconnected}\n * or {@link ConnectionState.Connecting}.\n * Callers MUST check the connection status before calling this method and log\n * an error as needed.\n *\n * The function will resolve once the socket is connected. If you need to know\n * when a connection has been established, as in we have received the\n * {@link ConnectedMessage}, you should await the {@link #connectResolver}\n * promise. The {@link #connectResolver} promise rejects if an error message\n * is received before the connected message is received or if the connection\n * attempt times out.\n */\n async #connect(\n lc: ZeroLogContext,\n additionalConnectParams: Record<string, string> | undefined,\n ): Promise<void> {\n if (this.closed) {\n return;\n }\n\n assert(this.#server, 'No server provided');\n\n // can be called from both disconnected and connecting states.\n // connecting() handles incrementing attempt counter if already connecting.\n assert(\n this.#connectionManager.is(ConnectionStatus.Disconnected) ||\n this.#connectionManager.is(ConnectionStatus.Connecting),\n 'connect() called from invalid state: ' +\n this.#connectionManager.state.name,\n );\n\n const wsid = nanoid();\n lc = addWebSocketIDToLogContext(wsid, lc);\n lc.info?.('Connecting...', {navigatorOnline: navigator?.onLine});\n\n this.#connectionManager.connecting();\n\n // connect() called but connect start time is defined. This should not\n // happen.\n assert(this.#connectStart === undefined, 'connect start time is defined');\n\n const now = Date.now();\n this.#connectStart = now;\n if (this.#totalToConnectStart === undefined) {\n this.#totalToConnectStart = now;\n }\n\n if (this.closed) {\n return;\n }\n this.#connectCookie = valita.parse(\n await this.#rep.cookie,\n nullableVersionSchema,\n 'passthrough',\n );\n if (this.closed) {\n return;\n }\n\n // Reject connect after a timeout.\n const timeoutID = setTimeout(() => {\n lc.debug?.('Rejecting connect resolver due to timeout');\n const timeoutError = new ClientError({\n kind: ClientErrorKind.ConnectTimeout,\n message: `Connection attempt timed out after ${CONNECT_TIMEOUT_MS / 1000} seconds`,\n });\n this.#connectResolver.reject(timeoutError);\n this.#disconnect(lc, timeoutError);\n }, CONNECT_TIMEOUT_MS);\n const abortHandler = () => {\n clearTimeout(timeoutID);\n };\n // signal.aborted cannot be true here because we checked for `this.closed` above.\n this.#closeAbortController.signal.addEventListener('abort', abortHandler);\n\n const [ws, initConnectionQueries, deletedClients] = await createSocket(\n this.#rep,\n this.#queryManager,\n this.#deleteClientsManager,\n toWSString(this.#server),\n this.#connectCookie,\n this.clientID,\n await this.clientGroupID,\n this.#clientSchema,\n this.userID,\n fromReplicacheAuthToken(this.#rep.auth),\n this.#lastMutationIDReceived,\n wsid,\n this.#options.logLevel === 'debug',\n lc,\n this.#options.mutateURL,\n this.#options.getQueriesURL,\n additionalConnectParams,\n await this.#activeClientsManager,\n this.#options.maxHeaderLength,\n );\n\n if (this.closed) {\n return;\n }\n\n this.#initConnectionQueries = initConnectionQueries;\n this.#deletedClients = deletedClients;\n ws.addEventListener('message', this.#onMessage);\n ws.addEventListener('open', this.#onOpen);\n ws.addEventListener('close', this.#onClose);\n this.#socket = ws;\n this.#socketResolver.resolve(ws);\n\n try {\n lc.debug?.('Waiting for connection to be acknowledged');\n await this.#connectResolver.promise;\n this.#mutationTracker.onConnected(this.#lastMutationIDReceived);\n // push any outstanding mutations on reconnect.\n this.#rep.push().catch(() => {});\n } finally {\n clearTimeout(timeoutID);\n this.#closeAbortController.signal.removeEventListener(\n 'abort',\n abortHandler,\n );\n }\n }\n\n #disconnect(\n lc: ZeroLogContext,\n reason: ZeroError,\n closeCode?: CloseCode,\n ): void {\n if (shouldReportConnectError(reason)) {\n this.#connectErrorCount++;\n this.#metrics.lastConnectError.set(getLastConnectErrorValue(reason));\n this.#metrics.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#metrics.setConnectError(reason);\n if (\n this.#connectErrorCount % CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY ===\n 1\n ) {\n this.#checkConnectivity(`connectErrorCount=${this.#connectErrorCount}`);\n }\n }\n\n lc.info?.('disconnecting', {\n navigatorOnline: navigator?.onLine,\n reason: reason.kind,\n connectStart: this.#connectStart,\n totalToConnectStart: this.#totalToConnectStart,\n connectedAt: this.#connectedAt,\n connectionDuration: this.#connectedAt\n ? Date.now() - this.#connectedAt\n : 0,\n messageCount: this.#messageCount,\n connectionState: this.#connectionManager.state,\n connectErrorCount: this.#connectErrorCount,\n });\n\n const connectionStatus = this.#connectionManager.state.name;\n switch (connectionStatus) {\n case ConnectionStatus.Connected: {\n if (this.#connectStart !== undefined) {\n lc.error?.(\n 'disconnect() called while connected but connect start time is defined.',\n );\n // this._connectStart reset below.\n }\n break;\n }\n case ConnectionStatus.Closed:\n lc.debug?.('disconnect() called while closed');\n return;\n\n case ConnectionStatus.Disconnected:\n case ConnectionStatus.Connecting:\n case ConnectionStatus.NeedsAuth:\n case ConnectionStatus.Error:\n break;\n\n default:\n unreachable(connectionStatus);\n }\n\n this.#socketResolver = resolver();\n lc.debug?.('Creating new connect resolver');\n this.#connectResolver = resolver();\n this.#messageCount = 0;\n this.#connectStart = undefined; // don't reset this._totalToConnectStart\n this.#connectedAt = 0;\n this.#socket?.removeEventListener('message', this.#onMessage);\n this.#socket?.removeEventListener('open', this.#onOpen);\n this.#socket?.removeEventListener('close', this.#onClose);\n this.#socket?.close(closeCode);\n this.#socket = undefined;\n this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;\n this.#pokeHandler.handleDisconnect();\n\n const transition = getErrorConnectionTransition(reason);\n\n switch (transition.status) {\n case ConnectionStatus.NeedsAuth:\n this.#connectionManager.needsAuth(transition.reason);\n break;\n case ConnectionStatus.Error:\n this.#connectionManager.error(transition.reason);\n break;\n case ConnectionStatus.Disconnected:\n this.#connectionManager.disconnected(transition.reason);\n break;\n case ConnectionStatus.Closed:\n this.#connectionManager.closed();\n break;\n case NO_STATUS_TRANSITION:\n this.#connectionManager.connecting(transition.reason);\n break;\n default:\n unreachable(transition);\n }\n }\n\n #handlePokeStart(_lc: ZeroLogContext, pokeMessage: PokeStartMessage): void {\n this.#abortPingTimeout();\n this.#pokeHandler.handlePokeStart(pokeMessage[1]);\n }\n\n #handlePokePart(_lc: ZeroLogContext, pokeMessage: PokePartMessage): void {\n this.#abortPingTimeout();\n const lastMutationIDChangeForSelf = this.#pokeHandler.handlePokePart(\n pokeMessage[1],\n );\n if (lastMutationIDChangeForSelf !== undefined) {\n this.#lastMutationIDReceived = lastMutationIDChangeForSelf;\n }\n }\n\n #handlePokeEnd(_lc: ZeroLogContext, pokeMessage: PokeEndMessage): void {\n this.#abortPingTimeout();\n this.#pokeHandler.handlePokeEnd(pokeMessage[1]);\n }\n\n #onPokeError(): void {\n const lc = this.#lc;\n lc.info?.(\n 'poke error, disconnecting?',\n !this.#connectionManager.is(ConnectionStatus.Disconnected),\n );\n\n // It is theoretically possible that we get disconnected during the\n // async poke above. Only disconnect if we are not already\n // disconnected.\n if (!this.#connectionManager.is(ConnectionStatus.Disconnected)) {\n this.#disconnect(\n lc,\n new ClientError({\n kind: ClientErrorKind.UnexpectedBaseCookie,\n message: 'Server returned unexpected base cookie during sync',\n }),\n );\n }\n }\n\n #handlePullResponse(\n lc: ZeroLogContext,\n pullResponseMessage: PullResponseMessage,\n ): void {\n this.#abortPingTimeout();\n const body = pullResponseMessage[1];\n lc = lc.withContext('requestID', body.requestID);\n lc.debug?.('Handling pull response', body);\n const resolver = this.#pendingPullsByRequestID.get(body.requestID);\n if (!resolver) {\n // This can happen because resolvers are deleted\n // from this._pendingPullsByRequestID when pulls timeout.\n lc.debug?.('No resolver found');\n return;\n }\n resolver.resolve(pullResponseMessage[1]);\n }\n\n async #pusher(req: PushRequest, requestID: string): Promise<PusherResult> {\n // The deprecation of pushVersion 0 predates zero-client\n assert(req.pushVersion === 1);\n // If we are connecting we wait until we are connected.\n await this.#connectResolver.promise;\n const lc = this.#lc.withContext('requestID', requestID);\n lc.debug?.(`pushing ${req.mutations.length} mutations`);\n const socket = this.#socket;\n assert(socket);\n\n const isMutationRecoveryPush =\n req.clientGroupID !== (await this.clientGroupID);\n const start = isMutationRecoveryPush\n ? 0\n : req.mutations.findIndex(\n m =>\n m.clientID === this.#lastMutationIDSent.clientID &&\n m.id === this.#lastMutationIDSent.id,\n ) + 1;\n lc.debug?.(\n isMutationRecoveryPush ? 'pushing for recovery' : 'pushing',\n req.mutations.length - start,\n 'mutations of',\n req.mutations.length,\n 'mutations.',\n );\n const now = Date.now();\n for (let i = start; i < req.mutations.length; i++) {\n const m = req.mutations[i];\n const timestamp = now - Math.round(performance.now() - m.timestamp);\n const zeroM =\n m.name === CRUD_MUTATION_NAME\n ? ({\n type: MutationType.CRUD,\n timestamp,\n id: m.id,\n clientID: m.clientID,\n name: m.name,\n args: [mapCRUD(m.args as CRUDMutationArg, this.#clientToServer)],\n } satisfies CRUDMutation)\n : ({\n type: MutationType.Custom,\n timestamp,\n id: m.id,\n clientID: m.clientID,\n name: m.name,\n args: [m.args],\n } satisfies CustomMutation);\n const msg: PushMessage = [\n 'push',\n {\n timestamp: now,\n clientGroupID: req.clientGroupID,\n mutations: [zeroM],\n pushVersion: req.pushVersion,\n requestID,\n },\n ];\n send(socket, msg);\n if (!isMutationRecoveryPush) {\n this.#lastMutationIDSent = {clientID: m.clientID, id: m.id};\n }\n }\n return {\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n\n async #runLoop() {\n this.#lc.info?.(`Starting Zero version: ${this.version}`);\n\n if (this.#server === null) {\n this.#lc.info?.('No socket origin provided, not starting connect loop.');\n this.#connectionManager.error(\n new ClientError({\n kind: ClientErrorKind.NoSocketOrigin,\n message: 'No server socket origin provided',\n }),\n );\n return;\n }\n\n let runLoopCounter = 0;\n const bareLogContext = this.#lc;\n const getLogContext = () => {\n let lc = bareLogContext;\n if (this.#socket) {\n lc = addWebSocketIDFromSocketToLogContext(this.#socket, lc);\n }\n return lc.withContext('runLoopCounter', runLoopCounter);\n };\n\n // Set initial auth from options\n const {auth} = this.#options;\n this.#setAuth(auth);\n\n let backoffMs: number | undefined;\n let additionalConnectParams: Record<string, string> | undefined;\n\n while (this.#connectionManager.shouldContinueRunLoop()) {\n runLoopCounter++;\n let lc = getLogContext();\n backoffMs = RUN_LOOP_INTERVAL_MS;\n\n try {\n const currentState = this.#connectionManager.state;\n\n switch (currentState.name) {\n case ConnectionStatus.Connecting:\n case ConnectionStatus.Disconnected: {\n if (this.#visibilityWatcher.visibilityState === 'hidden') {\n this.#metrics.setDisconnectedWaitingForVisible();\n // reset this._totalToConnectStart since this client\n // is no longer trying to connect due to being hidden.\n this.#totalToConnectStart = undefined;\n }\n\n // If hidden, we wait for the tab to become visible before trying again.\n // or for a state change (e.g. an error)\n const visibilityResult = await promiseRace({\n visible: this.#visibilityWatcher.waitForVisible(),\n stateChange: this.#connectionManager.waitForStateChange(),\n });\n\n if (visibilityResult.key === 'stateChange') {\n throwIfConnectionError(visibilityResult.result);\n break;\n }\n\n // If a reload is pending, do not try to reconnect.\n if (reloadScheduled()) {\n break;\n }\n\n await this.#connect(lc, additionalConnectParams);\n additionalConnectParams = undefined;\n\n throwIfConnectionError(this.#connectionManager.state);\n\n // Now we have a new socket, update lc with the new wsid.\n assert(this.#socket);\n lc = getLogContext();\n\n lc.debug?.('Connected successfully');\n break;\n }\n\n case ConnectionStatus.Connected: {\n // When connected we wait for whatever happens first out of:\n // - After PING_INTERVAL_MS we send a ping\n // - We get a message\n // - The tab becomes hidden (with a delay)\n // - We get a state change (e.g. an error or disconnect)\n\n const controller = new AbortController();\n this.#abortPingTimeout = () => controller.abort();\n const [pingTimeoutPromise, pingTimeoutAborted] = sleepWithAbort(\n PING_INTERVAL_MS,\n controller.signal,\n );\n\n const raceResult = await promiseRace({\n waitForPing: pingTimeoutPromise,\n waitForPingAborted: pingTimeoutAborted,\n tabHidden: this.#visibilityWatcher.waitForHidden(),\n stateChange: this.#connectionManager.waitForStateChange(),\n });\n\n switch (raceResult.key) {\n case 'waitForPing': {\n await this.#ping(lc);\n break;\n }\n\n case 'waitForPingAborted':\n break;\n\n case 'tabHidden': {\n const hiddenError = new ClientError({\n kind: ClientErrorKind.Hidden,\n message: 'Connection closed because tab was hidden',\n });\n this.#disconnect(lc, hiddenError);\n break;\n }\n\n case 'stateChange':\n throwIfConnectionError(raceResult.result);\n break;\n\n default:\n unreachable(raceResult);\n }\n\n break;\n }\n\n case ConnectionStatus.NeedsAuth: {\n // we pause the run loop and wait for connect() to be called with new credentials\n lc.info?.(\n `Run loop paused in needs-auth state. Call zero.connection.connect({auth}) to resume.`,\n currentState.reason,\n );\n\n await this.#connectionManager.waitForStateChange();\n break;\n }\n\n case ConnectionStatus.Error: {\n // we pause the run loop and wait for a state change\n lc.info?.(\n `Run loop paused in error state. Call zero.connection.connect() to resume.`,\n currentState.reason,\n );\n\n await this.#connectionManager.waitForStateChange();\n break;\n }\n\n case ConnectionStatus.Closed:\n // run loop will terminate\n break;\n\n default:\n unreachable(currentState);\n }\n } catch (ex) {\n const isClientClosedError =\n isClientError(ex) && ex.kind === ClientErrorKind.ClientClosed;\n\n if (\n !this.#connectionManager.is(ConnectionStatus.Connected) &&\n !isClientClosedError\n ) {\n const level = isAuthError(ex) ? 'warn' : 'error';\n const kind = isServerError(ex) ? ex.kind : 'Unknown Error';\n lc[level]?.('Failed to connect', ex, kind, {\n lmid: this.#lastMutationIDReceived,\n baseCookie: this.#connectCookie,\n });\n }\n\n lc.debug?.(\n 'Got an exception in the run loop',\n 'state:',\n this.#connectionManager.state,\n 'exception:',\n ex,\n );\n\n const transition = getErrorConnectionTransition(ex);\n\n switch (transition.status) {\n case NO_STATUS_TRANSITION: {\n // We continue the loop because the error does not indicate\n // a need to transition to a new state and we should continue retrying\n\n const backoffParams = getBackoffParams(transition.reason);\n if (backoffParams) {\n if (backoffParams.minBackoffMs !== undefined) {\n backoffMs = Math.max(backoffMs, backoffParams.minBackoffMs);\n }\n if (backoffParams.maxBackoffMs !== undefined) {\n backoffMs = Math.min(backoffMs, backoffParams.maxBackoffMs);\n }\n additionalConnectParams = backoffParams.reconnectParams;\n }\n\n lc.debug?.(\n 'Sleeping',\n backoffMs,\n 'ms before reconnecting due to error, state:',\n this.#connectionManager.state,\n );\n await sleep(backoffMs);\n break;\n }\n case ConnectionStatus.NeedsAuth: {\n lc.debug?.(\n 'Auth error encountered, transitioning to needs-auth state',\n );\n this.#connectionManager.needsAuth(transition.reason);\n // run loop will enter the needs-auth state case and await a state change\n break;\n }\n case ConnectionStatus.Error: {\n lc.debug?.('Fatal error encountered, transitioning to error state');\n\n this.#connectionManager.error(transition.reason);\n // run loop will enter the error state case and await a state change\n break;\n }\n case ConnectionStatus.Disconnected: {\n this.#connectionManager.disconnected(transition.reason);\n break;\n }\n case ConnectionStatus.Closed: {\n break;\n }\n default:\n unreachable(transition);\n }\n }\n }\n }\n\n async #puller(req: PullRequest, requestID: string): Promise<PullerResult> {\n // The deprecation of pushVersion 0 predates zero-client\n assert(req.pullVersion === 1);\n const lc = this.#lc.withContext('requestID', requestID);\n lc.debug?.('Pull', req);\n // Pull request for this instance's client group. A no-op response is\n // returned as pulls for this client group are handled via poke over the\n // socket.\n if (req.clientGroupID === (await this.clientGroupID)) {\n return {\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n\n // If we are connecting we wait until we are connected.\n await this.#connectResolver.promise;\n const socket = this.#socket;\n assert(socket);\n // Mutation recovery pull.\n lc.debug?.('Pull is for mutation recovery');\n const cookie = valita.parse(\n req.cookie,\n nullableVersionSchema,\n 'passthrough',\n );\n const pullRequestMessage: PullRequestMessage = [\n 'pull',\n {\n clientGroupID: req.clientGroupID,\n cookie,\n requestID,\n },\n ];\n send(socket, pullRequestMessage);\n const pullResponseResolver: Resolver<PullResponseBody> = resolver();\n this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);\n try {\n const raceResult = await promiseRace({\n timeout: sleep(PULL_TIMEOUT_MS),\n success: pullResponseResolver.promise,\n });\n switch (raceResult.key) {\n case 'timeout':\n lc.debug?.('Mutation recovery pull timed out');\n throw new ClientError({\n kind: ClientErrorKind.PullTimeout,\n message: 'Pull timed out',\n });\n case 'success': {\n lc.debug?.('Returning mutation recovery pull response');\n const response = await pullResponseResolver.promise;\n return {\n response: {\n cookie: response.cookie,\n lastMutationIDChanges: response.lastMutationIDChanges,\n patch: [],\n },\n httpRequestInfo: {\n errorMessage: '',\n httpStatusCode: 200,\n },\n };\n }\n default:\n unreachable(raceResult);\n }\n } finally {\n pullResponseResolver.reject(\n new ClientError({\n kind: ClientErrorKind.PullTimeout,\n message: 'Pull timed out',\n }),\n );\n this.#pendingPullsByRequestID.delete(requestID);\n }\n }\n\n /**\n * Sets the authentication token on the replicache instance.\n *\n * @param auth - The authentication token to set.\n */\n #setAuth(auth: string | undefined | null): void {\n this.#rep.auth = toReplicacheAuthToken(auth);\n }\n\n /**\n * A rough heuristic for whether the client is currently online and\n * authenticated.\n *\n * @deprecated Use `connection` instead, which provides more detailed connection state.\n */\n get online(): boolean {\n return this.#onlineManager.online;\n }\n\n /**\n * Subscribe to online status changes.\n *\n * This is useful when you want to update state based on the online status.\n *\n * @param listener - The listener to subscribe to.\n * @returns A function to unsubscribe the listener.\n *\n * @deprecated Use `connection` instead, which provides more detailed connection state.\n */\n onOnline = (listener: (online: boolean) => void): (() => void) =>\n this.#onlineManager.subscribe(listener);\n\n /**\n * Starts a ping and waits for a pong.\n */\n async #ping(lc: ZeroLogContext): Promise<void> {\n lc.debug?.('pinging');\n const {promise, resolve} = resolver();\n this.#onPong = resolve;\n const pingMessage: PingMessage = ['ping', {}];\n const t0 = performance.now();\n assert(this.#socket);\n send(this.#socket, pingMessage);\n\n const raceResult = await promiseRace({\n waitForPong: promise,\n pingTimeout: sleep(PING_TIMEOUT_MS),\n stateChange: this.#connectionManager.waitForStateChange(),\n });\n\n const delta = performance.now() - t0;\n switch (raceResult.key) {\n case 'waitForPong': {\n lc.debug?.('ping succeeded in', delta, 'ms');\n return;\n }\n\n case 'pingTimeout': {\n lc.info?.('ping failed in', delta, 'ms - disconnecting');\n const pingTimeoutError = new ClientError({\n kind: ClientErrorKind.PingTimeout,\n message: 'Server ping request failed',\n });\n this.#disconnect(lc, pingTimeoutError);\n throw pingTimeoutError;\n }\n\n case 'stateChange': {\n lc.debug?.(\n 'ping aborted due to connection state change',\n raceResult.result,\n );\n throwIfConnectionError(raceResult.result);\n break;\n }\n\n default:\n unreachable(raceResult);\n }\n }\n\n // Sends a set of metrics to the server. Throws unless the server\n // returns 200.\n // TODO: Reenable metrics reporting\n async #reportMetrics(_allSeries: Series[]) {\n // if (this.#server === null) {\n // this.#lc.info?.('Skipping metrics report, socketOrigin is null');\n // return;\n // }\n // const body = JSON.stringify({series: allSeries});\n // const url = new URL('/api/metrics/v0/report', this.#server);\n // url.searchParams.set('clientID', this.clientID);\n // url.searchParams.set('clientGroupID', await this.clientGroupID);\n // url.searchParams.set('userID', this.userID);\n // url.searchParams.set('requestID', nanoid());\n // const res = await fetch(url.toString(), {\n // method: 'POST',\n // body,\n // keepalive: true,\n // });\n // if (!res.ok) {\n // const maybeBody = await res.text();\n // throw new Error(\n // `unexpected response: ${res.status} ${res.statusText} body: ${maybeBody}`,\n // );\n // }\n }\n\n #checkConnectivity(reason: string) {\n void this.#checkConnectivityAsync(reason);\n }\n\n #checkConnectivityAsync(_reason: string) {\n // skipping connectivity checks for now - the server doesn't respond to\n // them so it just creates noise.\n // assert(this.#server);\n // if (this.closed) {\n // return;\n // }\n // try {\n // await checkConnectivity(\n // reason,\n // this.#server,\n // this.#lc,\n // this.#closeAbortController.signal,\n // this.#enableAnalytics,\n // );\n // } catch (e) {\n // this.#lc.info?.('Error checking connectivity for', reason, e);\n // }\n }\n\n #registerQueries(schema: Schema): MakeEntityQueriesFromSchema<S> {\n const rv = {} as Record<string, Query<Schema, string>>;\n const context = this.#zeroContext;\n // Not using parse yet\n for (const name of Object.keys(schema.tables)) {\n rv[name] = newQuery(context, schema, name);\n }\n\n return rv as MakeEntityQueriesFromSchema<S>;\n }\n\n /**\n * `inspector` is an object that can be used to inspect the state of the\n * queries a Zero instance uses. It is intended for debugging purposes.\n */\n get inspector(): Inspector {\n // We use esbuild dropLabels to strip this code when we build the code for the bundle size dashboard.\n // https://esbuild.github.io/api/#ignore-annotations\n // /packages/zero/tool/build.ts\n\n // oxlint-disable-next-line no-unused-labels\n BUNDLE_SIZE: {\n return (this.#inspector ??= new Inspector(\n this.#rep,\n this.#queryManager,\n async () => {\n await this.#connectResolver.promise;\n return this.#socket!;\n },\n ));\n }\n }\n\n #addMetric: <K extends keyof MetricMap>(\n metric: K,\n value: number,\n ...args: MetricMap[K]\n ) => void = (metric, value, ...args) => {\n assert(isClientMetric(metric), `Invalid metric: ${metric}`);\n this.#queryManager.addMetric(\n metric as keyof ClientMetricMap,\n value,\n ...(args as ClientMetricMap[keyof ClientMetricMap]),\n );\n };\n}\n\nexport class OnlineManager extends Subscribable<boolean> {\n #online = false;\n\n setOnline(online: boolean): void {\n if (this.#online === online) {\n return;\n }\n this.#online = online;\n this.notify(online);\n }\n\n get online(): boolean {\n return this.#online;\n }\n}\n\nexport async function createSocket(\n rep: ReplicacheImpl,\n queryManager: QueryManager,\n deleteClientsManager: DeleteClientsManager,\n socketOrigin: WSString,\n baseCookie: NullableVersion,\n clientID: string,\n clientGroupID: string,\n clientSchema: ClientSchema,\n userID: string,\n auth: string | undefined,\n lmid: number,\n wsid: string,\n debugPerf: boolean,\n lc: ZeroLogContext,\n userPushURL: string | undefined,\n userQueryURL: string | undefined,\n additionalConnectParams: Record<string, string> | undefined,\n activeClientsManager: Pick<ActiveClientsManager, 'activeClients'>,\n maxHeaderLength = 1024 * 8,\n): Promise<\n [\n WebSocket,\n Map<string, UpQueriesPatchOp> | undefined,\n DeleteClientsBody | undefined,\n ]\n> {\n const url = new URL(\n appendPath(socketOrigin, `/sync/v${PROTOCOL_VERSION}/connect`),\n );\n const {searchParams} = url;\n searchParams.set('clientID', clientID);\n searchParams.set('clientGroupID', clientGroupID);\n searchParams.set('userID', userID);\n searchParams.set('baseCookie', baseCookie === null ? '' : String(baseCookie));\n searchParams.set('ts', String(performance.now()));\n searchParams.set('lmid', String(lmid));\n searchParams.set('wsid', wsid);\n if (debugPerf) {\n searchParams.set('debugPerf', true.toString());\n }\n if (additionalConnectParams) {\n for (const k in additionalConnectParams) {\n if (searchParams.has(k)) {\n lc.warn?.(`skipping conflicting parameter ${k}`);\n } else {\n searchParams.set(k, additionalConnectParams[k]);\n }\n }\n }\n\n lc.info?.('Connecting to', url.toString());\n\n // Pass auth to the server via the `Sec-WebSocket-Protocol` header by passing\n // it as a `protocol` to the `WebSocket` constructor. The empty string is an\n // invalid `protocol`, and will result in an exception, so pass undefined\n // instead. encodeURIComponent to ensure it only contains chars allowed\n // for a `protocol`.\n const WS = mustGetBrowserGlobal('WebSocket');\n const queriesPatchP = rep.query(tx => queryManager.getQueriesPatch(tx));\n const deletedClientsArray = await deleteClientsManager.getDeletedClients();\n let deletedClients: DeleteClientsBody | undefined =\n convertDeletedClientsToBody(deletedClientsArray, clientGroupID);\n let queriesPatch: Map<string, UpQueriesPatchOp> | undefined =\n await queriesPatchP;\n const {activeClients} = activeClientsManager;\n\n let secProtocol = encodeSecProtocols(\n [\n 'initConnection',\n {\n desiredQueriesPatch: [...queriesPatch.values()],\n deleted: skipEmptyDeletedClients(deletedClients),\n // The clientSchema only needs to be sent for the very first request.\n // Henceforth it is stored with the CVR and verified automatically.\n ...(baseCookie === null ? {clientSchema} : {}),\n userPushURL,\n userQueryURL,\n activeClients: [...activeClients],\n },\n ],\n auth,\n );\n if (secProtocol.length > maxHeaderLength) {\n secProtocol = encodeSecProtocols(undefined, auth);\n if (secProtocol.length > maxHeaderLength) {\n lc.warn?.(\n `Encoded auth token length (${secProtocol.length}) exceeds ` +\n `ZeroOptions.maxHeaderLength (${maxHeaderLength}). This may ` +\n `cause connection failures.`,\n );\n }\n queriesPatch = undefined;\n } else {\n deletedClients = undefined;\n }\n return [\n new WS(\n // toString() required for RN URL polyfill.\n url.toString(),\n secProtocol,\n ),\n queriesPatch,\n skipEmptyDeletedClients(deletedClients),\n ];\n}\n\nfunction skipEmptyArray<T>(\n arr: readonly T[] | undefined,\n): readonly T[] | undefined {\n return arr && arr.length > 0 ? arr : undefined;\n}\n\nfunction skipEmptyDeletedClients(\n deletedClients: DeleteClientsBody | undefined,\n): DeleteClientsBody | undefined {\n if (!deletedClients) {\n return undefined;\n }\n const {clientIDs, clientGroupIDs} = deletedClients;\n if (\n (!clientIDs || clientIDs.length === 0) &&\n (!clientGroupIDs || clientGroupIDs.length === 0)\n ) {\n return undefined;\n }\n const data: Writable<DeleteClientsBody> = {};\n data.clientIDs = skipEmptyArray(clientIDs);\n data.clientGroupIDs = skipEmptyArray(clientGroupIDs);\n return data;\n}\n\nfunction convertDeletedClientsToBody(\n deletedClients: DeletedClients,\n clientGroupID: ClientGroupID,\n): DeleteClientsBody | undefined {\n if (deletedClients.length === 0) {\n return undefined;\n }\n\n const clientIDs = deletedClients\n .filter(pair => pair.clientID && pair.clientGroupID === clientGroupID)\n .map(pair => pair.clientID);\n if (clientIDs.length === 0) {\n return undefined;\n }\n\n // We no longer send clientGroupIDs\n return {clientIDs};\n}\n\n/**\n * Adds the wsid query parameter to the log context. If the URL does not\n * have a wsid we use a randomID instead.\n */\nfunction addWebSocketIDFromSocketToLogContext(\n {url}: {url: string},\n lc: ZeroLogContext,\n): ZeroLogContext {\n const wsid = new URL(url).searchParams.get('wsid') ?? nanoid();\n return addWebSocketIDToLogContext(wsid, lc);\n}\n\nfunction addWebSocketIDToLogContext(\n wsid: string,\n lc: ZeroLogContext,\n): ZeroLogContext {\n return lc.withContext('wsid', wsid);\n}\n\nfunction assertValidRunOptions(_options?: RunOptions): void {}\n\nasync function makeActiveClientsManager(\n clientGroupID: Promise<string>,\n clientID: string,\n signal: AbortSignal,\n onDelete: ActiveClientsManager['onDelete'],\n): Promise<ActiveClientsManager> {\n const manager = await ActiveClientsManager.create(\n await clientGroupID,\n clientID,\n signal,\n );\n manager.onDelete = onDelete;\n return manager;\n}\n", "import {Lock} from '@rocicorp/lock';\nimport {consoleLogSink, LogContext} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {getBrowserGlobal} from '../../shared/src/browser-env.ts';\nimport {getDocumentVisibilityWatcher} from '../../shared/src/document-visible.ts';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {promiseVoid} from '../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport {PullDelegate, PushDelegate} from './connection-loop-delegates.ts';\nimport {ConnectionLoop, MAX_DELAY_MS, MIN_DELAY_MS} from './connection-loop.ts';\nimport {assertCookie, type Cookie} from './cookies.ts';\nimport {LazyStore} from './dag/lazy-store.ts';\nimport {StoreImpl} from './dag/store-impl.ts';\nimport {ChunkNotFoundError, mustGetHeadHash, type Store} from './dag/store.ts';\nimport {\n baseSnapshotFromHash,\n DEFAULT_HEAD_NAME,\n isLocalMetaDD31,\n type LocalMeta,\n} from './db/commit.ts';\nimport {readFromDefaultHead} from './db/read.ts';\nimport {rebaseMutationAndCommit} from './db/rebase.ts';\nimport {newWriteLocal} from './db/write.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.ts';\nimport * as FormatVersion from './format-version-enum.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport {getDefaultPuller, isDefaultPuller} from './get-default-puller.ts';\nimport {getDefaultPusher, isDefaultPusher} from './get-default-pusher.ts';\nimport {getKVStoreProvider} from './get-kv-store-provider.ts';\nimport {assertHash, emptyHash, type Hash, newRandomHash} from './hash.ts';\nimport type {HTTPRequestInfo} from './http-request-info.ts';\nimport {httpStatusUnauthorized} from './http-status-unauthorized.ts';\nimport type {IndexDefinitions} from './index-defs.ts';\nimport type {StoreProvider} from './kv/store.ts';\nimport {createLogContext} from './log-options.ts';\nimport {makeIDBName} from './make-idb-name.ts';\nimport {MutationRecovery} from './mutation-recovery.ts';\nimport {initNewClientChannel} from './new-client-channel.ts';\nimport {\n initOnPersistChannel,\n type OnPersist,\n type PersistInfo,\n} from './on-persist-channel.ts';\nimport {\n type PendingMutation,\n pendingMutationsForAPI,\n} from './pending-mutations.ts';\nimport {\n CLIENT_MAX_INACTIVE_TIME,\n GC_INTERVAL,\n initClientGC,\n} from './persist/client-gc.ts';\nimport {initClientGroupGC} from './persist/client-group-gc.ts';\nimport {disableClientGroup} from './persist/client-groups.ts';\nimport {\n ClientStateNotFoundError,\n initClientV6,\n type OnClientsDeleted,\n hasClientState as persistHasClientState,\n} from './persist/clients.ts';\nimport {\n COLLECT_IDB_INTERVAL,\n initCollectIDBDatabases,\n INITIAL_COLLECT_IDB_DELAY,\n} from './persist/collect-idb-databases.ts';\nimport {HEARTBEAT_INTERVAL, startHeartbeats} from './persist/heartbeat.ts';\nimport {\n IDBDatabasesStore,\n type IndexedDBDatabase,\n} from './persist/idb-databases-store.ts';\nimport {makeClientID} from './persist/make-client-id.ts';\nimport {persistDD31} from './persist/persist.ts';\nimport {refresh} from './persist/refresh.ts';\nimport {ProcessScheduler} from './process-scheduler.ts';\nimport type {Puller} from './puller.ts';\nimport {type Pusher, PushError} from './pusher.ts';\nimport type {\n MutationTrackingData,\n ReplicacheOptions,\n ZeroOption,\n} from './replicache-options.ts';\nimport {ReportError} from './report-error.ts';\nimport {setIntervalWithSignal} from './set-interval-with-signal.ts';\nimport {\n type SubscribeOptions,\n SubscriptionImpl,\n type SubscriptionsManager,\n SubscriptionsManagerImpl,\n type WatchCallback,\n type WatchCallbackForOptions,\n type WatchNoIndexCallback,\n type WatchOptions,\n WatchSubscription,\n} from './subscriptions.ts';\nimport type {DiffsMap} from './sync/diff.ts';\nimport * as HandlePullResponseResultEnum from './sync/handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './sync/ids.ts';\nimport {PullError} from './sync/pull-error.ts';\nimport {beginPullV1, handlePullResponseV1, maybeEndPull} from './sync/pull.ts';\nimport {push, PUSH_VERSION_DD31} from './sync/push.ts';\nimport {newRequestID} from './sync/request-id.ts';\nimport {SYNC_HEAD_NAME} from './sync/sync-head-name.ts';\nimport {throwIfClosed} from './transaction-closed-error.ts';\nimport type {ReadTransaction, WriteTransaction} from './transactions.ts';\nimport {ReadTransactionImpl, WriteTransactionImpl} from './transactions.ts';\nimport type {\n BeginPullResult,\n MakeMutator,\n MakeMutators,\n MutatorDefs,\n MutatorReturn,\n PokeInternal,\n QueryInternal,\n RequestOptions,\n UpdateNeededReason,\n} from './types.ts';\nimport {version} from './version.ts';\nimport {\n withRead,\n withWrite,\n withWriteNoImplicitCommit,\n} from './with-transactions.ts';\n\ndeclare const TESTING: boolean;\n\ndeclare const process: {\n env: {\n ['DISABLE_MUTATION_RECOVERY']?: string | undefined;\n };\n};\n\n/**\n * The maximum number of time to call out to getAuth before giving up\n * and throwing an error.\n */\nconst MAX_REAUTH_TRIES = 8;\n\nconst PERSIST_IDLE_TIMEOUT_MS = 1000;\nconst REFRESH_IDLE_TIMEOUT_MS = 1000;\n\nconst PERSIST_THROTTLE_MS = 500;\nconst REFRESH_THROTTLE_MS = 500;\n\nconst LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 100 * 2 ** 20; // 100 MB\n\nconst RECOVER_MUTATIONS_INTERVAL_MS = 5 * 60 * 1000; // 5 mins\n\nconst noop = () => {\n // noop\n};\n\nconst updateNeededReasonNewClientGroup: UpdateNeededReason = {\n type: 'NewClientGroup',\n} as const;\n\n/** @deprecated Not used any more */\nexport interface MakeSubscriptionsManager {\n (queryInternal: QueryInternal, lc: LogContext): SubscriptionsManager;\n}\n\nexport interface ReplicacheImplOptions {\n /**\n * Defaults to true.\n */\n enableMutationRecovery?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledPersist?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enableScheduledRefresh?: boolean | undefined;\n\n /**\n * Defaults to true.\n */\n enablePullAndPushInOpen?: boolean | undefined;\n\n /**\n * @deprecated Not used anymore.\n */\n makeSubscriptionsManager?: unknown;\n\n /**\n * Default is `true`. If `false` if an exact match client group\n * is not found, a new client group is always made instead of forking\n * from an existing client group.\n */\n enableClientGroupForking?: boolean | undefined;\n\n /**\n * Callback for when Replicache has deleted clients.\n */\n onClientsDeleted?: OnClientsDeleted | undefined;\n\n /**\n * Internal option used by Zero.\n * Replicache will call this to and, if zero is enabled, will\n * invoke various hooks to allow Zero the keep IVM in sync with Replicache's b-trees.\n */\n zero?: ZeroOption | undefined;\n}\n\nexport class ReplicacheImpl<MD extends MutatorDefs = {}> {\n /** The URL to use when doing a pull request. */\n pullURL: string;\n\n /** The URL to use when doing a push request. */\n pushURL: string;\n\n /** The authorization token used when doing a push request. */\n #auth: string;\n\n /** The name of the Replicache database. Populated by {@link ReplicacheOptions#name}. */\n readonly name: string;\n\n readonly #subscriptions: SubscriptionsManager;\n readonly #mutationRecovery: MutationRecovery | undefined;\n\n /**\n * Client groups gets disabled when the server does not know about it.\n * A disabled client group prevents the client from pushing and pulling.\n */\n isClientGroupDisabled = false;\n\n readonly #kvStoreProvider: StoreProvider;\n\n lastMutationID: number = 0;\n\n /**\n * This is the name Replicache uses for the IndexedDB database where data is\n * stored.\n */\n get idbName(): string {\n return makeIDBName(this.name, this.schemaVersion);\n }\n\n set auth(auth: string) {\n if (this.#zero) {\n this.#zero.auth = auth;\n }\n\n this.#auth = auth;\n }\n\n get auth() {\n return this.#auth;\n }\n\n /** The schema version of the data understood by this application. */\n readonly schemaVersion: string;\n\n get #idbDatabase(): IndexedDBDatabase {\n return {\n name: this.idbName,\n replicacheName: this.name,\n replicacheFormatVersion: FormatVersion.Latest,\n schemaVersion: this.schemaVersion,\n };\n }\n #closed = false;\n #online = true;\n readonly #clientID = makeClientID();\n readonly #ready: Promise<void>;\n readonly #profileIDPromise: Promise<string>;\n readonly #clientGroupIDPromise: Promise<string>;\n readonly #mutatorRegistry: MutatorDefs = {};\n\n /**\n * The mutators that was registered in the constructor.\n */\n readonly mutate: MakeMutators<MD>;\n\n // Number of pushes/pulls at the moment.\n #pushCounter = 0;\n #pullCounter = 0;\n\n #pullConnectionLoop: ConnectionLoop;\n #pushConnectionLoop: ConnectionLoop;\n\n /**\n * The duration between each periodic {@link pull}. Setting this to `null`\n * disables periodic pull completely. Pull will still happen if you call\n * {@link pull} manually.\n */\n pullInterval: number | null;\n\n /**\n * The delay between when a change is made to Replicache and when Replicache\n * attempts to push that change.\n */\n pushDelay: number;\n\n readonly #requestOptions: Required<RequestOptions>;\n\n /**\n * The function to use to pull data from the server.\n */\n puller: Puller;\n\n /**\n * The function to use to push data to the server.\n */\n pusher: Pusher;\n\n readonly memdag: LazyStore;\n readonly perdag: Store;\n readonly #idbDatabases: IDBDatabasesStore;\n readonly #lc: LogContext;\n readonly #zero: ZeroOption | undefined;\n\n readonly #closeAbortController = new AbortController();\n\n readonly #persistLock = new Lock();\n readonly #enableScheduledPersist: boolean;\n readonly #enableScheduledRefresh: boolean;\n readonly #enablePullAndPushInOpen: boolean;\n #persistScheduler = new ProcessScheduler(\n () => this.persist(),\n PERSIST_IDLE_TIMEOUT_MS,\n PERSIST_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n readonly #onPersist: OnPersist;\n #refreshScheduler = new ProcessScheduler(\n () => this.refresh(),\n REFRESH_IDLE_TIMEOUT_MS,\n REFRESH_THROTTLE_MS,\n this.#closeAbortController.signal,\n );\n\n /**\n * The options used to control the {@link pull} and push request behavior. This\n * object is live so changes to it will affect the next pull or push call.\n */\n get requestOptions(): Required<RequestOptions> {\n return this.#requestOptions;\n }\n\n /**\n * `onSync(true)` is called when Replicache transitions from no push or pull\n * happening to at least one happening. `onSync(false)` is called in the\n * opposite case: when Replicache transitions from at least one push or pull\n * happening to none happening.\n *\n * This can be used in a React like app by doing something like the following:\n *\n * ```js\n * const [syncing, setSyncing] = useState(false);\n * useEffect(() => {\n * rep.onSync = setSyncing;\n * }, [rep]);\n * ```\n */\n onSync: ((syncing: boolean) => void) | null = null;\n\n /**\n * `onClientStateNotFound` is called when the persistent client has been\n * garbage collected. This can happen if the client has no pending mutations\n * and has not been used for a while.\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically.\n */\n onClientStateNotFound: (() => void) | null = reload;\n\n /**\n * `onUpdateNeeded` is called when a code update is needed.\n *\n * A code update can be needed because:\n * - the server no longer supports the {@link pushVersion},\n * {@link pullVersion} or {@link schemaVersion} of the current code.\n * - a new Replicache client has created a new client group, because its code\n * has different mutators, indexes, schema version and/or format version\n * from this Replicache client. This is likely due to the new client having\n * newer code. A code update is needed to be able to locally sync with this\n * new Replicache client (i.e. to sync while offline, the clients can still\n * sync with each other via the server).\n *\n * The default behavior is to reload the page (using `location.reload()`). Set\n * this to `null` or provide your own function to prevent the page from\n * reloading automatically. You may want to provide your own function to\n * display a toast to inform the end user there is a new version of your app\n * available and prompting them to refresh.\n */\n onUpdateNeeded: ((reason: UpdateNeededReason) => void) | null = reload;\n\n /**\n * This gets called when we get an HTTP unauthorized (401) response from the\n * push or pull endpoint. Set this to a function that will ask your user to\n * reauthenticate.\n */\n getAuth: (() => MaybePromise<string | null | undefined>) | null | undefined =\n null;\n\n // These three are used for testing\n onPushInvoked = () => undefined;\n onBeginPull = () => undefined;\n onRecoverMutations = (r: Promise<boolean>) => r;\n\n constructor(\n options: ReplicacheOptions<MD>,\n implOptions: ReplicacheImplOptions = {},\n ) {\n validateOptions(options);\n const {\n name,\n logLevel = 'info',\n logSinks = [consoleLogSink],\n pullURL = '',\n auth,\n pushDelay = 10,\n pushURL = '',\n schemaVersion = '',\n pullInterval = 60000,\n mutators = {} as MD,\n requestOptions = {},\n puller,\n pusher,\n indexes = {},\n clientMaxAgeMs = CLIENT_MAX_INACTIVE_TIME,\n } = options;\n const {\n enableMutationRecovery = true,\n enableScheduledPersist = true,\n enableScheduledRefresh = true,\n enablePullAndPushInOpen = true,\n enableClientGroupForking = true,\n onClientsDeleted = () => promiseVoid,\n } = implOptions;\n this.#zero = implOptions.zero;\n this.#auth = auth ?? '';\n this.pullURL = pullURL;\n this.pushURL = pushURL;\n this.name = name;\n this.schemaVersion = schemaVersion;\n this.pullInterval = pullInterval;\n this.pushDelay = pushDelay;\n this.puller = puller ?? getDefaultPuller(this);\n this.pusher = pusher ?? getDefaultPusher(this);\n\n this.#enableScheduledPersist = enableScheduledPersist;\n this.#enableScheduledRefresh = enableScheduledRefresh;\n this.#enablePullAndPushInOpen = enablePullAndPushInOpen;\n\n this.#lc = createLogContext(logLevel, logSinks, {name});\n this.#lc.debug?.('Constructing Replicache', {\n name,\n 'replicache version': version,\n });\n\n this.#subscriptions = new SubscriptionsManagerImpl(\n this.#queryInternal,\n this.#lc,\n this.#closeAbortController.signal,\n );\n\n const kvStoreProvider = getKVStoreProvider(this.#lc, options.kvStore);\n this.#kvStoreProvider = kvStoreProvider;\n\n const perKVStore = kvStoreProvider.create(this.idbName);\n\n this.#idbDatabases = new IDBDatabasesStore(kvStoreProvider.create);\n this.perdag = new StoreImpl(perKVStore, newRandomHash, assertHash);\n this.memdag = new LazyStore(\n this.perdag,\n LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n newRandomHash,\n assertHash,\n );\n\n // Use a promise-resolve pair so that we have a promise to use even before\n // we call the Open RPC.\n const readyResolver = resolver<void>();\n this.#ready = readyResolver.promise;\n\n const {minDelayMs = MIN_DELAY_MS, maxDelayMs = MAX_DELAY_MS} =\n requestOptions;\n this.#requestOptions = {maxDelayMs, minDelayMs};\n\n const visibilityWatcher = getDocumentVisibilityWatcher(\n getBrowserGlobal('document'),\n 0,\n this.#closeAbortController.signal,\n );\n\n this.#pullConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PULL'),\n new PullDelegate(this, () => this.#invokePull()),\n visibilityWatcher,\n );\n\n this.#pushConnectionLoop = new ConnectionLoop(\n this.#lc.withContext('PUSH'),\n new PushDelegate(this, () => this.#invokePush()),\n );\n\n this.mutate = this.#registerMutators(mutators);\n\n const profileIDResolver = resolver<string>();\n this.#profileIDPromise = profileIDResolver.promise;\n const clientGroupIDResolver = resolver<string>();\n this.#clientGroupIDPromise = clientGroupIDResolver.promise;\n\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n this.#mutationRecovery = new MutationRecovery({\n delegate: this,\n lc: this.#lc,\n enableMutationRecovery,\n wrapInOnlineCheck: this.#wrapInOnlineCheck.bind(this),\n wrapInReauthRetries: this.#wrapInReauthRetries.bind(this),\n isPullDisabled: this.#isPullDisabled.bind(this),\n isPushDisabled: this.#isPushDisabled.bind(this),\n clientGroupIDPromise: this.#clientGroupIDPromise,\n });\n }\n\n this.#onPersist = initOnPersistChannel(\n this.name,\n this.#closeAbortController.signal,\n persistInfo => {\n void this.#handlePersist(persistInfo);\n },\n );\n\n void this.#open(\n indexes,\n enableClientGroupForking,\n enableMutationRecovery,\n clientMaxAgeMs,\n profileIDResolver.resolve,\n clientGroupIDResolver.resolve,\n readyResolver.resolve,\n onClientsDeleted,\n );\n }\n\n async #open(\n indexes: IndexDefinitions,\n enableClientGroupForking: boolean,\n enableMutationRecovery: boolean,\n clientMaxAgeMs: number,\n profileIDResolver: (profileID: string) => void,\n resolveClientGroupID: (clientGroupID: ClientGroupID) => void,\n resolveReady: () => void,\n onClientsDeleted: OnClientsDeleted,\n ): Promise<void> {\n const {clientID} = this;\n // If we are currently closing a Replicache instance with the same name,\n // wait for it to finish closing.\n await closingInstances.get(this.name);\n await this.#idbDatabases.getProfileID().then(profileIDResolver);\n await this.#idbDatabases.putDatabase(this.#idbDatabase);\n const [client, headHash, , isNewClientGroup] = await initClientV6(\n clientID,\n this.#lc,\n this.perdag,\n Object.keys(this.#mutatorRegistry),\n indexes,\n FormatVersion.Latest,\n enableClientGroupForking,\n );\n\n resolveClientGroupID(client.clientGroupID);\n await withWrite(this.memdag, write =>\n write.setHead(DEFAULT_HEAD_NAME, headHash),\n );\n\n // Now we have a profileID, a clientID, a clientGroupID and DB!\n await this.#zero?.init(headHash, this.memdag);\n resolveReady();\n\n if (this.#enablePullAndPushInOpen) {\n this.pull().catch(noop);\n this.push().catch(noop);\n }\n\n const {signal} = this.#closeAbortController;\n\n startHeartbeats(\n clientID,\n this.perdag,\n () => {\n this.#clientStateNotFoundOnClient(clientID);\n },\n HEARTBEAT_INTERVAL,\n this.#lc,\n signal,\n );\n initClientGC(\n clientID,\n this.perdag,\n clientMaxAgeMs,\n GC_INTERVAL,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initCollectIDBDatabases(\n this.#idbDatabases,\n this.#kvStoreProvider.drop,\n COLLECT_IDB_INTERVAL,\n INITIAL_COLLECT_IDB_DELAY,\n 2 * clientMaxAgeMs,\n enableMutationRecovery,\n onClientsDeleted,\n this.#lc,\n signal,\n );\n initClientGroupGC(this.perdag, enableMutationRecovery, this.#lc, signal);\n initNewClientChannel(\n this.name,\n this.idbName,\n signal,\n client.clientGroupID,\n isNewClientGroup,\n () => {\n this.#fireOnUpdateNeeded(updateNeededReasonNewClientGroup);\n },\n this.perdag,\n );\n\n setIntervalWithSignal(\n () => this.recoverMutations(),\n RECOVER_MUTATIONS_INTERVAL_MS,\n signal,\n );\n void this.recoverMutations();\n\n getBrowserGlobal('document')?.addEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n }\n\n #onVisibilityChange = async () => {\n if (this.#closed) {\n return;\n }\n\n // In case of running in a worker, we don't have a document.\n if (getBrowserGlobal('document')?.visibilityState !== 'visible') {\n return;\n }\n\n await this.#checkForClientStateNotFoundAndCallHandler();\n };\n\n async #checkForClientStateNotFoundAndCallHandler(): Promise<boolean> {\n const {clientID} = this;\n const hasClientState = await withRead(this.perdag, read =>\n persistHasClientState(clientID, read),\n );\n if (!hasClientState) {\n this.#clientStateNotFoundOnClient(clientID);\n }\n return !hasClientState;\n }\n\n /**\n * The browser profile ID for this browser profile. Every instance of Replicache\n * browser-profile-wide shares the same profile ID.\n */\n get profileID(): Promise<string> {\n return this.#profileIDPromise;\n }\n\n /**\n * The client ID for this instance of Replicache. Each instance of Replicache\n * gets a unique client ID.\n */\n get clientID(): string {\n return this.#clientID;\n }\n\n /**\n * The client group ID for this instance of Replicache. Instances of\n * Replicache will have the same client group ID if and only if they have\n * the same name, mutators, indexes, schema version, format version, and\n * browser profile.\n */\n get clientGroupID(): Promise<string> {\n return this.#clientGroupIDPromise;\n }\n\n /**\n * `onOnlineChange` is called when the {@link online} property changes. See\n * {@link online} for more details.\n */\n onOnlineChange: ((online: boolean) => void) | null = null;\n\n /**\n * A rough heuristic for whether the client is currently online. Note that\n * there is no way to know for certain whether a client is online - the next\n * request can always fail. This property returns true if the last sync attempt succeeded,\n * and false otherwise.\n */\n get online(): boolean {\n return this.#online;\n }\n\n /**\n * Whether the Replicache database has been closed. Once Replicache has been\n * closed it no longer syncs and you can no longer read or write data out of\n * it. After it has been closed it is pretty much useless and should not be\n * used any more.\n */\n get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Closes this Replicache instance.\n *\n * When closed all subscriptions end and no more read or writes are allowed.\n */\n async close(): Promise<void> {\n this.#closed = true;\n const {promise, resolve} = resolver();\n closingInstances.set(this.name, promise);\n\n this.#closeAbortController.abort();\n\n getBrowserGlobal('document')?.removeEventListener(\n 'visibilitychange',\n this.#onVisibilityChange,\n );\n\n await this.#ready;\n const closingPromises = [\n this.memdag.close(),\n this.perdag.close(),\n this.#idbDatabases.close(),\n ];\n\n this.#pullConnectionLoop.close();\n this.#pushConnectionLoop.close();\n\n this.#subscriptions.clear();\n\n await Promise.all(closingPromises);\n closingInstances.delete(this.name);\n resolve();\n }\n\n async maybeEndPull(syncHead: Hash, requestID: string): Promise<void> {\n for (;;) {\n if (this.#closed) {\n return;\n }\n\n await this.#ready;\n const {clientID} = this;\n const lc = this.#lc\n .withContext('maybeEndPull')\n .withContext('requestID', requestID);\n const {replayMutations, diffs, oldMainHead, mainHead} =\n await maybeEndPull<LocalMeta>(\n this.memdag,\n lc,\n syncHead,\n clientID,\n this.#subscriptions,\n FormatVersion.Latest,\n );\n\n if (!replayMutations || replayMutations.length === 0) {\n // All done.\n this.#zero?.advance(oldMainHead, mainHead, diffs.get('') ?? []);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return;\n }\n\n // Replay.\n const zeroData = await this.#zero?.getTxData?.(syncHead);\n for (const mutation of replayMutations) {\n // TODO(greg): I'm not sure why this was in Replicache#_mutate...\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n const {meta} = mutation;\n syncHead = await withWriteNoImplicitCommit(this.memdag, dagWrite =>\n rebaseMutationAndCommit(\n mutation,\n dagWrite,\n syncHead,\n SYNC_HEAD_NAME,\n this.#mutatorRegistry,\n lc,\n isLocalMetaDD31(meta) ? meta.clientID : clientID,\n FormatVersion.Latest,\n zeroData,\n ),\n );\n }\n }\n }\n\n #invokePull(): Promise<boolean> {\n if (this.#isPullDisabled()) {\n return Promise.resolve(true);\n }\n\n return this.#wrapInOnlineCheck(async () => {\n try {\n this.#changeSyncCounters(0, 1);\n const {syncHead, requestID, ok} = await this.beginPull();\n if (!ok) {\n return false;\n }\n if (syncHead !== emptyHash) {\n await this.maybeEndPull(syncHead, requestID);\n }\n } catch (e) {\n throw await this.#convertToClientStateNotFoundError(e);\n } finally {\n this.#changeSyncCounters(0, -1);\n }\n return true;\n }, 'Pull');\n }\n\n #isPullDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pullURL === '' && isDefaultPuller(this.puller))\n );\n }\n\n async #wrapInOnlineCheck(\n f: () => Promise<boolean>,\n name: string,\n ): Promise<boolean> {\n let online = true;\n\n try {\n return await f();\n } catch (e) {\n // The error paths of beginPull and maybeEndPull need to be reworked.\n //\n // We want to distinguish between:\n // a) network requests failed -- we're offline basically\n // b) sync was aborted because one's already in progress\n // c) oh noes - something unexpected happened\n //\n // Right now, all of these come out as errors. We distinguish (b) with a\n // hacky string search. (a) and (c) are not distinguishable currently\n // because repc doesn't provide sufficient information, so we treat all\n // errors that aren't (b) as (a).\n if (e instanceof PushError || e instanceof PullError) {\n online = false;\n this.#lc.debug?.(`${name} threw:\\n`, e, '\\nwith cause:\\n', e.causedBy);\n } else if (e instanceof ReportError) {\n this.#lc.error?.(e);\n } else {\n this.#lc.info?.(`${name} threw:\\n`, e);\n }\n return false;\n } finally {\n if (this.#online !== online) {\n this.#online = online;\n this.onOnlineChange?.(online);\n if (online) {\n void this.recoverMutations();\n }\n }\n }\n }\n\n async #wrapInReauthRetries<R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth: () => MaybePromise<void> = noop,\n postAuth: () => MaybePromise<void> = noop,\n ): Promise<{\n result: R;\n authFailure: boolean;\n }> {\n const {clientID} = this;\n let reauthAttempts = 0;\n let lastResult;\n lc = lc.withContext(verb);\n do {\n const requestID = newRequestID(clientID);\n const requestLc = lc.withContext('requestID', requestID);\n const {httpRequestInfo, result} = await f(requestID, requestLc);\n lastResult = result;\n if (!httpRequestInfo) {\n return {\n result,\n authFailure: false,\n };\n }\n const {errorMessage, httpStatusCode} = httpRequestInfo;\n\n if (errorMessage || httpStatusCode !== 200) {\n // TODO(arv): Maybe we should not log the server URL when the error comes\n // from a Pusher/Puller?\n requestLc.error?.(\n `Got a non 200 response doing ${verb}: ${httpStatusCode}` +\n (errorMessage ? `: ${errorMessage}` : ''),\n );\n }\n if (httpStatusCode !== httpStatusUnauthorized) {\n return {\n result,\n authFailure: false,\n };\n }\n if (!this.getAuth) {\n return {\n result,\n authFailure: true,\n };\n }\n let auth;\n try {\n await preAuth();\n auth = await this.getAuth();\n } finally {\n await postAuth();\n }\n if (auth === null || auth === undefined) {\n return {\n result,\n authFailure: true,\n };\n }\n this.auth = auth;\n reauthAttempts++;\n } while (reauthAttempts < MAX_REAUTH_TRIES);\n lc.info?.('Tried to reauthenticate too many times');\n return {\n result: lastResult,\n authFailure: true,\n };\n }\n\n #isPushDisabled() {\n return (\n this.isClientGroupDisabled ||\n (this.pushURL === '' && isDefaultPusher(this.pusher))\n );\n }\n\n async #invokePush(): Promise<boolean> {\n if (TESTING) {\n this.onPushInvoked();\n }\n if (this.#isPushDisabled()) {\n return true;\n }\n\n await this.#ready;\n const profileID = await this.#profileIDPromise;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n return this.#wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n try {\n this.#changeSyncCounters(1, 0);\n const pusherResult = await push(\n requestID,\n this.memdag,\n requestLc,\n profileID,\n clientGroupID,\n clientID,\n this.pusher,\n this.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n } finally {\n this.#changeSyncCounters(-1, 0);\n }\n },\n 'push',\n this.#lc,\n );\n\n if (pusherResult === undefined) {\n // No pending mutations.\n return true;\n }\n\n const {response, httpRequestInfo} = pusherResult;\n\n if (isVersionNotSupportedResponse(response)) {\n this.#handleVersionNotSupportedResponse(response);\n } else if (isClientStateNotFoundResponse(response)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n // No pushResponse means we didn't do a push because there were no\n // pending mutations.\n return httpRequestInfo.httpStatusCode === 200;\n }, 'Push');\n }\n\n #handleVersionNotSupportedResponse(response: VersionNotSupportedResponse) {\n const reason: UpdateNeededReason = {\n type: response.error,\n };\n if (response.versionType) {\n reason.versionType = response.versionType;\n }\n this.#fireOnUpdateNeeded(reason);\n }\n\n /**\n * Push pushes pending changes to the {@link pushURL}.\n *\n * You do not usually need to manually call push. If {@link pushDelay} is\n * non-zero (which it is by default) pushes happen automatically shortly after\n * mutations.\n *\n * If the server endpoint fails push will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, push will happen immediately and ignore\n * {@link pushDelay}, {@link RequestOptions.minDelayMs} as well as the\n * exponential backoff in case of errors.\n * @returns A promise that resolves when the next push completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n push({now = false} = {}): Promise<void> {\n return throwIfError(this.#pushConnectionLoop.send(now));\n }\n\n /**\n * Pull pulls changes from the {@link pullURL}. If there are any changes local\n * changes will get replayed on top of the new server state.\n *\n * If the server endpoint fails pull will be continuously retried with an\n * exponential backoff.\n *\n * @param [now=false] If true, pull will happen immediately and ignore\n * {@link RequestOptions.minDelayMs} as well as the exponential backoff in\n * case of errors.\n * @returns A promise that resolves when the next pull completes. In case of\n * errors the first error will reject the returned promise. Subsequent errors\n * will not be reflected in the promise.\n */\n pull({now = false} = {}): Promise<void> {\n return throwIfError(this.#pullConnectionLoop.send(now));\n }\n\n /**\n * Applies an update from the server to Replicache.\n * Throws an error if cookie does not match. In that case the server thinks\n * this client has a different cookie than it does; the caller should disconnect\n * from the server and re-register, which transmits the cookie the client actually\n * has.\n *\n * @experimental This method is under development and its semantics will change.\n */\n async poke(poke: PokeInternal): Promise<void> {\n await this.#ready;\n // TODO(MP) Previously we created a request ID here and included it with the\n // PullRequest to the server so we could tie events across client and server\n // together. Since the direction is now reversed, creating and adding a request ID\n // here is kind of silly. We should consider creating the request ID\n // on the *server* and passing it down in the poke for inclusion here in the log\n // context\n const {clientID} = this;\n const requestID = newRequestID(clientID);\n const lc = this.#lc\n .withContext('handlePullResponse')\n .withContext('requestID', requestID);\n\n const {pullResponse} = poke;\n\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n return;\n }\n\n if (isClientStateNotFoundResponse(pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n return;\n }\n\n const result = await handlePullResponseV1(\n lc,\n this.memdag,\n deepFreeze(poke.baseCookie),\n pullResponse,\n clientID,\n FormatVersion.Latest,\n );\n\n switch (result.type) {\n case HandlePullResponseResultEnum.Applied:\n await this.maybeEndPull(result.syncHead, requestID);\n break;\n case HandlePullResponseResultEnum.CookieMismatch:\n throw new Error(\n 'unexpected base cookie for poke: ' + JSON.stringify(poke),\n );\n case HandlePullResponseResultEnum.NoOp:\n break;\n }\n }\n\n async beginPull(): Promise<BeginPullResult> {\n if (TESTING) {\n this.onBeginPull();\n }\n await this.#ready;\n const profileID = await this.profileID;\n const {clientID} = this;\n const clientGroupID = await this.#clientGroupIDPromise;\n const {\n result: {beginPullResponse, requestID},\n } = await this.#wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n const beginPullResponse = await beginPullV1(\n profileID,\n clientID,\n clientGroupID,\n this.schemaVersion,\n this.puller,\n requestID,\n this.memdag,\n FormatVersion.Latest,\n requestLc,\n );\n return {\n result: {beginPullResponse, requestID},\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n 'pull',\n this.#lc,\n () => this.#changeSyncCounters(0, -1),\n () => this.#changeSyncCounters(0, 1),\n );\n\n const {pullResponse} = beginPullResponse;\n if (isVersionNotSupportedResponse(pullResponse)) {\n this.#handleVersionNotSupportedResponse(pullResponse);\n } else if (isClientStateNotFoundResponse(beginPullResponse.pullResponse)) {\n await this.#clientStateNotFoundOnServer();\n }\n\n const {syncHead, httpRequestInfo} = beginPullResponse;\n return {requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200};\n }\n\n persist(): Promise<void> {\n // Prevent multiple persist calls from running at the same time.\n return this.#persistLock.withLock(async () => {\n const {clientID} = this;\n await this.#ready;\n if (this.#closed) {\n return;\n }\n try {\n await persistDD31(\n this.#lc,\n clientID,\n this.memdag,\n this.perdag,\n this.#mutatorRegistry,\n () => this.#closed,\n FormatVersion.Latest,\n this.#zero?.getTxData,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception persisting during close', e);\n } else {\n throw e;\n }\n }\n\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID);\n this.#onPersist({clientID, clientGroupID});\n });\n }\n\n async refresh(): Promise<void> {\n await this.#ready;\n const {clientID} = this;\n if (this.#closed) {\n return;\n }\n let refreshResult: Awaited<ReturnType<typeof refresh>>;\n try {\n refreshResult = await refresh(\n this.#lc,\n this.memdag,\n this.perdag,\n clientID,\n this.#mutatorRegistry,\n this.#subscriptions,\n () => this.closed,\n FormatVersion.Latest,\n this.#zero,\n );\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n this.#clientStateNotFoundOnClient(clientID);\n } else if (this.#closed) {\n this.#lc.debug?.('Exception refreshing during close', e);\n } else {\n throw e;\n }\n }\n if (refreshResult !== undefined) {\n await this.#subscriptions.fire(refreshResult.diffs);\n }\n }\n\n #fireOnClientStateNotFound() {\n this.onClientStateNotFound?.();\n }\n\n #clientStateNotFoundOnClient(clientID: ClientID) {\n this.#lc.error?.(`Client state not found on client, clientID: ${clientID}`);\n this.#fireOnClientStateNotFound();\n }\n\n async #clientStateNotFoundOnServer() {\n const clientGroupID = await this.#clientGroupIDPromise;\n this.#lc.error?.(\n `Client state not found on server, clientGroupID: ${clientGroupID}`,\n );\n await this.disableClientGroup();\n this.#fireOnClientStateNotFound();\n }\n\n async disableClientGroup(): Promise<void> {\n const clientGroupID = await this.#clientGroupIDPromise;\n assert(clientGroupID);\n this.isClientGroupDisabled = true;\n await withWrite(this.perdag, dagWrite =>\n disableClientGroup(clientGroupID, dagWrite),\n );\n }\n\n #fireOnUpdateNeeded(reason: UpdateNeededReason) {\n this.#lc.debug?.(`Update needed, reason: ${reason}`);\n this.onUpdateNeeded?.(reason);\n }\n\n async #schedulePersist(): Promise<void> {\n if (!this.#enableScheduledPersist) {\n return;\n }\n await this.#schedule('persist', this.#persistScheduler);\n }\n\n async #handlePersist(persistInfo: PersistInfo): Promise<void> {\n this.#lc.debug?.('Handling persist', persistInfo);\n const clientGroupID = await this.#clientGroupIDPromise;\n if (persistInfo.clientGroupID === clientGroupID) {\n void this.#scheduleRefresh();\n }\n }\n\n async #scheduleRefresh(): Promise<void> {\n if (!this.#enableScheduledRefresh) {\n return;\n }\n await this.#schedule('refresh from storage', this.#refreshScheduler);\n }\n\n async #schedule(name: string, scheduler: ProcessScheduler): Promise<void> {\n try {\n await scheduler.schedule();\n } catch (e) {\n if (e instanceof AbortError) {\n this.#lc.debug?.(`Scheduled ${name} did not complete before close.`);\n } else {\n this.#lc.error?.(`Error during ${name}`, e);\n }\n }\n }\n\n #changeSyncCounters(pushDelta: 0, pullDelta: 1 | -1): void;\n #changeSyncCounters(pushDelta: 1 | -1, pullDelta: 0): void;\n #changeSyncCounters(pushDelta: number, pullDelta: number): void {\n this.#pushCounter += pushDelta;\n this.#pullCounter += pullDelta;\n const delta = pushDelta + pullDelta;\n const counter = this.#pushCounter + this.#pullCounter;\n if ((delta === 1 && counter === 1) || counter === 0) {\n const syncing = counter > 0;\n // Run in a new microtask.\n void Promise.resolve().then(() => this.onSync?.(syncing));\n }\n }\n\n /**\n * Subscribe to the result of a {@link query}. The `body` function is\n * evaluated once and its results are returned via `onData`.\n *\n * Thereafter, each time the the result of `body` changes, `onData` is fired\n * again with the new result.\n *\n * `subscribe()` goes to significant effort to avoid extraneous work\n * re-evaluating subscriptions:\n *\n * 1. subscribe tracks the keys that `body` accesses each time it runs. `body`\n * is only re-evaluated when those keys change.\n * 2. subscribe only re-fires `onData` in the case that a result changes by\n * way of the `isEqual` option which defaults to doing a deep JSON value\n * equality check.\n *\n * Because of (1), `body` must be a pure function of the data in Replicache.\n * `body` must not access anything other than the `tx` parameter passed to it.\n *\n * Although subscribe is as efficient as it can be, it is somewhat constrained\n * by the goal of returning an arbitrary computation of the cache. For even\n * better performance (but worse dx), see {@link experimentalWatch}.\n *\n * If an error occurs in the `body` the `onError` function is called if\n * present. Otherwise, the error is logged at log level 'error'.\n *\n * To cancel the subscription, call the returned function.\n *\n * @param body The function to evaluate to get the value to pass into\n * `onData`.\n * @param options Options is either a function or an object. If it is a\n * function it is equivalent to passing it as the `onData` property of an\n * object.\n */\n subscribe<R>(\n body: (tx: ReadTransaction) => Promise<R>,\n options: SubscribeOptions<R> | ((result: R) => void),\n ): () => void {\n if (typeof options === 'function') {\n options = {onData: options};\n }\n\n const {onData, onError, onDone, isEqual} = options;\n return this.#subscriptions.add(\n new SubscriptionImpl(body, onData, onError, onDone, isEqual),\n );\n }\n\n /**\n * Watches Replicache for changes.\n *\n * The `callback` gets called whenever the underlying data changes and the\n * `key` changes matches the `prefix` of {@link ExperimentalWatchIndexOptions} or\n * {@link ExperimentalWatchNoIndexOptions} if present. If a change\n * occurs to the data but the change does not impact the key space the\n * callback is not called. In other words, the callback is never called with\n * an empty diff.\n *\n * This gets called after commit (a mutation or a rebase).\n *\n * @experimental This method is under development and its semantics will\n * change.\n */\n experimentalWatch(callback: WatchNoIndexCallback): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void;\n experimentalWatch<Options extends WatchOptions>(\n callback: WatchCallbackForOptions<Options>,\n options?: Options,\n ): () => void {\n return this.#subscriptions.add(\n new WatchSubscription(callback as WatchCallback, options),\n );\n }\n\n /**\n * Query is used for read transactions. It is recommended to use transactions\n * to ensure you get a consistent view across multiple calls to `get`, `has`\n * and `scan`.\n */\n query<R>(body: (tx: ReadTransaction) => Promise<R> | R): Promise<R> {\n return this.#queryInternal(body);\n }\n\n get cookie(): Promise<Cookie> {\n return this.#ready.then(() =>\n withRead(this.memdag, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n const cookie = baseSnapshotMeta.cookieJSON;\n assertCookie(cookie);\n return cookie;\n }),\n );\n }\n\n #queryInternal: QueryInternal = async body => {\n await this.#ready;\n const {clientID} = this;\n return withRead(this.memdag, async dagRead => {\n try {\n const dbRead = await readFromDefaultHead(dagRead, FormatVersion.Latest);\n const tx = new ReadTransactionImpl(clientID, dbRead, this.#lc);\n return await body(tx);\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n };\n\n #register<Return extends ReadonlyJSONValue | void, Args extends JSONValue>(\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: Args) => MaybePromise<Return>,\n ): (\n args?: Args,\n ) => Promise<Return> | {client: Promise<Return>; server: Promise<unknown>} {\n this.#mutatorRegistry[name] = mutatorImpl as (\n tx: WriteTransaction,\n args: JSONValue | undefined,\n ) => Promise<void | JSONValue>;\n\n return (\n args?: Args,\n ):\n | Promise<Return>\n | {client: Promise<Return>; server: Promise<unknown>} => {\n // DO NOT track CRUD mutations as they do not receive responses from\n // the server.\n const trackingData =\n name === '_zero_crud' ? undefined : this.#zero?.trackMutation();\n\n const result = this.#mutate(\n trackingData,\n name,\n mutatorImpl,\n args,\n performance.now(),\n );\n\n if (trackingData) {\n return {\n client: result,\n server: trackingData.serverPromise,\n // oxlint-disable-next-line no-thenable\n then: (onFulfilled, onRejected) => {\n this.#lc.warn?.(\n 'Awaiting the mutator result directly is being deprecated.' +\n ' Please use `await z.mutate[mutatorName].client` or `await result.mutate[mutatorName].server`',\n );\n return result.then(onFulfilled, onRejected);\n },\n };\n }\n\n return result;\n };\n }\n\n #registerMutators<\n M extends {\n [key: string]: (\n tx: WriteTransaction,\n args?: ReadonlyJSONValue,\n ) => MutatorReturn;\n },\n >(regs: M): MakeMutators<M> {\n type Mut = MakeMutators<M>;\n const rv: Partial<Mut> = Object.create(null);\n for (const k in regs) {\n rv[k] = this.#register(k, regs[k]) as MakeMutator<M[typeof k]>;\n }\n return rv as Mut;\n }\n\n async #mutate<\n R extends ReadonlyJSONValue | void,\n A extends ReadonlyJSONValue,\n >(\n trackingData: MutationTrackingData | undefined,\n name: string,\n mutatorImpl: (tx: WriteTransaction, args?: A) => MaybePromise<R>,\n args: A | undefined,\n timestamp: number,\n ): Promise<R> {\n const frozenArgs = deepFreeze(args ?? null);\n\n // Ensure that we run initial pending subscribe functions before starting a\n // write transaction.\n if (this.#subscriptions.hasPendingSubscriptionRuns) {\n await Promise.resolve();\n }\n\n await this.#ready;\n const {clientID} = this;\n return withWriteNoImplicitCommit(this.memdag, async dagWrite => {\n try {\n let result: R;\n let newHead: Hash;\n let diffs: DiffsMap;\n let headHash: Hash;\n try {\n headHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagWrite);\n const originalHash = null;\n\n const dbWrite = await newWriteLocal(\n headHash,\n name,\n frozenArgs,\n originalHash,\n dagWrite,\n timestamp,\n clientID,\n FormatVersion.Latest,\n );\n\n const mutationID = await dbWrite.getMutationID();\n const tx = new WriteTransactionImpl(\n clientID,\n mutationID,\n 'initial',\n await this.#zero?.getTxData(headHash, {\n openLazyRead: dagWrite,\n }),\n dbWrite,\n this.#lc,\n );\n\n if (trackingData) {\n this.#zero?.mutationIDAssigned(\n trackingData.ephemeralID,\n mutationID,\n );\n }\n\n result = await mutatorImpl(tx, args);\n\n throwIfClosed(dbWrite);\n const lastMutationID = await dbWrite.getMutationID();\n [newHead, diffs] = await dbWrite.commitWithDiffs(\n DEFAULT_HEAD_NAME,\n this.#subscriptions,\n );\n\n // Update this after the commit in case the commit fails.\n this.lastMutationID = lastMutationID;\n } catch (e) {\n // If we threw before we could persist the mutation\n // then we need to reject the mutation.\n if (trackingData) {\n this.#zero?.rejectMutation(trackingData.ephemeralID, e);\n }\n throw e;\n }\n\n this.#zero?.advance(headHash, newHead, diffs.get('') ?? []);\n\n // Send is not supposed to reject\n this.#pushConnectionLoop.send(false).catch(() => void 0);\n await this.#subscriptions.fire(diffs);\n void this.#schedulePersist();\n return result;\n } catch (ex) {\n throw await this.#convertToClientStateNotFoundError(ex);\n }\n });\n }\n\n /**\n * In the case we get a ChunkNotFoundError we check if the client got garbage\n * collected and if so change the error to a ClientStateNotFoundError instead\n */\n async #convertToClientStateNotFoundError(ex: unknown): Promise<unknown> {\n if (\n ex instanceof ChunkNotFoundError &&\n (await this.#checkForClientStateNotFoundAndCallHandler())\n ) {\n return new ClientStateNotFoundError(this.clientID);\n }\n\n return ex;\n }\n\n recoverMutations(): Promise<boolean> | void {\n if (!process.env.DISABLE_MUTATION_RECOVERY) {\n // oxlint-disable-next-line no-non-null-assertion\n const result = this.#mutationRecovery!.recoverMutations(\n this.#ready,\n this.perdag,\n this.#idbDatabase,\n this.#idbDatabases,\n this.#kvStoreProvider.create,\n );\n if (TESTING) {\n void this.onRecoverMutations(result);\n }\n return result;\n }\n }\n\n /**\n * List of pending mutations. The order of this is from oldest to newest.\n *\n * Gives a list of local mutations that have `mutationID` >\n * `syncHead.mutationID` that exists on the main client group.\n *\n * @experimental This method is experimental and may change in the future.\n */\n experimentalPendingMutations(): Promise<readonly PendingMutation[]> {\n return withRead(this.memdag, pendingMutationsForAPI);\n }\n}\n\n// This map is used to keep track of closing instances of Replicache. When an\n// instance is opening we wait for any currently closing instances.\nconst closingInstances: Map<string, Promise<unknown>> = new Map();\n\nasync function throwIfError(p: Promise<undefined | {error: unknown}>) {\n const res = await p;\n if (res) {\n throw res.error;\n }\n}\n\nfunction reload(): void {\n if (typeof location !== 'undefined') {\n location.reload();\n }\n}\n\nfunction validateOptions<MD extends MutatorDefs>(\n options: ReplicacheOptions<MD>,\n): void {\n const {name, clientMaxAgeMs} = options;\n if (typeof name !== 'string' || !name) {\n throw new TypeError('name is required and must be non-empty');\n }\n\n if (clientMaxAgeMs !== undefined) {\n const min = Math.max(GC_INTERVAL, HEARTBEAT_INTERVAL);\n if (typeof clientMaxAgeMs !== 'number' || clientMaxAgeMs <= min) {\n throw new TypeError(\n `clientAgeMaxMs must be a number larger than ${min}ms`,\n );\n }\n }\n}\n", "import {resolver} from '@rocicorp/resolver';\n\ntype PartialDocument = Pick<\n Document,\n 'visibilityState' | 'addEventListener' | 'removeEventListener'\n>;\n\nexport function getDocumentVisibilityWatcher(\n doc: PartialDocument | undefined,\n hiddenIntervalMS: number,\n signal: AbortSignal,\n): DocumentVisibilityWatcher {\n return doc\n ? new DocumentVisibilityWatcherImpl(doc, hiddenIntervalMS, signal)\n : new DocumentVisibilityWatcherNoDoc();\n}\n\nexport interface DocumentVisibilityWatcher {\n readonly visibilityState: DocumentVisibilityState;\n waitForVisible(): Promise<unknown>;\n waitForHidden(): Promise<unknown>;\n}\n\nclass DocumentVisibilityWatcherImpl implements DocumentVisibilityWatcher {\n readonly #doc: PartialDocument;\n readonly #hiddenIntervalMS: number;\n #timeoutID: ReturnType<typeof setTimeout> | 0 = 0;\n\n // This trails doc.visibilityState by hiddenIntervalMS when being hidden. This\n // is because we want to wait for the tab to be hidden for a while before\n // considering as hidden.\n visibilityState: DocumentVisibilityState;\n\n readonly #promises = new Set<{\n resolve: () => void;\n state: DocumentVisibilityState;\n }>();\n\n constructor(\n doc: PartialDocument,\n hiddenIntervalMS: number,\n signal: AbortSignal,\n ) {\n this.#doc = doc;\n this.#hiddenIntervalMS = hiddenIntervalMS;\n this.visibilityState = doc.visibilityState;\n // Safari got support for abort signal in addEventListener in version\n // 15 (Released 2021-09-20)\n this.#doc.addEventListener('visibilitychange', this.#onVisibilityChange, {\n signal,\n });\n }\n\n #onVisibilityChange = () => {\n if (this.#doc.visibilityState === 'visible') {\n clearTimeout(this.#timeoutID);\n this.#setVisibilityState('visible');\n } else {\n this.#timeoutID = setTimeout(() => {\n this.#setVisibilityState('hidden');\n }, this.#hiddenIntervalMS);\n }\n };\n\n #setVisibilityState(visibilityState: DocumentVisibilityState) {\n if (visibilityState === this.visibilityState) {\n return;\n }\n this.visibilityState = visibilityState;\n for (const entry of this.#promises) {\n const {resolve, state} = entry;\n if (state === visibilityState) {\n resolve();\n this.#promises.delete(entry);\n }\n }\n }\n\n waitForVisible(): Promise<unknown> {\n return this.#waitFor('visible');\n }\n\n waitForHidden(): Promise<unknown> {\n return this.#waitFor('hidden');\n }\n\n #waitFor(state: DocumentVisibilityState): Promise<unknown> {\n if (this.visibilityState === state) {\n return Promise.resolve();\n }\n\n const {promise, resolve} = resolver();\n this.#promises.add({resolve, state});\n return promise;\n }\n}\n\nconst resolvedPromise = Promise.resolve();\nconst promiseThatNeverResolves = new Promise(() => undefined);\n\nclass DocumentVisibilityWatcherNoDoc implements DocumentVisibilityWatcher {\n readonly visibilityState: DocumentVisibilityState = 'visible';\n waitForVisible(): Promise<unknown> {\n return resolvedPromise;\n }\n\n waitForHidden(): Promise<unknown> {\n return promiseThatNeverResolves;\n }\n}\n", "import type {ConnectionLoopDelegate} from './connection-loop.ts';\nimport type {ReplicacheImpl} from './replicache-impl.ts';\n\nclass ConnectionLoopDelegateImpl {\n readonly rep: ReplicacheImpl;\n readonly invokeSend: () => Promise<boolean>;\n\n // TODO: Remove the ability to have more than one concurrent connection and update tests.\n // Bug: https://github.com/rocicorp/replicache-internal/issues/303\n readonly maxConnections = 1;\n\n constructor(rep: ReplicacheImpl, invokeSend: () => Promise<boolean>) {\n this.rep = rep;\n this.invokeSend = invokeSend;\n }\n\n get maxDelayMs(): number {\n return this.rep.requestOptions.maxDelayMs;\n }\n\n get minDelayMs(): number {\n return this.rep.requestOptions.minDelayMs;\n }\n}\n\nexport class PullDelegate\n extends ConnectionLoopDelegateImpl\n implements ConnectionLoopDelegate\n{\n readonly debounceDelay = 0;\n\n get watchdogTimer(): number | null {\n return this.rep.pullInterval;\n }\n}\n\nexport class PushDelegate\n extends ConnectionLoopDelegateImpl\n implements ConnectionLoopDelegate\n{\n get debounceDelay(): number {\n return this.rep.pushDelay;\n }\n\n watchdogTimer = null;\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {resolver} from '@rocicorp/resolver';\nimport type {DocumentVisibilityWatcher} from '../../shared/src/document-visible.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\n\nexport const DEBOUNCE_DELAY_MS = 10;\n\nexport const MIN_DELAY_MS = 30;\nexport const MAX_DELAY_MS = 60_000;\n\ntype SendRecord = {duration: number; ok: boolean};\n\nexport interface ConnectionLoopDelegate {\n invokeSend(): Promise<boolean>;\n debounceDelay: number;\n // If null, no watchdog timer is used.\n watchdogTimer: number | null;\n maxConnections: number;\n maxDelayMs: number;\n minDelayMs: number;\n}\n\nexport class ConnectionLoop {\n // ConnectionLoop runs a loop sending network requests (either pushes or\n // pulls) to the server. Our goal, generally, is to send requests as fast as\n // we can, but to adjust in case of slowness, network errors, etc. We will\n // send requests in parallel if the server supports it. We also debounce\n // pushes since they frequently happen in series very near to one another\n // (e.g., during drag'n drops).\n //\n // The loop flows through the following states forever, until it is closed:\n //\n // Pending: Wait for event or watchdog\n // |\n // v\n // Debounce: Wait for more events (we debounce pushes)\n // |\n // v\n // Wait for available connection (we limit number of parallel requests\n // allowed)\n // |\n // v\n // Wait to send (if requests are taking too long, we will slow down)\n // |\n // v\n // Send (asynchronously, wrt the loop)\n // |\n // v\n // Back to the pending!\n\n // Controls whether the next iteration of the loop will wait at the pending\n // state.\n #pendingResolver = resolver<void>();\n\n /**\n * This resolver is used to allow us to skip sleeps when we do send(true)\n */\n #skipSleepsResolver = resolver<void>();\n\n /**\n * Resolver for the next send. Never rejects. Returns an error instead since\n * this resolver is used in cases where they might not be someone waiting,\n * and we don't want an unhandled promise rejection in that case.\n */\n #sendResolver = resolver<undefined | {error: unknown}>();\n\n readonly #delegate: ConnectionLoopDelegate;\n #closed = false;\n #abortSignal = new AbortController();\n\n /**\n * Number of pending send calls.\n *\n * We keep track of this because if close happens while we are waiting for the\n * send to resolve we should reject the send promise.\n */\n #sendCounter = 0;\n readonly #lc: LogContext;\n readonly #visibilityWatcher: DocumentVisibilityWatcher | undefined;\n\n constructor(\n lc: LogContext,\n delegate: ConnectionLoopDelegate,\n visibilityWatcher?: DocumentVisibilityWatcher,\n ) {\n this.#lc = lc;\n this.#delegate = delegate;\n this.#visibilityWatcher = visibilityWatcher;\n void this.run();\n }\n\n close(): void {\n this.#closed = true;\n this.#abortSignal.abort();\n if (this.#sendCounter > 0) {\n this.#sendResolver.resolve({error: closeError()});\n }\n }\n\n /**\n *\n * @returns Returns undefined if ok, otherwise it return the error that caused\n * the send to fail.\n */\n async send(now: boolean): Promise<undefined | {error: unknown}> {\n if (this.#closed) {\n return {error: closeError()};\n }\n this.#sendCounter++;\n this.#lc.debug?.('send', now);\n if (now) {\n this.#skipSleepsResolver.resolve();\n } else {\n await this.#visibilityWatcher?.waitForVisible();\n }\n\n this.#pendingResolver.resolve();\n\n const result = await this.#sendResolver.promise;\n this.#sendCounter--;\n return result;\n }\n\n async run(): Promise<void> {\n const sendRecords: SendRecord[] = [];\n\n let recoverResolver = resolver();\n let lastSendTime;\n\n // The number of active connections.\n let counter = 0;\n const delegate = this.#delegate;\n const {debug} = this.#lc;\n let delay = 0;\n\n debug?.('Starting connection loop');\n\n const sleepMaybeSkip: typeof sleep = ms =>\n Promise.race([this.#skipSleepsResolver.promise, sleep(ms)]);\n\n while (!this.#closed) {\n debug?.(\n didLastSendRequestFail(sendRecords)\n ? 'Last request failed. Trying again'\n : 'Waiting for a send',\n );\n\n // Wait until send is called or until the watchdog timer fires.\n const races = [this.#pendingResolver.promise];\n const t = delegate.watchdogTimer;\n if (t !== null) {\n // Wait for the watchdog timer to fire or the abort signal to be triggered.\n races.push(sleep(t, this.#abortSignal.signal).catch(() => {}));\n }\n await Promise.race(races);\n if (this.#closed) break;\n\n debug?.('Waiting for debounce');\n await sleepMaybeSkip(delegate.debounceDelay);\n if (this.#closed) break;\n debug?.('debounced');\n\n // This resolver is used to wait for incoming push calls.\n this.#pendingResolver = resolver();\n\n if (counter >= delegate.maxConnections) {\n debug?.('Too many request in flight. Waiting until one finishes...');\n await this.#waitUntilAvailableConnection();\n if (this.#closed) break;\n debug?.('...finished');\n }\n\n // We need to delay the next request even if there are no active requests\n // in case of error.\n if (counter > 0 || didLastSendRequestFail(sendRecords)) {\n delay = computeDelayAndUpdateDurations(delay, delegate, sendRecords);\n debug?.(\n didLastSendRequestFail(sendRecords)\n ? 'Last connection errored. Sleeping for'\n : 'More than one outstanding connection (' +\n counter +\n '). Sleeping for',\n delay,\n 'ms',\n );\n } else {\n // We set this to 0 here in case minDelayMs is mutated to a lower value\n // than the old delay so that we still get minDelayMs. This can happen\n // if we get an error during a run where minDelayMs is larger than the\n // current value of minDelayMs.\n delay = 0;\n }\n\n const clampedDelay = Math.min(\n delegate.maxDelayMs,\n Math.max(delegate.minDelayMs, delay),\n );\n if (lastSendTime !== undefined) {\n const timeSinceLastSend = Date.now() - lastSendTime;\n if (clampedDelay > timeSinceLastSend) {\n await Promise.race([\n sleepMaybeSkip(clampedDelay - timeSinceLastSend),\n recoverResolver.promise,\n ]);\n if (this.#closed) break;\n }\n }\n\n counter++;\n void (async () => {\n const start = Date.now();\n let ok: boolean;\n let error: unknown;\n try {\n lastSendTime = start;\n debug?.('Sending request');\n this.#skipSleepsResolver = resolver();\n ok = await delegate.invokeSend();\n debug?.('Send returned', ok);\n } catch (e) {\n debug?.('Send failed', e);\n error = e;\n ok = false;\n }\n if (this.#closed) {\n debug?.('Closed after invokeSend');\n return;\n }\n debug?.('Request done', {duration: Date.now() - start, ok});\n sendRecords.push({duration: Date.now() - start, ok});\n if (recovered(sendRecords)) {\n recoverResolver.resolve();\n recoverResolver = resolver();\n }\n counter--;\n this.#connectionAvailable();\n const sendResolver = this.#sendResolver;\n this.#sendResolver = resolver();\n if (error) {\n sendResolver.resolve({error});\n } else {\n sendResolver.resolve(undefined);\n }\n if (!ok) {\n // Keep trying\n this.#pendingResolver.resolve();\n }\n })();\n }\n }\n\n #waitingConnectionResolve: (() => void) | undefined = undefined;\n\n #connectionAvailable() {\n if (this.#waitingConnectionResolve) {\n const resolve = this.#waitingConnectionResolve;\n this.#waitingConnectionResolve = undefined;\n resolve();\n }\n }\n\n #waitUntilAvailableConnection() {\n const {promise, resolve} = resolver();\n this.#waitingConnectionResolve = resolve;\n return promise;\n }\n}\n\n// Number of connections to remember when computing the new delay.\nconst CONNECTION_MEMORY_COUNT = 9;\n\nfunction closeError() {\n return new Error('Closed');\n}\n\n// Computes a new delay based on the previous requests. We use the median of the\n// previous successful request divided by `maxConnections`. When we get errors\n// we do exponential backoff. As soon as we recover from an error we reset back\n// to delegate.minDelayMs.\nfunction computeDelayAndUpdateDurations(\n delay: number,\n delegate: ConnectionLoopDelegate,\n sendRecords: SendRecord[],\n): number {\n const {length} = sendRecords;\n if (length === 0) {\n return delay;\n }\n\n const {ok} = sendRecords[sendRecords.length - 1];\n const {maxConnections, minDelayMs} = delegate;\n\n if (!ok) {\n return delay === 0 ? minDelayMs : delay * 2;\n }\n\n if (length > 1) {\n // length > 1\n const previous: SendRecord = sendRecords[sendRecords.length - 2];\n\n // Prune\n while (sendRecords.length > CONNECTION_MEMORY_COUNT) {\n sendRecords.shift();\n }\n\n if (ok && !previous.ok) {\n // Recovered\n return minDelayMs;\n }\n }\n\n const med = median(\n sendRecords.filter(({ok}) => ok).map(({duration}) => duration),\n );\n\n return (med / maxConnections) | 0;\n}\n\nfunction median(values: number[]) {\n values.sort();\n const {length} = values;\n const half = length >> 1;\n if (length % 2 === 1) {\n return values[half];\n }\n return (values[half - 1] + values[half]) / 2;\n}\n\nfunction didLastSendRequestFail(sendRecords: SendRecord[]) {\n return sendRecords.length > 0 && !sendRecords[sendRecords.length - 1].ok;\n}\n\nfunction recovered(sendRecords: SendRecord[]) {\n return (\n sendRecords.length > 1 &&\n !sendRecords[sendRecords.length - 2].ok &&\n sendRecords[sendRecords.length - 1].ok\n );\n}\n", "import {RWLock} from '@rocicorp/lock';\nimport {joinIterables} from '../../../shared/src/iterables.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {getSizeOfValue} from '../../../shared/src/size-of-value.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport type {Hash} from '../hash.ts';\nimport {Chunk, type ChunkHasher, type Refs, createChunk} from './chunk.ts';\nimport {\n type HeadChange,\n type RefCountUpdatesDelegate,\n computeRefCountUpdates,\n} from './gc.ts';\nimport {type Read, type Store, type Write, mustGetChunk} from './store.ts';\n\n/**\n * Dag Store which lazily loads values from a source store and then caches\n * them in an LRU cache. The memory cache for chunks from the source store\n * size is limited to `sourceCacheSizeLimit` bytes, and values are evicted in an\n * LRU fashion. The purpose of this store is to avoid holding the entire client\n * view (i.e. the source store's content) in each tab's JavaScript heap.\n *\n * This store's heads are independent from the heads of source store, and are\n * only stored in memory.\n *\n * Chunks which are created via this store's {@link Write} transaction's\n * {@link createChunk} method are assumed to not be persisted to the source\n * store and thus are cached separately from the source store chunks. These\n * memory-only chunks will not be evicted, and their sizes are not counted\n * towards the source chunk cache size. A memory-only chunk will be deleted if\n * it is no longer reachable from one of this store's heads.\n *\n * Writes only manipulate the in memory state of this store and do not alter the\n * source store. Thus values must be written to the source store through a\n * separate process (see {@link persist}).\n *\n * Intended use:\n * 1. source store is the 'perdag', a slower persistent store (i.e.\n * dag.StoreImpl using a kv.IDBStore)\n * 2. this store's 'main' head is initialized to the hash of a chunk containing\n * a commit in the source store\n * 3. reads lazily read chunks from the source store and cache them\n * 3. writes are initially made to this store with memory-only chunks\n * 4. writes are asynchronously persisted to the source store through a separate\n * process (see {@link persist}}. This process gathers memory-only chunks\n * from this store and then writes them to the source store. It then informs\n * this store that these chunks are no longer memory-only by calling\n * {@link chunksPersisted}, which move these chunks\n * to this store's LRU cache of source chunks (making them eligible for\n * eviction).\n *\n * @param sourceStore Store to lazy load and cache values from.\n * @param sourceCacheSizeLimit Size limit in bytes for cache of chunks loaded\n * from `sourceStore`. This size of a value is determined using\n * `getSizeOfValue`. Keys do not count towards cache size. Memory-only chunks\n * do not count towards cache size.\n * @param getSizeOfValue Function for measuring the size in bytes of a value.\n */\nexport class LazyStore implements Store {\n /**\n * This lock is used to ensure correct isolation of Reads and Writes.\n * Multiple Reads are allowed in parallel but only a single Write. Reads and\n * Writes see an isolated view of the store (corresponding to the Serializable\n * level of transaction isolation defined in the SQL standard).\n *\n * To ensure these semantics the read lock must be acquired when a Read is\n * created and held til it is closed, and a Write lock must be acquired when a\n * Write is created and held til it is committed or closed.\n *\n * Code must have a read or write lock to\n * - read `_heads`\n * - read `_memOnlyChunks`\n * - read `_sourceStore`\n * - read and write `_sourceChunksCache`\n * - read and write `_refCounts`\n * - read and write `_refs`\n * and must have a write lock to\n * - write `_heads`\n * - write `_memOnlyChunks`\n */\n readonly #rwLock = new RWLock();\n readonly #heads = new Map<string, Hash>();\n readonly #sourceStore: Store;\n readonly #chunkHasher: ChunkHasher;\n readonly #assertValidHash: (hash: Hash) => void;\n\n /** The following are protected so testing subclass can access. */\n protected readonly _memOnlyChunks = new Map<Hash, Chunk>();\n protected readonly _sourceChunksCache: ChunksCache;\n /**\n * Ref counts are maintained so that chunks which are unreachable\n * from this stores heads can be eagerly and deterministically deleted from\n * `this._memOnlyChunks` and `this._sourceChunksCache`.\n *\n * These ref counts are independent from `this._sourceStore`'s ref counts.\n * These ref counts are based on reachability from `this._heads`.\n * A chunk is deleted from `this._memOnlyChunks` or\n * `this._sourceChunksCache` (which ever it is in) when its ref count becomes\n * zero.\n * These ref counts count the refs in `this._heads` and `this._refs`.\n *\n * Not all reachable chunk's refs are included in `this._refs`, because this\n * would require loading all chunks reachable in the source store in a\n * non-lazy manner. `this._refs` contains the refs of all currently reachable\n * chunks that were ever in `this._memOnlyChunks` or\n * `this._sourceChunksCache` (even if they have been evicted). A\n * chunk's ref information is lazily discovered and stored in `this._refs` and\n * counted in `this._refCounts`. A chunk's entries in `this._refs` and\n * `this._refCounts` are only deleted when a chunk is deleted due to it\n * becoming unreachable (it is not deleted if the chunk is evicted from the\n * source-store cache).\n *\n * The major implication of this lazy discovery of source store refs, is that\n * a reachable source store chunk may not be cached when loaded, because it is\n * not known to be reachable because some of the pertinent refs have not been\n * discovered. However, in practice chunks are read by traversing the graph\n * starting from a head, and all pertinent refs are discovered as part of the\n * traversal.\n *\n * These ref counts can be changed in two ways:\n * 1. A LazyRead has a cache miss and loads a chunk from the source store that\n * is reachable from this._heads. If this chunk's refs are not currently\n * counted, it will not have an entry in `this._refs`. In this case, the\n * chunks refs will be put in `this._refs` and `this._refCounts` will be\n * updated to count them.\n * 2. A LazyWrite commit updates a head (which can result in increasing or\n * decreasing ref count) or puts a reachable chunk (either a `memory-only` or\n * `source` chunk) that references this hash (increasing ref count). The\n * computation of these ref count changes is delegated to the\n * `computeRefCountUpdates` shared with dag.StoreImpl. In order to\n * delegate determining reachability to `computeRefCountUpdates` and defer\n * this determination until commit time, LazyWrite treats cache misses\n * as a 'put' of the lazily-loaded chunk.\n *\n * A chunk's hash may have an entry in `this._refCounts` without that\n * chunk have ever been in `this._memOnlyChunks` or `this._sourceChunksCache`.\n * This is the case when a head or a reachable chunk that was ever in\n * `this._memOnlyChunks` or `this._sourceChunksCache` references a chunk\n * which is not currently cached (either because it has not been read, or\n * because it has been evicted).\n */\n protected readonly _refCounts = new Map<Hash, number>();\n protected readonly _refs = new Map<Hash, readonly Hash[]>();\n\n constructor(\n sourceStore: Store,\n sourceCacheSizeLimit: number,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n getSizeOfChunk: (chunk: Chunk) => number = getSizeOfValue,\n ) {\n this._sourceChunksCache = new ChunksCache(\n sourceCacheSizeLimit,\n getSizeOfChunk,\n this._refCounts,\n this._refs,\n );\n this.#sourceStore = sourceStore;\n this.#chunkHasher = chunkHasher;\n this.#assertValidHash = assertValidHash;\n }\n\n async read(sourceRead?: Read): Promise<LazyRead> {\n const release = await this.#rwLock.read();\n return new LazyRead(\n this.#heads,\n this._memOnlyChunks,\n this._sourceChunksCache,\n this.#sourceStore,\n release,\n this.#assertValidHash,\n sourceRead,\n );\n }\n\n async write(): Promise<LazyWrite> {\n const release = await this.#rwLock.write();\n return new LazyWrite(\n this.#heads,\n this._memOnlyChunks,\n this._sourceChunksCache,\n this.#sourceStore,\n this._refCounts,\n this._refs,\n release,\n this.#chunkHasher,\n this.#assertValidHash,\n );\n }\n\n close(): Promise<void> {\n return promiseVoid;\n }\n\n /**\n * Does not acquire any lock on the store.\n */\n isCached(chunkHash: Hash): boolean {\n return (\n this._sourceChunksCache.getWithoutUpdatingLRU(chunkHash) !== undefined\n );\n }\n\n withSuspendedSourceCacheEvictsAndDeletes<T>(\n fn: () => MaybePromise<T>,\n ): Promise<T> {\n return this._sourceChunksCache.withSuspendedEvictsAndDeletes(fn);\n }\n}\n\nexport class LazyRead implements Read {\n protected readonly _heads: Map<string, Hash>;\n protected readonly _memOnlyChunks: Map<Hash, Chunk>;\n protected readonly _sourceChunksCache: ChunksCache;\n protected readonly _sourceStore: Store;\n #sourceRead: Promise<Read> | undefined = undefined;\n readonly #release: () => void;\n #closed = false;\n readonly assertValidHash: (hash: Hash) => void;\n readonly #sourceReadOwnedByCaller: boolean;\n\n constructor(\n heads: Map<string, Hash>,\n memOnlyChunks: Map<Hash, Chunk>,\n sourceChunksCache: ChunksCache,\n sourceStore: Store,\n release: () => void,\n assertValidHash: (hash: Hash) => void,\n // If the lazyRead is being run in the context of an existing\n // read, or write, from the perdag then we must use _that_\n // transaction's read. Trying to open our own `sourceRead` will\n // cause the outer transaction to auto-commit.\n sourceRead?: Read,\n ) {\n this._heads = heads;\n this._memOnlyChunks = memOnlyChunks;\n this._sourceChunksCache = sourceChunksCache;\n this._sourceStore = sourceStore;\n this.#release = release;\n this.assertValidHash = assertValidHash;\n this.#sourceRead =\n sourceRead !== undefined ? Promise.resolve(sourceRead) : undefined;\n this.#sourceReadOwnedByCaller = sourceRead !== undefined;\n }\n\n isMemOnlyChunkHash(hash: Hash): boolean {\n return this._memOnlyChunks.has(hash);\n }\n\n async hasChunk(hash: Hash): Promise<boolean> {\n return (await this.getChunk(hash)) !== undefined;\n }\n\n async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk !== undefined) {\n return memOnlyChunk;\n }\n let chunk = this._sourceChunksCache.get(hash);\n if (chunk === undefined) {\n chunk = await (await this._getSourceRead()).getChunk(hash);\n if (chunk !== undefined) {\n this._sourceChunksCache.put(chunk);\n }\n }\n return chunk;\n }\n\n mustGetChunk(hash: Hash): Promise<Chunk> {\n return mustGetChunk(this, hash);\n }\n\n getHead(name: string): Promise<Hash | undefined> {\n return Promise.resolve(this._heads.get(name));\n }\n\n release(): void {\n if (!this.#closed) {\n this.#release();\n if (!this.#sourceReadOwnedByCaller) {\n this.#sourceRead\n ?.then(read => read.release())\n // If creation of the read failed there is nothing to release.\n // Catch to avoid `Uncaught (in promise)` errors being reported.\n .catch(_ => {});\n }\n this.#closed = true;\n }\n }\n\n get closed(): boolean {\n return this.#closed;\n }\n\n protected _getSourceRead(): Promise<Read> {\n if (!this.#sourceRead) {\n this.#sourceRead = this._sourceStore.read();\n }\n return this.#sourceRead;\n }\n}\n\nexport class LazyWrite\n extends LazyRead\n implements Write, RefCountUpdatesDelegate\n{\n readonly #refCounts: Map<Hash, number>;\n readonly #refs: Map<Hash, readonly Hash[]>;\n readonly #chunkHasher: ChunkHasher;\n protected readonly _pendingHeadChanges = new Map<string, HeadChange>();\n protected readonly _pendingMemOnlyChunks = new Map<Hash, Chunk>();\n protected readonly _pendingCachedChunks = new Map<\n Hash,\n {chunk: Chunk; size: number}\n >();\n readonly #createdChunks = new Set<Hash>();\n\n constructor(\n heads: Map<string, Hash>,\n memOnlyChunks: Map<Hash, Chunk>,\n sourceChunksCache: ChunksCache,\n sourceStore: Store,\n refCounts: Map<Hash, number>,\n refs: Map<Hash, readonly Hash[]>,\n release: () => void,\n chunkHasher: ChunkHasher,\n assertValidHash: (hash: Hash) => void,\n ) {\n super(\n heads,\n memOnlyChunks,\n sourceChunksCache,\n sourceStore,\n release,\n assertValidHash,\n );\n this.#refCounts = refCounts;\n this.#refs = refs;\n this.#chunkHasher = chunkHasher;\n }\n\n createChunk = <V>(data: V, refs: Refs): Chunk<V> => {\n const chunk = createChunk(data, refs, this.#chunkHasher);\n this.#createdChunks.add(chunk.hash);\n return chunk;\n };\n\n putChunk<V>(c: Chunk<V>, size?: number): Promise<void> {\n const {hash, meta} = c;\n this.assertValidHash(hash);\n if (meta.length > 0) {\n for (const h of meta) {\n this.assertValidHash(h);\n }\n }\n if (this.#createdChunks.has(hash) || this.isMemOnlyChunkHash(hash)) {\n this._pendingMemOnlyChunks.set(hash, c);\n } else {\n this._pendingCachedChunks.set(hash, {chunk: c, size: size ?? -1});\n }\n return promiseVoid;\n }\n\n async setHead(name: string, hash: Hash): Promise<void> {\n await this.#setHead(name, hash);\n }\n\n async removeHead(name: string): Promise<void> {\n await this.#setHead(name, undefined);\n }\n\n async #setHead(name: string, hash: Hash | undefined): Promise<void> {\n const oldHash = await this.getHead(name);\n const v = this._pendingHeadChanges.get(name);\n if (v === undefined) {\n this._pendingHeadChanges.set(name, {new: hash, old: oldHash});\n } else {\n // Keep old if existing\n v.new = hash;\n }\n }\n\n override isMemOnlyChunkHash(hash: Hash): boolean {\n return (\n this._pendingMemOnlyChunks.has(hash) || super.isMemOnlyChunkHash(hash)\n );\n }\n\n override async getChunk(hash: Hash): Promise<Chunk | undefined> {\n const pendingMemOnlyChunk = this._pendingMemOnlyChunks.get(hash);\n if (pendingMemOnlyChunk !== undefined) {\n return pendingMemOnlyChunk;\n }\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk !== undefined) {\n return memOnlyChunk;\n }\n // In order to delegate determining reachability to `computeRefCountUpdates`\n // and defer this determination until commit time, treat cache misses\n // as a 'put' of the lazily-loaded chunk.\n const pendingCachedChunk = this._pendingCachedChunks.get(hash);\n if (pendingCachedChunk !== undefined) {\n return pendingCachedChunk.chunk;\n }\n let chunk = this._sourceChunksCache.get(hash);\n if (chunk === undefined) {\n chunk = await (await this._getSourceRead()).getChunk(hash);\n if (chunk !== undefined) {\n this._pendingCachedChunks.set(chunk.hash, {chunk, size: -1});\n }\n }\n return chunk;\n }\n\n override getHead(name: string): Promise<Hash | undefined> {\n const headChange = this._pendingHeadChanges.get(name);\n if (headChange) {\n return Promise.resolve(headChange.new);\n }\n return super.getHead(name);\n }\n\n async commit(): Promise<void> {\n const pendingChunks = new Set(\n joinIterables(\n this._pendingMemOnlyChunks.keys(),\n this._pendingCachedChunks.keys(),\n ),\n );\n const refCountUpdates = await computeRefCountUpdates(\n this._pendingHeadChanges.values(),\n pendingChunks,\n this,\n );\n\n for (const [hash, count] of refCountUpdates) {\n if (this.isMemOnlyChunkHash(hash)) {\n if (count === 0) {\n this.#refCounts.delete(hash);\n this._memOnlyChunks.delete(hash);\n this.#refs.delete(hash);\n } else {\n this.#refCounts.set(hash, count);\n const chunk = this._pendingMemOnlyChunks.get(hash);\n if (chunk) {\n this.#refs.set(hash, chunk.meta);\n this._memOnlyChunks.set(hash, chunk);\n }\n }\n refCountUpdates.delete(hash);\n }\n }\n\n this._sourceChunksCache.updateForCommit(\n this._pendingCachedChunks,\n refCountUpdates,\n );\n\n for (const [name, headChange] of this._pendingHeadChanges) {\n if (headChange.new) {\n this._heads.set(name, headChange.new);\n } else {\n this._heads.delete(name);\n }\n }\n\n this._pendingMemOnlyChunks.clear();\n this._pendingCachedChunks.clear();\n this._pendingHeadChanges.clear();\n this.release();\n }\n\n getRefCount(hash: Hash): number | undefined {\n return this.#refCounts.get(hash);\n }\n\n getRefs(hash: Hash): readonly Hash[] | undefined {\n const pendingMemOnlyChunk = this._pendingMemOnlyChunks.get(hash);\n if (pendingMemOnlyChunk) {\n return pendingMemOnlyChunk.meta;\n }\n const memOnlyChunk = this._memOnlyChunks.get(hash);\n if (memOnlyChunk) {\n return memOnlyChunk.meta;\n }\n const pendingCachedChunk = this._pendingCachedChunks.get(hash);\n if (pendingCachedChunk !== undefined) {\n return pendingCachedChunk.chunk.meta;\n }\n return this.#refs.get(hash);\n }\n\n areRefsCounted(hash: Hash): boolean {\n return this.#refs.has(hash);\n }\n\n chunksPersisted(chunkHashes: readonly Hash[]): void {\n const chunksToCache = [];\n for (const chunkHash of chunkHashes) {\n const chunk = this._memOnlyChunks.get(chunkHash);\n if (chunk) {\n this._memOnlyChunks.delete(chunkHash);\n chunksToCache.push(chunk);\n }\n }\n this._sourceChunksCache.persisted(chunksToCache);\n }\n}\n\ntype CacheEntry = {\n chunk: Chunk;\n size: number;\n};\n\nclass ChunksCache {\n readonly #cacheSizeLimit: number;\n readonly #getSizeOfChunk: (chunk: Chunk) => number;\n readonly #refCounts: Map<Hash, number>;\n readonly #refs: Map<Hash, readonly Hash[]>;\n #size = 0;\n #evictsAndDeletesSuspended = false;\n readonly #suspendedDeletes: Hash[] = [];\n\n /**\n * Iteration order is from least to most recently used.\n *\n * Public so that testing subclass can access.\n */\n readonly cacheEntries = new Map<Hash, CacheEntry>();\n\n constructor(\n cacheSizeLimit: number,\n getSizeOfChunk: (v: Chunk) => number,\n refCounts: Map<Hash, number>,\n refs: Map<Hash, readonly Hash[]>,\n ) {\n this.#cacheSizeLimit = cacheSizeLimit;\n this.#getSizeOfChunk = getSizeOfChunk;\n this.#refCounts = refCounts;\n this.#refs = refs;\n }\n\n get(hash: Hash): Chunk | undefined {\n const cacheEntry = this.cacheEntries.get(hash);\n if (cacheEntry) {\n // Update order in map for LRU tracking.\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, cacheEntry);\n }\n return cacheEntry?.chunk;\n }\n\n getWithoutUpdatingLRU(hash: Hash): Chunk | undefined {\n return this.cacheEntries.get(hash)?.chunk;\n }\n\n put(chunk: Chunk): void {\n const {hash} = chunk;\n // If there is an existing cache entry then the cached value must be\n // equivalent. Update order in map for LRU tracking and early return.\n const oldCacheEntry = this.cacheEntries.get(hash);\n if (oldCacheEntry) {\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, oldCacheEntry);\n return;\n }\n\n // Only cache if there is a ref from a head to this chunk\n const refCount = this.#refCounts.get(hash);\n if (refCount === undefined || refCount < 1) {\n return;\n }\n if (!this.#cacheChunk(chunk)) {\n return;\n }\n if (!this.#refs.has(hash)) {\n for (const refHash of chunk.meta) {\n this.#refCounts.set(refHash, (this.#refCounts.get(refHash) || 0) + 1);\n }\n this.#refs.set(hash, chunk.meta);\n }\n\n this.#ensureCacheSizeLimit();\n }\n\n #ensureCacheSizeLimit() {\n if (this.#evictsAndDeletesSuspended) {\n return;\n }\n for (const entry of this.cacheEntries.values()) {\n if (this.#size <= this.#cacheSizeLimit) {\n break;\n }\n this.#evict(entry);\n }\n }\n\n #cacheChunk(chunk: Chunk, size?: number): boolean {\n const chunkSize = size ?? this.#getSizeOfChunk(chunk);\n if (chunkSize > this.#cacheSizeLimit) {\n // This value cannot be cached due to its size exceeding the\n // cache size limit, don't evict other entries to try to make\n // room for it.\n return false;\n }\n this.#size += chunkSize;\n this.cacheEntries.set(chunk.hash, {chunk, size: chunkSize});\n return true;\n }\n\n #evict(cacheEntry: CacheEntry): void {\n const {hash} = cacheEntry.chunk;\n this.#size -= cacheEntry.size;\n this.cacheEntries.delete(hash);\n }\n\n #deleteEntryByHash(hash: Hash): void {\n this.#refCounts.delete(hash);\n this.#refs.delete(hash);\n const cacheEntry = this.cacheEntries.get(hash);\n if (cacheEntry) {\n this.#size -= cacheEntry.size;\n this.cacheEntries.delete(hash);\n }\n }\n\n updateForCommit(\n chunksToPut: Map<Hash, {chunk: Chunk; size: number}>,\n refCountUpdates: Map<Hash, number>,\n ): void {\n for (const [hash, count] of refCountUpdates) {\n if (count === 0) {\n if (!this.#evictsAndDeletesSuspended) {\n this.#deleteEntryByHash(hash);\n } else {\n this.#refCounts.set(hash, 0);\n this.#suspendedDeletes.push(hash);\n }\n } else {\n this.#refCounts.set(hash, count);\n const chunkAndSize = chunksToPut.get(hash);\n if (chunkAndSize) {\n const {chunk, size} = chunkAndSize;\n const oldCacheEntry = this.cacheEntries.get(hash);\n if (oldCacheEntry) {\n // If there is an existing cache entry then the cached value must be\n // equivalent. Update order in map for LRU tracking but avoid\n // recomputing size and creating a new cache entry.\n this.cacheEntries.delete(hash);\n this.cacheEntries.set(hash, oldCacheEntry);\n } else {\n this.#cacheChunk(chunk, size !== -1 ? size : undefined);\n this.#refs.set(hash, chunk.meta);\n }\n }\n }\n }\n this.#ensureCacheSizeLimit();\n }\n\n persisted(chunks: Iterable<Chunk>) {\n for (const chunk of chunks) {\n this.#cacheChunk(chunk);\n }\n this.#ensureCacheSizeLimit();\n }\n\n async withSuspendedEvictsAndDeletes<T>(\n fn: () => MaybePromise<T>,\n ): Promise<T> {\n this.#evictsAndDeletesSuspended = true;\n try {\n return await fn();\n } finally {\n this.#evictsAndDeletesSuspended = false;\n for (const hash of this.#suspendedDeletes) {\n if (this.#refCounts.get(hash) === 0) {\n this.#deleteEntryByHash(hash);\n }\n }\n this.#ensureCacheSizeLimit();\n }\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {greaterThan} from 'compare-utf8';\nimport type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {type IndexKey, decodeIndexKey} from './db/index.ts';\nimport type {Read} from './db/read.ts';\nimport type {Write} from './db/write.ts';\nimport {deepFreeze} from './frozen-json.ts';\nimport type {IndexDefinition} from './index-defs.ts';\nimport type {ZeroTxData} from './replicache-options.ts';\nimport type {ScanResult} from './scan-iterator.ts';\nimport {ScanResultImpl, fromKeyForIndexScanInternal} from './scan-iterator.ts';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanNoIndexOptions,\n type ScanOptions,\n isScanIndexOptions,\n toDbScanOptions,\n} from './scan-options.ts';\nimport type {ScanSubscriptionInfo} from './subscriptions.ts';\nimport type {ClientID} from './sync/ids.ts';\nimport {rejectIfClosed, throwIfClosed} from './transaction-closed-error.ts';\n\nexport type TransactionEnvironment = 'client' | 'server';\nexport type TransactionLocation = TransactionEnvironment;\nexport type TransactionReason = 'initial' | 'rebase' | 'authoritative';\n\n/**\n * Basic deep readonly type. It works for {@link JSONValue}.\n */\nexport type DeepReadonly<T> = T extends\n | null\n | boolean\n | string\n | number\n | undefined\n ? T\n : DeepReadonlyObject<T>;\n\nexport type DeepReadonlyObject<T> = {\n readonly [K in keyof T]: DeepReadonly<T[K]>;\n};\n\n/**\n * ReadTransactions are used with {@link Replicache.query} and\n * {@link Replicache.subscribe} and allows read operations on the\n * database.\n */\nexport interface ReadTransaction {\n readonly clientID: ClientID;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n readonly location: TransactionLocation;\n\n /**\n * Get a single value from the database. If the `key` is not present this\n * returns `undefined`.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined>;\n\n /** Determines if a single `key` is present in the database. */\n has(key: string): Promise<boolean>;\n\n /** Whether the database is empty. */\n isEmpty(): Promise<boolean>;\n\n /**\n * Gets many values from the database. This returns a {@link ScanResult} which\n * implements `AsyncIterable`. It also has methods to iterate over the\n * {@link ScanResult.keys | keys} and {@link ScanResult.entries | entries}.\n *\n * If `options` has an `indexName`, then this does a scan over an index with\n * that name. A scan over an index uses a tuple for the key consisting of\n * `[secondary: string, primary: string]`.\n *\n * If the {@link ScanResult} is used after the `ReadTransaction` has been closed\n * it will throw a {@link TransactionClosedError}.\n *\n * Important: The returned JSON is readonly and should not be modified. This\n * is only enforced statically by TypeScript and there are no runtime checks\n * for performance reasons. If you mutate the return value you will get\n * undefined behavior.\n */\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n}\n\nlet transactionIDCounter = 0;\n\nexport class ReadTransactionImpl implements ReadTransaction {\n readonly clientID: ClientID;\n readonly dbtx: Read;\n protected readonly _lc: LogContext;\n\n /**\n * The location in which this transaction is being used. This is either `client` or `server`.\n */\n readonly location: TransactionLocation;\n /** @deprecated Use {@link ReadTransaction.location} instead. */\n readonly environment: TransactionLocation;\n\n constructor(\n clientID: ClientID,\n dbRead: Read,\n lc: LogContext,\n rpcName = 'openReadTransaction',\n ) {\n this.clientID = clientID;\n this.dbtx = dbRead;\n this._lc = lc\n .withContext(rpcName)\n .withContext('txid', transactionIDCounter++);\n this.environment = 'client';\n this.location = 'client';\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<V extends JSONValue>(key: string): Promise<DeepReadonly<V> | undefined> {\n return (\n rejectIfClosed(this.dbtx) ||\n (this.dbtx.get(key) as Promise<DeepReadonly<V> | undefined>)\n );\n }\n\n // oxlint-disable-next-line require-await\n async has(key: string): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.has(key);\n }\n\n // oxlint-disable-next-line require-await\n async isEmpty(): Promise<boolean> {\n throwIfClosed(this.dbtx);\n return this.dbtx.isEmpty();\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n return scan(options, this.dbtx, noop);\n }\n}\n\nfunction noop(_: unknown): void {\n // empty\n}\n\nfunction scan<Options extends ScanOptions, V extends JSONValue>(\n options: Options | undefined,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n const iter = getScanIterator<Options, V>(dbRead, options);\n return makeScanResultFromScanIteratorInternal(\n iter,\n options ?? ({} as Options),\n dbRead,\n onLimitKey,\n );\n}\n\n// An implementation of ReadTransaction that keeps track of `keys` and `scans`\n// for use with Subscriptions.\nexport class SubscriptionTransactionWrapper implements ReadTransaction {\n readonly #keys: Set<string> = new Set();\n readonly #scans: ScanSubscriptionInfo[] = [];\n readonly #tx: ReadTransactionImpl;\n\n constructor(tx: ReadTransactionImpl) {\n this.#tx = tx;\n }\n\n get environment(): TransactionLocation {\n return this.#tx.location;\n }\n\n get location(): TransactionLocation {\n return this.#tx.location;\n }\n\n get clientID(): string {\n return this.#tx.clientID;\n }\n\n isEmpty(): Promise<boolean> {\n // Any change to the subscription requires rerunning it.\n this.#scans.push({options: {}});\n return this.#tx.isEmpty();\n }\n\n get(key: string): Promise<ReadonlyJSONValue | undefined>;\n get<T extends JSONValue>(key: string): Promise<DeepReadonly<T> | undefined> {\n this.#keys.add(key);\n return this.#tx.get(key) as Promise<DeepReadonly<T> | undefined>;\n }\n\n has(key: string): Promise<boolean> {\n this.#keys.add(key);\n return this.#tx.has(key);\n }\n\n scan(options: ScanIndexOptions): ScanResult<IndexKey, ReadonlyJSONValue>;\n scan(options?: ScanNoIndexOptions): ScanResult<string, ReadonlyJSONValue>;\n scan(options?: ScanOptions): ScanResult<IndexKey | string, ReadonlyJSONValue>;\n\n scan<V extends ReadonlyJSONValue>(\n options: ScanIndexOptions,\n ): ScanResult<IndexKey, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanNoIndexOptions,\n ): ScanResult<string, DeepReadonly<V>>;\n scan<V extends ReadonlyJSONValue>(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, DeepReadonly<V>>;\n\n scan(\n options?: ScanOptions,\n ): ScanResult<IndexKey | string, ReadonlyJSONValue> {\n const scanInfo: ScanSubscriptionInfo = {\n options: toDbScanOptions(options),\n inclusiveLimitKey: undefined,\n };\n this.#scans.push(scanInfo);\n return scan(options, this.#tx.dbtx, inclusiveLimitKey => {\n scanInfo.inclusiveLimitKey = inclusiveLimitKey;\n });\n }\n\n get keys(): ReadonlySet<string> {\n return this.#keys;\n }\n\n get scans(): ScanSubscriptionInfo[] {\n return this.#scans;\n }\n}\n\n/**\n * WriteTransactions are used with *mutators* which are registered using\n * {@link ReplicacheOptions.mutators} and allows read and write operations on the\n * database.\n */\nexport interface WriteTransaction extends ReadTransaction {\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction. This can be `initial`, `rebase` or `authoriative`.\n */\n readonly reason: TransactionReason;\n\n /**\n * Sets a single `value` in the database. The value will be frozen (using\n * `Object.freeze`) in debug mode.\n */\n set(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * @deprecated Use {@link WriteTransaction.set} instead.\n */\n put(key: string, value: ReadonlyJSONValue): Promise<void>;\n\n /**\n * Removes a `key` and its value from the database. Returns `true` if there was a\n * `key` to remove.\n */\n del(key: string): Promise<boolean>;\n}\n\n// Internal symbol, not exported by Replicache\n// but accessible to Zero.\nexport const zeroData = Symbol();\n\nexport class WriteTransactionImpl\n extends ReadTransactionImpl\n implements WriteTransaction\n{\n // use `declare` to specialize the type.\n declare readonly dbtx: Write;\n readonly reason: TransactionReason;\n readonly mutationID: number;\n readonly [zeroData]: ZeroTxData | undefined;\n\n constructor(\n clientID: ClientID,\n mutationID: number,\n reason: TransactionReason,\n zData: ZeroTxData | undefined,\n dbWrite: Write,\n lc: LogContext,\n rpcName = 'openWriteTransaction',\n ) {\n super(clientID, dbWrite, lc, rpcName);\n this.mutationID = mutationID;\n this.reason = reason;\n this[zeroData] = zData;\n }\n\n put(key: string, value: ReadonlyJSONValue): Promise<void> {\n return this.set(key, value);\n }\n\n async set(key: string, value: ReadonlyJSONValue): Promise<void> {\n throwIfClosed(this.dbtx);\n await this.dbtx.put(this._lc, key, deepFreeze(value));\n }\n\n del(key: string): Promise<boolean> {\n return rejectIfClosed(this.dbtx) ?? this.dbtx.del(this._lc, key);\n }\n}\n\nexport type CreateIndexDefinition = IndexDefinition & {name: string};\n\ntype Entry<Key, Value> = readonly [key: Key, value: Value];\n\ntype IndexKeyEntry<Value> = Entry<IndexKey, Value>;\n\ntype StringKeyEntry<Value> = Entry<string, Value>;\n\nexport type EntryForOptions<\n Options extends ScanOptions,\n V,\n> = Options extends ScanIndexOptions ? IndexKeyEntry<V> : StringKeyEntry<V>;\n\nfunction getScanIterator<Options extends ScanOptions, V>(\n dbRead: Read,\n options: Options | undefined,\n): AsyncIterable<EntryForOptions<Options, V>> {\n if (options && isScanIndexOptions(options)) {\n return getScanIteratorForIndexMap(dbRead, options) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n }\n\n return dbRead.map.scan(fromKeyForNonIndexScan(options)) as AsyncIterable<\n EntryForOptions<Options, V>\n >;\n}\n\nexport function fromKeyForNonIndexScan(\n options: ScanNoIndexOptions | undefined,\n): string {\n if (!options) {\n return '';\n }\n\n const {prefix = '', start} = options;\n if (start && greaterThan(start.key, prefix)) {\n return start.key;\n }\n return prefix;\n}\n\nfunction makeScanResultFromScanIteratorInternal<\n Options extends ScanOptions,\n V extends JSONValue,\n>(\n iter: AsyncIterable<EntryForOptions<Options, V>>,\n options: Options,\n dbRead: Read,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): ScanResult<KeyTypeForScanOptions<Options>, V> {\n return new ScanResultImpl(iter, options, dbRead, onLimitKey);\n}\n\nasync function* getScanIteratorForIndexMap(\n dbRead: Read,\n options: ScanIndexOptions,\n): AsyncIterable<IndexKeyEntry<ReadonlyJSONValue>> {\n const map = dbRead.getMapForIndex(options.indexName);\n for await (const entry of map.scan(fromKeyForIndexScanInternal(options))) {\n yield [decodeIndexKey(entry[0]), entry[1]];\n }\n}\n", "import {greaterThan} from 'compare-utf8';\nimport type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {asyncIterableToArray} from './async-iterable-to-array.ts';\nimport {type IndexKey, encodeIndexScanKey} from './db/index.ts';\nimport type {IterableUnion} from './iterable-union.ts';\nimport {\n type KeyTypeForScanOptions,\n type ScanIndexOptions,\n type ScanOptionIndexedStartKey,\n type ScanOptions,\n isScanIndexOptions,\n normalizeScanOptionIndexedStartKey,\n} from './scan-options.ts';\nimport {type Closed, throwIfClosed} from './transaction-closed-error.ts';\nimport {type EntryForOptions, fromKeyForNonIndexScan} from './transactions.ts';\n\ntype ScanKey = string | IndexKey;\n\ntype ToValue<Options extends ScanOptions, Value> = (\n entry: EntryForOptions<Options, ReadonlyJSONValue>,\n) => Value;\n\n/**\n * This class is used for the results of {@link ReadTransaction.scan | scan}. It\n * implements `AsyncIterable<JSONValue>` which allows you to use it in a `for\n * await` loop. There are also methods to iterate over the {@link keys},\n * {@link entries} or {@link values}.\n */\nexport class ScanResultImpl<Options extends ScanOptions, V>\n implements ScanResult<KeyTypeForScanOptions<Options>, V>\n{\n readonly #iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>;\n readonly #options: Options;\n readonly #dbDelegateOptions: Closed;\n readonly #onLimitKey: (inclusiveLimitKey: string) => void;\n\n constructor(\n iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>,\n options: Options,\n dbDelegateOptions: Closed,\n onLimitKey: (inclusiveLimitKey: string) => void,\n ) {\n this.#iter = iter;\n this.#options = options;\n this.#dbDelegateOptions = dbDelegateOptions;\n this.#onLimitKey = onLimitKey;\n }\n\n /** The default AsyncIterable. This is the same as {@link values}. */\n [Symbol.asyncIterator](): AsyncIterableIteratorToArray<V> {\n return this.values();\n }\n\n /** Async iterator over the values of the {@link ReadTransaction.scan | scan} call. */\n values(): AsyncIterableIteratorToArray<V> {\n return new AsyncIterableIteratorToArrayWrapperImpl(\n this.#newIterator(e => e[1] as V),\n );\n }\n\n /**\n * Async iterator over the keys of the {@link ReadTransaction.scan | scan}\n * call. If the {@link ReadTransaction.scan | scan} is over an index the key\n * is a tuple of `[secondaryKey: string, primaryKey]`\n */\n keys(): AsyncIterableIteratorToArray<KeyTypeForScanOptions<Options>> {\n type K = KeyTypeForScanOptions<Options>;\n return new AsyncIterableIteratorToArrayWrapperImpl<K>(\n this.#newIterator<K>(e => e[0] as K),\n );\n }\n\n /**\n * Async iterator over the entries of the {@link ReadTransaction.scan | scan}\n * call. An entry is a tuple of key values. If the\n * {@link ReadTransaction.scan | scan} is over an index the key is a tuple of\n * `[secondaryKey: string, primaryKey]`\n */\n entries(): AsyncIterableIteratorToArray<\n readonly [KeyTypeForScanOptions<Options>, V]\n > {\n type Key = KeyTypeForScanOptions<Options>;\n type Entry = readonly [Key, V];\n return new AsyncIterableIteratorToArrayWrapperImpl(\n this.#newIterator<Entry>(e => [e[0] as Key, e[1] as V]),\n );\n }\n\n /** Returns all the values as an array. Same as `values().toArray()` */\n toArray(): Promise<V[]> {\n return this.values().toArray();\n }\n\n #newIterator<T>(toValue: ToValue<Options, T>): AsyncIterableIterator<T> {\n return scanIterator(\n toValue,\n this.#iter,\n this.#options,\n this.#dbDelegateOptions,\n this.#onLimitKey,\n );\n }\n}\n\nexport interface ScanResult<K extends ScanKey, V> extends AsyncIterable<V> {\n /** The default AsyncIterable. This is the same as {@link values}. */\n [Symbol.asyncIterator](): AsyncIterableIteratorToArray<V>;\n\n /** Async iterator over the values of the {@link ReadTransaction.scan | scan} call. */\n values(): AsyncIterableIteratorToArray<V>;\n\n /**\n * Async iterator over the keys of the {@link ReadTransaction.scan | scan}\n * call. If the {@link ReadTransaction.scan | scan} is over an index the key\n * is a tuple of `[secondaryKey: string, primaryKey]`\n */\n keys(): AsyncIterableIteratorToArray<K>;\n\n /**\n * Async iterator over the entries of the {@link ReadTransaction.scan | scan}\n * call. An entry is a tuple of key values. If the\n * {@link ReadTransaction.scan | scan} is over an index the key is a tuple of\n * `[secondaryKey: string, primaryKey]`\n */\n entries(): AsyncIterableIteratorToArray<readonly [K, V]>;\n\n /** Returns all the values as an array. Same as `values().toArray()` */\n toArray(): Promise<V[]>;\n}\n\n/**\n * An interface that adds a {@link toArray} method to `AsyncIterableIterator`.\n *\n * Usage:\n *\n * ```ts\n * const keys: string[] = await rep.scan().keys().toArray();\n * ```\n */\nexport interface AsyncIterableIteratorToArray<V>\n extends AsyncIterableIterator<V> {\n toArray(): Promise<V[]>;\n}\n\nclass AsyncIterableIteratorToArrayWrapperImpl<V>\n implements AsyncIterableIterator<V>\n{\n readonly #it: AsyncIterableIterator<V>;\n\n constructor(it: AsyncIterableIterator<V>) {\n this.#it = it;\n }\n\n next() {\n return this.#it.next();\n }\n\n [Symbol.asyncIterator](): AsyncIterableIterator<V> {\n return this.#it[Symbol.asyncIterator]();\n }\n\n toArray(): Promise<V[]> {\n return asyncIterableToArray(this.#it);\n }\n}\n\nasync function* scanIterator<Options extends ScanOptions, Value>(\n toValue: ToValue<Options, Value>,\n iter: AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>,\n options: Options,\n closed: Closed,\n onLimitKey: (inclusiveLimitKey: string) => void,\n): AsyncIterableIterator<Value> {\n throwIfClosed(closed);\n\n let {limit = Infinity} = options;\n const {prefix = ''} = options;\n let exclusive = options.start?.exclusive;\n\n const isIndexScan = isScanIndexOptions(options);\n\n // iter has already been moved to the first entry\n for await (const entry of iter) {\n const key = entry[0];\n const keyToMatch: string = isIndexScan ? key[0] : (key as string);\n if (!keyToMatch.startsWith(prefix)) {\n return;\n }\n\n if (exclusive) {\n exclusive = true;\n if (isIndexScan) {\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (shouldSkipIndexScan(key as IndexKey, options.start!.key)) {\n continue;\n }\n } else {\n // oxlint-disable-next-line @typescript-eslint/no-non-null-assertion\n if (shouldSkipNonIndexScan(key as string, options.start!.key)) {\n continue;\n }\n }\n }\n\n yield toValue(entry);\n\n if (--limit === 0) {\n // We do not do the limit optimization for index scans in subscriptions.\n if (!isIndexScan) {\n onLimitKey(key as string);\n }\n return;\n }\n }\n}\n\nfunction shouldSkipIndexScan(\n key: IndexKey,\n startKey: ScanOptionIndexedStartKey,\n): boolean {\n const [secondaryStartKey, primaryStartKey] =\n normalizeScanOptionIndexedStartKey(startKey);\n const [secondaryKey, primaryKey] = normalizeScanOptionIndexedStartKey(key);\n if (secondaryKey !== secondaryStartKey) {\n return false;\n }\n if (primaryStartKey === undefined) {\n return true;\n }\n return primaryKey === primaryStartKey;\n}\n\nfunction shouldSkipNonIndexScan(key: string, startKey: string): boolean {\n return key === startKey;\n}\n\nexport type Entry<V> = readonly [key: string, value: V];\n\n/**\n * This is called when doing a {@link ReadTransaction.scan | scan} without an\n * `indexName`.\n *\n * @param fromKey The `fromKey` is computed by `scan` and is the key of the\n * first entry to return in the iterator. It is based on `prefix` and\n * `start.key` of the {@link ScanNoIndexOptions}.\n */\nexport type GetScanIterator = (\n fromKey: string,\n) => IterableUnion<Entry<ReadonlyJSONValue>>;\n\n/**\n * When using {@link makeScanResult} this is the type used for the function called when doing a {@link ReadTransaction.scan | scan} with an\n * `indexName`.\n *\n * @param indexName The name of the index we are scanning over.\n * @param fromSecondaryKey The `fromSecondaryKey` is computed by `scan` and is\n * the secondary key of the first entry to return in the iterator. It is based\n * on `prefix` and `start.key` of the {@link ScanIndexOptions}.\n * @param fromPrimaryKey The `fromPrimaryKey` is computed by `scan` and is the\n * primary key of the first entry to return in the iterator. It is based on\n * `prefix` and `start.key` of the {@link ScanIndexOptions}.\n */\nexport type GetIndexScanIterator = (\n indexName: string,\n fromSecondaryKey: string,\n fromPrimaryKey: string | undefined,\n) => IterableUnion<readonly [key: IndexKey, value: ReadonlyJSONValue]>;\n\n/**\n * A helper function that makes it easier to implement {@link ReadTransaction.scan}\n * with a custom backend.\n *\n * If you are implementing a custom backend and have an in memory pending async\n * iterable we provide two helper functions to make it easier to merge these\n * together. {@link mergeAsyncIterables} and {@link filterAsyncIterable}.\n *\n * For example:\n *\n * ```ts\n * const scanResult = makeScanResult(\n * options,\n * options.indexName\n * ? () => {\n * throw Error('not implemented');\n * }\n * : fromKey => {\n * const persisted: AsyncIterable<Entry<ReadonlyJSONValue>> = ...;\n * const pending: AsyncIterable<Entry<ReadonlyJSONValue | undefined>> = ...;\n * const iter = await mergeAsyncIterables(persisted, pending);\n * const filteredIter = await filterAsyncIterable(\n * iter,\n * entry => entry[1] !== undefined,\n * );\n * return filteredIter;\n * },\n * );\n * ```\n */\nexport function makeScanResult<Options extends ScanOptions>(\n options: Options,\n getScanIterator: Options extends ScanIndexOptions\n ? GetIndexScanIterator\n : GetScanIterator,\n): ScanResult<KeyTypeForScanOptions<Options>, ReadonlyJSONValue> {\n type AsyncIter = AsyncIterable<EntryForOptions<Options, ReadonlyJSONValue>>;\n\n if (isScanIndexOptions(options)) {\n const [fromSecondaryKey, fromPrimaryKey] = fromKeyForIndexScan(options);\n return new ScanResultImpl(\n (getScanIterator as GetIndexScanIterator)(\n options.indexName,\n fromSecondaryKey,\n fromPrimaryKey,\n ) as AsyncIter,\n options,\n {closed: false},\n _ => {\n // noop\n },\n );\n }\n const fromKey = fromKeyForNonIndexScan(options);\n return new ScanResultImpl(\n (getScanIterator as GetScanIterator)(fromKey) as AsyncIter,\n options,\n {closed: false},\n _ => {\n // noop\n },\n );\n}\n\nexport function fromKeyForIndexScan(\n options: ScanIndexOptions,\n): readonly [secondary: string, primary?: string | undefined] {\n const {prefix, start} = options;\n const prefixNormalized: [secondary: string, primary?: string | undefined] = [\n prefix ?? '',\n undefined,\n ];\n\n if (!start) {\n return prefixNormalized;\n }\n\n const startKeyNormalized = normalizeScanOptionIndexedStartKey(start.key);\n if (greaterThan(startKeyNormalized[0], prefixNormalized[0])) {\n return startKeyNormalized;\n }\n if (\n startKeyNormalized[0] === prefixNormalized[0] &&\n startKeyNormalized[1] !== undefined\n ) {\n return startKeyNormalized;\n }\n\n return prefixNormalized;\n}\n\nexport function fromKeyForIndexScanInternal(options: ScanIndexOptions): string {\n const {prefix, start} = options;\n let prefix2 = '';\n if (prefix !== undefined) {\n prefix2 = encodeIndexScanKey(prefix, undefined);\n }\n if (!start) {\n return prefix2;\n }\n\n const {key} = start;\n const [secondary, primary] = normalizeScanOptionIndexedStartKey(key);\n const startKey = encodeIndexScanKey(secondary, primary);\n\n if (greaterThan(startKey, prefix2)) {\n return startKey;\n }\n\n return prefix2;\n}\n", "import type {IndexKey} from './db/index.ts';\nimport type {ScanOptions as DbScanOptions} from './db/scan.ts';\n\n/**\n * Options for {@link ReadTransaction.scan | scan}\n */\nexport type ScanOptions = ScanIndexOptions | ScanNoIndexOptions;\n\n/**\n * Options for {@link ReadTransaction.scan | scan} when scanning over the entire key\n * space.\n */\nexport type ScanNoIndexOptions = {\n /** Only include keys starting with `prefix`. */\n prefix?: string | undefined;\n\n /** Only include up to `limit` results. */\n limit?: number | undefined;\n\n /** When provided the scan starts at this key. */\n start?:\n | {\n key: string;\n\n /** Whether the `key` is exclusive or inclusive. */\n exclusive?: boolean | undefined;\n }\n | undefined;\n};\n\n/**\n * Options for {@link ReadTransaction.scan | scan} when scanning over an index. When\n * scanning over and index you need to provide the `indexName` and the `start`\n * `key` is now a tuple consisting of secondary and primary key\n */\nexport type ScanIndexOptions = {\n /** Only include results starting with the *secondary* keys starting with `prefix`. */\n prefix?: string | undefined;\n\n /** Only include up to `limit` results. */\n limit?: number | undefined;\n\n /** Do a {@link ReadTransaction.scan | scan} over a named index. The `indexName` is\n * the name of an index defined when creating the {@link Replicache} instance using\n * {@link ReplicacheOptions.indexes}. */\n indexName: string;\n\n /** When provided the scan starts at this key. */\n start?:\n | {\n key: ScanOptionIndexedStartKey;\n\n /** Whether the `key` is exclusive or inclusive. */\n exclusive?: boolean | undefined;\n }\n | undefined;\n};\n\n/**\n * Type narrowing of {@link ScanOptions}.\n */\nexport function isScanIndexOptions(\n options: ScanOptions,\n): options is ScanIndexOptions {\n return (options as ScanIndexOptions).indexName !== undefined;\n}\n\n/**\n * If the options contains an `indexName` then the key type is a tuple of\n * secondary and primary.\n */\nexport type KeyTypeForScanOptions<O extends ScanOptions> =\n O extends ScanIndexOptions ? IndexKey : string;\n\n/**\n * The key to start scanning at.\n *\n * If you are scanning the primary index (i.e., you did not specify\n * `indexName`), then pass a single string for this field, which is the key in\n * the primary index to scan at.\n *\n * If you are scanning a secondary index (i.e., you specified `indexName`), then\n * use the tuple form. In that case, `secondary` is the secondary key to start\n * scanning at, and `primary` (if any) is the primary key to start scanning at.\n */\nexport type ScanOptionIndexedStartKey =\n | readonly [secondary: string, primary?: string | undefined]\n | string;\n\nexport function normalizeScanOptionIndexedStartKey(\n startKey: string | readonly [secondary: string, primary?: string | undefined],\n): readonly [secondary: string, primary?: string | undefined] {\n if (typeof startKey === 'string') {\n return [startKey];\n }\n return startKey;\n}\n\nexport function toDbScanOptions(options?: ScanOptions): DbScanOptions {\n if (!options) {\n return {};\n }\n let key: string | ScanOptionIndexedStartKey | undefined;\n let exclusive: boolean | undefined;\n let primary: string | undefined;\n let secondary: string | undefined;\n type MaybeIndexName = {indexName?: string};\n if (options.start) {\n ({key, exclusive} = options.start);\n if ((options as MaybeIndexName).indexName) {\n if (typeof key === 'string') {\n secondary = key;\n } else {\n secondary = key[0];\n primary = key[1];\n }\n } else {\n primary = key as string;\n }\n }\n\n return {\n prefix: options.prefix,\n startSecondaryKey: secondary,\n startKey: primary,\n startExclusive: exclusive,\n limit: options.limit,\n indexName: (options as MaybeIndexName).indexName,\n };\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {Write as DagWrite} from '../dag/store.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport {WriteTransactionImpl} from '../transactions.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {\n Commit,\n type LocalMeta,\n type LocalMetaDD31,\n type Meta,\n assertLocalMetaDD31,\n commitFromHash,\n isLocalMetaDD31,\n} from './commit.ts';\nimport {Write, newWriteLocal} from './write.ts';\nimport type {ZeroTxData} from '../replicache-options.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nasync function rebaseMutation(\n mutation: Commit<LocalMetaDD31>,\n dagWrite: DagWrite,\n basisHash: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Write> {\n const localMeta = mutation.meta;\n const name = localMeta.mutatorName;\n if (isLocalMetaDD31(localMeta)) {\n assert(\n localMeta.clientID === mutationClientID,\n 'mutationClientID must match clientID of LocalMeta',\n );\n }\n const maybeMutatorImpl = mutators[name];\n if (!maybeMutatorImpl) {\n // Developers must not remove mutator names from code deployed with the\n // same schemaVersion because Replicache needs to be able to replay\n // mutations during pull.\n //\n // If we detect that this has happened, stub in a no-op mutator so that at\n // least sync can move forward. Note that the server-side mutation will\n // still get sent. This doesn't remove the queued local mutation, it just\n // removes its visible effects.\n lc.error?.(`Cannot rebase unknown mutator ${name}`);\n }\n const mutatorImpl =\n maybeMutatorImpl ||\n (async () => {\n // no op\n });\n\n const args = localMeta.mutatorArgsJSON;\n\n const basisCommit = await commitFromHash(basisHash, dagWrite);\n const nextMutationID = await basisCommit.getNextMutationID(\n mutationClientID,\n dagWrite,\n );\n if (nextMutationID !== localMeta.mutationID) {\n throw new Error(\n `Inconsistent mutation ID: original: ${localMeta.mutationID}, next: ${nextMutationID} - mutationClientID: ${mutationClientID} mutatorName: ${name}`,\n );\n }\n\n if (formatVersion >= FormatVersion.DD31) {\n assertLocalMetaDD31(localMeta);\n }\n\n const dbWrite = await newWriteLocal(\n basisHash,\n name,\n args,\n mutation.chunk.hash,\n dagWrite,\n localMeta.timestamp,\n mutationClientID,\n formatVersion,\n );\n\n const tx = new WriteTransactionImpl(\n mutationClientID,\n await dbWrite.getMutationID(),\n 'rebase',\n zeroData,\n dbWrite,\n lc,\n );\n await mutatorImpl(tx, args);\n return dbWrite;\n}\n\nexport async function rebaseMutationAndPutCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Commit<Meta>> {\n const tx = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return tx.putCommit();\n}\n\nexport async function rebaseMutationAndCommit(\n mutation: Commit<LocalMeta>,\n dagWrite: DagWrite,\n basis: Hash,\n headName: string,\n mutators: MutatorDefs,\n lc: LogContext,\n // TODO(greg): mutationClientID can be retrieved from mutation if LocalMeta\n // is a LocalMetaDD31. As part of DD31 cleanup we can remove this arg.\n mutationClientID: ClientID,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Hash> {\n const dbWrite = await rebaseMutation(\n mutation,\n dagWrite,\n basis,\n mutators,\n lc,\n mutationClientID,\n formatVersion,\n zeroData,\n );\n return dbWrite.commit(headName);\n}\n", "import {callDefaultFetch} from './call-default-fetch.ts';\nimport {\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport type {Pusher, PusherResult} from './pusher.ts';\nimport type {PushRequest} from './sync/push.ts';\n\n/**\n * This creates a default pusher which uses HTTP POST to send the push request.\n */\nexport function getDefaultPusher(rep: {pushURL: string; auth: string}): Pusher {\n async function pusher(\n requestBody: PushRequest,\n requestID: string,\n ): Promise<PusherResult> {\n const [response, httpRequestInfo] = await callDefaultFetch(\n rep.pushURL,\n rep.auth,\n requestID,\n requestBody,\n );\n if (!response) {\n return {httpRequestInfo};\n }\n\n const rv: PusherResult = {\n httpRequestInfo,\n };\n\n let result;\n try {\n result = await response.json();\n } catch {\n // Ignore JSON parse errors. It is valid to return a non-JSON response.\n return rv;\n }\n\n if (\n isClientStateNotFoundResponse(result) ||\n isVersionNotSupportedResponse(result)\n ) {\n rv.response = result;\n }\n\n return rv;\n }\n\n defaultPushers.add(pusher);\n return pusher;\n}\n\nconst defaultPushers = new WeakSet();\n\nexport function isDefaultPusher(pusher: Pusher): boolean {\n return defaultPushers.has(pusher);\n}\n", "export const httpStatusUnauthorized = 401;\n", "/**\n * Wrapper error class that should be reported as error (logger.error)\n */\nexport class ReportError extends Error {}\n", "export function toError(e: unknown): Error {\n if (e instanceof Error) {\n return e;\n }\n return new Error(String(e));\n}\n", "export const Applied = 0;\nexport const NoOp = 1;\nexport const CookieMismatch = 2;\n\nexport type Applied = typeof Applied;\nexport type NoOp = typeof NoOp;\nexport type CookieMismatch = typeof CookieMismatch;\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assertObject} from '../../../shared/src/asserts.ts';\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from '../../../shared/src/json.ts';\nimport type {Write} from '../db/write.ts';\nimport {\n type FrozenJSONObject,\n type FrozenJSONValue,\n deepFreeze,\n} from '../frozen-json.ts';\nimport type {PatchOperationInternal} from '../patch-operation.ts';\nimport type {DiffOperation} from '../btree/node.ts';\n\nexport type Diff =\n | DiffOperation<string>\n | {\n op: 'clear';\n };\n\nexport async function apply(\n lc: LogContext,\n dbWrite: Write,\n patch: readonly PatchOperationInternal[],\n): Promise<void> {\n for (const p of patch) {\n switch (p.op) {\n case 'put': {\n const frozen = deepFreeze(p.value);\n await dbWrite.put(lc, p.key, frozen);\n break;\n }\n case 'update': {\n const existing = await dbWrite.get(p.key);\n const entries: [\n string,\n FrozenJSONValue | ReadonlyJSONValue | undefined,\n ][] = [];\n const addToEntries = (toAdd: FrozenJSONObject | ReadonlyJSONObject) => {\n for (const [key, value] of Object.entries(toAdd)) {\n if (\n !p.constrain ||\n p.constrain.length === 0 ||\n p.constrain.indexOf(key) > -1\n ) {\n entries.push([key, value]);\n }\n }\n };\n if (existing !== undefined) {\n assertObject(existing);\n addToEntries(existing);\n }\n if (p.merge) {\n addToEntries(p.merge);\n }\n const frozen = deepFreeze(Object.fromEntries(entries));\n await dbWrite.put(lc, p.key, frozen);\n\n break;\n }\n case 'del': {\n const existing = await dbWrite.get(p.key);\n if (existing === undefined) {\n continue;\n }\n await dbWrite.del(lc, p.key);\n break;\n }\n case 'clear':\n await dbWrite.clear();\n break;\n }\n }\n}\n", "/**\n * This error is thrown when the puller fails for any reason.\n */\n\nexport class PullError extends Error {\n name = 'PullError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to pull');\n this.causedBy = causedBy;\n }\n}\n", "export const SYNC_HEAD_NAME = 'sync';\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {deepEqual} from '../../../shared/src/json.ts';\nimport {diff} from '../btree/diff.ts';\nimport {BTreeRead} from '../btree/read.ts';\nimport {compareCookies, type Cookie} from '../cookies.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n assertSnapshotMetaDD31,\n baseSnapshotFromHash,\n Commit,\n commitFromHash,\n commitIsLocalDD31,\n DEFAULT_HEAD_NAME,\n type LocalMeta,\n localMutations as localMutations_1,\n snapshotMetaParts,\n} from '../db/commit.ts';\nimport {newWriteSnapshotDD31} from '../db/write.ts';\nimport {isErrorResponse} from '../error-responses.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport {deepFreeze, type FrozenJSONValue} from '../frozen-json.ts';\nimport {assertPullerResultV1} from '../get-default-puller.ts';\nimport {emptyHash, type Hash} from '../hash.ts';\nimport type {HTTPRequestInfo} from '../http-request-info.ts';\nimport type {\n Puller,\n PullerResult,\n PullResponseOKV1Internal,\n PullResponseV1,\n} from '../puller.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead, withWriteNoImplicitCommit} from '../with-transactions.ts';\nimport {\n addDiffsForIndexes,\n type DiffComputationConfig,\n DiffsMap,\n} from './diff.ts';\nimport * as HandlePullResponseResultType from './handle-pull-response-result-type-enum.ts';\nimport type {ClientGroupID, ClientID} from './ids.ts';\nimport * as patch from './patch.ts';\nimport {PullError} from './pull-error.ts';\nimport {SYNC_HEAD_NAME} from './sync-head-name.ts';\n\ntype FormatVersion = (typeof FormatVersion)[keyof typeof FormatVersion];\n\nexport const PULL_VERSION_SDD = 0;\nexport const PULL_VERSION_DD31 = 1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequest = PullRequestV1;\n\n/**\n * The JSON value used as the body when doing a POST to the [pull\n * endpoint](/reference/server-pull).\n */\nexport type PullRequestV1 = {\n pullVersion: 1;\n // schemaVersion can optionally be used by the customer's app\n // to indicate to the data layer what format of Client View the\n // app understands.\n schemaVersion: string;\n profileID: string;\n cookie: Cookie;\n\n clientGroupID: ClientGroupID;\n};\n\nexport function isPullRequestV1(pr: PullRequest): pr is PullRequestV1 {\n return pr.pullVersion === PULL_VERSION_DD31;\n}\n\nexport type BeginPullResponseV1 = {\n httpRequestInfo: HTTPRequestInfo;\n pullResponse?: PullResponseV1;\n syncHead: Hash;\n};\n\nexport async function beginPullV1(\n profileID: string,\n clientID: ClientID,\n clientGroupID: ClientGroupID,\n schemaVersion: string,\n puller: Puller,\n requestID: string,\n store: Store,\n formatVersion: FormatVersion,\n lc: LogContext,\n createSyncBranch = true,\n): Promise<BeginPullResponseV1> {\n const baseCookie = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head found');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n return baseSnapshotMeta.cookieJSON;\n });\n\n const pullReq: PullRequestV1 = {\n profileID,\n clientGroupID,\n cookie: baseCookie,\n pullVersion: PULL_VERSION_DD31,\n schemaVersion,\n };\n\n const {response, httpRequestInfo} = await callPuller(\n lc,\n puller,\n pullReq,\n requestID,\n );\n\n // If Puller did not get a pull response we still want to return the HTTP\n // request info.\n if (!response) {\n return {\n httpRequestInfo,\n syncHead: emptyHash,\n };\n }\n\n if (!createSyncBranch || isErrorResponse(response)) {\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead: emptyHash,\n };\n }\n\n const result = await handlePullResponseV1(\n lc,\n store,\n baseCookie,\n response,\n clientID,\n formatVersion,\n );\n\n return {\n httpRequestInfo,\n pullResponse: response,\n syncHead:\n result.type === HandlePullResponseResultType.Applied\n ? result.syncHead\n : emptyHash,\n };\n}\n\nasync function callPuller(\n lc: LogContext,\n puller: Puller,\n pullReq: PullRequest,\n requestID: string,\n): Promise<PullerResult> {\n lc.debug?.('Starting pull...');\n const pullStart = Date.now();\n let pullerResult: PullerResult;\n try {\n pullerResult = await puller(pullReq, requestID);\n lc.debug?.(\n `...Pull ${pullerResult.response ? 'complete' : 'failed'} in `,\n Date.now() - pullStart,\n 'ms',\n );\n } catch (e) {\n throw new PullError(toError(e));\n }\n try {\n assertPullerResultV1(pullerResult);\n return pullerResult;\n } catch (e) {\n throw new ReportError('Invalid puller result', toError(e));\n }\n}\n\ntype HandlePullResponseResult =\n | {\n type: HandlePullResponseResultType.Applied;\n syncHead: Hash;\n }\n | {\n type:\n | HandlePullResponseResultType.NoOp\n | HandlePullResponseResultType.CookieMismatch;\n };\n\nfunction badOrderMessage(\n name: string,\n receivedValue: string,\n lastSnapshotValue: string,\n) {\n return `Received ${name} ${receivedValue} is < than last snapshot ${name} ${lastSnapshotValue}; ignoring client view`;\n}\n\nexport function handlePullResponseV1(\n lc: LogContext,\n store: Store,\n expectedBaseCookie: FrozenJSONValue,\n response: PullResponseOKV1Internal,\n clientID: ClientID,\n formatVersion: FormatVersion,\n): Promise<HandlePullResponseResult> {\n // It is possible that another sync completed while we were pulling. Ensure\n // that is not the case by re-checking the base snapshot.\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n const mainHead = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHead === undefined) {\n throw new Error('Main head disappeared');\n }\n const baseSnapshot = await baseSnapshotFromHash(mainHead, dagRead);\n const baseSnapshotMeta = baseSnapshot.meta;\n assertSnapshotMetaDD31(baseSnapshotMeta);\n const baseCookie = baseSnapshotMeta.cookieJSON;\n\n // TODO(MP) Here we are using whether the cookie has changed as a proxy for whether\n // the base snapshot changed, which is the check we used to do. I don't think this\n // is quite right. We need to firm up under what conditions we will/not accept an\n // update from the server: https://github.com/rocicorp/replicache/issues/713.\n // In DD31 this is expected to happen if a refresh occurs during a pull.\n if (!deepEqual(expectedBaseCookie, baseCookie)) {\n lc.debug?.(\n 'handlePullResponse: cookie mismatch, response is not applicable',\n );\n return {\n type: HandlePullResponseResultType.CookieMismatch,\n };\n }\n\n // Check that the lastMutationIDs are not going backwards.\n for (const [clientID, lmidChange] of Object.entries(\n response.lastMutationIDChanges,\n )) {\n const lastMutationID = baseSnapshotMeta.lastMutationIDs[clientID];\n if (lastMutationID !== undefined && lmidChange < lastMutationID) {\n throw new Error(\n badOrderMessage(\n `${clientID} lastMutationID`,\n String(lmidChange),\n String(lastMutationID),\n ),\n );\n }\n }\n\n const frozenResponseCookie = deepFreeze(response.cookie);\n if (compareCookies(frozenResponseCookie, baseCookie) < 0) {\n throw new Error(\n badOrderMessage(\n 'cookie',\n JSON.stringify(frozenResponseCookie),\n JSON.stringify(baseCookie),\n ),\n );\n }\n\n if (deepEqual(frozenResponseCookie, baseCookie)) {\n if (response.patch.length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but patch is not empty`,\n );\n }\n if (Object.keys(response.lastMutationIDChanges).length > 0) {\n lc.error?.(\n `handlePullResponse: cookie ${JSON.stringify(\n baseCookie,\n )} did not change, but lastMutationIDChanges is not empty`,\n );\n }\n // If the cookie doesn't change, it's a nop.\n return {\n type: HandlePullResponseResultType.NoOp,\n };\n }\n\n const dbWrite = await newWriteSnapshotDD31(\n baseSnapshot.chunk.hash,\n {...baseSnapshotMeta.lastMutationIDs, ...response.lastMutationIDChanges},\n frozenResponseCookie,\n dagWrite,\n clientID,\n formatVersion,\n );\n\n await patch.apply(lc, dbWrite, response.patch);\n\n return {\n type: HandlePullResponseResultType.Applied,\n syncHead: await dbWrite.commit(SYNC_HEAD_NAME),\n };\n });\n}\n\nexport function maybeEndPull<M extends LocalMeta>(\n store: Store,\n lc: LogContext,\n expectedSyncHead: Hash,\n clientID: ClientID,\n diffConfig: DiffComputationConfig,\n formatVersion: FormatVersion,\n): Promise<{\n syncHead: Hash;\n mainHead: Hash;\n oldMainHead: Hash;\n replayMutations: Commit<M>[];\n diffs: DiffsMap;\n}> {\n return withWriteNoImplicitCommit(store, async dagWrite => {\n const dagRead = dagWrite;\n // Ensure sync head is what the caller thinks it is.\n const syncHeadHash = await dagRead.getHead(SYNC_HEAD_NAME);\n if (syncHeadHash === undefined) {\n throw new Error('Missing sync head');\n }\n if (syncHeadHash !== expectedSyncHead) {\n lc.error?.(\n 'maybeEndPull, Wrong sync head. Expecting:',\n expectedSyncHead,\n 'got:',\n syncHeadHash,\n );\n throw new Error('Wrong sync head');\n }\n\n // Ensure another sync has not landed a new snapshot on the main chain.\n // TODO: In DD31, it is expected that a newer snapshot might have appeared\n // on the main chain. In that case, we just abort this pull.\n const syncSnapshot = await baseSnapshotFromHash(syncHeadHash, dagRead);\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (mainHeadHash === undefined) {\n throw new Error('Missing main head');\n }\n const mainSnapshot = await baseSnapshotFromHash(mainHeadHash, dagRead);\n\n const {meta} = syncSnapshot;\n const syncSnapshotBasis = meta.basisHash;\n if (syncSnapshot === null) {\n throw new Error('Sync snapshot with no basis');\n }\n if (syncSnapshotBasis !== mainSnapshot.chunk.hash) {\n throw new Error('Overlapping syncs');\n }\n\n // Collect pending commits from the main chain and determine which\n // of them if any need to be replayed.\n const syncHead = await commitFromHash(syncHeadHash, dagRead);\n const pending: Commit<M>[] = [];\n const localMutations = await localMutations_1(mainHeadHash, dagRead);\n for (const commit of localMutations) {\n let cid = clientID;\n assert(commitIsLocalDD31(commit));\n cid = commit.meta.clientID;\n\n if (\n (await commit.getMutationID(cid, dagRead)) >\n (await syncHead.getMutationID(cid, dagRead))\n ) {\n // We know that the dag can only contain either LocalMetaSDD or LocalMetaDD31\n pending.push(commit as Commit<M>);\n }\n }\n // pending() gave us the pending mutations in sync-head-first order whereas\n // caller wants them in the order to replay (lower mutation ids first).\n pending.reverse();\n\n // We return the keys that changed due to this pull. This is used by\n // subscriptions in the JS API when there are no more pending mutations.\n const diffsMap = new DiffsMap();\n\n // Return replay commits if any.\n if (pending.length > 0) {\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: mainHeadHash,\n replayMutations: pending,\n // The changed keys are not reported when further replays are\n // needed. The diffs will be reported at the end when there\n // are no more mutations to be replay and then it will be reported\n // relative to DEFAULT_HEAD_NAME.\n diffs: diffsMap,\n };\n }\n\n // TODO check invariants\n\n // Compute diffs (changed keys) for value map and index maps.\n const mainHead = await commitFromHash(mainHeadHash, dagRead);\n if (diffConfig.shouldComputeDiffs()) {\n const mainHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n mainHead.valueHash,\n );\n const syncHeadMap = new BTreeRead(\n dagRead,\n formatVersion,\n syncHead.valueHash,\n );\n const valueDiff = await diff(mainHeadMap, syncHeadMap);\n diffsMap.set('', valueDiff);\n await addDiffsForIndexes(\n mainHead,\n syncHead,\n dagRead,\n diffsMap,\n diffConfig,\n formatVersion,\n );\n }\n\n // No mutations to replay so set the main head to the sync head and sync complete!\n await Promise.all([\n dagWrite.setHead(DEFAULT_HEAD_NAME, syncHeadHash),\n dagWrite.removeHead(SYNC_HEAD_NAME),\n ]);\n await dagWrite.commit();\n // main head was set to sync head\n const newMainHeadHash = syncHeadHash;\n\n if (lc.debug) {\n const [oldLastMutationID, oldCookie] = snapshotMetaParts(\n mainSnapshot,\n clientID,\n );\n const [newLastMutationID, newCookie] = snapshotMetaParts(\n syncSnapshot,\n clientID,\n );\n lc.debug(\n `Successfully pulled new snapshot with lastMutationID:`,\n newLastMutationID,\n `(prev:`,\n oldLastMutationID,\n `), cookie: `,\n newCookie,\n `(prev:`,\n oldCookie,\n `), sync head hash:`,\n syncHeadHash,\n ', main head hash:',\n mainHeadHash,\n `, valueHash:`,\n syncHead.valueHash,\n `(prev:`,\n mainSnapshot.valueHash,\n );\n }\n\n return {\n syncHead: syncHeadHash,\n oldMainHead: mainHeadHash,\n mainHead: newMainHeadHash,\n replayMutations: [],\n diffs: diffsMap,\n };\n });\n}\n", "import {assertObject} from '../../shared/src/asserts.ts';\nimport {\n assertVersionNotSupportedResponse,\n type ClientStateNotFoundResponse,\n isClientStateNotFoundResponse,\n type VersionNotSupportedResponse,\n} from './error-responses.ts';\nimport {\n assertHTTPRequestInfo,\n type HTTPRequestInfo,\n} from './http-request-info.ts';\nimport type {PushRequest} from './sync/push.ts';\n\nexport type PusherResult = {\n response?: PushResponse | undefined;\n httpRequestInfo: HTTPRequestInfo;\n};\n\n/**\n * The response from a push can contain information about error conditions.\n */\nexport type PushResponse =\n | ClientStateNotFoundResponse\n | VersionNotSupportedResponse;\n\nexport function assertPusherResult(v: unknown): asserts v is PusherResult {\n assertObject(v);\n assertHTTPRequestInfo(v.httpRequestInfo);\n if (v.response !== undefined) {\n assertPushResponse(v.response);\n }\n}\n\nfunction assertPushResponse(v: unknown): asserts v is PushResponse {\n if (isClientStateNotFoundResponse(v)) {\n return;\n }\n assertVersionNotSupportedResponse(v);\n}\n\n/**\n * Pusher is the function type used to do the fetch part of a push. The request\n * is a POST request where the body is JSON with the type {@link PushRequest}.\n *\n * The return value should either be a {@link HTTPRequestInfo} or a\n * {@link PusherResult}. The reason for the two different return types is that\n * we didn't use to care about the response body of the push request. The\n * default pusher implementation checks if the response body is JSON and if it\n * matches the type {@link PusherResponse}. If it does, it is included in the\n * return value.\n */\nexport type Pusher = (\n requestBody: PushRequest,\n requestID: string,\n) => Promise<PusherResult>;\n\n/**\n * This error is thrown when the pusher fails for any reason.\n */\nexport class PushError extends Error {\n name = 'PushError';\n // causedBy is used instead of cause, because while cause has been proposed as a\n // JavaScript language standard for this purpose (see\n // https://github.com/tc39/proposal-error-cause) current browser behavior is\n // inconsistent.\n causedBy?: Error | undefined;\n constructor(causedBy?: Error) {\n super('Failed to push');\n this.causedBy = causedBy;\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport {jsonSchema} from '../../../shared/src/json-schema.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport * as valita from '../../../shared/src/valita.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n commitIsLocalDD31,\n localMutations,\n} from '../db/commit.ts';\nimport type {FrozenJSONValue} from '../frozen-json.ts';\nimport {\n PushError,\n type Pusher,\n type PusherResult,\n assertPusherResult,\n} from '../pusher.ts';\nimport {ReportError} from '../report-error.ts';\nimport {toError} from '../to-error.ts';\nimport {withRead} from '../with-transactions.ts';\nimport {\n type ClientGroupID,\n type ClientID,\n clientGroupIDSchema,\n clientIDSchema,\n} from './ids.ts';\n\nexport const PUSH_VERSION_SDD = 0;\nexport const PUSH_VERSION_DD31 = 1;\n\n/**\n * Mutation describes a single mutation done on the client.\n */\nexport type MutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: ReadonlyJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nexport type Mutation = MutationV1;\n\nconst mutationV1Schema: valita.Type<MutationV1> = valita.readonlyObject({\n id: valita.number(),\n name: valita.string(),\n args: jsonSchema,\n timestamp: valita.number(),\n clientID: clientIDSchema,\n});\n\n/**\n * The JSON value used as the body when doing a POST to the [push\n * endpoint](/reference/server-push).\n */\nexport type PushRequestV1 = {\n pushVersion: 1;\n /**\n * `schemaVersion` can optionally be used to specify to the push endpoint\n * version information about the mutators the app is using (e.g., format of\n * mutator args).\n */\n schemaVersion: string;\n profileID: string;\n\n clientGroupID: ClientGroupID;\n mutations: MutationV1[];\n};\n\nconst pushRequestV1Schema = valita.object({\n pushVersion: valita.literal(1),\n schemaVersion: valita.string(),\n profileID: valita.string(),\n clientGroupID: clientGroupIDSchema,\n mutations: valita.array(mutationV1Schema),\n});\n\nexport type PushRequest = PushRequestV1;\n\nexport function assertPushRequestV1(\n value: unknown,\n): asserts value is PushRequestV1 {\n valita.assert(value, pushRequestV1Schema);\n}\n\n/**\n * Mutation describes a single mutation done on the client.\n */\ntype FrozenMutationV1 = {\n readonly id: number;\n readonly name: string;\n readonly args: FrozenJSONValue;\n readonly timestamp: number;\n readonly clientID: ClientID;\n};\n\nfunction convertDD31(lm: LocalMetaDD31): FrozenMutationV1 {\n return {\n id: lm.mutationID,\n name: lm.mutatorName,\n args: lm.mutatorArgsJSON,\n timestamp: lm.timestamp,\n clientID: lm.clientID,\n };\n}\n\nexport async function push(\n requestID: string,\n store: Store,\n lc: LogContext,\n profileID: string,\n clientGroupID: ClientGroupID | undefined,\n _clientID: ClientID,\n pusher: Pusher,\n schemaVersion: string,\n pushVersion: typeof PUSH_VERSION_SDD | typeof PUSH_VERSION_DD31,\n): Promise<PusherResult | undefined> {\n // Find pending commits between the base snapshot and the main head and push\n // them to the data layer.\n const pending = await withRead(store, async dagRead => {\n const mainHeadHash = await dagRead.getHead(DEFAULT_HEAD_NAME);\n if (!mainHeadHash) {\n throw new Error('Internal no main head');\n }\n return localMutations(mainHeadHash, dagRead);\n // Important! Don't hold the lock through an HTTP request!\n });\n\n if (pending.length === 0) {\n return undefined;\n }\n\n // Commit.pending gave us commits in head-first order; the bindings\n // want tail first (in mutation id order).\n pending.reverse();\n\n assert(pushVersion === PUSH_VERSION_DD31);\n\n const pushMutations: FrozenMutationV1[] = [];\n for (const commit of pending) {\n if (commitIsLocalDD31(commit)) {\n pushMutations.push(convertDD31(commit.meta));\n } else {\n throw new Error('Internal non local pending commit');\n }\n }\n assert(clientGroupID);\n const pushReq: PushRequestV1 = {\n profileID,\n clientGroupID,\n mutations: pushMutations,\n pushVersion: PUSH_VERSION_DD31,\n schemaVersion,\n };\n\n lc.debug?.('Starting push...');\n const pushStart = Date.now();\n const pusherResult = await callPusher(pusher, pushReq, requestID);\n lc.debug?.('...Push complete in ', Date.now() - pushStart, 'ms');\n return pusherResult;\n}\n\nasync function callPusher(\n pusher: Pusher,\n body: PushRequestV1,\n requestID: string,\n): Promise<PusherResult> {\n let pusherResult: PusherResult;\n try {\n pusherResult = await pusher(body, requestID);\n } catch (e) {\n throw new PushError(toError(e));\n }\n try {\n assertPusherResult(pusherResult);\n return pusherResult;\n } catch (e) {\n throw new ReportError('Invalid pusher result', toError(e));\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert, assertNotUndefined} from '../../shared/src/asserts.ts';\nimport type {Enum} from '../../shared/src/enum.ts';\nimport type {MaybePromise} from '../../shared/src/types.ts';\nimport {throwChunkHasher} from './dag/chunk.ts';\nimport {LazyStore} from './dag/lazy-store.ts';\nimport {StoreImpl} from './dag/store-impl.ts';\nimport type {Store} from './dag/store.ts';\nimport {DEFAULT_HEAD_NAME} from './db/commit.ts';\nimport {\n type ClientStateNotFoundResponse,\n type VersionNotSupportedResponse,\n isClientStateNotFoundResponse,\n isVersionNotSupportedResponse,\n} from './error-responses.ts';\nimport * as FormatVersion from './format-version-enum.ts';\nimport {parseReplicacheFormatVersion as parseFormatVersion} from './format-version.ts';\nimport {assertHash, newRandomHash} from './hash.ts';\nimport type {HTTPRequestInfo} from './http-request-info.ts';\nimport type {CreateStore} from './kv/store.ts';\nimport {\n type ClientGroup,\n type ClientGroupMap,\n getClientGroups,\n disableClientGroup as persistDisableClientGroup,\n setClientGroups,\n} from './persist/client-groups.ts';\nimport type {\n IDBDatabasesStore,\n IndexedDBDatabase,\n} from './persist/idb-databases-store.ts';\nimport type {PullResponseOKV1, PullResponseV1, Puller} from './puller.ts';\nimport type {PushResponse, Pusher} from './pusher.ts';\nimport type {ClientGroupID, ClientID} from './sync/ids.ts';\nimport {beginPullV1} from './sync/pull.ts';\nimport {PUSH_VERSION_DD31, push} from './sync/push.ts';\nimport {withRead, withWrite} from './with-transactions.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst MUTATION_RECOVERY_LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT = 10 * 2 ** 20; // 10 MB\n\ninterface ReplicacheDelegate {\n clientID: ClientID;\n closed: boolean;\n idbName: string;\n name: string;\n online: boolean;\n profileID: Promise<string>;\n puller: Puller;\n pusher: Pusher;\n}\n\ninterface MutationRecoveryOptions {\n delegate: ReplicacheDelegate;\n readonly wrapInOnlineCheck: (\n f: () => Promise<boolean>,\n name: string,\n ) => Promise<boolean>;\n readonly wrapInReauthRetries: <R>(\n f: (\n requestID: string,\n requestLc: LogContext,\n ) => Promise<{\n httpRequestInfo: HTTPRequestInfo | undefined;\n result: R;\n }>,\n verb: string,\n lc: LogContext,\n preAuth?: () => MaybePromise<void>,\n postAuth?: () => MaybePromise<void>,\n ) => Promise<{\n result: R;\n authFailure: boolean;\n }>;\n readonly isPushDisabled: () => boolean;\n readonly isPullDisabled: () => boolean;\n readonly lc: LogContext;\n readonly enableMutationRecovery: boolean;\n readonly clientGroupIDPromise: Promise<ClientGroupID | undefined>;\n}\n\nexport class MutationRecovery {\n #recoveringMutations = false;\n readonly #options: MutationRecoveryOptions;\n\n constructor(options: MutationRecoveryOptions) {\n this.#options = options;\n }\n\n async recoverMutations(\n ready: Promise<unknown>,\n perdag: Store,\n idbDatabase: IndexedDBDatabase,\n idbDatabases: IDBDatabasesStore,\n createStore: CreateStore,\n ): Promise<boolean> {\n const {lc, enableMutationRecovery, isPushDisabled, delegate} =\n this.#options;\n\n if (\n !enableMutationRecovery ||\n this.#recoveringMutations ||\n !delegate.online ||\n delegate.closed ||\n isPushDisabled()\n ) {\n return false;\n }\n const stepDescription = 'Recovering mutations.';\n lc.debug?.('Start:', stepDescription);\n try {\n this.#recoveringMutations = true;\n await ready;\n await recoverMutationsFromPerdag(idbDatabase, this.#options, perdag);\n for (const database of Object.values(await idbDatabases.getDatabases())) {\n if (delegate.closed) {\n lc.debug?.('Exiting early due to close:', stepDescription);\n return true;\n }\n if (\n database.replicacheName === delegate.name &&\n database.name !== delegate.idbName\n ) {\n switch (database.replicacheFormatVersion) {\n case FormatVersion.SDD:\n case FormatVersion.DD31:\n case FormatVersion.V6:\n case FormatVersion.V7:\n await recoverMutationsWithNewPerdag(\n database,\n this.#options,\n createStore,\n );\n }\n }\n }\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n } finally {\n lc.debug?.('End:', stepDescription);\n this.#recoveringMutations = false;\n }\n return true;\n }\n}\n\nfunction logMutationRecoveryError(\n e: unknown,\n lc: LogContext,\n stepDescription: string,\n closedDelegate: {closed: boolean},\n) {\n if (closedDelegate.closed) {\n lc.debug?.(\n `Mutation recovery error likely due to close during:\\n${stepDescription}\\nError:\\n`,\n e,\n );\n } else {\n lc.error?.(\n `Mutation recovery error during:\\n${stepDescription}\\nError:\\n`,\n e,\n );\n }\n}\n\nasync function recoverMutationsWithNewPerdag(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n createStore: CreateStore,\n) {\n const perKvStore = createStore(database.name);\n const perdag = new StoreImpl(perKvStore, newRandomHash, assertHash);\n try {\n await recoverMutationsFromPerdag(database, options, perdag);\n } finally {\n await perdag.close();\n }\n}\n\nfunction recoverMutationsFromPerdag(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n perdag: Store,\n): Promise<void> {\n assert(database.replicacheFormatVersion >= FormatVersion.DD31);\n return recoverMutationsFromPerdagDD31(database, options, perdag);\n}\n\nasync function recoverMutationsFromPerdagDD31(\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n perdag: Store,\n): Promise<void> {\n const {delegate, lc} = options;\n const stepDescription = `Recovering mutations from db ${database.name}.`;\n lc.debug?.('Start:', stepDescription);\n try {\n const formatVersion = parseFormatVersion(database.replicacheFormatVersion);\n let clientGroups: ClientGroupMap | undefined = await withRead(\n perdag,\n read => getClientGroups(read),\n );\n const clientGroupIDsVisited = new Set<ClientGroupID>();\n while (clientGroups) {\n let newClientGroups: ClientGroupMap | undefined;\n for (const [clientGroupID, clientGroup] of clientGroups) {\n if (delegate.closed) {\n lc.debug?.('Exiting early due to close:', stepDescription);\n return;\n }\n if (!clientGroupIDsVisited.has(clientGroupID)) {\n clientGroupIDsVisited.add(clientGroupID);\n newClientGroups = await recoverMutationsOfClientGroupDD31(\n clientGroup,\n clientGroupID,\n perdag,\n database,\n options,\n formatVersion,\n );\n if (newClientGroups) {\n break;\n }\n }\n }\n clientGroups = newClientGroups;\n }\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n }\n lc.debug?.('End:', stepDescription);\n}\n\nfunction isResponseThatShouldDisableClientGroup(\n response: PushResponse | PullResponseV1 | undefined,\n): response is ClientStateNotFoundResponse | VersionNotSupportedResponse {\n return (\n isClientStateNotFoundResponse(response) ||\n isVersionNotSupportedResponse(response)\n );\n}\n\nasync function disableClientGroup(\n lc: LogContext,\n selfClientGroupID: string,\n clientGroupID: string,\n response: ClientStateNotFoundResponse | VersionNotSupportedResponse,\n perdag: Store,\n) {\n if (isClientStateNotFoundResponse(response)) {\n lc.debug?.(\n `Client group ${selfClientGroupID} cannot recover mutations for client group ${clientGroupID}. The client group is unknown on the server. Marking it as disabled.`,\n );\n } else if (isVersionNotSupportedResponse(response)) {\n lc.debug?.(\n `Client group ${selfClientGroupID} cannot recover mutations for client group ${clientGroupID}. The client group's version is not supported on the server. versionType: ${response.versionType}. Marking it as disabled.`,\n );\n }\n // The client group is not the main client group so we do not need the\n // Replicache instance to update its internal _isClientGroupDisabled\n // property.\n await withWrite(perdag, perdagWrite =>\n persistDisableClientGroup(clientGroupID, perdagWrite),\n );\n}\n\n/**\n * @returns When mutations are recovered the resulting updated client group map.\n * Otherwise undefined, which can be because there were no mutations to\n * recover, or because an error occurred when trying to recover the mutations.\n */\nasync function recoverMutationsOfClientGroupDD31(\n clientGroup: ClientGroup,\n clientGroupID: ClientGroupID,\n perdag: Store,\n database: IndexedDBDatabase,\n options: MutationRecoveryOptions,\n formatVersion: FormatVersion,\n): Promise<ClientGroupMap | undefined> {\n assert(database.replicacheFormatVersion >= FormatVersion.DD31);\n\n const {\n delegate,\n lc,\n wrapInOnlineCheck,\n wrapInReauthRetries,\n isPushDisabled,\n isPullDisabled,\n clientGroupIDPromise,\n } = options;\n\n const selfClientGroupID = await clientGroupIDPromise;\n assertNotUndefined(selfClientGroupID);\n if (selfClientGroupID === clientGroupID) {\n return;\n }\n\n let clientID: ClientID | undefined;\n\n // If all local mutations have been applied then exit.\n let allAckd = true;\n for (const [cid, mutationID] of Object.entries(clientGroup.mutationIDs)) {\n // if not present then the server has not acknowledged this client's mutations.\n if (\n !clientGroup.lastServerAckdMutationIDs[cid] ||\n clientGroup.lastServerAckdMutationIDs[cid] < mutationID\n ) {\n clientID = cid;\n allAckd = false;\n break;\n }\n }\n if (allAckd) {\n return;\n }\n\n if (clientGroup.disabled) {\n lc.debug?.(\n `Not recovering mutations for client group ${clientGroupID} because group is disabled.`,\n );\n return;\n }\n\n const stepDescription = `Recovering mutations for client group ${clientGroupID}.`;\n lc.debug?.('Start:', stepDescription);\n const lazyDagForOtherClientGroup = new LazyStore(\n perdag,\n MUTATION_RECOVERY_LAZY_STORE_SOURCE_CHUNK_CACHE_SIZE_LIMIT,\n throwChunkHasher,\n assertHash,\n );\n try {\n await withWrite(lazyDagForOtherClientGroup, write =>\n write.setHead(DEFAULT_HEAD_NAME, clientGroup.headHash),\n );\n\n if (isPushDisabled()) {\n lc.debug?.(\n `Cannot recover mutations for client group ${clientGroupID} because push is disabled.`,\n );\n return;\n }\n\n const {pusher} = delegate;\n\n const pushDescription = 'recoveringMutationsPush';\n const pushSucceeded = await wrapInOnlineCheck(async () => {\n const {result: pusherResult} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n assert(clientID);\n assert(lazyDagForOtherClientGroup);\n const pusherResult = await push(\n requestID,\n lazyDagForOtherClientGroup,\n requestLc,\n await delegate.profileID,\n clientGroupID,\n // TODO(DD31): clientID is not needed in DD31. It is currently kept for debugging purpose.\n clientID,\n pusher,\n database.schemaVersion,\n PUSH_VERSION_DD31,\n );\n return {\n result: pusherResult,\n httpRequestInfo: pusherResult?.httpRequestInfo,\n };\n },\n pushDescription,\n lc,\n );\n if (!pusherResult) {\n return false;\n }\n const pusherResponse = pusherResult.response;\n if (isResponseThatShouldDisableClientGroup(pusherResponse)) {\n await disableClientGroup(\n lc,\n selfClientGroupID,\n clientGroupID,\n pusherResponse,\n perdag,\n );\n return false;\n }\n return pusherResult.httpRequestInfo.httpStatusCode === 200;\n }, pushDescription);\n if (!pushSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientGroupID} due to a push error.`,\n );\n return;\n }\n\n if (isPullDisabled()) {\n lc.debug?.(\n `Cannot confirm mutations were recovered for client ${clientGroupID} ` +\n `because pull is disabled.`,\n );\n return;\n }\n const {puller} = delegate;\n\n const pullDescription = 'recoveringMutationsPull';\n let okPullResponse: PullResponseOKV1 | undefined;\n const pullSucceeded = await wrapInOnlineCheck(async () => {\n const {result: beginPullResponse} = await wrapInReauthRetries(\n async (requestID: string, requestLc: LogContext) => {\n assert(clientID);\n const beginPullResponse = await beginPullV1(\n await delegate.profileID,\n clientID,\n clientGroupID,\n database.schemaVersion,\n puller,\n requestID,\n lazyDagForOtherClientGroup,\n formatVersion,\n requestLc,\n false,\n );\n return {\n result: beginPullResponse,\n httpRequestInfo: beginPullResponse.httpRequestInfo,\n };\n },\n pullDescription,\n lc,\n );\n const {pullResponse} = beginPullResponse;\n if (isResponseThatShouldDisableClientGroup(pullResponse)) {\n await disableClientGroup(\n lc,\n selfClientGroupID,\n clientGroupID,\n pullResponse,\n perdag,\n );\n return false;\n }\n if (\n !pullResponse ||\n beginPullResponse.httpRequestInfo.httpStatusCode !== 200\n ) {\n return false;\n }\n okPullResponse = pullResponse;\n return true;\n }, pullDescription);\n if (!pullSucceeded) {\n lc.debug?.(\n `Failed to recover mutations for client ${clientGroupID} due to a pull error.`,\n );\n return;\n }\n\n // TODO(arv): Refactor to make pullResponse a const.\n // pullResponse must be non undefined because pullSucceeded is true.\n assert(okPullResponse);\n lc.debug?.(\n `Client group ${selfClientGroupID} recovered mutations for client group ${clientGroupID}. Details`,\n {\n mutationIDs: clientGroup.mutationIDs,\n lastServerAckdMutationIDs: clientGroup.lastServerAckdMutationIDs,\n lastMutationIDChanges: okPullResponse.lastMutationIDChanges,\n },\n );\n\n return await withWrite(perdag, async dagWrite => {\n const clientGroups = await getClientGroups(dagWrite);\n const clientGroupToUpdate = clientGroups.get(clientGroupID);\n if (!clientGroupToUpdate) {\n return clientGroups;\n }\n\n assert(okPullResponse);\n const lastServerAckdMutationIDsUpdates: Record<ClientID, number> = {};\n let anyMutationIDsUpdated = false;\n for (const [clientID, lastMutationIDChange] of Object.entries(\n okPullResponse.lastMutationIDChanges,\n )) {\n if (\n (clientGroupToUpdate.lastServerAckdMutationIDs[clientID] ?? 0) <\n lastMutationIDChange\n ) {\n lastServerAckdMutationIDsUpdates[clientID] = lastMutationIDChange;\n anyMutationIDsUpdated = true;\n }\n }\n if (!anyMutationIDsUpdated) {\n return clientGroups;\n }\n\n const newClientGroups = new Map(clientGroups).set(clientGroupID, {\n ...clientGroupToUpdate,\n lastServerAckdMutationIDs: {\n ...clientGroupToUpdate.lastServerAckdMutationIDs,\n ...lastServerAckdMutationIDsUpdates,\n },\n });\n await setClientGroups(newClientGroups, dagWrite);\n return newClientGroups;\n });\n } catch (e) {\n logMutationRecoveryError(e, lc, stepDescription, delegate);\n } finally {\n await lazyDagForOtherClientGroup.close();\n lc.debug?.('End:', stepDescription);\n }\n return;\n}\n", "/* oxlint-disable @typescript-eslint/no-explicit-any */\n\nclass NoopBroadcastChannel implements BroadcastChannel {\n readonly name: string;\n\n onmessage: ((this: BroadcastChannel, ev: MessageEvent<any>) => any) | null =\n null;\n\n onmessageerror:\n | ((this: BroadcastChannel, ev: MessageEvent<any>) => any)\n | null = null;\n\n constructor(name: string) {\n this.name = name;\n }\n\n addEventListener(): void {\n // noop\n }\n removeEventListener(): void {\n // noop\n }\n dispatchEvent(): boolean {\n return false;\n }\n\n close(): void {\n // noop\n }\n\n postMessage(): void {\n // noop\n }\n}\n\nconst bc: typeof BroadcastChannel =\n typeof BroadcastChannel === 'undefined'\n ? NoopBroadcastChannel\n : BroadcastChannel;\n\nexport {bc as BroadcastChannel};\n", "import {BroadcastChannel} from '../../shared/src/broadcast-channel.ts';\nimport type {Read, Store} from './dag/store.ts';\nimport {getClientGroup} from './persist/client-groups.ts';\nimport {withRead} from './with-transactions.ts';\n\n// Older clients (<= replicache@13.0.1), listened on this channel name\n// and *asserted* that the messages received were an array containing exactly\n// one string.\nfunction makeChannelNameV0(replicacheName: string): string {\n return `replicache-new-client-group:${replicacheName}`;\n}\n\n// This channel name was introduced when we first needed to change the message\n// format. The design of the messages sent on this channel allows for\n// the message content to be extended in the future in a way that is\n// forward and backwards compatible. The message format can be extended\n// by adding new *optional* fields.\nfunction makeChannelNameV1(replicacheName: string): string {\n return `replicache-new-client-group-v1:${replicacheName}`;\n}\n\nexport {\n makeChannelNameV0 as makeChannelNameV0ForTesting,\n makeChannelNameV1 as makeChannelNameV1ForTesting,\n};\n\n// This message type can be extended with optional properties.\ntype NewClientChannelMessageV1 = {clientGroupID: string; idbName: string};\n\nfunction isNewClientChannelMessageV1(\n message: unknown,\n): message is NewClientChannelMessageV1 {\n return (\n typeof message === 'object' &&\n typeof (message as {clientGroupID: unknown}).clientGroupID === 'string' &&\n typeof (message as {idbName: unknown}).idbName === 'string'\n );\n}\n\nexport function initNewClientChannel(\n replicacheName: string,\n idbName: string,\n signal: AbortSignal,\n clientGroupID: string,\n isNewClientGroup: boolean,\n onUpdateNeeded: () => void,\n perdag: Store,\n) {\n if (signal.aborted) {\n return;\n }\n\n const channelV1 = new BroadcastChannel(makeChannelNameV1(replicacheName));\n if (isNewClientGroup) {\n channelV1.postMessage({clientGroupID, idbName});\n // Send expected format to V0 channel for old clients.\n const channelV0 = new BroadcastChannel(makeChannelNameV0(replicacheName));\n channelV0.postMessage([clientGroupID]);\n channelV0.close();\n }\n\n channelV1.onmessage = async (e: MessageEvent) => {\n const {data} = e;\n if (isNewClientChannelMessageV1(data)) {\n const {clientGroupID: newClientGroupID, idbName: newClientIDBName} = data;\n if (newClientGroupID !== clientGroupID) {\n if (newClientIDBName === idbName) {\n // Check if this client can see the new client's newClientGroupID in its\n // perdag. It should be able to if the clients share persistent\n // storage. However, with `ReplicacheOption.kvStore`\n // and `IDBStoreWithMemFallback` clients may not actually share\n // persistent storage. If storage is not shared, then there is no point\n // in updating, since clients cannot sync locally. If clients do update\n // in this case, they can continually cause each other to update, since\n // on each update the clients get assigned a new client group.\n const updateNeeded = await withRead(\n perdag,\n async (perdagRead: Read) =>\n (await getClientGroup(newClientGroupID, perdagRead)) !==\n undefined,\n );\n if (updateNeeded) {\n onUpdateNeeded();\n }\n } else {\n // Idb name is different, indicating new schema or format version.\n // Update to get assigned to newClientIDBName, and hopefully\n // newClientGroupID.\n // If storage is not actually shared (i.e. due to\n // `ReplicacheOption.kvStore`\n // or `IDBStoreWithMemFallback`) the new client will not\n // get assigned to newClientGroupID, but should get the\n // newClientIDBName.\n // Note: we don't try to read from newClientIDBName to see\n // if this client shares storage with the new client, because\n // the newClientIDBName may have a format version this client\n // cannot read.\n onUpdateNeeded();\n return;\n }\n }\n }\n };\n\n signal.addEventListener('abort', () => channelV1.close(), {once: true});\n}\n", "import {assertObject, assertString} from '../../shared/src/asserts.ts';\nimport {BroadcastChannel} from '../../shared/src/broadcast-channel.ts';\nimport type {ClientGroupID, ClientID} from './sync/ids.ts';\n\nfunction makeChannelName(replicacheName: string): string {\n return `replicache-on-persist:${replicacheName}`;\n}\n\nexport type PersistInfo = {\n clientGroupID: ClientGroupID;\n clientID: ClientID;\n};\n\nexport type OnPersist = (persistInfo: PersistInfo) => void;\n\ntype HandlePersist = OnPersist;\n\nfunction assertPersistInfo(value: unknown): asserts value is PersistInfo {\n assertObject(value);\n assertString(value.clientGroupID);\n assertString(value.clientID);\n}\n\nexport function initOnPersistChannel(\n replicacheName: string,\n signal: AbortSignal,\n handlePersist: HandlePersist,\n): OnPersist {\n if (signal.aborted) {\n return () => undefined;\n }\n const channel = new BroadcastChannel(makeChannelName(replicacheName));\n\n channel.onmessage = e => {\n const {data} = e;\n assertPersistInfo(data);\n handlePersist({\n clientGroupID: data.clientGroupID,\n clientID: data.clientID,\n });\n };\n\n signal.addEventListener('abort', () => channel.close(), {once: true});\n\n return (persistInfo: PersistInfo) => {\n if (signal.aborted) {\n return;\n }\n channel.postMessage(persistInfo);\n handlePersist(persistInfo);\n };\n}\n", "import type {ReadonlyJSONValue} from '../../shared/src/json.ts';\nimport {mustGetHeadHash, type Read} from './dag/store.ts';\nimport {DEFAULT_HEAD_NAME, localMutationsDD31} from './db/commit.ts';\nimport type {ClientID} from './sync/ids.ts';\n\nexport type PendingMutation = {\n readonly name: string;\n readonly id: number;\n readonly args: ReadonlyJSONValue;\n readonly clientID: ClientID;\n};\n\n/**\n * This returns the pending changes with the oldest mutations first.\n */\nexport async function pendingMutationsForAPI(\n dagRead: Read,\n): Promise<readonly PendingMutation[]> {\n const mainHeadHash = await mustGetHeadHash(DEFAULT_HEAD_NAME, dagRead);\n const pending = await localMutationsDD31(mainHeadHash, dagRead);\n return pending\n .map(p => ({\n id: p.meta.mutationID,\n name: p.meta.mutatorName,\n args: p.meta.mutatorArgsJSON,\n clientID: p.meta.clientID,\n }))\n .reverse();\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n addDeletedClients,\n type WritableDeletedClients,\n} from '../deleted-clients.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport {withWrite} from '../with-transactions.ts';\nimport type {Client, OnClientsDeleted} from './clients.ts';\nimport {type ClientMap, getClients, setClients} from './clients.ts';\n\n/**\n * The maximum time a client can be inactive before it is garbage collected.\n * This means that this is the maximum time a tab can be in the background\n * (frozen) and still be able to sync when it comes back to the foreground.\n */\nexport const CLIENT_MAX_INACTIVE_TIME = 24 * 60 * 60 * 1000; // 24 hours\n\n/**\n * How frequently to try to garbage collect clients.\n */\nexport const GC_INTERVAL = 5 * 60 * 1000; // 5 minutes\n\nlet latestGCUpdate: Promise<ClientMap> | undefined;\nexport function getLatestGCUpdate(): Promise<ClientMap> | undefined {\n return latestGCUpdate;\n}\n\nexport function initClientGC(\n clientID: ClientID,\n dagStore: Store,\n clientMaxInactiveTime: number,\n gcInterval: number,\n onClientsDeleted: OnClientsDeleted,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'ClientGC',\n () => {\n latestGCUpdate = gcClients(\n clientID,\n dagStore,\n clientMaxInactiveTime,\n onClientsDeleted,\n );\n return latestGCUpdate;\n },\n () => gcInterval,\n lc,\n signal,\n );\n}\n\nfunction gcClients(\n clientID: ClientID,\n dagStore: Store,\n clientMaxInactiveTime: number,\n onClientsDeleted: OnClientsDeleted,\n): Promise<ClientMap> {\n return withWrite(dagStore, async dagWrite => {\n const now = Date.now();\n const clients = await getClients(dagWrite);\n const deletedClients: WritableDeletedClients = [];\n const newClients: Map<ClientID, Client> = new Map();\n for (const [id, client] of clients) {\n if (\n id === clientID /* never collect ourself */ ||\n now - client.heartbeatTimestampMs <= clientMaxInactiveTime\n ) {\n newClients.set(id, client);\n } else {\n deletedClients.push({\n clientGroupID: client.clientGroupID,\n clientID: id,\n });\n }\n }\n\n if (newClients.size === clients.size) {\n return clients;\n }\n await setClients(newClients, dagWrite);\n const normalizedDeletedClients = await addDeletedClients(\n dagWrite,\n deletedClients,\n );\n await onClientsDeleted(normalizedDeletedClients);\n return newClients;\n });\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {ClientGroupID} from '../sync/ids.ts';\nimport {withWrite} from '../with-transactions.ts';\nimport {\n clientGroupHasPendingMutations,\n getClientGroups,\n setClientGroups,\n type ClientGroupMap,\n} from './client-groups.ts';\nimport {getClients} from './clients.ts';\n\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\n\nlet latestGCUpdate: Promise<ClientGroupMap> | undefined;\nexport function getLatestGCUpdate(): Promise<ClientGroupMap> | undefined {\n return latestGCUpdate;\n}\n\nexport function initClientGroupGC(\n dagStore: Store,\n enableMutationRecovery: boolean,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'ClientGroupGC',\n () => {\n latestGCUpdate = gcClientGroups(dagStore, enableMutationRecovery);\n return latestGCUpdate;\n },\n () => GC_INTERVAL_MS,\n lc,\n signal,\n );\n}\n\n/**\n * This removes client groups that have no clients and no pending mutations.\n * If {@linkcode enableMutationRecovery} is true, it will keep client groups with\n * pending mutations. If it is false, it will remove client groups even when they\n * have pending mutations.\n */\nexport function gcClientGroups(\n dagStore: Store,\n enableMutationRecovery: boolean,\n): Promise<ClientGroupMap> {\n return withWrite(dagStore, async tx => {\n const clients = await getClients(tx);\n const clientGroupIDs = new Set();\n for (const client of clients.values()) {\n clientGroupIDs.add(client.clientGroupID);\n }\n const clientGroups = new Map();\n const removeClientGroups: Set<ClientGroupID> = new Set();\n for (const [clientGroupID, clientGroup] of await getClientGroups(tx)) {\n if (\n clientGroupIDs.has(clientGroupID) ||\n (enableMutationRecovery && clientGroupHasPendingMutations(clientGroup))\n ) {\n clientGroups.set(clientGroupID, clientGroup);\n } else {\n removeClientGroups.add(clientGroupID);\n }\n }\n await setClientGroups(clientGroups, tx);\n // Client group GC doesn't delete individual clients, so we don't call onClientsDeleted\n return clientGroups;\n });\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {initBgIntervalProcess} from '../bg-interval.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport {withWrite} from '../with-transactions.ts';\nimport {\n type ClientMap,\n ClientStateNotFoundError,\n getClients,\n setClients,\n} from './clients.ts';\n\nexport const HEARTBEAT_INTERVAL = 60 * 1000;\n\nexport let latestHeartbeatUpdate: Promise<ClientMap> | undefined;\n\nexport function startHeartbeats(\n clientID: ClientID,\n dagStore: Store,\n onClientStateNotFound: () => void,\n heartbeatIntervalMs: number,\n lc: LogContext,\n signal: AbortSignal,\n): void {\n initBgIntervalProcess(\n 'Heartbeat',\n async () => {\n latestHeartbeatUpdate = writeHeartbeat(clientID, dagStore);\n try {\n return await latestHeartbeatUpdate;\n } catch (e) {\n if (e instanceof ClientStateNotFoundError) {\n onClientStateNotFound();\n return;\n }\n throw e;\n }\n },\n () => heartbeatIntervalMs,\n lc,\n signal,\n );\n}\n\nexport function writeHeartbeat(\n clientID: ClientID,\n dagStore: Store,\n): Promise<ClientMap> {\n return withWrite(dagStore, async dagWrite => {\n const clients = await getClients(dagWrite);\n const client = clients.get(clientID);\n if (!client) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const newClient = {\n ...client,\n heartbeatTimestampMs: Date.now(),\n };\n const newClients = new Map(clients).set(clientID, newClient);\n\n await setClients(newClients, dagWrite);\n return newClients;\n });\n}\n", "import type {Hash} from '../hash.ts';\nimport type {Chunk} from './chunk.ts';\nimport type {MustGetChunk} from './store.ts';\n\n/**\n * A visitor walks the DAG starting at a given root and visits each chunk.\n */\nexport class Visitor {\n #seen: Set<Hash> = new Set();\n #dagRead: MustGetChunk;\n\n constructor(dagRead: MustGetChunk) {\n this.#dagRead = dagRead;\n }\n\n async visit(h: Hash) {\n if (this.#seen.has(h)) {\n return;\n }\n this.#seen.add(h);\n const chunk = await this.#dagRead.mustGetChunk(h);\n await this.visitChunk(chunk);\n }\n\n async visitChunk(chunk: Chunk<unknown>) {\n await Promise.all(chunk.meta.map(ref => this.visit(ref)));\n }\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyRead} from '../dag/lazy-store.ts';\nimport {Visitor} from '../dag/visitor.ts';\nimport type {Hash} from '../hash.ts';\n\nexport class GatherMemoryOnlyVisitor extends Visitor {\n readonly #gatheredChunks: Map<Hash, Chunk> = new Map();\n readonly #lazyRead: LazyRead;\n\n constructor(dagRead: LazyRead) {\n super(dagRead);\n this.#lazyRead = dagRead;\n }\n\n get gatheredChunks(): ReadonlyMap<Hash, Chunk> {\n return this.#gatheredChunks;\n }\n\n override visit(h: Hash): Promise<void> {\n if (!this.#lazyRead.isMemOnlyChunkHash(h)) {\n // Not a memory-only hash, no need to visit anything else.\n return promiseVoid;\n }\n return super.visit(h);\n }\n\n override visitChunk(chunk: Chunk): Promise<void> {\n this.#gatheredChunks.set(chunk.hash, chunk);\n return super.visitChunk(chunk);\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read, Store, Write} from '../dag/store.ts';\nimport {\n Commit,\n DEFAULT_HEAD_NAME,\n type LocalMetaDD31,\n type Meta,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsDD31,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ClientGroupID, ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n type ClientGroup,\n getClientGroup,\n setClientGroup,\n} from './client-groups.ts';\nimport {\n assertClientV6,\n assertHasClientState,\n getClientGroupIDForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {GatherMemoryOnlyVisitor} from './gather-mem-only-visitor.ts';\nimport type {ZeroOption, ZeroTxData} from '../replicache-options.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\n/**\n * Persists the client's memdag state to the client's perdag client group.\n *\n * Persists the base snapshot from memdag to the client's perdag client group,\n * but only if it\u2019s newer than the client's perdag client group\u2019s base snapshot.\n * The base snapshot is persisted by gathering all memory-only chunks in the dag\n * subgraph rooted at the base snapshot's commit and writing them to the perdag.\n * Once the base snapshot is persisted, rebases onto this new base snapshot all\n * local commits from the client's perdag client group that are not already\n * reflected in the base snapshot.\n *\n * Whether or not the base snapshot is persisted, rebases onto the client's\n * perdag client group all memdag local commits not already in the client's\n * perdag client group's history.\n *\n * Also updates the `lastMutationIDs` and `lastServerAckdMutationIDs` properties\n * of the client's client group's entry in the `ClientGroupMap`.\n */\nexport async function persistDD31(\n lc: LogContext,\n clientID: ClientID,\n memdag: LazyStore,\n perdag: Store,\n mutators: MutatorDefs,\n closed: () => boolean,\n formatVersion: FormatVersion,\n getZeroData: ZeroOption['getTxData'] | undefined,\n onGatherMemOnlyChunksForTest = () => Promise.resolve(),\n): Promise<void> {\n if (closed()) {\n return;\n }\n\n const [perdagLMID, perdagBaseSnapshot, mainClientGroupID] = await withRead(\n perdag,\n async perdagRead => {\n await assertHasClientState(clientID, perdagRead);\n const mainClientGroupID = await getClientGroupIDForClient(\n clientID,\n perdagRead,\n );\n assert(\n mainClientGroupID,\n `No main client group for clientID: ${clientID}`,\n );\n const [, perdagMainClientGroupHeadCommit] = await getClientGroupInfo(\n perdagRead,\n mainClientGroupID,\n );\n const perdagLMID = await perdagMainClientGroupHeadCommit.getMutationID(\n clientID,\n perdagRead,\n );\n const perdagBaseSnapshot = await baseSnapshotFromCommit(\n perdagMainClientGroupHeadCommit,\n perdagRead,\n );\n assertSnapshotCommitDD31(perdagBaseSnapshot);\n return [perdagLMID, perdagBaseSnapshot, mainClientGroupID];\n },\n );\n\n if (closed()) {\n return;\n }\n const [newMemdagMutations, memdagBaseSnapshot, gatheredChunks] =\n await withRead(memdag, async memdagRead => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagRead,\n );\n const newMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLMID || 0},\n memdagRead,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagRead,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n let gatheredChunks: ReadonlyMap<Hash, Chunk> | undefined;\n if (\n compareCookiesForSnapshots(memdagBaseSnapshot, perdagBaseSnapshot) > 0\n ) {\n await onGatherMemOnlyChunksForTest();\n // Might need to persist snapshot, we will have to double check\n // after gathering the snapshot chunks from memdag\n const memdagBaseSnapshotHash = memdagBaseSnapshot.chunk.hash;\n // Gather all memory only chunks from base snapshot on the memdag.\n const visitor = new GatherMemoryOnlyVisitor(memdagRead);\n await visitor.visit(memdagBaseSnapshotHash);\n gatheredChunks = visitor.gatheredChunks;\n }\n\n return [newMutations, memdagBaseSnapshot, gatheredChunks];\n });\n\n if (closed()) {\n return;\n }\n\n let memdagBaseSnapshotPersisted = false;\n const zeroDataForMemdagBaseSnapshot =\n getZeroData && (await getZeroData(memdagBaseSnapshot.chunk.hash));\n\n await withWrite(perdag, async perdagWrite => {\n const [mainClientGroup, latestPerdagMainClientGroupHeadCommit] =\n await getClientGroupInfo(perdagWrite, mainClientGroupID);\n\n // These initial values for newMainClientGroupHeadHash, mutationIDs,\n // lastServerAckdMutationIDs are correct for the case where the memdag\n // snapshot is *not* persisted. If the memdag snapshot is persisted\n // these values are overwritten appropriately.\n let newMainClientGroupHeadHash: Hash =\n latestPerdagMainClientGroupHeadCommit.chunk.hash;\n let mutationIDs: Record<ClientID, number> = {\n ...mainClientGroup.mutationIDs,\n };\n let {lastServerAckdMutationIDs} = mainClientGroup;\n\n if (gatheredChunks) {\n // check if memdag snapshot still newer than perdag snapshot\n\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n\n const latestPerdagBaseSnapshot = await baseSnapshotFromCommit(\n latestPerdagMainClientGroupHeadCommit,\n perdagWrite,\n );\n assertSnapshotCommitDD31(latestPerdagBaseSnapshot);\n\n // check if memdag snapshot still newer than perdag snapshot\n if (\n compareCookiesForSnapshots(\n memdagBaseSnapshot,\n latestPerdagBaseSnapshot,\n ) > 0\n ) {\n // still newer, persist memdag snapshot by writing chunks\n memdagBaseSnapshotPersisted = true;\n await Promise.all(\n Array.from(gatheredChunks.values(), c => perdagWrite.putChunk(c)),\n );\n\n await setClient(\n clientID,\n {\n ...client,\n persistHash: memdagBaseSnapshot.chunk.hash,\n },\n perdagWrite,\n );\n // Rebase local mutations from perdag main client group onto new\n // snapshot\n newMainClientGroupHeadHash = memdagBaseSnapshot.chunk.hash;\n const mainClientGroupLocalMutations = await localMutationsDD31(\n mainClientGroup.headHash,\n perdagWrite,\n );\n\n lastServerAckdMutationIDs = memdagBaseSnapshot.meta.lastMutationIDs;\n mutationIDs = {...lastServerAckdMutationIDs};\n\n newMainClientGroupHeadHash = await rebase(\n mainClientGroupLocalMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForMemdagBaseSnapshot,\n );\n }\n }\n\n let zeroDataForPerdagHeadCommit: ZeroTxData | undefined;\n if (!memdagBaseSnapshotPersisted) {\n zeroDataForPerdagHeadCommit =\n getZeroData &&\n (await getZeroData(newMainClientGroupHeadHash, {\n openLazySourceRead: perdagWrite,\n }));\n }\n\n // rebase new memdag mutations onto perdag\n newMainClientGroupHeadHash = await rebase(\n newMemdagMutations,\n newMainClientGroupHeadHash,\n perdagWrite,\n mutators,\n mutationIDs,\n lc,\n formatVersion,\n zeroDataForPerdagHeadCommit ?? zeroDataForMemdagBaseSnapshot,\n );\n\n const newMainClientGroup = {\n ...mainClientGroup,\n headHash: newMainClientGroupHeadHash,\n mutationIDs,\n lastServerAckdMutationIDs,\n };\n\n await setClientGroup(mainClientGroupID, newMainClientGroup, perdagWrite);\n });\n\n if (gatheredChunks && memdagBaseSnapshotPersisted) {\n await withWrite(memdag, memdagWrite =>\n memdagWrite.chunksPersisted([...gatheredChunks.keys()]),\n );\n }\n}\n\nasync function getClientGroupInfo(\n perdagRead: Read,\n clientGroupID: ClientGroupID,\n): Promise<[ClientGroup, Commit<Meta>]> {\n const clientGroup = await getClientGroup(clientGroupID, perdagRead);\n assert(clientGroup, `No client group for clientGroupID: ${clientGroupID}`);\n return [clientGroup, await commitFromHash(clientGroup.headHash, perdagRead)];\n}\n\nasync function rebase(\n mutations: Commit<LocalMetaDD31>[],\n basis: Hash,\n write: Write,\n mutators: MutatorDefs,\n mutationIDs: Record<ClientID, number>,\n lc: LogContext,\n formatVersion: FormatVersion,\n zeroData: ZeroTxData | undefined,\n): Promise<Hash> {\n for (let i = mutations.length - 1; i >= 0; i--) {\n const mutationCommit = mutations[i];\n const {meta} = mutationCommit;\n const newMainHead = await commitFromHash(basis, write);\n if (\n (await mutationCommit.getMutationID(meta.clientID, write)) >\n (await newMainHead.getMutationID(meta.clientID, write))\n ) {\n mutationIDs[meta.clientID] = meta.mutationID;\n basis = (\n await rebaseMutationAndPutCommit(\n mutationCommit,\n write,\n basis,\n mutators,\n lc,\n meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n return basis;\n}\n", "import {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport {getSizeOfValue} from '../../../shared/src/size-of-value.ts';\nimport type {Chunk} from '../dag/chunk.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Read} from '../dag/store.ts';\nimport {Visitor} from '../dag/visitor.ts';\nimport type {Hash} from '../hash.ts';\n\nexport type ChunkWithSize = {chunk: Chunk; size: number};\n\nexport class GatherNotCachedVisitor extends Visitor {\n readonly #gatheredChunks: Map<Hash, ChunkWithSize> = new Map();\n #gatheredChunksTotalSize = 0;\n readonly #lazyStore: LazyStore;\n readonly #gatherSizeLimit: number;\n readonly #getSizeOfChunk: (chunk: Chunk) => number;\n\n constructor(\n dagRead: Read,\n lazyStore: LazyStore,\n gatherSizeLimit: number,\n getSizeOfChunk: (chunk: Chunk) => number = getSizeOfValue,\n ) {\n super(dagRead);\n this.#lazyStore = lazyStore;\n this.#gatherSizeLimit = gatherSizeLimit;\n this.#getSizeOfChunk = getSizeOfChunk;\n }\n\n get gatheredChunks(): ReadonlyMap<Hash, ChunkWithSize> {\n return this.#gatheredChunks;\n }\n\n override visit(h: Hash): Promise<void> {\n if (\n this.#gatheredChunksTotalSize >= this.#gatherSizeLimit ||\n this.#lazyStore.isCached(h)\n ) {\n return promiseVoid;\n }\n return super.visit(h);\n }\n\n override visitChunk(chunk: Chunk): Promise<void> {\n if (this.#gatheredChunksTotalSize < this.#gatherSizeLimit) {\n const size = this.#getSizeOfChunk(chunk);\n this.#gatheredChunks.set(chunk.hash, {chunk, size});\n this.#gatheredChunksTotalSize += size;\n }\n\n return super.visitChunk(chunk);\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {sleep} from '../../../shared/src/sleep.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Store} from '../dag/store.ts';\nimport {\n Commit,\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport {\n type DiffComputationConfig,\n DiffsMap,\n diffCommits,\n} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.ts';\nimport type {ZeroOption} from '../replicache-options.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\nconst DELAY_MS = 300;\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n oldHead: Hash;\n newHead: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n zero: ZeroOption | undefined,\n): Promise<{oldHead: Hash; newHead: Hash; diffs: DiffsMap} | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n } as const;\n }\n // pull/poke and refresh are racing to see who gets to update\n // the memdag (the one with the newer base snapshot cookie wins)\n // pull/poke updates are preferable so delay refresh slightly to\n // make pull/poke the winner except when pull/pokes are slow.\n // This is especially important for pokes, as refresh winning\n // will result in the next poke's cookie not matching necessitating\n // a disconnect/reconnect.\n await sleep(DELAY_MS);\n if (closed()) {\n return {\n type: 'aborted',\n };\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n if (newMemdagMutations.length > 0) {\n const zeroData = await zero?.getTxData?.(newMemdagHeadHash, {\n openLazyRead: memdagWrite,\n });\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n newMemdagHeadHash = (\n await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n oldHead: memdagHeadCommit.chunk.hash,\n newHead: newMemdagHeadHash,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n } as const;\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n\n // Advance zero here before setting refresh hashes\n // since we must advance before delegating control of the microtask\n // loop.\n zero?.advance(result.oldHead, result.newHead, result.diffs.get('') ?? []);\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return {\n oldHead: result.oldHead,\n newHead: result.newHead,\n diffs: result.diffs,\n };\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n", "import {type Resolver, resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\nimport {requestIdle as defaultRequestIdle} from './request-idle.ts';\n\nexport class ProcessScheduler {\n readonly #process: () => Promise<void>;\n readonly #idleTimeoutMs: number;\n readonly #throttleMs: number;\n readonly #abortSignal: AbortSignal;\n readonly #requestIdle: typeof defaultRequestIdle;\n #scheduledResolver: Resolver<void> | undefined = undefined;\n #runResolver: Resolver<void> | undefined = undefined;\n // oxlint-disable-next-line no-unused-private-class-members -- False positive, this is used in #run\n #runPromise = Promise.resolve();\n // oxlint-disable-next-line no-unused-private-class-members -- False positive, this is used in #run\n #throttlePromise = Promise.resolve();\n\n /**\n * Supports scheduling a `process` to be run with certain constraints.\n * - Process runs are never concurrent.\n * - Multiple calls to schedule will be fulfilled by a single process\n * run started after the call to schedule. A call is never fulfilled by an\n * already running process run. This can be thought of as debouncing.\n * - Process runs are throttled so that the process runs at most once every\n * `throttleMs`.\n * - Process runs try to run during an idle period, but will delay at most\n * `idleTimeoutMs`.\n * - Scheduled runs which have not completed when `abortSignal` is aborted\n * will reject with an `AbortError`.\n */\n constructor(\n process: () => Promise<void>,\n idleTimeoutMs: number,\n throttleMs: number,\n abortSignal: AbortSignal,\n requestIdle = defaultRequestIdle,\n ) {\n this.#process = process;\n this.#idleTimeoutMs = idleTimeoutMs;\n this.#throttleMs = throttleMs;\n this.#abortSignal = abortSignal;\n this.#requestIdle = requestIdle;\n this.#abortSignal.addEventListener(\n 'abort',\n () => {\n const abortError = new AbortError('Aborted');\n this.#runResolver?.reject(abortError);\n this.#scheduledResolver?.reject(abortError);\n this.#runResolver = undefined;\n this.#scheduledResolver = undefined;\n },\n {once: true},\n );\n }\n\n schedule(): Promise<void> {\n if (this.#abortSignal.aborted) {\n return Promise.reject(new AbortError('Aborted'));\n }\n if (this.#scheduledResolver) {\n return this.#scheduledResolver.promise;\n }\n this.#scheduledResolver = resolver();\n void this.#scheduleInternal();\n return this.#scheduledResolver.promise;\n }\n\n async #scheduleInternal(): Promise<void> {\n try {\n await this.#runPromise;\n // Prevent errors thrown by process from cancelling scheduled runs.\n // this._runPromise is also awaited below and errors are explicitly\n // propagated to promises returned from schedule.\n } catch {}\n await this.#throttlePromise;\n if (!this.#scheduledResolver) {\n return;\n }\n await this.#requestIdle(this.#idleTimeoutMs);\n if (!this.#scheduledResolver) {\n return;\n }\n this.#throttlePromise = throttle(this.#throttleMs, this.#abortSignal);\n this.#runResolver = this.#scheduledResolver;\n this.#scheduledResolver = undefined;\n try {\n this.#runPromise = this.#process();\n await this.#runPromise;\n this.#runResolver?.resolve();\n } catch (e) {\n this.#runResolver?.reject(e);\n }\n this.#runResolver = undefined;\n }\n}\n\nasync function throttle(\n timeMs: number,\n abortSignal: AbortSignal,\n): Promise<void> {\n try {\n await sleep(timeMs, abortSignal);\n } catch (e) {\n assert(e instanceof AbortError);\n }\n}\n", "// TODO(arv): Remove workaround once docs/ builds cleanly without this.\ndeclare function requestIdleCallback(\n callback: () => void,\n options?: {timeout?: number},\n): number;\n\n/**\n * A Promise wrapper for requestIdleCallback with fallback to setTimeout for\n * browsers without support (aka Safari)\n */\nexport function requestIdle(timeout: number): Promise<void> {\n return new Promise(resolve => {\n if (typeof requestIdleCallback === 'function') {\n requestIdleCallback(() => resolve(), {timeout});\n } else {\n setTimeout(() => resolve(), timeout);\n }\n });\n}\n", "export function setIntervalWithSignal(\n fn: () => void,\n ms: number,\n signal: AbortSignal,\n): void {\n if (!signal.aborted) {\n const interval = setInterval(fn, ms);\n signal.addEventListener('abort', () => {\n clearInterval(interval);\n });\n }\n}\n", "import type {LogContext} from '@rocicorp/logger';\nimport {compareUTF8, greaterThan, lessThan, lessThanEq} from 'compare-utf8';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {binarySearch} from '../../shared/src/binary-search.ts';\nimport type {Enum} from '../../shared/src/enum.ts';\nimport {deepEqual} from '../../shared/src/json.ts';\nimport type {\n Diff,\n DiffOperation,\n IndexDiff,\n InternalDiff,\n InternalDiffOperation,\n NoIndexDiff,\n} from './btree/node.ts';\nimport type {IndexKey} from './db/index.ts';\nimport {decodeIndexKey} from './db/index.ts';\nimport type {ScanOptions} from './db/scan.ts';\nimport * as InvokeKind from './invoke-kind-enum.ts';\nimport type {DiffComputationConfig, DiffsMap} from './sync/diff.ts';\nimport {\n type ReadTransaction,\n SubscriptionTransactionWrapper,\n} from './transactions.ts';\nimport type {QueryInternal} from './types.ts';\n\ntype InvokeKind = Enum<typeof InvokeKind>;\n\nexport interface Subscription<R> {\n hasIndexSubscription(indexName: string): boolean;\n\n invoke(\n tx: ReadTransaction,\n kind: InvokeKind,\n diffs: DiffsMap | undefined,\n ): Promise<R>;\n\n matches(diffs: DiffsMap): boolean;\n\n updateDeps(\n keys: ReadonlySet<string>,\n scans: ReadonlyArray<Readonly<ScanSubscriptionInfo>>,\n ): void;\n\n readonly onData: (result: R) => void;\n readonly onError: ((error: unknown) => void) | undefined;\n readonly onDone: (() => void) | undefined;\n}\n\nconst emptySet: ReadonlySet<string> = new Set();\n\nconst unitializedLastValue = Symbol();\ntype UnitializedLastValue = typeof unitializedLastValue;\n\nexport class SubscriptionImpl<R> implements Subscription<R> {\n readonly #body: (tx: ReadTransaction) => Promise<R>;\n readonly #onData: (result: R) => void;\n #lastValue: R | UnitializedLastValue = unitializedLastValue;\n #keys = emptySet;\n #scans: readonly Readonly<ScanSubscriptionInfo>[] = [];\n\n readonly onError: ((error: unknown) => void) | undefined;\n readonly onDone: (() => void) | undefined;\n readonly #isEqual: (a: R, b: R) => boolean;\n\n constructor(\n body: (tx: ReadTransaction) => Promise<R>,\n onData: (result: R) => void,\n onError: ((error: unknown) => void) | undefined,\n onDone: (() => void) | undefined,\n // deepEqual operates on any JSON value but argument might be more specific.\n isEqual: (a: R, b: R) => boolean = deepEqual as (a: R, b: R) => boolean,\n ) {\n this.#body = body;\n this.#onData = onData;\n this.onError = onError;\n this.onDone = onDone;\n this.#isEqual = isEqual;\n }\n\n hasIndexSubscription(indexName: string): boolean {\n for (const scan of this.#scans) {\n if (scan.options.indexName === indexName) {\n return true;\n }\n }\n return false;\n }\n\n invoke(\n tx: ReadTransaction,\n _kind: InvokeKind,\n _diffs: DiffsMap | undefined,\n ): Promise<R> {\n return this.#body(tx);\n }\n\n matches(diffs: DiffsMap): boolean {\n for (const [indexName, diff] of diffs) {\n if (diffMatchesSubscription(this.#keys, this.#scans, indexName, diff)) {\n return true;\n }\n }\n\n return false;\n }\n\n updateDeps(\n keys: ReadonlySet<string>,\n scans: readonly Readonly<ScanSubscriptionInfo>[],\n ): void {\n this.#keys = keys;\n this.#scans = scans;\n }\n\n onData(result: R): void {\n if (\n this.#lastValue === unitializedLastValue ||\n !this.#isEqual(this.#lastValue, result)\n ) {\n this.#lastValue = result;\n this.#onData(result);\n }\n }\n}\n\nexport {SubscriptionImpl as SubscriptionImplForTesting};\n\n/**\n * Function that gets passed into {@link Replicache.experimentalWatch} and gets\n * called when the data in Replicache changes.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type WatchNoIndexCallback = (diff: NoIndexDiff) => void;\n\nexport type WatchCallbackForOptions<Options extends WatchOptions> =\n Options extends WatchIndexOptions ? WatchIndexCallback : WatchNoIndexCallback;\n\n/**\n * Function that gets passed into {@link Replicache.experimentalWatch} when doing a\n * watch on a secondary index map and gets called when the data in Replicache\n * changes.\n *\n * @experimental This type is experimental and may change in the future.\n */\nexport type WatchIndexCallback = (diff: IndexDiff) => void;\n\n/**\n * Options for {@link Replicache.experimentalWatch}.\n *\n * @experimental This interface is experimental and may change in the future.\n */\nexport type WatchOptions = WatchIndexOptions | WatchNoIndexOptions;\n\n/**\n * Options object passed to {@link Replicache.experimentalWatch}. This is for an\n * index watch.\n */\nexport type WatchIndexOptions = WatchNoIndexOptions & {\n /**\n * When provided, the `watch` is limited to the changes that apply to the index map.\n */\n indexName: string;\n};\n\n/**\n * Options object passed to {@link Replicache.experimentalWatch}. This is for a non\n * index watch.\n */\nexport type WatchNoIndexOptions = {\n /**\n * When provided, the `watch` is limited to changes where the `key` starts\n * with `prefix`.\n */\n prefix?: string | undefined;\n\n /**\n * When this is set to `true` (default is `false`), the `watch` callback will\n * be called once asynchronously when watch is called. The arguments in that\n * case is a diff where we consider all the existing values in Replicache as\n * being added.\n */\n initialValuesInFirstDiff?: boolean | undefined;\n};\n\nexport type WatchCallback = (diff: Diff) => void;\n\nexport class WatchSubscription implements Subscription<Diff | undefined> {\n readonly #callback: WatchCallback;\n readonly #prefix: string;\n readonly #indexName: string | undefined;\n readonly #initialValuesInFirstDiff: boolean;\n\n readonly onError: ((error: unknown) => void) | undefined = undefined;\n readonly onDone: (() => void) | undefined = undefined;\n\n constructor(callback: WatchCallback, options?: WatchOptions) {\n this.#callback = callback;\n this.#prefix = options?.prefix ?? '';\n this.#indexName = (options as WatchIndexOptions)?.indexName;\n this.#initialValuesInFirstDiff = options?.initialValuesInFirstDiff ?? false;\n }\n\n hasIndexSubscription(indexName: string): boolean {\n return this.#indexName === indexName;\n }\n\n onData(result: Diff | undefined): void {\n if (result !== undefined) {\n this.#callback(result);\n }\n }\n\n invoke(\n tx: ReadTransaction,\n kind: InvokeKind,\n diffs: DiffsMap | undefined,\n ): Promise<Diff | undefined> {\n const invoke = async <Key extends IndexKey | string>(\n indexName: string | undefined,\n prefix: string,\n compareKey: (diff: DiffOperation<Key>) => string,\n convertInternalDiff: (\n diff: InternalDiff,\n ) => readonly DiffOperation<Key>[],\n ): Promise<readonly DiffOperation<Key>[] | undefined> => {\n let diff: readonly DiffOperation<Key>[];\n if (kind === InvokeKind.InitialRun) {\n if (!this.#initialValuesInFirstDiff) {\n // We are using `undefined` here as a sentinel value to indicate that we\n // should not call the callback in `onDone`.\n return undefined;\n }\n\n // For the initial run, we need to get the \"diffs\" for the whole tree.\n assert(diffs === undefined);\n\n const newDiff: DiffOperation<Key>[] = [];\n for await (const entry of tx.scan({prefix, indexName}).entries()) {\n newDiff.push({\n op: 'add',\n key: entry[0] as Key,\n newValue: entry[1],\n });\n }\n diff = newDiff;\n } else {\n assert(diffs);\n const maybeDiff = diffs.get(indexName ?? '') ?? [];\n diff = convertInternalDiff(maybeDiff);\n }\n const newDiff: DiffOperation<Key>[] = [];\n const {length} = diff;\n for (\n let i = diffBinarySearch(diff, prefix, compareKey);\n i < length;\n i++\n ) {\n if (compareKey(diff[i]).startsWith(prefix)) {\n newDiff.push(diff[i]);\n } else {\n break;\n }\n }\n\n // For initial run we should always return something.\n return kind === InvokeKind.InitialRun || newDiff.length > 0\n ? newDiff\n : undefined;\n };\n\n if (this.#indexName) {\n return invoke<IndexKey>(\n this.#indexName,\n this.#prefix,\n diff => diff.key[0],\n internalDiff => convertDiffValues(internalDiff, decodeIndexKey),\n );\n }\n\n return invoke<string>(\n undefined,\n this.#prefix,\n diff => diff.key,\n internalDiff => convertDiffValues(internalDiff, k => k),\n );\n }\n\n matches(diffs: DiffsMap): boolean {\n const diff = diffs.get(this.#indexName ?? '');\n if (diff === undefined) {\n return false;\n }\n\n return watcherMatchesDiff(diff, this.#prefix, this.#indexName);\n }\n\n updateDeps(\n _keys: ReadonlySet<string>,\n _scans: readonly Readonly<ScanSubscriptionInfo>[],\n ): void {\n // not used\n }\n}\n\nfunction convertDiffValues<Key>(\n diff: InternalDiff,\n convertKey: (k: string) => Key,\n): DiffOperation<Key>[] {\n return diff.map(op => {\n const key = convertKey(op.key);\n switch (op.op) {\n case 'add':\n return {\n op: 'add',\n key,\n newValue: op.newValue,\n };\n case 'change':\n return {\n op: 'change',\n key,\n oldValue: op.oldValue,\n newValue: op.newValue,\n };\n case 'del':\n return {\n op: 'del',\n key,\n oldValue: op.oldValue,\n };\n }\n });\n}\n\n/**\n * The options passed to {@link Replicache.subscribe}.\n */\nexport interface SubscribeOptions<R> {\n /**\n * Called when the return value of the body function changes.\n */\n onData: (result: R) => void;\n\n /**\n * If present, called when an error occurs.\n */\n onError?: ((error: unknown) => void) | undefined;\n\n /**\n * If present, called when the subscription is removed/done.\n */\n onDone?: (() => void) | undefined;\n\n /**\n * If present this function is used to determine if the value returned by the\n * body function has changed. If not provided a JSON deep equality check is\n * used.\n */\n isEqual?: ((a: R, b: R) => boolean) | undefined;\n}\n\nexport type UnknownSubscription = Subscription<unknown>;\n\ntype SubscriptionSet = Set<UnknownSubscription>;\n\nexport interface SubscriptionsManager extends DiffComputationConfig {\n clear(): void;\n fire(diffs: DiffsMap): Promise<void>;\n hasPendingSubscriptionRuns: boolean;\n add<R>(subscription: Subscription<R>): () => void;\n}\n\nexport class SubscriptionsManagerImpl implements SubscriptionsManager {\n readonly #subscriptions: SubscriptionSet = new Set();\n readonly #pendingSubscriptions: SubscriptionSet = new Set();\n readonly #queryInternal: QueryInternal;\n readonly #lc: LogContext;\n hasPendingSubscriptionRuns = false;\n readonly #signal: AbortSignal;\n\n constructor(\n queryInternal: QueryInternal,\n lc: LogContext,\n signal: AbortSignal,\n ) {\n this.#queryInternal = queryInternal;\n this.#lc = lc;\n this.#signal = signal;\n }\n\n add<R>(subscription: Subscription<R>): () => void {\n this.#subscriptions.add(subscription as UnknownSubscription);\n void this.#scheduleInitialSubscriptionRun(\n subscription as UnknownSubscription,\n );\n return () =>\n this.#subscriptions.delete(subscription as UnknownSubscription);\n }\n\n clear(): void {\n for (const subscription of this.#subscriptions) {\n subscription.onDone?.();\n }\n this.#subscriptions.clear();\n }\n\n fire(diffs: DiffsMap): Promise<void> {\n const subscriptions = subscriptionsForDiffs(this.#subscriptions, diffs);\n return this.#fireSubscriptions(subscriptions, InvokeKind.Regular, diffs);\n }\n\n async #fireSubscriptions(\n subscriptions: Iterable<UnknownSubscription>,\n kind: InvokeKind,\n diffs: DiffsMap | undefined,\n ) {\n if (this.#signal.aborted) {\n return;\n }\n\n const subs = [...subscriptions] as readonly Subscription<unknown>[];\n if (subs.length === 0) {\n return;\n }\n\n // Use allSettled to gather fulfilled and rejected promises.\n const results = await this.#queryInternal(tx =>\n Promise.allSettled(\n subs.map(async s => {\n const stx = new SubscriptionTransactionWrapper(tx);\n try {\n return await s.invoke(stx, kind, diffs);\n } finally {\n // We need to keep track of the subscription keys even if there was an\n // exception because changes to the keys can make the subscription\n // body succeed.\n s.updateDeps(stx.keys, stx.scans);\n }\n }),\n ),\n );\n\n this.callCallbacks(subs, results);\n }\n\n // Public method so that ZQL can wrap it in a transaction.\n callCallbacks(\n subs: readonly Subscription<unknown>[],\n results: PromiseSettledResult<unknown>[],\n ) {\n for (let i = 0; i < subs.length; i++) {\n const s = subs[i];\n const result = results[i];\n if (result.status === 'fulfilled') {\n s.onData(result.value);\n } else {\n if (s.onError) {\n s.onError(result.reason);\n } else {\n this.#lc.error?.('Error in subscription body:', result.reason);\n }\n }\n }\n }\n\n async #scheduleInitialSubscriptionRun(s: UnknownSubscription) {\n this.#pendingSubscriptions.add(s);\n\n if (!this.hasPendingSubscriptionRuns) {\n this.hasPendingSubscriptionRuns = true;\n await Promise.resolve();\n this.hasPendingSubscriptionRuns = false;\n const subscriptions = [...this.#pendingSubscriptions];\n this.#pendingSubscriptions.clear();\n await this.#fireSubscriptions(\n subscriptions,\n InvokeKind.InitialRun,\n undefined,\n );\n }\n }\n\n shouldComputeDiffs(): boolean {\n return this.#subscriptions.size > 0;\n }\n\n shouldComputeDiffsForIndex(indexName: string): boolean {\n for (const s of this.#subscriptions) {\n if (s.hasIndexSubscription(indexName)) {\n return true;\n }\n }\n return false;\n }\n}\n\nexport type ScanSubscriptionInfo = {\n options: ScanOptions;\n inclusiveLimitKey?: string | undefined;\n};\n\nfunction diffMatchesSubscription(\n keys: ReadonlySet<string>,\n scans: Iterable<Readonly<ScanSubscriptionInfo>>,\n indexName: string,\n diff: InternalDiff,\n): boolean {\n // Keys can only match for non index scans.\n if (indexName === '') {\n for (const diffEntry of diff) {\n if (keys.has(diffEntry.key)) {\n return true;\n }\n }\n }\n\n for (const scanInfo of scans) {\n if (scanInfoMatchesDiff(scanInfo, indexName, diff)) {\n return true;\n }\n }\n return false;\n}\n\nfunction scanInfoMatchesDiff(\n scanInfo: ScanSubscriptionInfo,\n changeIndexName: string,\n diff: InternalDiff,\n): boolean {\n // TODO(arv): Use binary search\n for (const diffEntry of diff) {\n if (scanInfoMatchesKey(scanInfo, changeIndexName, diffEntry.key)) {\n return true;\n }\n }\n\n return false;\n}\n\nexport function scanInfoMatchesKey(\n scanInfo: ScanSubscriptionInfo,\n changeIndexName: string,\n changedKey: string,\n): boolean {\n const {\n indexName = '',\n limit,\n prefix,\n startKey,\n startExclusive,\n startSecondaryKey,\n } = scanInfo.options;\n\n if (changeIndexName !== indexName) {\n return false;\n }\n\n if (!indexName) {\n // A scan with limit <= 0 can have no matches\n if (limit !== undefined && limit <= 0) {\n return false;\n }\n\n // No prefix and no start. Must recompute the subscription because all keys\n // will have an effect on the subscription.\n if (!prefix && !startKey) {\n return true;\n }\n\n if (\n prefix &&\n (!changedKey.startsWith(prefix) ||\n isKeyPastInclusiveLimit(scanInfo, changedKey))\n ) {\n return false;\n }\n\n if (\n startKey &&\n ((startExclusive && lessThanEq(changedKey, startKey)) ||\n lessThan(changedKey, startKey) ||\n isKeyPastInclusiveLimit(scanInfo, changedKey))\n ) {\n return false;\n }\n\n return true;\n }\n\n // No prefix and no start. Must recompute the subscription because all keys\n // will have an effect on the subscription.\n if (!prefix && !startKey && !startSecondaryKey) {\n return true;\n }\n\n const [changedKeySecondary, changedKeyPrimary] = decodeIndexKey(changedKey);\n\n if (prefix) {\n if (!changedKeySecondary.startsWith(prefix)) {\n return false;\n }\n }\n\n if (\n startSecondaryKey &&\n ((startExclusive && lessThanEq(changedKeySecondary, startSecondaryKey)) ||\n lessThan(changedKeySecondary, startSecondaryKey))\n ) {\n return false;\n }\n\n if (\n startKey &&\n ((startExclusive && lessThanEq(changedKeyPrimary, startKey)) ||\n lessThan(changedKeyPrimary, startKey))\n ) {\n return false;\n }\n\n return true;\n}\n\nfunction isKeyPastInclusiveLimit(\n scanInfo: ScanSubscriptionInfo,\n changedKey: string,\n): boolean {\n const {inclusiveLimitKey} = scanInfo;\n return (\n scanInfo.options.limit !== undefined &&\n inclusiveLimitKey !== undefined &&\n greaterThan(changedKey, inclusiveLimitKey)\n );\n}\n\nfunction* subscriptionsForDiffs<V>(\n subscriptions: Set<Subscription<V>>,\n diffs: DiffsMap,\n): Generator<Subscription<V>> {\n for (const subscription of subscriptions) {\n if (subscription.matches(diffs)) {\n yield subscription;\n }\n }\n}\n\nfunction watcherMatchesDiff(\n diff: InternalDiff,\n prefix: string,\n indexName: string | undefined,\n): boolean {\n if (prefix === '') {\n return true;\n }\n\n const compareKey = indexName\n ? (diffOp: InternalDiffOperation) => decodeIndexKey(diffOp.key)[0]\n : (diffOp: InternalDiffOperation) => diffOp.key;\n const i = diffBinarySearch(diff, prefix, compareKey);\n return i < diff.length && compareKey(diff[i]).startsWith(prefix);\n}\n\nexport function diffBinarySearch<Key, Value>(\n diff: readonly InternalDiffOperation<Key, Value>[],\n prefix: string,\n compareKey: (diff: InternalDiffOperation<Key, Value>) => string,\n): number {\n return binarySearch(diff.length, i =>\n compareUTF8(prefix, compareKey(diff[i])),\n );\n}\n", "export const InitialRun = 0;\nexport const Regular = 1;\n\nexport type InitialRun = typeof InitialRun;\nexport type Regular = typeof Regular;\n", "import {getNonCryptoRandomValues} from '../../../shared/src/random-values.ts';\nimport type {ClientID} from './ids.ts';\n\nlet sessionID = '';\nfunction getSessionID() {\n if (sessionID === '') {\n const buf = new Uint8Array(4);\n getNonCryptoRandomValues(buf);\n sessionID = Array.from(buf, x => x.toString(16)).join('');\n }\n return sessionID;\n}\n\nconst REQUEST_COUNTERS: Map<string, number> = new Map();\n\n/**\n * Returns a new requestID of the form <client ID>-<session ID>-<request\n * count>. The request count enables one to find the request following or\n * preceding a given request. The sessionid scopes the request count, ensuring\n * the requestID is probabilistically unique across restarts (which is good\n * enough).\n */\nexport function newRequestID(clientID: ClientID): string {\n const counter = REQUEST_COUNTERS.get(clientID) ?? 0;\n REQUEST_COUNTERS.set(clientID, counter + 1);\n return `${clientID}-${getSessionID()}-${counter}`;\n}\n", "// The env value should be filled in by esbuild.\n\ndeclare const process: {\n env: {\n ['REPLICACHE_VERSION']?: string;\n };\n};\n\n/**\n * The current version of Replicache.\n */\nexport const version: string = process.env.REPLICACHE_VERSION ?? '0.0.0';\n", "type PromiseRaceResult<T extends Record<string, PromiseLike<unknown>>> = {\n [K in Extract<keyof T, string>]: {\n key: K;\n status: 'fulfilled';\n result: Awaited<T[K]>;\n };\n}[Extract<keyof T, string>];\n\nconst NO_PROMISES_MESSAGE = 'No promises to race';\n\nconst wrapPromise = <K extends string, V>(\n key: K,\n promise: PromiseLike<V>,\n): Promise<{key: K; status: 'fulfilled'; result: V}> =>\n Promise.resolve(promise).then(result => ({\n key,\n status: 'fulfilled' as const,\n result,\n }));\n\n/**\n * Race a record of promises and resolve with the first resolved entry.\n *\n * @param promises Record of promises to race.\n * @returns Promise resolving to a discriminated union of key/result pairs.\n * @throws An error if the record is empty or if a promise is rejected.\n */\nexport async function promiseRace<\n T extends Record<string, PromiseLike<unknown>>,\n>(promises: T): Promise<PromiseRaceResult<T> & {}> {\n const keys = Object.keys(promises) as Array<Extract<keyof T, string>>;\n\n if (keys.length === 0) {\n throw new Error(NO_PROMISES_MESSAGE);\n }\n\n const wrapped = keys.map(key =>\n wrapPromise(key, promises[key] as PromiseLike<Awaited<T[typeof key]>>),\n );\n\n return await Promise.race(wrapped);\n}\n", "export function emptyFunction() {}\nexport const emptyObject = Object.freeze({});\nexport const emptyArray = Object.freeze([]);\nexport function identity<T>(x: T): T {\n return x;\n}\n", "import * as v from '../../shared/src/valita.ts';\n\nexport const deleteClientsBodySchema = v.union(\n v.readonlyObject({\n clientIDs: v.readonlyArray(v.string()).optional(),\n clientGroupIDs: v.readonlyArray(v.string()).optional(),\n }),\n);\n\nexport const deleteClientsMessageSchema = v.tuple([\n v.literal('deleteClients'),\n deleteClientsBodySchema,\n]);\n\nexport type DeleteClientsBody = v.Infer<typeof deleteClientsBodySchema>;\nexport type DeleteClientsMessage = v.Infer<typeof deleteClientsMessageSchema>;\n", "import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {astSchema} from './ast.ts';\n\nexport const putOpSchema = v.object({\n op: v.literal('put'),\n hash: v.string(),\n ttl: v.number().optional(),\n});\n\nexport const upPutOpSchema = putOpSchema.extend({\n // All fields are optional in this transitional period.\n // - ast is filled in for client queries\n // - name and args are filled in for custom queries\n ast: astSchema.optional(),\n name: v.string().optional(),\n args: v.readonly(v.array(jsonSchema)).optional(),\n});\n\nconst delOpSchema = v.object({\n op: v.literal('del'),\n hash: v.string(),\n});\n\nconst clearOpSchema = v.object({\n op: v.literal('clear'),\n});\n\nconst patchOpSchema = v.union(putOpSchema, delOpSchema, clearOpSchema);\nconst upPatchOpSchema = v.union(upPutOpSchema, delOpSchema, clearOpSchema);\n\nexport const queriesPatchSchema = v.array(patchOpSchema);\nexport const upQueriesPatchSchema = v.array(upPatchOpSchema);\n\nexport type QueriesPutOp = v.Infer<typeof putOpSchema>;\nexport type QueriesDelOp = v.Infer<typeof delOpSchema>;\nexport type QueriesClearOp = v.Infer<typeof clearOpSchema>;\nexport type QueriesPatchOp = v.Infer<typeof patchOpSchema>;\nexport type UpQueriesPatchOp = v.Infer<typeof upPatchOpSchema>;\nexport type QueriesPatch = v.Infer<typeof queriesPatchSchema>;\nexport type UpQueriesPatch = v.Infer<typeof upQueriesPatchSchema>;\n", "import * as v from '../../shared/src/valita.ts';\nimport {clientSchemaSchema} from './client-schema.ts';\nimport {deleteClientsBodySchema} from './delete-clients.ts';\nimport {upQueriesPatchSchema} from './queries-patch.ts';\n\n/**\n * After opening a websocket the client waits for a `connected` message\n * from the server. It then sends an `initConnection` message to the\n * server. The server waits for the `initConnection` message before\n * beginning to send pokes to the newly connected client, so as to avoid\n * syncing lots of queries which are no longer desired by the client.\n */\n\nexport const connectedBodySchema = v.object({\n wsid: v.string(),\n timestamp: v.number().optional(),\n});\n\nexport const connectedMessageSchema = v.tuple([\n v.literal('connected'),\n connectedBodySchema,\n]);\n\nconst initConnectionBodySchema = v.object({\n desiredQueriesPatch: upQueriesPatchSchema,\n clientSchema: clientSchemaSchema.optional(),\n deleted: deleteClientsBodySchema.optional(),\n // parameters to configure the mutate endpoint\n userPushURL: v.string().optional(),\n // parameters to configure the query endpoint\n userQueryURL: v.string().optional(),\n\n /**\n * `activeClients` is an optional array of client IDs that are currently active\n * in the client group. This is used to inform the server about the clients\n * that are currently active (aka running, aka alive), so it can inactive\n * queries from inactive clients.\n */\n activeClients: v.array(v.string()).optional(),\n});\n\nexport const initConnectionMessageSchema = v.tuple([\n v.literal('initConnection'),\n initConnectionBodySchema,\n]);\n\nexport type ConnectedBody = v.Infer<typeof connectedBodySchema>;\nexport type ConnectedMessage = v.Infer<typeof connectedMessageSchema>;\nexport type InitConnectionBody = v.Infer<typeof initConnectionBodySchema>;\nexport type InitConnectionMessage = v.Infer<typeof initConnectionMessageSchema>;\n\nexport function encodeSecProtocols(\n initConnectionMessage: InitConnectionMessage | undefined,\n authToken: string | undefined,\n): string {\n const protocols = {\n initConnectionMessage,\n authToken,\n };\n // WS sec protocols needs to be URI encoded. To save space, we base64 encode\n // the JSON before URI encoding it. But InitConnectionMessage can contain\n // arbitrary unicode strings, so we need to encode the JSON as UTF-8 first.\n // Phew!\n const bytes = new TextEncoder().encode(JSON.stringify(protocols));\n\n // Convert bytes to string without spreading all bytes as arguments\n // to avoid \"Maximum call stack size exceeded\" error with large data\n const s = Array.from(bytes, byte => String.fromCharCode(byte)).join('');\n\n return encodeURIComponent(btoa(s));\n}\n\nexport function decodeSecProtocols(secProtocol: string): {\n initConnectionMessage: InitConnectionMessage | undefined;\n authToken: string | undefined;\n} {\n const binString = atob(decodeURIComponent(secProtocol));\n const bytes = Uint8Array.from(binString, c => c.charCodeAt(0));\n return JSON.parse(new TextDecoder().decode(bytes));\n}\n", "export const CRUD = 'crud';\nexport const Custom = 'custom';\nexport type MutationType = typeof CRUD | typeof Custom;\n\nexport type CRUD = typeof CRUD;\nexport type Custom = typeof Custom;\n", "import {jsonSchema} from '../../shared/src/json-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport type {NameMapper} from '../../zero-types/src/name-mapper.ts';\nimport {rowSchema} from './data.ts';\nimport {pushFailedBodySchema} from './error.ts';\nimport {mutationIDSchema} from './mutation-id.ts';\nimport * as MutationType from './mutation-type-enum.ts';\nimport {primaryKeySchema, primaryKeyValueRecordSchema} from './primary-key.ts';\n\n// NOTE! If you change this name you must also change the\n// string in `replicache-impl.ts` But CRUD mutators are being\n// deleted soon so this should not happen.\nexport const CRUD_MUTATION_NAME = '_zero_crud';\n\n/**\n * Inserts if entity with id does not already exist.\n */\nconst insertOpSchema = v.object({\n op: v.literal('insert'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n value: rowSchema,\n});\n\n/**\n * Upsert semantics. Inserts if entity with id does not already exist,\n * otherwise updates existing entity with id.\n */\nconst upsertOpSchema = v.object({\n op: v.literal('upsert'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n value: rowSchema,\n});\n\n/**\n * Updates if entity with id exists, otherwise does nothing.\n */\nconst updateOpSchema = v.object({\n op: v.literal('update'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n // Partial value with at least the primary key fields\n value: rowSchema,\n});\n\n/**\n * Deletes entity with id if it exists, otherwise does nothing.\n */\nconst deleteOpSchema = v.object({\n op: v.literal('delete'),\n tableName: v.string(),\n primaryKey: primaryKeySchema,\n // Partial value representing the primary key\n value: primaryKeyValueRecordSchema,\n});\n\nconst crudOpSchema = v.union(\n insertOpSchema,\n upsertOpSchema,\n updateOpSchema,\n deleteOpSchema,\n);\n\nconst crudArgSchema = v.object({\n ops: v.array(crudOpSchema),\n});\n\nconst crudArgsSchema = v.tuple([crudArgSchema]);\n\nexport const crudMutationSchema = v.object({\n type: v.literal(MutationType.CRUD),\n id: v.number(),\n clientID: v.string(),\n name: v.literal(CRUD_MUTATION_NAME),\n args: crudArgsSchema,\n timestamp: v.number(),\n});\n\nexport const customMutationSchema = v.object({\n type: v.literal(MutationType.Custom),\n id: v.number(),\n clientID: v.string(),\n name: v.string(),\n args: v.array(jsonSchema),\n timestamp: v.number(),\n});\n\nexport const mutationSchema = v.union(crudMutationSchema, customMutationSchema);\n\nexport const pushBodySchema = v.object({\n clientGroupID: v.string(),\n mutations: v.array(mutationSchema),\n pushVersion: v.number(),\n // For legacy (CRUD) mutations, the schema is tied to the client group /\n // sync connection. For custom mutations, schema versioning is delegated\n // to the custom protocol / api-server.\n schemaVersion: v.number().optional(),\n timestamp: v.number(),\n requestID: v.string(),\n});\n\nexport const pushMessageSchema = v.tuple([v.literal('push'), pushBodySchema]);\n\nconst appErrorSchema = v.object({\n error: v.literal('app'),\n // The user can return any additional data here\n message: v.string().optional(),\n details: jsonSchema.optional(),\n});\nconst zeroErrorSchema = v.object({\n error: v.union(\n /** @deprecated push oooMutation errors are now represented as ['error', { ... }] messages */\n v.literal('oooMutation'),\n v.literal('alreadyProcessed'),\n ),\n details: jsonSchema.optional(),\n});\n\nconst mutationOkSchema = v.object({\n // The user can return any additional data here\n data: jsonSchema.optional(),\n});\nconst mutationErrorSchema = v.union(appErrorSchema, zeroErrorSchema);\n\nexport const mutationResultSchema = v.union(\n mutationOkSchema,\n mutationErrorSchema,\n);\n\nexport const mutationResponseSchema = v.object({\n id: mutationIDSchema,\n result: mutationResultSchema,\n});\n\nconst pushOkSchema = v.object({\n mutations: v.array(mutationResponseSchema),\n});\n\n/**\n * @deprecated push errors are now represented as ['error', { ... }] messages\n */\nconst unsupportedPushVersionSchema = v.object({\n /** @deprecated */\n error: v.literal('unsupportedPushVersion'),\n /** @deprecated */\n mutationIDs: v.array(mutationIDSchema).optional(),\n});\n/**\n * @deprecated push errors are now represented as ['error', { ... }] messages\n */\nconst unsupportedSchemaVersionSchema = v.object({\n /** @deprecated */\n error: v.literal('unsupportedSchemaVersion'),\n /** @deprecated */\n mutationIDs: v.array(mutationIDSchema).optional(),\n});\n/**\n * @deprecated push http errors are now represented as ['error', { ... }] messages\n */\nconst httpErrorSchema = v.object({\n /** @deprecated */\n error: v.literal('http'),\n /** @deprecated */\n status: v.number(),\n /** @deprecated */\n details: v.string(),\n /** @deprecated */\n mutationIDs: v.array(mutationIDSchema).optional(),\n});\n/**\n * @deprecated push zero errors are now represented as ['error', { ... }] messages\n */\nconst zeroPusherErrorSchema = v.object({\n /** @deprecated */\n error: v.literal('zeroPusher'),\n /** @deprecated */\n details: v.string(),\n /** @deprecated */\n mutationIDs: v.array(mutationIDSchema).optional(),\n});\n/**\n * @deprecated push errors are now represented as ['error', { ... }] messages\n */\nconst pushErrorSchema = v.union(\n unsupportedPushVersionSchema,\n unsupportedSchemaVersionSchema,\n httpErrorSchema,\n zeroPusherErrorSchema,\n);\n\nexport const pushResponseBodySchema = v.union(pushOkSchema, pushErrorSchema);\n\nexport const pushResponseSchema = v.union(\n pushResponseBodySchema,\n pushFailedBodySchema,\n);\nexport const pushResponseMessageSchema = v.tuple([\n v.literal('pushResponse'),\n pushResponseBodySchema,\n]);\n\nexport const ackMutationResponsesMessageSchema = v.tuple([\n v.literal('ackMutationResponses'),\n mutationIDSchema,\n]);\n\n/**\n * The schema for the querystring parameters of the custom push endpoint.\n */\nexport const pushParamsSchema = v.object({\n schema: v.string(),\n appID: v.string(),\n});\n\nexport type InsertOp = v.Infer<typeof insertOpSchema>;\nexport type UpsertOp = v.Infer<typeof upsertOpSchema>;\nexport type UpdateOp = v.Infer<typeof updateOpSchema>;\nexport type DeleteOp = v.Infer<typeof deleteOpSchema>;\nexport type CRUDOp = v.Infer<typeof crudOpSchema>;\nexport type CRUDOpKind = CRUDOp['op'];\nexport type CRUDMutationArg = v.Infer<typeof crudArgSchema>;\nexport type CRUDMutation = v.Infer<typeof crudMutationSchema>;\nexport type CustomMutation = v.Infer<typeof customMutationSchema>;\nexport type Mutation = v.Infer<typeof mutationSchema>;\nexport type PushBody = v.Infer<typeof pushBodySchema>;\nexport type PushMessage = v.Infer<typeof pushMessageSchema>;\nexport type PushResponseBody = v.Infer<typeof pushResponseBodySchema>;\nexport type PushResponse = v.Infer<typeof pushResponseSchema>;\nexport type PushResponseMessage = v.Infer<typeof pushResponseMessageSchema>;\nexport type MutationResponse = v.Infer<typeof mutationResponseSchema>;\nexport type MutationOk = v.Infer<typeof mutationOkSchema>;\nexport type MutationError = v.Infer<typeof mutationErrorSchema>;\n/**\n * @deprecated push errors are now represented as ['error', { ... }] messages\n */\nexport type PushError = v.Infer<typeof pushErrorSchema>;\nexport type PushOk = v.Infer<typeof pushOkSchema>;\nexport type MutationResult = v.Infer<typeof mutationResultSchema>;\nexport type AckMutationMessage = v.Infer<\n typeof ackMutationResponsesMessageSchema\n>;\nexport type {MutationID} from './mutation-id.ts';\n\nexport function mapCRUD(\n arg: CRUDMutationArg,\n map: NameMapper,\n): CRUDMutationArg {\n return {\n ops: arg.ops.map(\n ({op, tableName, primaryKey, value}) =>\n ({\n op,\n tableName: map.tableName(tableName),\n primaryKey: map.columns(tableName, primaryKey),\n value: map.row(tableName, value),\n // The cast is necessary because ts objects to the `value` field\n // for \"delete\" ops being different.\n }) as unknown as CRUDOp,\n ),\n };\n}\n", "import * as v from '../../shared/src/valita.ts';\nimport {mutationIDSchema} from './mutation-id.ts';\nimport {mutationResponseSchema} from './push.ts';\n\n/**\n * Mutation results are stored ephemerally in the client\n * hence why we only have the `put` operation.\n *\n * On put the mutation promise is resolved/rejected\n * and reference released.\n */\nexport const putOpSchema = v.object({\n op: v.literal('put'),\n mutation: mutationResponseSchema,\n});\nexport const delOpSchema = v.object({\n op: v.literal('del'),\n id: mutationIDSchema,\n});\n\nconst patchOpSchema = v.union(putOpSchema, delOpSchema);\nexport const mutationsPatchSchema = v.array(patchOpSchema);\nexport type MutationPatch = v.Infer<typeof patchOpSchema>;\n", "import {jsonObjectSchema} from '../../shared/src/json-schema.ts';\nimport * as v from '../../shared/src/valita.ts';\nimport {rowSchema} from './data.ts';\nimport {primaryKeyValueRecordSchema} from './primary-key.ts';\n\nconst putOpSchema = v.object({\n op: v.literal('put'),\n tableName: v.string(),\n value: rowSchema,\n});\n\nconst updateOpSchema = v.object({\n op: v.literal('update'),\n tableName: v.string(),\n id: primaryKeyValueRecordSchema,\n merge: jsonObjectSchema.optional(),\n constrain: v.array(v.string()).optional(),\n});\n\nconst delOpSchema = v.object({\n op: v.literal('del'),\n tableName: v.string(),\n id: primaryKeyValueRecordSchema,\n});\n\nconst clearOpSchema = v.object({\n op: v.literal('clear'),\n});\n\nconst rowPatchOpSchema = v.union(\n putOpSchema,\n updateOpSchema,\n delOpSchema,\n clearOpSchema,\n);\n\nexport const rowsPatchSchema = v.array(rowPatchOpSchema);\nexport type RowPatchOp = v.Infer<typeof rowPatchOpSchema>;\n", "import * as v from '../../shared/src/valita.ts';\n\nexport const versionSchema = v.string();\nexport const nullableVersionSchema = v.union(versionSchema, v.null());\n\nexport type Version = v.Infer<typeof versionSchema>;\nexport type NullableVersion = v.Infer<typeof nullableVersionSchema>;\n", "import * as v from '../../shared/src/valita.ts';\nimport {mutationsPatchSchema} from './mutations-patch.ts';\nimport {queriesPatchSchema} from './queries-patch.ts';\nimport {rowsPatchSchema} from './row-patch.ts';\nimport {nullableVersionSchema, versionSchema} from './version.ts';\n\n/**\n * Pokes use a multi-part format. Pokes send entity data to the client and can\n * be multiple mega-bytes in size. Using a multi-part format allows the server\n * to avoid having to have the full poke in memory at one time.\n *\n * Each poke is assigned a `pokeID`, a unique id (within the context of the\n * connection) for identifying the poke. All messages for a poke will have the\n * same `pokeID`.\n *\n * A poke begins with a `poke-start` message which contains the `baseCookie`\n * the poke is updating from and the `cookie` the poke is updating to.\n *\n * The poke continues with zero to many `poke-part` messages, each of which\n * can contain patch parts. These patch parts should be merged in the order\n * received.\n *\n * Finally, the poke ends with a `poke-end` message. The merged `poke-parts`\n * can now be applied as a whole to update from `baseCookie` to `cookie`.\n *\n * Poke messages can be intermingled with other `down` messages, but cannot be\n * intermingled with poke messages for a different `pokeID`. If this is\n * observed it is an unexpected error; the client should ignore both pokes,\n * disconnect, and reconnect.\n */\n\nexport const pokeStartBodySchema = v.object({\n pokeID: v.string(),\n // We always specify a Version as our cookie, but Replicache starts clients\n // with initial cookie `null`, before the first request. So we have to be\n // able to send a base cookie with value `null` to match that state.\n baseCookie: nullableVersionSchema,\n /**\n * This field is always set if the poke contains a `rowsPatch`.\n * It may be absent for patches that only update clients and queries.\n */\n schemaVersions: v\n .object({\n minSupportedVersion: v.number(),\n maxSupportedVersion: v.number(),\n })\n .optional(),\n timestamp: v.number().optional(),\n});\n\nexport const pokePartBodySchema = v.object({\n pokeID: v.string(),\n // Changes to last mutation id by client id.\n lastMutationIDChanges: v.record(v.number()).optional(),\n // Patches to the desired query sets by client id.\n desiredQueriesPatches: v.record(queriesPatchSchema).optional(),\n // Patches to the set of queries for which entities are sync'd in\n // rowsPatch.\n gotQueriesPatch: queriesPatchSchema.optional(),\n // Patches to the rows set.\n rowsPatch: rowsPatchSchema.optional(),\n // Mutation results patch\n mutationsPatch: mutationsPatchSchema.optional(),\n});\n\nexport const pokeEndBodySchema = v.object({\n pokeID: v.string(),\n // Note: This should be ignored (and may be empty) if cancel === `true`.\n cookie: versionSchema,\n // If `true`, the poke with id `pokeID` should be discarded without\n // applying it.\n cancel: v.boolean().optional(),\n});\n\nexport const pokeStartMessageSchema = v.tuple([\n v.literal('pokeStart'),\n pokeStartBodySchema,\n]);\nexport const pokePartMessageSchema = v.tuple([\n v.literal('pokePart'),\n pokePartBodySchema,\n]);\nexport const pokeEndMessageSchema = v.tuple([\n v.literal('pokeEnd'),\n pokeEndBodySchema,\n]);\n\nexport type PokeStartBody = v.Infer<typeof pokeStartBodySchema>;\nexport type PokePartBody = v.Infer<typeof pokePartBodySchema>;\nexport type PokeEndBody = v.Infer<typeof pokeEndBodySchema>;\n\nexport type PokeStartMessage = v.Infer<typeof pokeStartMessageSchema>;\nexport type PokePartMessage = v.Infer<typeof pokePartMessageSchema>;\nexport type PokeEndMessage = v.Infer<typeof pokeEndMessageSchema>;\n", "import * as v from '../../shared/src/valita.ts';\n\nexport const pongBodySchema = v.object({});\nexport const pongMessageSchema = v.tuple([v.literal('pong'), pongBodySchema]);\n\nexport type PongBody = v.Infer<typeof pongBodySchema>;\nexport type PongMessage = v.Infer<typeof pongMessageSchema>;\n", "import * as v from '../../shared/src/valita.ts';\nimport {nullableVersionSchema, versionSchema} from './version.ts';\n\nexport const pullRequestBodySchema = v.object({\n clientGroupID: v.string(),\n cookie: nullableVersionSchema,\n requestID: v.string(),\n});\n\nexport const pullResponseBodySchema = v.object({\n cookie: versionSchema,\n // Matches pullRequestBodySchema requestID that initiated this response\n requestID: v.string(),\n lastMutationIDChanges: v.record(v.number()),\n // Pull is currently only used for mutation recovery which does not use\n // the patch so we save work by not computing the patch.\n});\n\nexport const pullRequestMessageSchema = v.tuple([\n v.literal('pull'),\n pullRequestBodySchema,\n]);\n\nexport const pullResponseMessageSchema = v.tuple([\n v.literal('pull'),\n pullResponseBodySchema,\n]);\n\nexport type PullRequestBody = v.Infer<typeof pullRequestBodySchema>;\nexport type PullResponseBody = v.Infer<typeof pullResponseBodySchema>;\n\nexport type PullRequestMessage = v.Infer<typeof pullRequestMessageSchema>;\nexport type PullResponseMessage = v.Infer<typeof pullResponseMessageSchema>;\n", "import * as v from '../../shared/src/valita.ts';\nimport {connectedMessageSchema} from './connect.ts';\nimport {transformErrorMessageSchema} from './custom-queries.ts';\nimport {deleteClientsMessageSchema} from './delete-clients.ts';\nimport {errorMessageSchema} from './error.ts';\nimport {inspectDownMessageSchema} from './inspect-down.ts';\nimport {\n pokeEndMessageSchema,\n pokePartMessageSchema,\n pokeStartMessageSchema,\n} from './poke.ts';\nimport {pongMessageSchema} from './pong.ts';\nimport {pullResponseMessageSchema} from './pull.ts';\nimport {pushResponseMessageSchema} from './push.ts';\n\nexport const downstreamSchema = v.union(\n connectedMessageSchema,\n errorMessageSchema,\n pongMessageSchema,\n pokeStartMessageSchema,\n pokePartMessageSchema,\n pokeEndMessageSchema,\n pullResponseMessageSchema,\n deleteClientsMessageSchema,\n pushResponseMessageSchema,\n inspectDownMessageSchema,\n transformErrorMessageSchema,\n);\n\nexport type Downstream = v.Infer<typeof downstreamSchema>;\n", "import {assert} from '../../shared/src/asserts.ts';\n\n/**\n * The current `PROTOCOL_VERSION` of the code.\n *\n * The `PROTOCOL_VERSION` encompasses both the wire-protocol of the `/sync/...`\n * connection between the browser and `zero-cache`, as well as the format of\n * the `AST` objects stored in both components (i.e. IDB and CVR).\n *\n * A change in the `AST` schema (e.g. new functionality added) must be\n * accompanied by an increment of the `PROTOCOL_VERSION` and a new major\n * release. The server (`zero-cache`) must be deployed before clients start\n * running the new code.\n */\n// History:\n// -- Version 5 adds support for `pokeEnd.cookie`. (0.14)\n// -- Version 6 makes `pokeStart.cookie` optional. (0.16)\n// -- Version 7 introduces the initConnection.clientSchema field. (0.17)\n// -- Version 8 drops support for Version 5 (0.18).\n// -- Version 11 adds inspect queries. (0.18)\n// -- Version 12 adds 'timestamp' and 'date' types to the ClientSchema ValueType. (not shipped, reversed by version 14)\n// -- Version 14 removes 'timestamp' and 'date' types from the ClientSchema ValueType. (0.18)\n// -- Version 15 adds a `userPushParams` field to `initConnection` (0.19)\n// -- Version 16 adds a new error type (alreadyProcessed) to mutation responses (0.19)\n// -- Version 17 deprecates `AST` in downstream query puts. It was never used anyway. (0.21)\n// -- Version 18 adds `name` and `args` to the `queries-patch` protocol (0.21)\n// -- Version 19 adds `activeClients` to the `initConnection` protocol (0.22)\n// -- Version 20 changes inspector down message (0.22)\n// -- Version 21 removes `AST` in downstream query puts which was deprecated in Version 17, removes support for versions < 18 (0.22)\n// -- Version 22 adds an optional 'userQueryParams' field to `initConnection` (0.22)\n// -- Version 23 add `mutationResults` to poke (0.22)\n// -- Version 24 adds `ackMutationResults` to upstream (0.22).\n// -- version 25 modifies `mutationsResults` to include `del` patches (0.22)\n// -- version 26 adds inspect/metrics and adds metrics to inspect/query (0.23)\n// -- version 27 adds inspect/version (0.23)\n// -- version 28 adds more inspect/metrics (0.23)\n// -- version 29 adds error responses for custom queries (0.23)\n// -- version 30 adds an optional primaryKey to the ClientSchema (0.24)\n// -- version 31 adds admin password authentication to inspector RPC calls (0.24)\n// -- version 32 adds analyze-query to the inspector RPC calls (0.24)\n// -- version 33 adds `flip` to CorrelatedSubquery (0.25)\n// -- version 34 moves `flip` from CorrelatedSubquery to CorrelatedSubqueryCondition (0.25)\n// -- version 35 adds `readRows`, `readRowCountsByQuery` and `readRowCount` to analyze-query result (0.25)\n// -- version 36 changes inspector analyze-query and adds error response to RPC (0.25)\n// -- version 37 adds `elapsed` to AnalyzeQueryResult (0.25)\n// -- version 38 adds structured push/transform error responses (0.25)\n// -- version 39 removes per-transform error types and adds `message` to app error (0.25)\nexport const PROTOCOL_VERSION = 39;\n\n/**\n * The minimum server-supported sync protocol version (i.e. the version\n * declared in the \"/sync/v{#}/connect\" URL). The contract for\n * backwards compatibility is that a `zero-cache` supports the current\n * `PROTOCOL_VERSION` and at least the previous one (i.e. `PROTOCOL_VERSION - 1`)\n * if not earlier ones as well. This corresponds to supporting clients running\n * the current release and the previous (major) release. Any client connections\n * from protocol versions before `MIN_SERVER_SUPPORTED_PROTOCOL_VERSION` are\n * closed with a `VersionNotSupported` error.\n */\nexport const MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 18;\n\nassert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);\n", "import type {JSONValue, ReadonlyJSONValue} from '../../shared/src/json.ts';\n\n// Value type from zero-protocol (JSONValue/ReadonlyJSONValue | undefined)\n// Defined here to avoid circular dependency with zero-protocol\nexport type Value = JSONValue | ReadonlyJSONValue | undefined;\n\nexport type ColumnNames = {[src: string]: string};\n\nexport type DestNames = {\n tableName: string;\n columns: ColumnNames;\n allColumnsSame: boolean;\n};\n\nexport class NameMapper {\n readonly #tables = new Map<string, DestNames>();\n\n constructor(tables: Map<string, DestNames>) {\n this.#tables = tables;\n }\n\n #getTable(src: string, ctx?: JSONValue): DestNames {\n const table = this.#tables.get(src);\n if (!table) {\n throw new Error(\n `unknown table \"${src}\" ${!ctx ? '' : `in ${JSON.stringify(ctx)}`}`,\n );\n }\n return table;\n }\n\n tableName(src: string, context?: JSONValue): string {\n return this.#getTable(src, context).tableName;\n }\n\n columnName(table: string, src: string, ctx?: JSONValue): string {\n const dst = this.#getTable(table, ctx).columns[src];\n if (!dst) {\n throw new Error(\n `unknown column \"${src}\" of \"${table}\" table ${\n !ctx ? '' : `in ${JSON.stringify(ctx)}`\n }`,\n );\n }\n return dst;\n }\n\n row<V extends Value>(\n table: string,\n row: Readonly<Record<string, V>>,\n ): Readonly<Record<string, V>> {\n const dest = this.#getTable(table);\n const {allColumnsSame, columns} = dest;\n if (allColumnsSame) {\n return row;\n }\n const clientRow: Record<string, V> = {};\n for (const col in row) {\n // Note: columns with unknown names simply pass through.\n clientRow[columns[col] ?? col] = row[col];\n }\n return clientRow;\n }\n\n columns<Columns extends readonly string[] | undefined>(\n table: string,\n cols: Columns,\n ): Columns {\n const dest = this.#getTable(table);\n const {allColumnsSame, columns} = dest;\n\n // Note: Columns not defined in the schema simply pass through.\n return cols === undefined || allColumnsSame\n ? cols\n : (cols.map(col => columns[col] ?? col) as unknown as Columns);\n }\n}\n", "import {NameMapper} from '../../zero-types/src/name-mapper.ts';\nimport type {TableSchema} from './table-schema.ts';\n\nexport {NameMapper};\n\nexport function clientToServer(\n tables: Record<string, TableSchema>,\n): NameMapper {\n return createMapperFrom('client', tables);\n}\n\nexport function serverToClient(\n tables: Record<string, TableSchema>,\n): NameMapper {\n return createMapperFrom('server', tables);\n}\n\nfunction createMapperFrom(\n src: 'client' | 'server',\n tables: Record<string, TableSchema>,\n): NameMapper {\n const mapping = new Map(\n Object.entries(tables).map(\n ([tableName, {serverName: serverTableName, columns}]) => {\n let allColumnsSame = true;\n const names: Record<string, string> = {};\n for (const [name, {serverName}] of Object.entries(columns)) {\n if (serverName && serverName !== name) {\n allColumnsSame = false;\n }\n if (src === 'client') {\n names[name] = serverName ?? name;\n } else {\n names[serverName ?? name] = name;\n }\n }\n return [\n src === 'client' ? tableName : (serverTableName ?? tableName),\n {\n tableName:\n src === 'client' ? (serverTableName ?? tableName) : tableName,\n columns: names,\n allColumnsSame,\n },\n ];\n },\n ),\n );\n return new NameMapper(mapping);\n}\n\n/**\n * Returns an \"identity\" NameMapper that simply serves the purpose\n * of validating that all table and column names conform to the\n * specified `tablesToColumns` map.\n */\nexport function validator(tablesToColumns: Map<string, string[]>): NameMapper {\n const identity = new Map(\n [...tablesToColumns.entries()].map(([tableName, columns]) => [\n tableName,\n {\n tableName,\n columns: Object.fromEntries(columns.map(c => [c, c])),\n allColumnsSame: true,\n },\n ]),\n );\n return new NameMapper(identity);\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport type {Expand} from '../../../shared/src/expand.ts';\nimport type {SchemaValueToTSType} from '../../../zero-types/src/schema-value.ts';\nimport type {Schema, TableSchema} from '../../../zero-types/src/schema.ts';\nimport type {Query} from '../query/query.ts';\n\ntype ClientID = string;\n\nexport type Location = 'client' | 'server';\nexport type TransactionReason = 'optimistic' | 'rebase' | 'authoritative';\n\nexport interface TransactionBase<S extends Schema> {\n readonly location: Location;\n readonly clientID: ClientID;\n /**\n * The ID of the mutation that is being applied.\n */\n readonly mutationID: number;\n\n /**\n * The reason for the transaction.\n */\n readonly reason: TransactionReason;\n\n readonly mutate: SchemaCRUD<S>;\n readonly query: SchemaQuery<S>;\n}\n\nexport type Transaction<S extends Schema, TWrappedTransaction = unknown> =\n | ServerTransaction<S, TWrappedTransaction>\n | ClientTransaction<S>;\n\nexport interface ServerTransaction<S extends Schema, TWrappedTransaction>\n extends TransactionBase<S> {\n readonly location: 'server';\n readonly reason: 'authoritative';\n readonly dbTransaction: DBTransaction<TWrappedTransaction>;\n}\n\n/**\n * An instance of this is passed to custom mutator implementations and\n * allows reading and writing to the database and IVM at the head\n * at which the mutator is being applied.\n */\nexport interface ClientTransaction<S extends Schema>\n extends TransactionBase<S> {\n readonly location: 'client';\n readonly reason: 'optimistic' | 'rebase';\n}\n\nexport interface Row {\n [column: string]: unknown;\n}\n\nexport interface DBConnection<TWrappedTransaction> {\n transaction: <T>(\n cb: (tx: DBTransaction<TWrappedTransaction>) => Promise<T>,\n ) => Promise<T>;\n}\n\nexport interface DBTransaction<T> extends Queryable {\n readonly wrappedTransaction: T;\n}\n\ninterface Queryable {\n query: (query: string, args: unknown[]) => Promise<Iterable<Row>>;\n}\n\nexport type SchemaCRUD<S extends Schema> = {\n [Table in keyof S['tables']]: TableCRUD<S['tables'][Table]>;\n};\n\nexport type TableCRUD<S extends TableSchema> = {\n /**\n * Writes a row if a row with the same primary key doesn't already exists.\n * Non-primary-key fields that are 'optional' can be omitted or set to\n * `undefined`. Such fields will be assigned the value `null` optimistically\n * and then the default value as defined by the server.\n */\n insert: (value: InsertValue<S>) => Promise<void>;\n\n /**\n * Writes a row unconditionally, overwriting any existing row with the same\n * primary key. Non-primary-key fields that are 'optional' can be omitted or\n * set to `undefined`. Such fields will be assigned the value `null`\n * optimistically and then the default value as defined by the server.\n */\n upsert: (value: UpsertValue<S>) => Promise<void>;\n\n /**\n * Updates a row with the same primary key. If no such row exists, this\n * function does nothing. All non-primary-key fields can be omitted or set to\n * `undefined`. Such fields will be left unchanged from previous value.\n */\n update: (value: UpdateValue<S>) => Promise<void>;\n\n /**\n * Deletes the row with the specified primary key. If no such row exists, this\n * function does nothing.\n */\n delete: (id: DeleteID<S>) => Promise<void>;\n};\n\nexport type SchemaQuery<S extends Schema> = {\n readonly [K in keyof S['tables'] & string]: Query<S, K>;\n};\n\nexport type DeleteID<S extends TableSchema> = Expand<PrimaryKeyFields<S>>;\n\ntype PrimaryKeyFields<S extends TableSchema> = {\n [K in Extract<\n S['primaryKey'][number],\n keyof S['columns']\n >]: SchemaValueToTSType<S['columns'][K]>;\n};\n\nexport type InsertValue<S extends TableSchema> = Expand<\n PrimaryKeyFields<S> & {\n [K in keyof S['columns'] as S['columns'][K] extends {optional: true}\n ? K\n : never]?: SchemaValueToTSType<S['columns'][K]> | undefined;\n } & {\n [K in keyof S['columns'] as S['columns'][K] extends {optional: true}\n ? never\n : K]: SchemaValueToTSType<S['columns'][K]>;\n }\n>;\n\nexport type UpsertValue<S extends TableSchema> = InsertValue<S>;\n\nexport type UpdateValue<S extends TableSchema> = Expand<\n PrimaryKeyFields<S> & {\n [K in keyof S['columns']]?:\n | SchemaValueToTSType<S['columns'][K]>\n | undefined;\n }\n>;\n\nexport function customMutatorKey(namespace: string, name: string) {\n assert(!namespace.includes('|'), 'mutator namespaces must not include a |');\n assert(!name.includes('|'), 'mutator names must not include a |');\n return `${namespace}|${name}`;\n}\n\nexport function splitMutatorKey(key: string) {\n return key.split('|') as [string, string];\n}\n", "import type {AST} from '../../../zero-protocol/src/ast.ts';\n\nexport type ClientMetricMap = {\n 'query-materialization-client': [queryID: string];\n 'query-materialization-end-to-end': [queryID: string, ast: AST];\n 'query-update-client': [queryID: string];\n};\n\nexport type ServerMetricMap = {\n 'query-materialization-server': [queryID: string];\n 'query-update-server': [queryID: string];\n};\n\nexport type MetricMap = ClientMetricMap & ServerMetricMap;\n\nexport interface MetricsDelegate {\n addMetric<K extends keyof MetricMap>(\n metric: K,\n value: number,\n ...args: MetricMap[K]\n ): void;\n}\n\nexport function isClientMetric(\n metric: keyof MetricMap,\n): metric is keyof ClientMetricMap {\n return metric.endsWith('-client') || metric.endsWith('-end-to-end');\n}\n\nexport function isServerMetric(\n metric: keyof MetricMap,\n): metric is keyof ServerMetricMap {\n return metric.endsWith('-server');\n}\n", "/* oxlint-disable @typescript-eslint/no-explicit-any */\nimport {resolver} from '@rocicorp/resolver';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport {\n SUBQ_PREFIX,\n type AST,\n type CompoundKey,\n type Condition,\n type Ordering,\n type Parameter,\n type SimpleOperator,\n type System,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {Row as IVMRow} from '../../../zero-protocol/src/data.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport type {Schema, TableSchema} from '../../../zero-types/src/schema.ts';\nimport {buildPipeline} from '../builder/builder.ts';\nimport {NotImplementedError} from '../error.ts';\nimport {ArrayView} from '../ivm/array-view.ts';\nimport {defaultFormat} from '../ivm/default-format.ts';\nimport type {Input} from '../ivm/operator.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport {\n and,\n cmp,\n ExpressionBuilder,\n simplifyCondition,\n type ExpressionFactory,\n} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {GotCallback, QueryDelegate} from './query-delegate.ts';\nimport {\n delegateSymbol,\n type ExistsOptions,\n type GetFilterType,\n type HumanReadable,\n type MaterializeOptions,\n type PreloadOptions,\n type PullRow,\n type Query,\n type QueryRowType,\n type QueryTable,\n type RunOptions,\n} from './query.ts';\nimport {DEFAULT_PRELOAD_TTL_MS, DEFAULT_TTL_MS, type TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\nexport type AnyQuery = Query<Schema, string, any>;\n\nexport function materialize<S extends Schema, T, Q>(\n query: Q,\n delegate: QueryDelegate,\n factoryOrOptions?:\n | ViewFactory<S, QueryTable<Q>, QueryRowType<Q>, T>\n | MaterializeOptions,\n maybeOptions?: MaterializeOptions,\n) {\n if (typeof factoryOrOptions === 'function') {\n return (query as AnyQuery)\n [delegateSymbol](delegate)\n .materialize(factoryOrOptions, maybeOptions?.ttl);\n }\n return (query as AnyQuery)\n [delegateSymbol](delegate)\n .materialize(factoryOrOptions?.ttl);\n}\n\nconst astSymbol = Symbol();\n\nexport function ast(query: AnyQuery): AST {\n return (query as AbstractQuery<Schema, string>)[astSymbol];\n}\n\nexport function newQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n>(\n delegate: QueryDelegate | undefined,\n schema: TSchema,\n table: TTable,\n): Query<TSchema, TTable> {\n return new QueryImpl(\n delegate,\n schema,\n table,\n {table},\n defaultFormat,\n undefined,\n );\n}\n\nexport const newQuerySymbol = Symbol();\n\nexport abstract class AbstractQuery<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n> implements Query<TSchema, TTable, TReturn>\n{\n readonly #schema: TSchema;\n protected readonly _delegate: QueryDelegate | undefined;\n readonly #tableName: TTable;\n readonly _ast: AST;\n readonly format: Format;\n #hash: string = '';\n readonly #system: System;\n readonly #currentJunction: string | undefined;\n readonly customQueryID: CustomQueryID | undefined;\n\n constructor(\n delegate: QueryDelegate | undefined,\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n system: System,\n customQueryID: CustomQueryID | undefined,\n currentJunction?: string,\n ) {\n this.#schema = schema;\n this._delegate = delegate;\n this.#tableName = tableName;\n this._ast = ast;\n this.format = format;\n this.#system = system;\n this.#currentJunction = currentJunction;\n this.customQueryID = customQueryID;\n }\n\n [delegateSymbol](delegate: QueryDelegate): Query<TSchema, TTable, TReturn> {\n return this[newQuerySymbol](\n delegate,\n this.#schema,\n this.#tableName,\n this._ast,\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n }\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TSchema, TTable, TReturn> {\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n this._ast,\n this.format,\n {\n name,\n args,\n },\n this.#currentJunction,\n );\n }\n\n get [astSymbol](): AST {\n return this._ast;\n }\n\n get ast() {\n return this._completeAst();\n }\n\n hash(): string {\n if (!this.#hash) {\n this.#hash = hashOfAST(this._completeAst());\n }\n return this.#hash;\n }\n\n // TODO(arv): Put this in the delegate?\n protected abstract [newQuerySymbol]<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn,\n >(\n delegate: QueryDelegate | undefined,\n schema: TSchema,\n table: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n ): AbstractQuery<TSchema, TTable, TReturn>;\n\n one = (): Query<TSchema, TTable, TReturn | undefined> =>\n this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n limit: 1,\n },\n {\n ...this.format,\n singular: true,\n },\n this.customQueryID,\n this.#currentJunction,\n );\n\n whereExists = (\n relationship: string,\n cbOrOptions?: ((q: AnyQuery) => AnyQuery) | ExistsOptions,\n options?: ExistsOptions,\n ): Query<TSchema, TTable, TReturn> => {\n const cb = typeof cbOrOptions === 'function' ? cbOrOptions : undefined;\n const opts = typeof cbOrOptions === 'function' ? options : cbOrOptions;\n const flipped = opts?.flip ?? false;\n return this.where(({exists}) => exists(relationship, cb, {flip: flipped}));\n };\n\n related = (\n relationship: string,\n cb?: (q: AnyQuery) => AnyQuery,\n ): AnyQuery => {\n if (relationship.startsWith(SUBQ_PREFIX)) {\n throw new Error(\n `Relationship names may not start with \"${SUBQ_PREFIX}\". That is a reserved prefix.`,\n );\n }\n cb = cb ?? (q => q);\n\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n if (isOneHop(related)) {\n const {destSchema, destField, sourceField, cardinality} = related[0];\n const q: AnyQuery = this[newQuerySymbol](\n this._delegate,\n this.#schema,\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: cardinality === 'one',\n },\n this.customQueryID,\n undefined,\n ) as AnyQuery;\n // Intentionally not setting to `one` as it is a perf degradation\n // and the user should not be making the mistake of setting cardinality to\n // `one` when it is actually not.\n // if (cardinality === 'one') {\n // q = q.one();\n // }\n const sq = cb(q) as AbstractQuery<Schema, string>;\n assert(\n isCompoundKey(sourceField),\n 'The source of a relationship must specify at last 1 field',\n );\n assert(\n isCompoundKey(destField),\n 'The destination of a relationship must specify at last 1 field',\n );\n assert(\n sourceField.length === destField.length,\n 'The source and destination of a relationship must have the same number of fields',\n );\n\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n related: [\n ...(this._ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: addPrimaryKeysToAst(\n this.#schema.tables[destSchema],\n sq._ast,\n ),\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const sq = cb(\n this[newQuerySymbol](\n this._delegate,\n this.#schema,\n destSchema,\n {\n table: destSchema,\n alias: relationship,\n },\n {\n relationships: {},\n singular: secondRelation.cardinality === 'one',\n },\n this.customQueryID,\n relationship,\n ) as unknown as QueryImpl<Schema, string>,\n ) as unknown as QueryImpl<Schema, string>;\n\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n related: [\n ...(this._ast.related ?? []),\n {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n hidden: true,\n subquery: {\n table: junctionSchema,\n alias: relationship,\n orderBy: addPrimaryKeys(\n this.#schema.tables[junctionSchema],\n undefined,\n ),\n related: [\n {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n subquery: addPrimaryKeysToAst(\n this.#schema.tables[destSchema],\n sq._ast,\n ),\n },\n ],\n },\n },\n ],\n },\n {\n ...this.format,\n relationships: {\n ...this.format.relationships,\n [relationship]: sq.format,\n },\n },\n this.customQueryID,\n this.#currentJunction,\n ) as AnyQuery;\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n where = (\n fieldOrExpressionFactory: string | ExpressionFactory<TSchema, TTable>,\n opOrValue?: SimpleOperator | GetFilterType<any, any, any> | Parameter,\n value?: GetFilterType<any, any, any> | Parameter,\n ): Query<TSchema, TTable, TReturn> => {\n let cond: Condition;\n\n if (typeof fieldOrExpressionFactory === 'function') {\n cond = fieldOrExpressionFactory(\n new ExpressionBuilder(this._exists) as ExpressionBuilder<\n TSchema,\n TTable\n >,\n );\n } else {\n assert(opOrValue !== undefined, 'Invalid condition');\n cond = cmp(fieldOrExpressionFactory, opOrValue, value);\n }\n\n const existingWhere = this._ast.where;\n if (existingWhere) {\n cond = and(existingWhere, cond);\n }\n\n const where = simplifyCondition(cond);\n\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n where,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n start = (\n row: Partial<PullRow<TTable, TSchema>>,\n opts?: {inclusive: boolean},\n ): Query<TSchema, TTable, TReturn> =>\n this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n start: {\n row,\n exclusive: !opts?.inclusive,\n },\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n\n limit = (limit: number): Query<TSchema, TTable, TReturn> => {\n if (limit < 0) {\n throw new Error('Limit must be non-negative');\n }\n if ((limit | 0) !== limit) {\n throw new Error('Limit must be an integer');\n }\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Limit is not supported in junction relationships yet. Junction relationship being limited: ' +\n this.#currentJunction,\n );\n }\n\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n limit,\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n orderBy = <TSelector extends keyof TSchema['tables'][TTable]['columns']>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TSchema, TTable, TReturn> => {\n if (this.#currentJunction) {\n throw new NotImplementedError(\n 'Order by is not supported in junction relationships yet. Junction relationship being ordered: ' +\n this.#currentJunction,\n );\n }\n return this[newQuerySymbol](\n this._delegate,\n this.#schema,\n this.#tableName,\n {\n ...this._ast,\n orderBy: [...(this._ast.orderBy ?? []), [field as string, direction]],\n },\n this.format,\n this.customQueryID,\n this.#currentJunction,\n );\n };\n\n protected _exists = (\n relationship: string,\n cb: ((query: AnyQuery) => AnyQuery) | undefined,\n options?: ExistsOptions,\n ): Condition => {\n cb = cb ?? (q => q);\n const flip = options?.flip ?? false;\n const related = this.#schema.relationships[this.#tableName][relationship];\n assert(related, 'Invalid relationship');\n\n if (isOneHop(related)) {\n const {destSchema, sourceField, destField} = related[0];\n assert(isCompoundKey(sourceField), 'Invalid relationship');\n assert(isCompoundKey(destField), 'Invalid relationship');\n\n const sq = cb(\n this[newQuerySymbol](\n this._delegate,\n this.#schema,\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n undefined,\n ) as AnyQuery,\n ) as unknown as QueryImpl<any, any>;\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: sourceField,\n childField: destField,\n },\n subquery: addPrimaryKeysToAst(\n this.#schema.tables[destSchema],\n sq._ast,\n ),\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n if (isTwoHop(related)) {\n const [firstRelation, secondRelation] = related;\n assert(isCompoundKey(firstRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(firstRelation.destField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.sourceField), 'Invalid relationship');\n assert(isCompoundKey(secondRelation.destField), 'Invalid relationship');\n const {destSchema} = secondRelation;\n const junctionSchema = firstRelation.destSchema;\n const queryToDest = cb(\n this[newQuerySymbol](\n this._delegate,\n this.#schema,\n destSchema,\n {\n table: destSchema,\n alias: `${SUBQ_PREFIX}zhidden_${relationship}`,\n },\n defaultFormat,\n this.customQueryID,\n relationship,\n ) as AnyQuery,\n );\n\n return {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: firstRelation.sourceField,\n childField: firstRelation.destField,\n },\n subquery: {\n table: junctionSchema,\n alias: `${SUBQ_PREFIX}${relationship}`,\n orderBy: addPrimaryKeys(\n this.#schema.tables[junctionSchema],\n undefined,\n ),\n where: {\n type: 'correlatedSubquery',\n related: {\n system: this.#system,\n correlation: {\n parentField: secondRelation.sourceField,\n childField: secondRelation.destField,\n },\n\n subquery: addPrimaryKeysToAst(\n this.#schema.tables[destSchema],\n (queryToDest as QueryImpl<any, any>)._ast,\n ),\n },\n op: 'EXISTS',\n flip,\n },\n },\n },\n op: 'EXISTS',\n flip,\n };\n }\n\n throw new Error(`Invalid relationship ${relationship}`);\n };\n\n #completedAST: AST | undefined;\n\n protected _completeAst(): AST {\n if (!this.#completedAST) {\n const finalOrderBy = addPrimaryKeys(\n this.#schema.tables[this.#tableName],\n this._ast.orderBy,\n );\n if (this._ast.start) {\n const {row} = this._ast.start;\n const narrowedRow: Writable<IVMRow> = {};\n for (const [field] of finalOrderBy) {\n narrowedRow[field] = row[field];\n }\n this.#completedAST = {\n ...this._ast,\n start: {\n ...this._ast.start,\n row: narrowedRow,\n },\n orderBy: finalOrderBy,\n };\n } else {\n this.#completedAST = {\n ...this._ast,\n orderBy: addPrimaryKeys(\n this.#schema.tables[this.#tableName],\n this._ast.orderBy,\n ),\n };\n }\n }\n return this.#completedAST;\n }\n\n abstract materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n abstract materialize<T>(\n factory: ViewFactory<TSchema, TTable, TReturn, T>,\n ttl?: TTL,\n ): T;\n\n abstract run(options?: RunOptions): Promise<HumanReadable<TReturn>>;\n\n abstract preload(): {\n cleanup: () => void;\n complete: Promise<void>;\n };\n}\n\nconst completedAstSymbol = Symbol();\n\nexport function completedAST(q: Query<Schema, string, any>) {\n return (q as QueryImpl<Schema, string>)[completedAstSymbol];\n}\n\nexport class QueryImpl<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n> extends AbstractQuery<TSchema, TTable, TReturn> {\n readonly #system: System;\n\n constructor(\n delegate: QueryDelegate | undefined,\n schema: TSchema,\n tableName: TTable,\n ast: AST = {table: tableName},\n format: Format = defaultFormat,\n system: System = 'client',\n customQueryID?: CustomQueryID,\n currentJunction?: string,\n ) {\n super(\n delegate,\n schema,\n tableName,\n ast,\n format,\n system,\n customQueryID,\n currentJunction,\n );\n this.#system = system;\n }\n\n get [completedAstSymbol](): AST {\n return this._completeAst();\n }\n\n protected [newQuerySymbol]<\n TSchema extends Schema,\n TTable extends string,\n TReturn,\n >(\n delegate: QueryDelegate | undefined,\n schema: TSchema,\n tableName: TTable,\n ast: AST,\n format: Format,\n customQueryID: CustomQueryID | undefined,\n currentJunction: string | undefined,\n ): QueryImpl<TSchema, TTable, TReturn> {\n return new QueryImpl(\n delegate,\n schema,\n tableName,\n ast,\n format,\n this.#system,\n customQueryID,\n currentJunction,\n );\n }\n\n materialize<T>(\n factoryOrTTL?: ViewFactory<TSchema, TTable, TReturn, T> | TTL,\n ttl: TTL = DEFAULT_TTL_MS,\n ): T {\n const delegate = must(\n this._delegate,\n 'materialize requires a query delegate to be set',\n );\n let factory: ViewFactory<TSchema, TTable, TReturn, T> | undefined;\n if (typeof factoryOrTTL === 'function') {\n factory = factoryOrTTL;\n } else {\n ttl = factoryOrTTL ?? DEFAULT_TTL_MS;\n }\n const ast = this._completeAst();\n const queryID = this.customQueryID\n ? hashOfNameAndArgs(this.customQueryID.name, this.customQueryID.args)\n : this.hash();\n const queryCompleteResolver = resolver<true>();\n let queryComplete: boolean | ErroredQuery = delegate.defaultQueryComplete;\n const updateTTL = (newTTL: TTL) => {\n this.customQueryID\n ? delegate.updateCustomQuery(this.customQueryID, newTTL)\n : delegate.updateServerQuery(ast, newTTL);\n };\n\n const gotCallback: GotCallback = (got, error) => {\n if (error) {\n queryCompleteResolver.reject(error);\n queryComplete = error;\n return;\n }\n\n if (got) {\n delegate.addMetric(\n 'query-materialization-end-to-end',\n performance.now() - t0,\n queryID,\n ast,\n );\n queryComplete = true;\n queryCompleteResolver.resolve(true);\n }\n };\n\n let removeCommitObserver: (() => void) | undefined;\n const onDestroy = () => {\n input.destroy();\n removeCommitObserver?.();\n removeAddedQuery();\n };\n\n const t0 = performance.now();\n\n const removeAddedQuery = this.customQueryID\n ? delegate.addCustomQuery(ast, this.customQueryID, ttl, gotCallback)\n : delegate.addServerQuery(ast, ttl, gotCallback);\n\n const input = buildPipeline(ast, delegate, queryID);\n\n const view = delegate.batchViewUpdates(() =>\n (factory ?? arrayViewFactory)(\n this,\n input,\n this.format,\n onDestroy,\n cb => {\n removeCommitObserver = delegate.onTransactionCommit(cb);\n },\n queryComplete || queryCompleteResolver.promise,\n updateTTL,\n ),\n );\n\n delegate.addMetric(\n 'query-materialization-client',\n performance.now() - t0,\n queryID,\n );\n\n return view as T;\n }\n\n run(options?: RunOptions): Promise<HumanReadable<TReturn>> {\n const delegate = must(\n this._delegate,\n 'run requires a query delegate to be set',\n );\n delegate.assertValidRunOptions(options);\n const v: TypedView<HumanReadable<TReturn>> = this.materialize(options?.ttl);\n if (options?.type === 'complete') {\n return new Promise(resolve => {\n v.addListener((data, type) => {\n if (type === 'complete') {\n v.destroy();\n resolve(data as HumanReadable<TReturn>);\n } else if (type === 'error') {\n v.destroy();\n resolve(Promise.reject(data));\n }\n });\n });\n }\n\n options?.type satisfies 'unknown' | undefined;\n\n const ret = v.data;\n v.destroy();\n return Promise.resolve(ret);\n }\n\n preload(options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n } {\n const delegate = must(\n this._delegate,\n 'preload requires a query delegate to be set',\n );\n const ttl = options?.ttl ?? DEFAULT_PRELOAD_TTL_MS;\n const ast = this._completeAst();\n const {resolve, promise: complete} = resolver<void>();\n if (this.customQueryID) {\n const cleanup = delegate.addCustomQuery(\n ast,\n this.customQueryID,\n ttl,\n got => {\n if (got) {\n resolve();\n }\n },\n );\n return {\n cleanup,\n complete,\n };\n }\n\n const cleanup = delegate.addServerQuery(ast, ttl, got => {\n if (got) {\n resolve();\n }\n });\n return {\n cleanup,\n complete,\n };\n }\n}\n\nfunction addPrimaryKeys(\n schema: TableSchema,\n orderBy: Ordering | undefined,\n): Ordering {\n orderBy = orderBy ?? [];\n const {primaryKey} = schema;\n const primaryKeysToAdd = new Set(primaryKey);\n\n for (const [field] of orderBy) {\n primaryKeysToAdd.delete(field);\n }\n\n if (primaryKeysToAdd.size === 0) {\n return orderBy;\n }\n\n return [\n ...orderBy,\n ...[...primaryKeysToAdd].map(key => [key, 'asc'] as [string, 'asc']),\n ];\n}\n\nfunction addPrimaryKeysToAst(schema: TableSchema, ast: AST): AST {\n return {\n ...ast,\n orderBy: addPrimaryKeys(schema, ast.orderBy),\n };\n}\n\nfunction arrayViewFactory<\n TSchema extends Schema,\n TTable extends string,\n TReturn,\n>(\n _query: AbstractQuery<TSchema, TTable, TReturn>,\n input: Input,\n format: Format,\n onDestroy: () => void,\n onTransactionCommit: (cb: () => void) => void,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n): TypedView<HumanReadable<TReturn>> {\n const v = new ArrayView<HumanReadable<TReturn>>(\n input,\n format,\n queryComplete,\n updateTTL,\n );\n v.onDestroy = onDestroy;\n onTransactionCommit(() => {\n v.flush();\n });\n return v;\n}\n\nfunction isCompoundKey(field: readonly string[]): field is CompoundKey {\n return Array.isArray(field) && field.length >= 1;\n}\n\nfunction isOneHop<T>(r: readonly T[]): r is readonly [T] {\n return r.length === 1;\n}\n\nfunction isTwoHop<T>(r: readonly T[]): r is readonly [T, T] {\n return r.length === 2;\n}\n", "import {h64} from '../../shared/src/hash.ts';\nimport {normalizeAST, type AST} from './ast.ts';\n\nconst hashCache = new WeakMap<AST, string>();\n\nexport function hashOfAST(ast: AST): string {\n const normalized = normalizeAST(ast);\n const cached = hashCache.get(normalized);\n if (cached) {\n return cached;\n }\n const hash = h64(JSON.stringify(normalized)).toString(36);\n hashCache.set(normalized, hash);\n return hash;\n}\n\nexport function hashOfNameAndArgs(\n name: string,\n args: readonly unknown[],\n): string {\n const argsString = JSON.stringify(args);\n return h64(`${name}:${argsString}`).toString(36);\n}\n", "import type {FetchRequest, Input, InputBase, Output} from './operator.ts';\nimport {drainStreams, type Node} from './data.ts';\nimport type {Change} from './change.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\nimport type {BuilderDelegate} from '../builder/builder.ts';\n\n/**\n * The `where` clause of a ZQL query is implemented using a sub-graph of\n * `FilterOperators`. This sub-graph starts with a `FilterStart` operator,\n * that adapts from the normal `Operator` `Output`, to the\n * `FilterOperator` `FilterInput`, and ends with a `FilterEnd` operator that\n * adapts from a `FilterOperator` `FilterOutput` to a normal `Operator` `Input`.\n * `FilterOperator'`s do not have `fetch` or `cleanup` instead they have a\n * `filter(node: Node, cleanup: boolean): boolean` method.\n * They also have `push` which is just like normal `Operator` push.\n * Not having a `fetch` means these `FilterOperator`'s cannot modify\n * `Node` `row`s or `relationship`s, but they shouldn't, they should just\n * filter.\n *\n * This `FilterOperator` abstraction enables much more efficient processing of\n * `fetch` for `where` clauses containing OR conditions.\n *\n * See https://github.com/rocicorp/mono/pull/4339\n */\n\nexport interface FilterInput extends InputBase {\n /** Tell the input where to send its output. */\n setFilterOutput(output: FilterOutput): void;\n}\n\nexport interface FilterOutput extends Output {\n filter(node: Node, cleanup: boolean): boolean;\n}\n\nexport interface FilterOperator extends FilterInput, FilterOutput {}\n\n/**\n * An implementation of FilterOutput that throws if push or filter is called.\n * It is used as the initial value for for an operator's output before it is\n * set.\n */\nexport const throwFilterOutput: FilterOutput = {\n push(_change: Change): void {\n throw new Error('Output not set');\n },\n\n filter(_node: Node, _cleanup): boolean {\n throw new Error('Output not set');\n },\n};\n\nexport class FilterStart implements FilterInput, Output {\n readonly #input: Input;\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: Input) {\n this.#input = input;\n input.setOutput(this);\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n this.#output.push(change, this);\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n for (const node of this.#input.fetch(req)) {\n if (this.#output.filter(node, false)) {\n yield node;\n }\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n for (const node of this.#input.cleanup(req)) {\n if (this.#output.filter(node, true)) {\n yield node;\n } else {\n drainStreams(node);\n }\n }\n }\n}\n\nexport class FilterEnd implements Input, FilterOutput {\n readonly #start: FilterStart;\n readonly #input: FilterInput;\n\n #output: Output = throwFilterOutput;\n\n constructor(start: FilterStart, input: FilterInput) {\n this.#start = start;\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n for (const node of this.#start.fetch(req)) {\n yield node;\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n for (const node of this.#start.cleanup(req)) {\n yield node;\n }\n }\n\n filter(_node: Node, _cleanup: boolean) {\n return true;\n }\n\n setOutput(output: Output) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n this.#output.push(change, this);\n }\n}\n\nexport function buildFilterPipeline(\n input: Input,\n delegate: BuilderDelegate,\n pipeline: (filterInput: FilterInput) => FilterInput,\n): Input {\n const filterStart = new FilterStart(input);\n delegate.addEdge(input, filterStart);\n const middle = pipeline(filterStart);\n delegate.addEdge(filterStart, middle);\n const filterEnd = new FilterEnd(filterStart, middle);\n delegate.addEdge(middle, filterEnd);\n return filterEnd;\n}\n", "import type {JSONValue} from '../../../shared/src/json.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport type {Constraint} from './constraint.ts';\nimport type {Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * Input to an operator.\n */\nexport interface InputBase {\n /** The schema of the data this input returns. */\n getSchema(): SourceSchema;\n\n /**\n * Completely destroy the input. Destroying an input\n * causes it to call destroy on its upstreams, fully\n * cleaning up a pipeline.\n */\n destroy(): void;\n}\n\nexport interface Input extends InputBase {\n /** Tell the input where to send its output. */\n setOutput(output: Output): void;\n\n /**\n * Fetch data. May modify the data in place.\n * Returns nodes sorted in order of `SourceSchema.compareRows`.\n */\n fetch(req: FetchRequest): Stream<Node>;\n\n /**\n * Cleanup maintained state. This is called when `output` will no longer need\n * the data returned by {@linkcode fetch}. The receiving operator should clean up any\n * resources it has allocated to service such requests.\n *\n * This is different from {@linkcode destroy} which means this input will no longer\n * be called at all, for any input.\n *\n * Returns the same thing as {@linkcode fetch}. This allows callers to properly\n * propagate the cleanup message through the graph.\n */\n cleanup(req: FetchRequest): Stream<Node>;\n}\n\nexport type FetchRequest = {\n readonly constraint?: Constraint | undefined;\n /** If supplied, `start.row` must have previously been output by fetch or push. */\n readonly start?: Start | undefined;\n\n /** Whether to fetch in reverse order of the SourceSchema's sort. */\n readonly reverse?: boolean | undefined;\n};\n\nexport type Start = {\n readonly row: Row;\n readonly basis: 'at' | 'after';\n};\n\n/**\n * An output for an operator. Typically another Operator but can also be\n * the code running the pipeline.\n */\nexport interface Output {\n /**\n * Push incremental changes to data previously received with fetch().\n * Consumers must apply all pushed changes or incremental result will\n * be incorrect.\n * Callers must maintain some invariants for correct operation:\n * - Only add rows which do not already exist (by deep equality).\n * - Only remove rows which do exist (by deep equality).\n */\n push(change: Change, pusher: InputBase): void;\n}\n\n/**\n * An implementation of Output that throws if pushed to. It is used as the\n * initial value for for an operator's output before it is set.\n */\nexport const throwOutput: Output = {\n push(_change: Change): void {\n throw new Error('Output not set');\n },\n};\n\n/**\n * Operators are arranged into pipelines.\n * They are stateful.\n * Each operator is an input to the next operator in the chain and an output\n * to the previous.\n */\nexport interface Operator extends Input, Output {}\n\n/**\n * Operators get access to storage that they can store their internal\n * state in.\n */\nexport interface Storage {\n set(key: string, value: JSONValue): void;\n get(key: string, def?: JSONValue): JSONValue | undefined;\n /**\n * If options is not specified, defaults to scanning all entries.\n */\n scan(options?: {prefix: string}): Stream<[string, JSONValue]>;\n del(key: string): void;\n}\n", "/**\n * streams are lazy forward-only iterables.\n * Once a stream reaches the end it can't be restarted.\n * They are iterable, not iterator, so that they can be used in for-each,\n * and so that we know when consumer has stopped iterating the stream. This allows us\n * to clean up resources like sql statements.\n */\nexport type Stream<T> = Iterable<T>;\n\nexport function* take<T>(stream: Stream<T>, limit: number): Stream<T> {\n if (limit < 1) {\n return;\n }\n let count = 0;\n for (const v of stream) {\n yield v;\n if (++count === limit) {\n break;\n }\n }\n}\n\nexport function first<T>(stream: Stream<T>): T | undefined {\n const it = stream[Symbol.iterator]();\n const {value} = it.next();\n it.return?.();\n return value;\n}\n", "import {areEqual} from '../../../shared/src/arrays.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey} from '../../../zero-protocol/src/ast.ts';\nimport {type Change} from './change.ts';\nimport {normalizeUndefined, type Node, type NormalizedValue} from './data.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {type Storage} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {first} from './stream.ts';\n\ntype SizeStorageKeyPrefix = `row/${string}/`;\n/**\n * Key is of format\n * `row/${JSON.stringify(parentJoinKeyValues)}/${JSON.stringify(primaryKeyValues)}`\n * This format allows us to look up an existing cached size for a given set of\n * `parentJoinKeyValues` by scanning for prefix\n * `row/${JSON.stringify(parentJoinKeyValues)}/` and using the first result, and\n * to look up the cached size for a specific row by the full key.\n * If the parent join and primary key are the same, then format is changed to\n * `row//${JSON.stringify(primaryKeyValues)}` to shorten the key, since there\n * is no point in looking up an existing cached size by\n * `parentJoinKeyValues` if the specific rows cached size is missing.\n */\ntype SizeStorageKey = `${SizeStorageKeyPrefix}${string}`;\n\ninterface ExistsStorage {\n get(key: SizeStorageKey): number | undefined;\n set(key: SizeStorageKey, value: number): void;\n del(key: SizeStorageKey): void;\n scan({prefix}: {prefix: SizeStorageKeyPrefix}): Iterable<[string, number]>;\n}\n\n/**\n * The Exists operator filters data based on whether or not a relationship is\n * non-empty.\n */\nexport class Exists implements FilterOperator {\n readonly #input: FilterInput;\n readonly #relationshipName: string;\n readonly #storage: ExistsStorage;\n readonly #not: boolean;\n readonly #parentJoinKey: CompoundKey;\n readonly #noSizeReuse: boolean;\n\n #output: FilterOutput = throwFilterOutput;\n\n /**\n * This instance variable is `true` when this operator is processing a `push`,\n * and is used to disable reuse of cached sizes across rows with the\n * same parent join key value.\n * This is necessary because during a push relationships can be inconsistent\n * due to push communicating changes (which may change multiple Nodes) one\n * Node at a time.\n */\n #inPush = false;\n\n constructor(\n input: FilterInput,\n storage: Storage,\n relationshipName: string,\n parentJoinKey: CompoundKey,\n type: 'EXISTS' | 'NOT EXISTS',\n ) {\n this.#input = input;\n this.#relationshipName = relationshipName;\n this.#input.setFilterOutput(this);\n this.#storage = storage as ExistsStorage;\n assert(\n this.#input.getSchema().relationships[relationshipName],\n `Input schema missing ${relationshipName}`,\n );\n this.#not = type === 'NOT EXISTS';\n this.#parentJoinKey = parentJoinKey;\n\n // If the parentJoinKey is the primary key, no sense in trying to reuse.\n this.#noSizeReuse = areEqual(\n parentJoinKey,\n this.#input.getSchema().primaryKey,\n );\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n filter(node: Node, cleanup: boolean): boolean {\n const result = this.#filter(node) && this.#output.filter(node, cleanup);\n if (cleanup) {\n this.#delSize(node);\n }\n return result;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n assert(!this.#inPush, 'Unexpected re-entrancy');\n this.#inPush = true;\n try {\n switch (change.type) {\n // add, remove and edit cannot change the size of the\n // this.#relationshipName relationship, so simply #pushWithFilter\n case 'add':\n case 'edit': {\n this.#pushWithFilter(change);\n return;\n }\n case 'remove': {\n const size = this.#getSize(change.node);\n // If size is undefined, this operator has not output\n // this row before and so it is unnecessary to output a remove for\n // it.\n if (size === undefined) {\n return;\n }\n this.#pushWithFilter(change, size);\n this.#delSize(change.node);\n return;\n }\n case 'child':\n // Only add and remove child changes for the\n // this.#relationshipName relationship, can change the size\n // of the this.#relationshipName relationship, for other\n // child changes simply #pushWithFilter\n if (\n change.child.relationshipName !== this.#relationshipName ||\n change.child.change.type === 'edit' ||\n change.child.change.type === 'child'\n ) {\n this.#pushWithFilter(change);\n return;\n }\n switch (change.child.change.type) {\n case 'add': {\n let size = this.#getSize(change.node);\n if (size !== undefined) {\n size++;\n this.#setSize(change.node, size);\n } else {\n size = this.#fetchSize(change.node);\n }\n if (size === 1) {\n if (this.#not) {\n // Since the add child change currently being processed is not\n // pushed to output, the added child needs to be excluded from\n // the remove being pushed to output (since the child has\n // never been added to the output).\n this.#output.push(\n {\n type: 'remove',\n node: {\n row: change.node.row,\n relationships: {\n ...change.node.relationships,\n [this.#relationshipName]: () => [],\n },\n },\n },\n this,\n );\n } else {\n this.#output.push(\n {\n type: 'add',\n node: change.node,\n },\n this,\n );\n }\n } else {\n this.#pushWithFilter(change, size);\n }\n return;\n }\n case 'remove': {\n let size = this.#getSize(change.node);\n if (size !== undefined) {\n assert(size > 0);\n size--;\n this.#setSize(change.node, size);\n } else {\n size = this.#fetchSize(change.node);\n }\n if (size === 0) {\n if (this.#not) {\n this.#output.push(\n {\n type: 'add',\n node: change.node,\n },\n this,\n );\n } else {\n // Since the remove child change currently being processed is\n // not pushed to output, the removed child needs to be added to\n // the remove being pushed to output.\n this.#output.push(\n {\n type: 'remove',\n node: {\n row: change.node.row,\n relationships: {\n ...change.node.relationships,\n [this.#relationshipName]: () => [\n change.child.change.node,\n ],\n },\n },\n },\n this,\n );\n }\n } else {\n this.#pushWithFilter(change, size);\n }\n return;\n }\n }\n return;\n default:\n unreachable(change);\n }\n } finally {\n this.#inPush = false;\n }\n }\n\n /**\n * Returns whether or not the node's this.#relationshipName\n * relationship passes the exist/not exists filter condition.\n * If the optional `size` is passed it is used.\n * Otherwise, if there is a stored size for the row it is used.\n * Otherwise the size is computed by streaming the node's\n * relationship with this.#relationshipName (this computed size is also\n * stored).\n */\n #filter(node: Node, size?: number): boolean {\n const exists = (size ?? this.#getOrFetchSize(node)) > 0;\n return this.#not ? !exists : exists;\n }\n\n /**\n * Pushes a change if this.#filter is true for its row.\n */\n #pushWithFilter(change: Change, size?: number): void {\n if (this.#filter(change.node, size)) {\n this.#output.push(change, this);\n }\n }\n\n #getSize(node: Node): number | undefined {\n return this.#storage.get(this.#makeSizeStorageKey(node));\n }\n\n #setSize(node: Node, size: number) {\n this.#storage.set(this.#makeSizeStorageKey(node), size);\n }\n\n #delSize(node: Node) {\n this.#storage.del(this.#makeSizeStorageKey(node));\n }\n\n #getOrFetchSize(node: Node): number {\n const size = this.#getSize(node);\n if (size !== undefined) {\n return size;\n }\n return this.#fetchSize(node);\n }\n\n #fetchSize(node: Node): number {\n if (!this.#noSizeReuse && !this.#inPush) {\n const cachedSizeEntry = first(\n this.#storage.scan({\n prefix: this.#makeSizeStorageKeyPrefix(node),\n }),\n );\n if (cachedSizeEntry !== undefined) {\n this.#setSize(node, cachedSizeEntry[1]);\n return cachedSizeEntry[1];\n }\n }\n\n const relationship = node.relationships[this.#relationshipName];\n assert(relationship);\n let size = 0;\n for (const _relatedNode of relationship()) {\n size++;\n }\n\n this.#setSize(node, size);\n return size;\n }\n\n #makeSizeStorageKeyPrefix(node: Node): SizeStorageKeyPrefix {\n return `row/${\n this.#noSizeReuse\n ? ''\n : JSON.stringify(this.#getKeyValues(node, this.#parentJoinKey))\n }/`;\n }\n\n #makeSizeStorageKey(node: Node): SizeStorageKey {\n return `${this.#makeSizeStorageKeyPrefix(node)}${JSON.stringify(\n this.#getKeyValues(node, this.#input.getSchema().primaryKey),\n )}`;\n }\n\n #getKeyValues(node: Node, def: CompoundKey): NormalizedValue[] {\n const values: NormalizedValue[] = [];\n for (const key of def) {\n values.push(normalizeUndefined(node.row[key]));\n }\n return values;\n }\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Change} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {InputBase, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\n/**\n * # pushAccumulatedChanges\n *\n * Pushes the changes that were accumulated by\n * [fan-out, fan-in] or [ufo, ufi] sub-graphs.\n *\n * This function is called at the end of the sub-graph.\n *\n * The sub-graphs represents `OR`s.\n *\n * Changes that can enter the subgraphs:\n * 1. child (due to exist joins being above the sub-graph)\n * 2. add\n * 3. remove\n * 4. edit\n *\n * # Changes that can exit into `pushAccumulatedChanges`:\n *\n * ## Child\n * If a `child` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `child` change\n * - stop the `child` change (e.g., filter)\n * - convert it to an `add` or `remove` (e.g., exists filter)\n *\n * ## Add\n * If an `add` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `add` change\n * - hide the change (e.g., filter)\n *\n * ## Remove\n * If a `remove` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `remove` change\n * - hide the change (e.g., filter)\n *\n * ## Edit\n * If an `edit` change enters a sub-graph, it will flow to all branches.\n * Each branch will either:\n * - preserve the `edit` change\n * - convert it to an `add` (e.g., filter where old didn't match but new does)\n * - convert it to a `remove` (e.g., filter where old matched but new doesn't)\n *\n * This results in some invariants:\n * - an add coming in will only create adds coming out\n * - a remove coming in will only create removes coming out\n * - an edit coming in can create adds, removes, and edits coming out\n * - a child coming in can create adds, removes, and children coming out\n *\n * # Return of `pushAccumulatedChanges`\n *\n * This function will only push a single change.\n * Given the above invariants, how is this possible?\n *\n * An add that becomes many `adds` results in a single add\n * as the `add` is the same row across all adds. Branches do not change the row.\n *\n * A remove that becomes many `removes` results in a single remove\n * for the same reason.\n *\n * If a child enters and exits, it takes precedence over all other changes.\n * If a child enters and is converted only to add and remove it exits as an edit.\n * If a child enters and is converted to only add or only remove, it exits as that change.\n *\n * If an edit enters and is converted to add and remove it exits as an edit.\n * If an edit enters and is converted to only add or only remove, it exits as that change.\n * If an edit enters and exits as edits only, it exits as a single edit.\n */\nexport function pushAccumulatedChanges(\n accumulatedPushes: Change[],\n output: Output,\n pusher: InputBase,\n fanOutChangeType: Change['type'],\n mergeRelationships: (existing: Change, incoming: Change) => Change,\n addEmptyRelationships: (change: Change) => Change,\n) {\n if (accumulatedPushes.length === 0) {\n // It is possible for no forks to pass along the push.\n // E.g., if no filters match in any fork.\n return;\n }\n\n // collapse down to a single change per type\n const candidatesToPush = new Map<Change['type'], Change>();\n for (const change of accumulatedPushes) {\n if (fanOutChangeType === 'child' && change.type !== 'child') {\n assert(\n candidatesToPush.has(change.type) === false,\n () =>\n `Fan-in:child expected at most one ${change.type} when fan-out is of type child`,\n );\n }\n\n const existing = candidatesToPush.get(change.type);\n let mergedChange = change;\n if (existing) {\n // merge in relationships\n mergedChange = mergeRelationships(existing, change);\n }\n candidatesToPush.set(change.type, mergedChange);\n }\n\n accumulatedPushes.length = 0;\n\n const types = [...candidatesToPush.keys()];\n /**\n * Based on the received `fanOutChangeType` only certain output types are valid.\n *\n * - remove must result in all removes\n * - add must result in all adds\n * - edit must result in add or removes or edits\n * - child must result in a single add or single remove or many child changes\n * - Single add or remove because the relationship will be unique to one exist check within the fan-out,fan-in sub-graph\n * - Many child changes because other operators may preserve the child change\n */\n switch (fanOutChangeType) {\n case 'remove':\n assert(\n types.length === 1 && types[0] === 'remove',\n 'Fan-in:remove expected all removes',\n );\n output.push(\n addEmptyRelationships(must(candidatesToPush.get('remove'))),\n pusher,\n );\n return;\n case 'add':\n assert(\n types.length === 1 && types[0] === 'add',\n 'Fan-in:add expected all adds',\n );\n output.push(\n addEmptyRelationships(must(candidatesToPush.get('add'))),\n pusher,\n );\n return;\n case 'edit': {\n assert(\n types.every(\n type => type === 'add' || type === 'remove' || type === 'edit',\n ),\n 'Fan-in:edit expected all adds, removes, or edits',\n );\n const addChange = candidatesToPush.get('add');\n const removeChange = candidatesToPush.get('remove');\n let editChange = candidatesToPush.get('edit');\n\n // If an `edit` is present, it supersedes `add` and `remove`\n // as it semantically represents both.\n if (editChange) {\n if (addChange) {\n editChange = mergeRelationships(editChange, addChange);\n }\n if (removeChange) {\n editChange = mergeRelationships(editChange, removeChange);\n }\n output.push(addEmptyRelationships(editChange), pusher);\n return;\n }\n\n // If `edit` didn't make it through but both `add` and `remove` did,\n // convert back to an edit.\n //\n // When can this happen?\n //\n // EDIT old: a=1, new: a=2\n // |\n // FanOut\n // / \\\n // a=1 a=2\n // | |\n // remove add\n // \\ /\n // FanIn\n //\n // The left filter converts the edit into a remove.\n // The right filter converts the edit into an add.\n if (addChange && removeChange) {\n output.push(\n addEmptyRelationships({\n type: 'edit',\n node: addChange.node,\n oldNode: removeChange.node,\n } as const),\n pusher,\n );\n return;\n }\n\n output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n case 'child': {\n assert(\n types.every(\n type =>\n type === 'add' || // exists can change child to add or remove\n type === 'remove' || // exists can change child to add or remove\n type === 'child', // other operators may preserve the child change\n ),\n 'Fan-in:child expected all adds, removes, or children',\n );\n assert(\n types.length <= 2,\n 'Fan-in:child expected at most 2 types on a child change from fan-out',\n );\n\n // If any branch preserved the original child change, that takes precedence over all other changes.\n const childChange = candidatesToPush.get('child');\n if (childChange) {\n output.push(childChange, pusher);\n return;\n }\n\n const addChange = candidatesToPush.get('add');\n const removeChange = candidatesToPush.get('remove');\n\n assert(\n addChange === undefined || removeChange === undefined,\n 'Fan-in:child expected either add or remove, not both',\n );\n\n output.push(\n addEmptyRelationships(must(addChange ?? removeChange)),\n pusher,\n );\n return;\n }\n default:\n fanOutChangeType satisfies never;\n }\n}\n\n/**\n * Puts relationships from `right` into `left` if they don't already exist in `left`.\n */\nexport function mergeRelationships(left: Change, right: Change): Change {\n // change types will always match\n // unless we have an edit on the left\n // then the right could be edit, add, or remove\n if (left.type === right.type) {\n switch (left.type) {\n case 'add': {\n return {\n type: 'add',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n };\n }\n case 'remove': {\n return {\n type: 'remove',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n };\n }\n case 'edit': {\n assert(right.type === 'edit');\n // merge edits into a single edit\n return {\n type: 'edit',\n node: {\n row: left.node.row,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n oldNode: {\n row: left.oldNode.row,\n relationships: {\n ...right.oldNode.relationships,\n ...left.oldNode.relationships,\n },\n },\n };\n }\n }\n }\n\n // left is always an edit here\n assert(left.type === 'edit');\n switch (right.type) {\n case 'add': {\n return {\n type: 'edit',\n node: {\n ...left.node,\n relationships: {\n ...right.node.relationships,\n ...left.node.relationships,\n },\n },\n oldNode: left.oldNode,\n };\n }\n case 'remove': {\n return {\n type: 'edit',\n node: left.node,\n oldNode: {\n ...left.oldNode,\n relationships: {\n ...right.node.relationships,\n ...left.oldNode.relationships,\n },\n },\n };\n }\n }\n\n unreachable();\n}\n\nexport function makeAddEmptyRelationships(\n schema: SourceSchema,\n): (change: Change) => Change {\n return (change: Change): Change => {\n if (Object.keys(schema.relationships).length === 0) {\n return change;\n }\n\n switch (change.type) {\n case 'add':\n case 'remove': {\n const ret = {\n ...change,\n node: {\n ...change.node,\n relationships: {\n ...change.node.relationships,\n },\n },\n };\n\n mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));\n\n return ret;\n }\n case 'edit': {\n const ret = {\n ...change,\n node: {\n ...change.node,\n relationships: {\n ...change.node.relationships,\n },\n },\n oldNode: {\n ...change.oldNode,\n relationships: {\n ...change.oldNode.relationships,\n },\n },\n };\n\n mergeEmpty(ret.node.relationships, Object.keys(schema.relationships));\n mergeEmpty(\n ret.oldNode.relationships,\n Object.keys(schema.relationships),\n );\n\n return ret;\n }\n case 'child':\n return change; // children only have relationships along the path to the change\n }\n };\n}\n\n/**\n * For each relationship in `schema` that does not exist\n * in `relationships`, add it with an empty stream.\n *\n * This modifies the `relationships` object in place.\n */\nexport function mergeEmpty(\n relationships: Record<string, () => Stream<Node>>,\n relationshipNames: string[],\n) {\n for (const relName of relationshipNames) {\n if (relationships[relName] === undefined) {\n relationships[relName] = () => emptyArray;\n }\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {identity} from '../../../shared/src/sentinels.ts';\nimport type {Change} from './change.ts';\nimport {type Node} from './data.ts';\nimport type {FanOut} from './fan-out.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {pushAccumulatedChanges} from './push-accumulated.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The FanIn operator merges multiple streams into one.\n * It eliminates duplicates and must be paired with a fan-out operator\n * somewhere upstream of the fan-in.\n *\n * issue\n * |\n * fan-out\n * / \\\n * a b\n * \\ /\n * fan-in\n * |\n */\nexport class FanIn implements FilterOperator {\n readonly #inputs: readonly FilterInput[];\n readonly #schema: SourceSchema;\n #output: FilterOutput = throwFilterOutput;\n #accumulatedPushes: Change[] = [];\n\n constructor(fanOut: FanOut, inputs: FilterInput[]) {\n this.#inputs = inputs;\n this.#schema = fanOut.getSchema();\n for (const input of inputs) {\n input.setFilterOutput(this);\n assert(this.#schema === input.getSchema(), `Schema mismatch in fan-in`);\n }\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#output = output;\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n getSchema() {\n return this.#schema;\n }\n\n filter(node: Node, cleanup: boolean): boolean {\n return this.#output.filter(node, cleanup);\n }\n\n push(change: Change) {\n this.#accumulatedPushes.push(change);\n }\n\n fanOutDonePushingToAllBranches(fanOutChangeType: Change['type']) {\n if (this.#inputs.length === 0) {\n assert(\n this.#accumulatedPushes.length === 0,\n 'If there are no inputs then fan-in should not receive any pushes.',\n );\n return;\n }\n\n pushAccumulatedChanges(\n this.#accumulatedPushes,\n this.#output,\n this,\n fanOutChangeType,\n identity,\n identity,\n );\n }\n}\n", "import {must} from '../../../shared/src/must.ts';\nimport type {Change} from './change.ts';\nimport type {FanIn} from './fan-in.ts';\nimport type {Node} from './data.ts';\nimport type {\n FilterInput,\n FilterOperator,\n FilterOutput,\n} from './filter-operators.ts';\n\n/**\n * Forks a stream into multiple streams.\n * Is meant to be paired with a `FanIn` operator which will\n * later merge the forks back together.\n */\nexport class FanOut implements FilterOperator {\n readonly #input: FilterInput;\n readonly #outputs: FilterOutput[] = [];\n #fanIn: FanIn | undefined;\n #destroyCount: number = 0;\n\n constructor(input: FilterInput) {\n this.#input = input;\n input.setFilterOutput(this);\n }\n\n setFanIn(fanIn: FanIn) {\n this.#fanIn = fanIn;\n }\n\n setFilterOutput(output: FilterOutput): void {\n this.#outputs.push(output);\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n ++this.#destroyCount;\n if (this.#destroyCount === this.#outputs.length) {\n this.#input.destroy();\n }\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n\n getSchema() {\n return this.#input.getSchema();\n }\n\n filter(node: Node, cleanup: boolean): boolean {\n let result = false;\n for (const output of this.#outputs) {\n result = output.filter(node, cleanup) || result;\n // Cleanup needs to be forwarded to all outputs, don't short circuit\n // cleanup. For non-cleanup we can short-circuit on first true.\n if (!cleanup && result) {\n return true;\n }\n }\n return result;\n }\n\n push(change: Change) {\n for (const out of this.#outputs) {\n out.push(change, this);\n }\n must(\n this.#fanIn,\n 'fan-out must have a corresponding fan-in set!',\n ).fanOutDonePushingToAllBranches(change.type);\n }\n}\n", "import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {EditChange} from './change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\n/**\n * This takes an {@linkcode EditChange} and a predicate that determines if a row\n * should be present based on the row's data. It then splits the change and\n * pushes the appropriate changes to the output based on the predicate.\n */\nexport function maybeSplitAndPushEditChange(\n change: EditChange,\n predicate: (row: Row) => boolean,\n output: Output,\n pusher: InputBase,\n) {\n const oldWasPresent = predicate(change.oldNode.row);\n const newIsPresent = predicate(change.node.row);\n\n if (oldWasPresent && newIsPresent) {\n output.push(change, pusher);\n } else if (oldWasPresent && !newIsPresent) {\n output.push(\n {\n type: 'remove',\n node: change.oldNode,\n },\n pusher,\n );\n } else if (!oldWasPresent && newIsPresent) {\n output.push(\n {\n type: 'add',\n node: change.node,\n },\n pusher,\n );\n }\n}\n", "import {unreachable} from '../../../shared/src/asserts.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport type {InputBase, Output} from './operator.ts';\n\nexport function filterPush(\n change: Change,\n output: Output,\n pusher: InputBase,\n predicate?: (row: Row) => boolean,\n) {\n if (!predicate) {\n output.push(change, pusher);\n return;\n }\n switch (change.type) {\n case 'add':\n case 'remove':\n if (predicate(change.node.row)) {\n output.push(change, pusher);\n }\n break;\n case 'child':\n if (predicate(change.node.row)) {\n output.push(change, pusher);\n }\n break;\n case 'edit':\n maybeSplitAndPushEditChange(change, predicate, output, pusher);\n break;\n default:\n unreachable(change);\n }\n}\n", "import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {\n throwFilterOutput,\n type FilterInput,\n type FilterOperator,\n type FilterOutput,\n} from './filter-operators.ts';\nimport {filterPush} from './filter-push.ts';\nimport {type Node} from './data.ts';\nimport type {SourceSchema} from './schema.ts';\n\n/**\n * The Filter operator filters data through a predicate. It is stateless.\n *\n * The predicate must be pure.\n */\nexport class Filter implements FilterOperator {\n readonly #input: FilterInput;\n readonly #predicate: (row: Row) => boolean;\n\n #output: FilterOutput = throwFilterOutput;\n\n constructor(input: FilterInput, predicate: (row: Row) => boolean) {\n this.#input = input;\n this.#predicate = predicate;\n input.setFilterOutput(this);\n }\n\n filter(node: Node, cleanup: boolean): boolean {\n return this.#predicate(node.row) && this.#output.filter(node, cleanup);\n }\n\n setFilterOutput(output: FilterOutput) {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n push(change: Change) {\n filterPush(change, this.#output, this, this.#predicate);\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {stringCompare} from '../../../shared/src/string-compare.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport type {\n Condition,\n SimpleCondition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {valuesEqual} from './data.ts';\n\nexport type Constraint = {\n readonly [key: string]: Value;\n};\n\nexport function constraintMatchesRow(\n constraint: Constraint,\n row: Row,\n): boolean {\n for (const key in constraint) {\n if (!valuesEqual(row[key], constraint[key])) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Constraints are compatible if:\n * 1. They do not have any keys in common\n * 2. They have keys in common, but the values for those keys are equal\n */\nexport function constraintsAreCompatible(\n left: Constraint,\n right: Constraint,\n): boolean {\n for (const key in left) {\n if (key in right && !valuesEqual(left[key], right[key])) {\n return false;\n }\n }\n return true;\n}\n\nexport function constraintMatchesPrimaryKey(\n constraint: Constraint,\n primary: PrimaryKey,\n): boolean {\n return keyMatchesPrimaryKey(Object.keys(constraint), primary);\n}\n\nexport function keyMatchesPrimaryKey(\n key: Iterable<string>,\n primary: PrimaryKey,\n): boolean {\n const constraintKeys = [...key];\n\n if (constraintKeys.length !== primary.length) {\n return false;\n }\n\n // Primary key is always sorted\n // Constraint does not have to be sorted\n constraintKeys.sort(stringCompare);\n\n for (let i = 0; i < constraintKeys.length; i++) {\n if (constraintKeys[i] !== primary[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Pulls top level `and` components out of a condition tree.\n * The resulting array of simple conditions would match a superset of\n * values that the original condition would match.\n *\n * Examples:\n * a AND b OR c\n *\n * In this case we cannot pull anything because the `or` is at the top level.\n *\n * a AND b AND c\n * We can pull all three.\n *\n * a AND (b OR c)\n * We can only pull `a`.\n */\nexport function pullSimpleAndComponents(\n condition: Condition,\n): SimpleCondition[] {\n if (condition.type === 'and') {\n return condition.conditions.flatMap(pullSimpleAndComponents);\n }\n\n if (condition.type === 'simple') {\n return [condition];\n }\n\n if (condition.type === 'or' && condition.conditions.length === 1) {\n return pullSimpleAndComponents(condition.conditions[0]);\n }\n\n return [];\n}\n\n/**\n * Checks if the supplied filters constitute a primary key lookup.\n * If so, returns the constraint that would be used to look up the primary key.\n * If not, returns undefined.\n */\nexport function primaryKeyConstraintFromFilters(\n condition: Condition | undefined,\n primary: PrimaryKey,\n): Constraint | undefined {\n if (condition === undefined) {\n return undefined;\n }\n\n const conditions = pullSimpleAndComponents(condition);\n if (conditions.length === 0) {\n return undefined;\n }\n\n const ret: Writable<Constraint> = {};\n for (const subCondition of conditions) {\n if (subCondition.op === '=') {\n const column = extractColumn(subCondition);\n if (column !== undefined) {\n if (!primary.includes(column.name)) {\n continue;\n }\n ret[column.name] = column.value;\n }\n }\n }\n\n if (Object.keys(ret).length !== primary.length) {\n return undefined;\n }\n\n return ret;\n}\n\nfunction extractColumn(\n condition: SimpleCondition,\n): {name: string; value: Value} | undefined {\n if (condition.left.type === 'column') {\n assert(condition.right.type === 'literal');\n return {name: condition.left.name, value: condition.right.value};\n }\n\n return undefined;\n}\n\ndeclare const TESTING: boolean;\n\nexport class SetOfConstraint {\n #data: Constraint[] = [];\n\n constructor() {\n // Only used in testing\n assert(TESTING);\n }\n\n #indexOf(value: Constraint): number {\n return this.#data.findIndex(v => constraintEquals(v, value));\n }\n\n has(value: Constraint): boolean {\n return this.#indexOf(value) !== -1;\n }\n\n add(value: Constraint): this {\n if (!this.has(value)) {\n this.#data.push(value);\n }\n return this;\n }\n}\n\nfunction constraintEquals(a: Constraint, b: Constraint): boolean {\n const aEntries = Object.entries(a);\n const bEntries = Object.entries(b);\n if (aEntries.length !== bEntries.length) {\n return false;\n }\n for (let i = 0; i < aEntries.length; i++) {\n if (\n aEntries[i][0] !== bEntries[i][0] ||\n !valuesEqual(aEntries[i][1], bEntries[i][1])\n ) {\n return false;\n }\n }\n return true;\n}\n", "import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\nimport {compareValues, valuesEqual, type Node} from './data.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey} from '../../../zero-protocol/src/ast.ts';\n\nexport type JoinChangeOverlay = {\n change: Change;\n position: Row | undefined;\n};\n\nexport function* generateWithOverlay(\n stream: Stream<Node>,\n overlay: Change,\n schema: SourceSchema,\n): Stream<Node> {\n let applied = false;\n let editOldApplied = false;\n let editNewApplied = false;\n for (const node of stream) {\n let yieldNode = true;\n if (!applied) {\n switch (overlay.type) {\n case 'add': {\n if (schema.compareRows(overlay.node.row, node.row) === 0) {\n applied = true;\n yieldNode = false;\n }\n break;\n }\n case 'remove': {\n if (schema.compareRows(overlay.node.row, node.row) < 0) {\n applied = true;\n yield overlay.node;\n }\n break;\n }\n case 'edit': {\n if (\n !editOldApplied &&\n schema.compareRows(overlay.oldNode.row, node.row) < 0\n ) {\n editOldApplied = true;\n if (editNewApplied) {\n applied = true;\n }\n yield overlay.oldNode;\n }\n if (\n !editNewApplied &&\n schema.compareRows(overlay.node.row, node.row) === 0\n ) {\n editNewApplied = true;\n if (editOldApplied) {\n applied = true;\n }\n yieldNode = false;\n }\n break;\n }\n case 'child': {\n if (schema.compareRows(overlay.node.row, node.row) === 0) {\n applied = true;\n yield {\n row: node.row,\n relationships: {\n ...node.relationships,\n [overlay.child.relationshipName]: () =>\n generateWithOverlay(\n node.relationships[overlay.child.relationshipName](),\n overlay.child.change,\n schema.relationships[overlay.child.relationshipName],\n ),\n },\n };\n yieldNode = false;\n }\n break;\n }\n }\n }\n if (yieldNode) {\n yield node;\n }\n }\n if (!applied) {\n if (overlay.type === 'remove') {\n applied = true;\n yield overlay.node;\n } else if (overlay.type === 'edit') {\n assert(editNewApplied);\n editOldApplied = true;\n applied = true;\n yield overlay.oldNode;\n }\n }\n\n assert(applied);\n}\n\nexport function rowEqualsForCompoundKey(\n a: Row,\n b: Row,\n key: CompoundKey,\n): boolean {\n for (let i = 0; i < key.length; i++) {\n if (compareValues(a[key[i]], b[key[i]]) !== 0) {\n return false;\n }\n }\n return true;\n}\n\nexport function isJoinMatch(\n parent: Row,\n parentKey: CompoundKey,\n child: Row,\n childKey: CompoundKey,\n) {\n for (let i = 0; i < parentKey.length; i++) {\n if (!valuesEqual(parent[parentKey[i]], child[childKey[i]])) {\n return false;\n }\n }\n return true;\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {binarySearch} from '../../../shared/src/binary-search.ts';\nimport {emptyArray} from '../../../shared/src/sentinels.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Value} from '../../../zero-protocol/src/data.ts';\nimport type {Change} from './change.ts';\nimport {constraintsAreCompatible, type Constraint} from './constraint.ts';\nimport type {Node} from './data.ts';\nimport {\n generateWithOverlay,\n isJoinMatch,\n rowEqualsForCompoundKey,\n type JoinChangeOverlay,\n} from './join-utils.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Output,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {first, type Stream} from './stream.ts';\n\ntype Args = {\n parent: Input;\n child: Input;\n // The nth key in childKey corresponds to the nth key in parentKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * An *inner* join which fetches nodes from its child input first and then\n * fetches their related nodes from its parent input. Output nodes are the\n * nodes from parent input (in parent input order), which have at least one\n * related child. These output nodes have a new relationship added to them,\n * which has the name `relationshipName`. The value of the relationship is a\n * stream of related nodes from the child input (in child input order).\n */\nexport class FlippedJoin implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: JoinChangeOverlay | undefined;\n\n constructor({\n parent,\n child,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#child.destroy();\n this.#parent.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n // TODO: When parentKey is the parent's primary key (or more\n // generally when the parent cardinality is expected to be small) a different\n // algorithm should be used: For each child node, fetch all parent nodes\n // eagerly and then sort using quicksort.\n *fetch(req: FetchRequest): Stream<Node> {\n // Translate constraints for the parent on parts of the join key to\n // constraints for the child.\n const childConstraint: Record<string, Value> = {};\n let hasChildConstraint = false;\n if (req.constraint) {\n for (const [key, value] of Object.entries(req.constraint)) {\n const index = this.#parentKey.indexOf(key);\n if (index !== -1) {\n hasChildConstraint = true;\n childConstraint[this.#childKey[index]] = value;\n }\n }\n }\n const childNodes = [\n ...this.#child.fetch(\n hasChildConstraint ? {constraint: childConstraint} : {},\n ),\n ];\n // FlippedJoin's split-push change overlay logic is largely\n // the same as Join's with the exception of remove. For remove,\n // the change is undone here, and then re-applied to parents with order\n // less than or equal to change.position below. This is necessary\n // because if the removed node was the last related child, the\n // related parents with position greater than change.position\n // (which should not yet have the node removed), would not even\n // be fetched here, and would be absent from the output all together.\n if (this.#inprogressChildChange?.change.type === 'remove') {\n const removedNode = this.#inprogressChildChange.change.node;\n const compare = this.#child.getSchema().compareRows;\n const insertPos = binarySearch(childNodes.length, i =>\n compare(removedNode.row, childNodes[i].row),\n );\n childNodes.splice(insertPos, 0, removedNode);\n }\n const parentIterators: Iterator<Node>[] = [];\n let threw = false;\n try {\n for (const childNode of childNodes) {\n // TODO: consider adding the ability to pass a set of\n // ids to fetch, and have them applied to sqlite using IN.\n const constraintFromChild: Writable<Constraint> = {};\n for (let i = 0; i < this.#parentKey.length; i++) {\n constraintFromChild[this.#parentKey[i]] =\n childNode.row[this.#childKey[i]];\n }\n if (\n req.constraint &&\n !constraintsAreCompatible(constraintFromChild, req.constraint)\n ) {\n parentIterators.push(emptyArray[Symbol.iterator]());\n } else {\n const stream = this.#parent.fetch({\n ...req,\n constraint: {\n ...req.constraint,\n ...constraintFromChild,\n },\n });\n const iterator = stream[Symbol.iterator]();\n parentIterators.push(iterator);\n }\n }\n const nextParentNodes: (Node | null)[] = [];\n for (let i = 0; i < parentIterators.length; i++) {\n const iter = parentIterators[i];\n const result = iter.next();\n nextParentNodes[i] = result.done ? null : result.value;\n }\n\n while (true) {\n let minParentNode = null;\n let minParentNodeChildIndexes: number[] = [];\n for (let i = 0; i < nextParentNodes.length; i++) {\n const parentNode = nextParentNodes[i];\n if (parentNode === null) {\n continue;\n }\n if (minParentNode === null) {\n minParentNode = parentNode;\n minParentNodeChildIndexes.push(i);\n } else {\n const compareResult =\n this.#schema.compareRows(parentNode.row, minParentNode.row) *\n (req.reverse ? -1 : 1);\n if (compareResult === 0) {\n minParentNodeChildIndexes.push(i);\n } else if (compareResult < 0) {\n minParentNode = parentNode;\n minParentNodeChildIndexes = [i];\n }\n }\n }\n if (minParentNode === null) {\n return;\n }\n const relatedChildNodes: Node[] = [];\n for (const minParentNodeChildIndex of minParentNodeChildIndexes) {\n relatedChildNodes.push(childNodes[minParentNodeChildIndex]);\n const iter = parentIterators[minParentNodeChildIndex];\n const result = iter.next();\n nextParentNodes[minParentNodeChildIndex] = result.done\n ? null\n : result.value;\n }\n let overlaidRelatedChildNodes = relatedChildNodes;\n if (\n this.#inprogressChildChange &&\n this.#inprogressChildChange.position &&\n isJoinMatch(\n this.#inprogressChildChange.change.node.row,\n this.#childKey,\n minParentNode.row,\n this.#parentKey,\n )\n ) {\n const hasInprogressChildChangeBeenPushedForMinParentNode =\n this.#parent\n .getSchema()\n .compareRows(\n minParentNode.row,\n this.#inprogressChildChange.position,\n ) <= 0;\n if (this.#inprogressChildChange.change.type === 'remove') {\n if (hasInprogressChildChangeBeenPushedForMinParentNode) {\n // Remove form relatedChildNodes since the removed child\n // was inserted into childNodes above.\n overlaidRelatedChildNodes = relatedChildNodes.filter(\n n => n !== this.#inprogressChildChange?.change.node,\n );\n }\n } else if (!hasInprogressChildChangeBeenPushedForMinParentNode) {\n overlaidRelatedChildNodes = [\n ...generateWithOverlay(\n relatedChildNodes,\n this.#inprogressChildChange.change,\n this.#child.getSchema(),\n ),\n ];\n }\n }\n\n // yield node if after the overlay it still has relationship nodes\n if (overlaidRelatedChildNodes.length > 0) {\n yield {\n ...minParentNode,\n relationships: {\n ...minParentNode.relationships,\n [this.#relationshipName]: () => overlaidRelatedChildNodes,\n },\n };\n }\n }\n } catch (e) {\n threw = true;\n for (const iter of parentIterators) {\n try {\n iter.throw?.(e);\n } catch (_cleanupError) {\n // error in the iter.throw cleanup,\n // catch so other iterators are cleaned up\n }\n }\n throw e;\n } finally {\n if (!threw) {\n for (const iter of parentIterators) {\n try {\n iter.return?.();\n } catch (_cleanupError) {\n // error in the iter.return cleanup,\n // catch so other iterators are cleaned up\n }\n }\n }\n }\n }\n\n *cleanup(_req: FetchRequest): Stream<Node> {}\n\n #pushChild(change: Change): void {\n const pushChildChange = (exists?: boolean) => {\n this.#inprogressChildChange = {\n change,\n position: undefined,\n };\n try {\n const parentNodeStream = this.#parent.fetch({\n constraint: Object.fromEntries(\n this.#parentKey.map((key, i) => [\n key,\n change.node.row[this.#childKey[i]],\n ]),\n ),\n });\n for (const parentNode of parentNodeStream) {\n this.#inprogressChildChange = {\n change,\n position: parentNode.row,\n };\n const childNodeStream = () =>\n this.#child.fetch({\n constraint: Object.fromEntries(\n this.#childKey.map((key, i) => [\n key,\n parentNode.row[this.#parentKey[i]],\n ]),\n ),\n });\n if (!exists) {\n for (const childNode of childNodeStream()) {\n if (\n this.#child\n .getSchema()\n .compareRows(childNode.row, change.node.row) !== 0\n ) {\n exists = true;\n break;\n }\n }\n }\n if (exists) {\n this.#output.push(\n {\n type: 'child',\n node: {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: childNodeStream,\n },\n },\n child: {\n relationshipName: this.#relationshipName,\n change,\n },\n },\n this,\n );\n } else {\n this.#output.push(\n {\n ...change,\n node: {\n ...parentNode,\n relationships: {\n ...parentNode.relationships,\n [this.#relationshipName]: () => [change.node],\n },\n },\n },\n this,\n );\n }\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n };\n\n switch (change.type) {\n case 'add':\n case 'remove':\n pushChildChange();\n break;\n case 'edit': {\n assert(\n rowEqualsForCompoundKey(\n change.oldNode.row,\n change.node.row,\n this.#childKey,\n ),\n `Child edit must not change relationship.`,\n );\n pushChildChange(true);\n break;\n }\n case 'child':\n pushChildChange(true);\n break;\n }\n }\n\n #pushParent(change: Change): void {\n const childNodeStream = (node: Node) => () =>\n this.#child.fetch({\n constraint: Object.fromEntries(\n this.#childKey.map((key, i) => [key, node.row[this.#parentKey[i]]]),\n ),\n });\n\n const flip = (node: Node) => ({\n ...node,\n relationships: {\n ...node.relationships,\n [this.#relationshipName]: childNodeStream(node),\n },\n });\n\n // If no related child don't push as this is an inner join.\n if (first(childNodeStream(change.node)()) === undefined) {\n return;\n }\n\n switch (change.type) {\n case 'add':\n case 'remove':\n case 'child': {\n this.#output.push(\n {\n ...change,\n node: flip(change.node),\n },\n this,\n );\n break;\n }\n case 'edit': {\n assert(\n rowEqualsForCompoundKey(\n change.oldNode.row,\n change.node.row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n this.#output.push(\n {\n type: 'edit',\n oldNode: flip(change.oldNode),\n node: flip(change.node),\n },\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {CompoundKey, System} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {Change, ChildChange} from './change.ts';\nimport type {Node} from './data.ts';\nimport {\n generateWithOverlay,\n isJoinMatch,\n rowEqualsForCompoundKey,\n type JoinChangeOverlay,\n} from './join-utils.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Output,\n type Storage,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {take, type Stream} from './stream.ts';\n\ntype Args = {\n parent: Input;\n child: Input;\n storage: Storage;\n // The nth key in parentKey corresponds to the nth key in childKey.\n parentKey: CompoundKey;\n childKey: CompoundKey;\n relationshipName: string;\n hidden: boolean;\n system: System;\n};\n\n/**\n * The Join operator joins the output from two upstream inputs. Zero's join\n * is a little different from SQL's join in that we output hierarchical data,\n * not a flat table. This makes it a lot more useful for UI programming and\n * avoids duplicating tons of data like left join would.\n *\n * The Nodes output from Join have a new relationship added to them, which has\n * the name #relationshipName. The value of the relationship is a stream of\n * child nodes which are the corresponding values from the child source.\n */\nexport class Join implements Input {\n readonly #parent: Input;\n readonly #child: Input;\n readonly #storage: Storage;\n readonly #parentKey: CompoundKey;\n readonly #childKey: CompoundKey;\n readonly #relationshipName: string;\n readonly #schema: SourceSchema;\n\n #output: Output = throwOutput;\n\n #inprogressChildChange: JoinChangeOverlay | undefined;\n\n constructor({\n parent,\n child,\n storage,\n parentKey,\n childKey,\n relationshipName,\n hidden,\n system,\n }: Args) {\n assert(parent !== child, 'Parent and child must be different operators');\n assert(\n parentKey.length === childKey.length,\n 'The parentKey and childKey keys must have same length',\n );\n this.#parent = parent;\n this.#child = child;\n this.#storage = storage;\n this.#parentKey = parentKey;\n this.#childKey = childKey;\n this.#relationshipName = relationshipName;\n\n const parentSchema = parent.getSchema();\n const childSchema = child.getSchema();\n this.#schema = {\n ...parentSchema,\n relationships: {\n ...parentSchema.relationships,\n [relationshipName]: {\n ...childSchema,\n isHidden: hidden,\n system,\n },\n },\n };\n\n parent.setOutput({\n push: (change: Change) => this.#pushParent(change),\n });\n child.setOutput({\n push: (change: Change) => this.#pushChild(change),\n });\n }\n\n destroy(): void {\n this.#parent.destroy();\n this.#child.destroy();\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n for (const parentNode of this.#parent.fetch(req)) {\n yield this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n 'fetch',\n );\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n for (const parentNode of this.#parent.cleanup(req)) {\n yield this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n 'cleanup',\n );\n }\n }\n\n #pushParent(change: Change): void {\n switch (change.type) {\n case 'add':\n this.#output.push(\n {\n type: 'add',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'fetch',\n ),\n },\n this,\n );\n break;\n case 'remove':\n this.#output.push(\n {\n type: 'remove',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'cleanup',\n ),\n },\n this,\n );\n break;\n case 'child':\n this.#output.push(\n {\n type: 'child',\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'fetch',\n ),\n child: change.child,\n },\n this,\n );\n break;\n case 'edit': {\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(\n change.oldNode.row,\n change.node.row,\n this.#parentKey,\n ),\n `Parent edit must not change relationship.`,\n );\n this.#output.push(\n {\n type: 'edit',\n oldNode: this.#processParentNode(\n change.oldNode.row,\n change.oldNode.relationships,\n 'cleanup',\n ),\n node: this.#processParentNode(\n change.node.row,\n change.node.relationships,\n 'fetch',\n ),\n },\n this,\n );\n break;\n }\n default:\n unreachable(change);\n }\n }\n\n #pushChild(change: Change): void {\n const pushChildChange = (childRow: Row, change: Change) => {\n this.#inprogressChildChange = {\n change,\n position: undefined,\n };\n try {\n const parentNodes = this.#parent.fetch({\n constraint: Object.fromEntries(\n this.#parentKey.map((key, i) => [key, childRow[this.#childKey[i]]]),\n ),\n });\n\n for (const parentNode of parentNodes) {\n this.#inprogressChildChange.position = parentNode.row;\n const childChange: ChildChange = {\n type: 'child',\n node: this.#processParentNode(\n parentNode.row,\n parentNode.relationships,\n 'fetch',\n ),\n child: {\n relationshipName: this.#relationshipName,\n change,\n },\n };\n this.#output.push(childChange, this);\n }\n } finally {\n this.#inprogressChildChange = undefined;\n }\n };\n\n switch (change.type) {\n case 'add':\n case 'remove':\n pushChildChange(change.node.row, change);\n break;\n case 'child':\n pushChildChange(change.node.row, change);\n break;\n case 'edit': {\n const childRow = change.node.row;\n const oldChildRow = change.oldNode.row;\n // Assert the edit could not change the relationship.\n assert(\n rowEqualsForCompoundKey(oldChildRow, childRow, this.#childKey),\n 'Child edit must not change relationship.',\n );\n pushChildChange(childRow, change);\n break;\n }\n\n default:\n unreachable(change);\n }\n }\n\n #processParentNode(\n parentNodeRow: Row,\n parentNodeRelations: Record<string, () => Stream<Node>>,\n mode: ProcessParentMode,\n ): Node {\n let method: ProcessParentMode = mode;\n let storageUpdated = false;\n const childStream = () => {\n if (!storageUpdated) {\n if (mode === 'cleanup') {\n this.#storage.del(\n makeStorageKey(\n this.#parentKey,\n this.#parent.getSchema().primaryKey,\n parentNodeRow,\n ),\n );\n const empty =\n [\n ...take(\n this.#storage.scan({\n prefix: makeStorageKeyPrefix(parentNodeRow, this.#parentKey),\n }),\n 1,\n ),\n ].length === 0;\n method = empty ? 'cleanup' : 'fetch';\n }\n\n storageUpdated = true;\n // Defer the work to update storage until the child stream\n // is actually accessed\n if (mode === 'fetch') {\n this.#storage.set(\n makeStorageKey(\n this.#parentKey,\n this.#parent.getSchema().primaryKey,\n parentNodeRow,\n ),\n true,\n );\n }\n }\n\n const stream = this.#child[method]({\n constraint: Object.fromEntries(\n this.#childKey.map((key, i) => [\n key,\n parentNodeRow[this.#parentKey[i]],\n ]),\n ),\n });\n\n if (\n this.#inprogressChildChange &&\n isJoinMatch(\n parentNodeRow,\n this.#parentKey,\n this.#inprogressChildChange.change.node.row,\n this.#childKey,\n ) &&\n this.#inprogressChildChange.position &&\n this.#schema.compareRows(\n parentNodeRow,\n this.#inprogressChildChange.position,\n ) > 0\n ) {\n return generateWithOverlay(\n stream,\n this.#inprogressChildChange.change,\n this.#child.getSchema(),\n );\n }\n return stream;\n };\n\n return {\n row: parentNodeRow,\n relationships: {\n ...parentNodeRelations,\n [this.#relationshipName]: childStream,\n },\n };\n }\n}\n\ntype ProcessParentMode = 'fetch' | 'cleanup';\n\n/** Exported for testing. */\nexport function makeStorageKeyForValues(values: readonly Value[]): string {\n const json = JSON.stringify(['pKeySet', ...values]);\n return json.substring(1, json.length - 1) + ',';\n}\n\n/** Exported for testing. */\nexport function makeStorageKeyPrefix(row: Row, key: CompoundKey): string {\n return makeStorageKeyForValues(key.map(k => row[k]));\n}\n\n/** Exported for testing.\n * This storage key tracks the primary keys seen for each unique\n * value joined on. This is used to know when to cleanup a child's state.\n */\nexport function makeStorageKey(\n key: CompoundKey,\n primaryKey: PrimaryKey,\n row: Row,\n): string {\n const values: Value[] = key.map(k => row[k]);\n for (const key of primaryKey) {\n values.push(row[key]);\n }\n return makeStorageKeyForValues(values);\n}\n", "import type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {AddChange, Change, ChildChange, RemoveChange} from './change.ts';\nimport type {Comparator, Node} from './data.ts';\nimport {maybeSplitAndPushEditChange} from './maybe-split-and-push-edit-change.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Bound = {\n row: Row;\n exclusive: boolean;\n};\n\n/**\n * Skip sets the start position for the pipeline. No rows before the bound will\n * be output.\n */\nexport class Skip implements Operator {\n readonly #input: Input;\n readonly #bound: Bound;\n readonly #comparator: Comparator;\n\n #output: Output = throwOutput;\n\n constructor(input: Input, bound: Bound) {\n this.#input = input;\n this.#bound = bound;\n this.#comparator = input.getSchema().compareRows;\n input.setOutput(this);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n return this.#fetchOrCleanup('fetch', req);\n }\n\n cleanup(req: FetchRequest): Stream<Node> {\n return this.#fetchOrCleanup('fetch', req);\n }\n\n *#fetchOrCleanup(method: 'fetch' | 'cleanup', req: FetchRequest) {\n const start = this.#getStart(req);\n if (start === 'empty') {\n return;\n }\n const nodes = this.#input[method]({...req, start});\n if (!req.reverse) {\n yield* nodes;\n return;\n }\n for (const node of nodes) {\n if (!this.#shouldBePresent(node.row)) {\n return;\n }\n yield node;\n }\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n #shouldBePresent(row: Row): boolean {\n const cmp = this.#comparator(this.#bound.row, row);\n return cmp < 0 || (cmp === 0 && !this.#bound.exclusive);\n }\n\n push(change: Change): void {\n const shouldBePresent = (row: Row) => this.#shouldBePresent(row);\n if (change.type === 'edit') {\n maybeSplitAndPushEditChange(change, shouldBePresent, this.#output, this);\n return;\n }\n\n change satisfies AddChange | RemoveChange | ChildChange;\n\n if (shouldBePresent(change.node.row)) {\n this.#output.push(change, this);\n }\n }\n\n #getStart(req: FetchRequest): Start | undefined | 'empty' {\n const boundStart = {\n row: this.#bound.row,\n basis: this.#bound.exclusive ? 'after' : 'at',\n } as const;\n\n if (!req.start) {\n if (req.reverse) {\n return undefined;\n }\n return boundStart;\n }\n\n const cmp = this.#comparator(this.#bound.row, req.start.row);\n\n if (!req.reverse) {\n // The skip bound is after the requested bound. The requested bound cannot\n // be relevant because even if it was basis: 'after', the skip bound is\n // itself after the requested bound. Return the skip bound.\n if (cmp > 0) {\n return boundStart;\n }\n\n // The skip bound and requested bound are equal. If either is exclusive,\n // return that bound with exclusive. Otherwise, return the skip bound.\n if (cmp === 0) {\n if (this.#bound.exclusive || req.start.basis === 'after') {\n return {\n row: this.#bound.row,\n basis: 'after',\n };\n }\n return boundStart;\n }\n\n return req.start;\n }\n\n req.reverse satisfies true;\n\n // bound is after the start, but request is for reverse so results\n // must be empty\n if (cmp > 0) {\n return 'empty';\n }\n\n if (cmp === 0) {\n // if both are inclusive, the result can be the single row at bound\n // return it as start\n if (!this.#bound.exclusive && req.start.basis === 'at') {\n return boundStart;\n }\n // otherwise the results must be empty, one or both are exclusive\n // in opposite directions\n return 'empty';\n }\n\n // bound is before the start, return start\n return req.start;\n }\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {hasOwn} from '../../../shared/src/has-own.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {assertOrderingIncludesPK} from '../builder/builder.ts';\nimport {type Change, type EditChange, type RemoveChange} from './change.ts';\nimport type {Constraint} from './constraint.ts';\nimport {compareValues, type Comparator, type Node} from './data.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n type Storage,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {first, take, type Stream} from './stream.ts';\n\nconst MAX_BOUND_KEY = 'maxBound';\n\ntype TakeState = {\n size: number;\n bound: Row | undefined;\n};\n\ninterface TakeStorage {\n get(key: typeof MAX_BOUND_KEY): Row | undefined;\n get(key: string): TakeState | undefined;\n set(key: typeof MAX_BOUND_KEY, value: Row): void;\n set(key: string, value: TakeState): void;\n del(key: string): void;\n}\n\nexport type PartitionKey = PrimaryKey;\n\n/**\n * The Take operator is for implementing limit queries. It takes the first n\n * nodes of its input as determined by the input\u2019s comparator. It then keeps\n * a *bound* of the last item it has accepted so that it can evaluate whether\n * new incoming pushes should be accepted or rejected.\n *\n * Take can count rows globally or by unique value of some field.\n *\n * Maintains the invariant that its output size is always <= limit, even\n * mid processing of a push.\n */\nexport class Take implements Operator {\n readonly #input: Input;\n readonly #storage: TakeStorage;\n readonly #limit: number;\n readonly #partitionKey: PartitionKey | undefined;\n readonly #partitionKeyComparator: Comparator | undefined;\n // Fetch overlay needed for some split push cases.\n #rowHiddenFromFetch: Row | undefined;\n\n #output: Output = throwOutput;\n\n constructor(\n input: Input,\n storage: Storage,\n limit: number,\n partitionKey?: PartitionKey,\n ) {\n assert(limit >= 0, 'Limit must be non-negative');\n assertOrderingIncludesPK(\n input.getSchema().sort,\n input.getSchema().primaryKey,\n );\n input.setOutput(this);\n this.#input = input;\n this.#storage = storage as TakeStorage;\n this.#limit = limit;\n this.#partitionKey = partitionKey;\n this.#partitionKeyComparator =\n partitionKey && makePartitionKeyComparator(partitionKey);\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n *fetch(req: FetchRequest): Stream<Node> {\n if (\n !this.#partitionKey ||\n (req.constraint &&\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey))\n ) {\n const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);\n const takeState = this.#storage.get(takeStateKey);\n if (!takeState) {\n yield* this.#initialFetch(req);\n return;\n }\n if (takeState.bound === undefined) {\n return;\n }\n for (const inputNode of this.#input.fetch(req)) {\n if (this.getSchema().compareRows(takeState.bound, inputNode.row) < 0) {\n return;\n }\n if (\n this.#rowHiddenFromFetch &&\n this.getSchema().compareRows(\n this.#rowHiddenFromFetch,\n inputNode.row,\n ) === 0\n ) {\n continue;\n }\n yield inputNode;\n }\n return;\n }\n // There is a partition key, but the fetch is not constrained or constrained\n // on a different key. Thus we don't have a single take state to bound by.\n // This currently only happens with nested sub-queries\n // e.g. issues include issuelabels include label. We could remove this\n // case if we added a translation layer (powered by some state) in join.\n // Specifically we need joinKeyValue => parent constraint key\n const maxBound = this.#storage.get(MAX_BOUND_KEY);\n if (maxBound === undefined) {\n return;\n }\n for (const inputNode of this.#input.fetch(req)) {\n if (this.getSchema().compareRows(inputNode.row, maxBound) > 0) {\n return;\n }\n const takeStateKey = getTakeStateKey(this.#partitionKey, inputNode.row);\n const takeState = this.#storage.get(takeStateKey);\n if (\n takeState?.bound !== undefined &&\n this.getSchema().compareRows(takeState.bound, inputNode.row) >= 0\n ) {\n yield inputNode;\n }\n }\n }\n\n *#initialFetch(req: FetchRequest): Stream<Node> {\n assert(req.start === undefined, 'Start should be undefined');\n assert(!req.reverse, 'Reverse should be false');\n assert(\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey),\n 'Constraint should match partition key',\n );\n\n if (this.#limit === 0) {\n return;\n }\n\n const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);\n assert(\n this.#storage.get(takeStateKey) === undefined,\n 'Take state should be undefined',\n );\n\n let size = 0;\n let bound: Row | undefined;\n let downstreamEarlyReturn = true;\n let exceptionThrown = false;\n try {\n for (const inputNode of this.#input.fetch(req)) {\n yield inputNode;\n bound = inputNode.row;\n size++;\n if (size === this.#limit) {\n break;\n }\n }\n downstreamEarlyReturn = false;\n } catch (e) {\n exceptionThrown = true;\n throw e;\n } finally {\n if (!exceptionThrown) {\n this.#setTakeState(\n takeStateKey,\n size,\n bound,\n this.#storage.get(MAX_BOUND_KEY),\n );\n // If it becomes necessary to support downstream early return, this\n // assert should be removed, and replaced with code that consumes\n // the input stream until limit is reached or the input stream is\n // exhausted so that takeState is properly hydrated.\n assert(\n !downstreamEarlyReturn,\n 'Unexpected early return prevented full hydration',\n );\n }\n }\n }\n\n *cleanup(req: FetchRequest): Stream<Node> {\n assert(req.start === undefined, 'Start should be undefined');\n assert(\n constraintMatchesPartitionKey(req.constraint, this.#partitionKey),\n 'Constraint should match partition key',\n );\n const takeStateKey = getTakeStateKey(this.#partitionKey, req.constraint);\n this.#storage.del(takeStateKey);\n let size = 0;\n for (const inputNode of this.#input.cleanup(req)) {\n if (size === this.#limit) {\n return;\n }\n size++;\n yield inputNode;\n }\n }\n\n #getStateAndConstraint(row: Row) {\n const takeStateKey = getTakeStateKey(this.#partitionKey, row);\n const takeState = this.#storage.get(takeStateKey);\n let maxBound: Row | undefined;\n let constraint: Constraint | undefined;\n if (takeState) {\n maxBound = this.#storage.get(MAX_BOUND_KEY);\n constraint =\n this.#partitionKey &&\n Object.fromEntries(\n this.#partitionKey.map(key => [key, row[key]] as const),\n );\n }\n\n return {takeState, takeStateKey, maxBound, constraint} as\n | {\n takeState: undefined;\n takeStateKey: string;\n maxBound: undefined;\n constraint: undefined;\n }\n | {\n takeState: TakeState;\n takeStateKey: string;\n maxBound: Row | undefined;\n constraint: Constraint | undefined;\n };\n }\n\n push(change: Change): void {\n if (change.type === 'edit') {\n this.#pushEditChange(change);\n return;\n }\n\n const {takeState, takeStateKey, maxBound, constraint} =\n this.#getStateAndConstraint(change.node.row);\n if (!takeState) {\n return;\n }\n\n const {compareRows} = this.getSchema();\n\n if (change.type === 'add') {\n if (takeState.size < this.#limit) {\n this.#setTakeState(\n takeStateKey,\n takeState.size + 1,\n takeState.bound === undefined ||\n compareRows(takeState.bound, change.node.row) < 0\n ? change.node.row\n : takeState.bound,\n maxBound,\n );\n this.#output.push(change, this);\n return;\n }\n // size === limit\n if (\n takeState.bound === undefined ||\n compareRows(change.node.row, takeState.bound) >= 0\n ) {\n return;\n }\n // added row < bound\n let beforeBoundNode: Node | undefined;\n let boundNode: Node;\n if (this.#limit === 1) {\n boundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n }),\n ),\n );\n } else {\n [boundNode, beforeBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n reverse: true,\n }),\n 2,\n );\n }\n const removeChange: RemoveChange = {\n type: 'remove',\n node: boundNode,\n };\n // Remove before add to maintain invariant that\n // output size <= limit.\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n beforeBoundNode === undefined ||\n compareRows(change.node.row, beforeBoundNode.row) > 0\n ? change.node.row\n : beforeBoundNode.row,\n maxBound,\n );\n this.#withRowHiddenFromFetch(change.node.row, () => {\n this.#output.push(removeChange, this);\n });\n this.#output.push(change, this);\n } else if (change.type === 'remove') {\n if (takeState.bound === undefined) {\n // change is after bound\n return;\n }\n const compToBound = compareRows(change.node.row, takeState.bound);\n if (compToBound > 0) {\n // change is after bound\n return;\n }\n const [beforeBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'after',\n },\n constraint,\n reverse: true,\n }),\n 1,\n );\n\n let newBound: {node: Node; push: boolean} | undefined;\n if (beforeBoundNode) {\n const push = compareRows(beforeBoundNode.row, takeState.bound) > 0;\n newBound = {\n node: beforeBoundNode,\n push,\n };\n }\n if (!newBound?.push) {\n for (const node of this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n })) {\n const push = compareRows(node.row, takeState.bound) > 0;\n newBound = {\n node,\n push,\n };\n if (push) {\n break;\n }\n }\n }\n\n if (newBound?.push) {\n this.#output.push(change, this);\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n newBound.node.row,\n maxBound,\n );\n this.#output.push(\n {\n type: 'add',\n node: newBound.node,\n },\n this,\n );\n return;\n }\n this.#setTakeState(\n takeStateKey,\n takeState.size - 1,\n newBound?.node.row,\n maxBound,\n );\n this.#output.push(change, this);\n } else if (change.type === 'child') {\n // A 'child' change should be pushed to output if its row\n // is <= bound.\n if (\n takeState.bound &&\n compareRows(change.node.row, takeState.bound) <= 0\n ) {\n this.#output.push(change, this);\n }\n }\n }\n\n #pushEditChange(change: EditChange): void {\n assert(\n !this.#partitionKeyComparator ||\n this.#partitionKeyComparator(change.oldNode.row, change.node.row) === 0,\n 'Unexpected change of partition key',\n );\n\n const {takeState, takeStateKey, maxBound, constraint} =\n this.#getStateAndConstraint(change.oldNode.row);\n if (!takeState) {\n return;\n }\n\n assert(takeState.bound, 'Bound should be set');\n const {compareRows} = this.getSchema();\n const oldCmp = compareRows(change.oldNode.row, takeState.bound);\n const newCmp = compareRows(change.node.row, takeState.bound);\n\n const replaceBoundAndForwardChange = () => {\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n change.node.row,\n maxBound,\n );\n this.#output.push(change, this);\n };\n\n // The bounds row was changed.\n if (oldCmp === 0) {\n // The new row is the new bound.\n if (newCmp === 0) {\n // no need to update the state since we are keeping the bounds\n this.#output.push(change, this);\n return;\n }\n\n if (newCmp < 0) {\n if (this.#limit === 1) {\n replaceBoundAndForwardChange();\n return;\n }\n\n // New row will be in the result but it might not be the bounds any\n // more. We need to find the row before the bounds to determine the new\n // bounds.\n\n const beforeBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'after',\n },\n constraint,\n reverse: true,\n }),\n ),\n );\n\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n beforeBoundNode.row,\n maxBound,\n );\n this.#output.push(change, this);\n return;\n }\n\n assert(newCmp > 0, 'New comparison must be greater than 0');\n // Find the first item at the old bounds. This will be the new bounds.\n const newBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n }),\n ),\n );\n\n // The next row is the new row. We can replace the bounds and keep the\n // edit change.\n if (compareRows(newBoundNode.row, change.node.row) === 0) {\n replaceBoundAndForwardChange();\n return;\n }\n\n // The new row is now outside the bounds, so we need to remove the old\n // row and add the new bounds row.\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n newBoundNode.row,\n maxBound,\n );\n this.#withRowHiddenFromFetch(newBoundNode.row, () => {\n this.#output.push(\n {\n type: 'remove',\n node: change.oldNode,\n },\n this,\n );\n });\n this.#output.push(\n {\n type: 'add',\n node: newBoundNode,\n },\n this,\n );\n return;\n }\n\n if (oldCmp > 0) {\n assert(newCmp !== 0, 'Invalid state. Row has duplicate primary key');\n\n // Both old and new outside of bounds\n if (newCmp > 0) {\n return;\n }\n\n // old was outside, new is inside. Pushing out the old bounds\n assert(newCmp < 0, 'New comparison must be less than 0');\n\n const [oldBoundNode, newBoundNode] = take(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'at',\n },\n constraint,\n reverse: true,\n }),\n 2,\n );\n // Remove before add to maintain invariant that\n // output size <= limit.\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n newBoundNode.row,\n maxBound,\n );\n this.#withRowHiddenFromFetch(change.node.row, () => {\n this.#output.push(\n {\n type: 'remove',\n node: oldBoundNode,\n },\n this,\n );\n });\n this.#output.push(\n {\n type: 'add',\n node: change.node,\n },\n this,\n );\n\n return;\n }\n\n if (oldCmp < 0) {\n assert(newCmp !== 0, 'Invalid state. Row has duplicate primary key');\n\n // Both old and new inside of bounds\n if (newCmp < 0) {\n this.#output.push(change, this);\n return;\n }\n\n // old was inside, new is larger than old bound\n\n assert(newCmp > 0, 'New comparison must be greater than 0');\n\n // at this point we need to find the row after the bound and use that or\n // the newRow as the new bound.\n const afterBoundNode = must(\n first(\n this.#input.fetch({\n start: {\n row: takeState.bound,\n basis: 'after',\n },\n constraint,\n }),\n ),\n );\n\n // The new row is the new bound. Use an edit change.\n if (compareRows(afterBoundNode.row, change.node.row) === 0) {\n replaceBoundAndForwardChange();\n return;\n }\n\n this.#output.push(\n {\n type: 'remove',\n node: change.oldNode,\n },\n this,\n );\n this.#setTakeState(\n takeStateKey,\n takeState.size,\n afterBoundNode.row,\n maxBound,\n );\n this.#output.push(\n {\n type: 'add',\n node: afterBoundNode,\n },\n this,\n );\n return;\n }\n\n unreachable();\n }\n\n #withRowHiddenFromFetch(row: Row, fn: () => void) {\n this.#rowHiddenFromFetch = row;\n try {\n fn();\n } finally {\n this.#rowHiddenFromFetch = undefined;\n }\n }\n\n #setTakeState(\n takeStateKey: string,\n size: number,\n bound: Row | undefined,\n maxBound: Row | undefined,\n ) {\n this.#storage.set(takeStateKey, {\n size,\n bound,\n });\n if (\n bound !== undefined &&\n (maxBound === undefined ||\n this.getSchema().compareRows(bound, maxBound) > 0)\n ) {\n this.#storage.set(MAX_BOUND_KEY, bound);\n }\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n}\n\nfunction getTakeStateKey(\n partitionKey: PartitionKey | undefined,\n rowOrConstraint: Row | Constraint | undefined,\n): string {\n // The order must be consistent. We always use the order as defined by the\n // partition key.\n const partitionValues: Value[] = [];\n\n if (partitionKey && rowOrConstraint) {\n for (const key of partitionKey) {\n partitionValues.push(rowOrConstraint[key]);\n }\n }\n\n return JSON.stringify(['take', ...partitionValues]);\n}\n\nfunction constraintMatchesPartitionKey(\n constraint: Constraint | undefined,\n partitionKey: PartitionKey | undefined,\n): boolean {\n if (constraint === undefined || partitionKey === undefined) {\n return constraint === partitionKey;\n }\n if (partitionKey.length !== Object.keys(constraint).length) {\n return false;\n }\n for (const key of partitionKey) {\n if (!hasOwn(constraint, key)) {\n return false;\n }\n }\n return true;\n}\n\nfunction makePartitionKeyComparator(partitionKey: PartitionKey): Comparator {\n return (a, b) => {\n for (const key of partitionKey) {\n const cmp = compareValues(a[key], b[key]);\n if (cmp !== 0) {\n return cmp;\n }\n }\n return 0;\n };\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {mergeIterables} from '../../../shared/src/iterables.ts';\nimport type {Writable} from '../../../shared/src/writable.ts';\nimport type {Change} from './change.ts';\nimport type {Constraint} from './constraint.ts';\nimport type {Node} from './data.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type InputBase,\n type Operator,\n type Output,\n} from './operator.ts';\nimport {\n makeAddEmptyRelationships,\n mergeRelationships,\n pushAccumulatedChanges,\n} from './push-accumulated.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {first, type Stream} from './stream.ts';\nimport type {UnionFanOut} from './union-fan-out.ts';\n\nexport class UnionFanIn implements Operator {\n readonly #inputs: readonly Input[];\n readonly #schema: SourceSchema;\n #fanOutPushStarted: boolean = false;\n #output: Output = throwOutput;\n #accumulatedPushes: Change[] = [];\n\n constructor(fanOut: UnionFanOut, inputs: Input[]) {\n this.#inputs = inputs;\n const fanOutSchema = fanOut.getSchema();\n fanOut.setFanIn(this);\n\n const schema: Writable<SourceSchema> = {\n tableName: fanOutSchema.tableName,\n columns: fanOutSchema.columns,\n primaryKey: fanOutSchema.primaryKey,\n relationships: {\n ...fanOutSchema.relationships,\n },\n isHidden: fanOutSchema.isHidden,\n system: fanOutSchema.system,\n compareRows: fanOutSchema.compareRows,\n sort: fanOutSchema.sort,\n };\n\n // now go through inputs and merge relationships\n const relationshipsFromBranches: Set<string> = new Set();\n for (const input of inputs) {\n const inputSchema = input.getSchema();\n assert(\n schema.tableName === inputSchema.tableName,\n `Table name mismatch in union fan-in: ${schema.tableName} !== ${inputSchema.tableName}`,\n );\n assert(\n schema.primaryKey === inputSchema.primaryKey,\n `Primary key mismatch in union fan-in`,\n );\n assert(\n schema.system === inputSchema.system,\n `System mismatch in union fan-in: ${schema.system} !== ${inputSchema.system}`,\n );\n assert(\n schema.compareRows === inputSchema.compareRows,\n `compareRows mismatch in union fan-in`,\n );\n assert(schema.sort === inputSchema.sort, `Sort mismatch in union fan-in`);\n\n for (const [relName, relSchema] of Object.entries(\n inputSchema.relationships,\n )) {\n if (relName in fanOutSchema.relationships) {\n continue;\n }\n\n // All branches will have unique relationship names except for relationships\n // that come in from `fanOut`.\n assert(\n !relationshipsFromBranches.has(relName),\n `Relationship ${relName} exists in multiple upstream inputs to union fan-in`,\n );\n schema.relationships[relName] = relSchema;\n relationshipsFromBranches.add(relName);\n }\n\n input.setOutput(this);\n }\n\n this.#schema = schema;\n this.#inputs = inputs;\n }\n\n cleanup(_req: FetchRequest): Stream<Node> {\n // Cleanup is going away. Not implemented.\n return [];\n }\n\n destroy(): void {\n for (const input of this.#inputs) {\n input.destroy();\n }\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n const iterables = this.#inputs.map(input => input.fetch(req));\n return mergeIterables(\n iterables,\n (l, r) => this.#schema.compareRows(l.row, r.row),\n true,\n );\n }\n\n getSchema(): SourceSchema {\n return this.#schema;\n }\n\n push(change: Change, pusher: InputBase): void {\n if (!this.#fanOutPushStarted) {\n this.#pushInternalChange(change, pusher);\n } else {\n this.#accumulatedPushes.push(change);\n }\n }\n\n /**\n * An internal change means that a change was received inside the fan-out/fan-in sub-graph.\n *\n * These changes always come from children of a flip-join as no other push generating operators\n * currently exist between union-fan-in and union-fan-out. All other pushes\n * enter into union-fan-out before reaching union-fan-in.\n *\n * - normal joins for `exists` come before `union-fan-out`\n * - joins for `related` come after `union-fan-out`\n * - take comes after `union-fan-out`\n *\n * The algorithm for deciding whether or not to forward a push that came from inside the ufo/ufi sub-graph:\n * 1. If the change is a `child` change we can forward it. This is because all child branches in the ufo/ufi sub-graph are unique.\n * 2. If the change is `add` we can forward it iff no `fetches` for the row return any results.\n * If another branch has it, the add was already emitted in the past.\n * 3. If the change is `remove` we can forward it iff no `fetches` for the row return any results.\n * If no other branches have the change, the remove can be sent as the value is no longer present.\n * If other branches have it, the last branch the processes the remove will send the remove.\n * 4. Edits will always come through as child changes as flip join will flip them into children.\n * An edit that would result in a remove or add will have been split into an add/remove pair rather than being an edit.\n */\n #pushInternalChange(change: Change, pusher: InputBase): void {\n if (change.type === 'child') {\n this.#output.push(change, this);\n return;\n }\n\n assert(change.type === 'add' || change.type === 'remove');\n\n let hadMatch = false;\n for (const input of this.#inputs) {\n if (input === pusher) {\n hadMatch = true;\n continue;\n }\n\n const constraint: Writable<Constraint> = {};\n for (const key of this.#schema.primaryKey) {\n constraint[key] = change.node.row[key];\n }\n const fetchResult = input.fetch({\n constraint,\n });\n\n if (first(fetchResult) !== undefined) {\n // Another branch has the row, so the add/remove is not needed.\n return;\n }\n }\n\n assert(hadMatch, 'Pusher was not one of the inputs to union-fan-in!');\n\n // No other branches have the row, so we can push the change.\n this.#output.push(change, this);\n }\n\n fanOutStartedPushing() {\n assert(this.#fanOutPushStarted === false);\n this.#fanOutPushStarted = true;\n }\n\n fanOutDonePushing(fanOutChangeType: Change['type']) {\n assert(this.#fanOutPushStarted);\n this.#fanOutPushStarted = false;\n if (this.#inputs.length === 0) {\n return;\n }\n\n if (this.#accumulatedPushes.length === 0) {\n // It is possible for no forks to pass along the push.\n // E.g., if no filters match in any fork.\n return;\n }\n\n pushAccumulatedChanges(\n this.#accumulatedPushes,\n this.#output,\n this,\n fanOutChangeType,\n mergeRelationships,\n makeAddEmptyRelationships(this.#schema),\n );\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Change} from './change.ts';\nimport type {Node} from './data.ts';\nimport type {FetchRequest, Input, Operator, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {Stream} from './stream.ts';\nimport type {UnionFanIn} from './union-fan-in.ts';\n\nexport class UnionFanOut implements Operator {\n #destroyCount: number = 0;\n #unionFanIn?: UnionFanIn;\n readonly #input: Input;\n readonly #outputs: Output[] = [];\n\n constructor(input: Input) {\n this.#input = input;\n input.setOutput(this);\n }\n\n setFanIn(fanIn: UnionFanIn) {\n assert(!this.#unionFanIn, 'FanIn already set for this FanOut');\n this.#unionFanIn = fanIn;\n }\n\n push(change: Change): void {\n must(this.#unionFanIn).fanOutStartedPushing();\n for (const output of this.#outputs) {\n output.push(change, this);\n }\n must(this.#unionFanIn).fanOutDonePushing(change.type);\n }\n\n setOutput(output: Output): void {\n this.#outputs.push(output);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n return this.#input.fetch(req);\n }\n\n cleanup(_req: FetchRequest): Stream<Node> {\n // Cleanup is going away. Not implemented.\n return [];\n }\n\n destroy(): void {\n if (this.#destroyCount < this.#outputs.length) {\n ++this.#destroyCount;\n if (this.#destroyCount === this.#outputs.length) {\n this.#input.destroy();\n }\n } else {\n throw new Error('FanOut already destroyed once for each output');\n }\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * A PlannerFanIn node can either be a normal FanIn or UnionFanIn.\n *\n * These have different performance characteristics so we need to distinguish them.\n *\n * A normal FanIn only does a single fetch to FanOut, regardless of how many internal\n * branches / inputs it has.\n *\n * A UnionFanIn does a fetch per internal branch / input. This causes an exponential\n * increase in cost if many UnionFanIns are chained after on another. E.g., `(A or B) AND (C or D)`.\n *\n * To capture this cost blow-up, union fan in assigns different branch patterns to their inputs.\n *\n * Since UFI will generate a unique branch pattern per input, planner-connection will yield a higher cost\n * each time a UFI is present. planner-connection will return the sum of the costs of each unique branch pattern.\n */\nexport class PlannerFanIn {\n readonly kind = 'fan-in' as const;\n #type: 'FI' | 'UFI';\n #output?: PlannerNode | undefined;\n readonly #inputs: Exclude<PlannerNode, PlannerTerminus>[];\n\n constructor(inputs: Exclude<PlannerNode, PlannerTerminus>[]) {\n this.#type = 'FI';\n this.#inputs = inputs;\n }\n\n get type() {\n return this.#type;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return 'join';\n }\n\n setOutput(node: PlannerNode): void {\n this.#output = node;\n }\n\n get output(): PlannerNode {\n assert(this.#output !== undefined, 'Output not set');\n return this.#output;\n }\n\n reset() {\n this.#type = 'FI';\n }\n\n convertToUFI(): void {\n this.#type = 'UFI';\n }\n\n /**\n * Propagate unlimiting when a parent join is flipped.\n * Fan-in propagates to all of its inputs.\n */\n propagateUnlimitFromFlippedJoin(): void {\n for (const input of this.#inputs) {\n if (\n 'propagateUnlimitFromFlippedJoin' in input &&\n typeof input.propagateUnlimitFromFlippedJoin === 'function'\n ) {\n (\n input as {propagateUnlimitFromFlippedJoin(): void}\n ).propagateUnlimitFromFlippedJoin();\n }\n }\n }\n\n estimateCost(\n downstreamChildSelectivity: number,\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n // FanIn always sums costs of its inputs\n // But it needs to pass the correct branch pattern to each input\n let totalCost: CostEstimate = {\n returnedRows: 0,\n cost: 0,\n scanEst: 0,\n startupCost: 0,\n selectivity: 0,\n limit: undefined,\n };\n\n if (this.#type === 'FI') {\n // Normal FanIn: all inputs get the same branch pattern with 0 prepended\n const updatedPattern = [0, ...branchPattern];\n let maxrows = 0;\n let maxRunningCost = 0;\n let maxStartupCost = 0;\n let maxScanEst = 0;\n\n let noMatchProb = 1.0;\n for (const input of this.#inputs) {\n const cost = input.estimateCost(\n downstreamChildSelectivity,\n updatedPattern,\n planDebugger,\n );\n if (cost.returnedRows > maxrows) {\n maxrows = cost.returnedRows;\n }\n if (cost.cost > maxRunningCost) {\n maxRunningCost = cost.cost;\n }\n if (cost.startupCost > maxStartupCost) {\n maxStartupCost = cost.startupCost;\n }\n if (cost.scanEst > maxScanEst) {\n maxScanEst = cost.scanEst;\n }\n\n // OR branches: combine selectivities assuming independent events\n // P(A OR B) = 1 - (1-A)(1-B)\n // Track probability of NO match in any branch\n noMatchProb *= 1 - cost.selectivity;\n\n // all inputs should have the same limit.\n assert(\n totalCost.limit === undefined || cost.limit === totalCost.limit,\n 'All FanIn inputs should have the same limit',\n );\n totalCost.limit = cost.limit;\n }\n\n totalCost.returnedRows = maxrows;\n totalCost.cost = maxRunningCost;\n totalCost.selectivity = 1 - noMatchProb;\n totalCost.startupCost = maxStartupCost;\n totalCost.scanEst = maxScanEst;\n } else {\n // Union FanIn (UFI): each input gets unique branch pattern\n let i = 0;\n\n let noMatchProb = 1.0;\n for (const input of this.#inputs) {\n const updatedPattern = [i, ...branchPattern];\n const cost = input.estimateCost(\n downstreamChildSelectivity,\n updatedPattern,\n planDebugger,\n );\n totalCost.returnedRows += cost.returnedRows;\n totalCost.cost += cost.cost;\n totalCost.scanEst += cost.scanEst;\n totalCost.startupCost = totalCost.startupCost + cost.startupCost;\n\n // OR branches: combine selectivities assuming independent events\n // P(A OR B) = 1 - (1-A)(1-B)\n // Track probability of NO match in any branch\n noMatchProb *= 1 - cost.selectivity;\n\n // all inputs should have the same limit.\n assert(\n totalCost.limit === undefined || cost.limit === totalCost.limit,\n 'All FanIn inputs should have the same limit',\n );\n totalCost.limit = cost.limit;\n i++;\n }\n totalCost.selectivity = 1 - noMatchProb;\n }\n\n planDebugger?.log({\n type: 'node-cost',\n nodeType: 'fan-in',\n node: this.#type,\n branchPattern,\n downstreamChildSelectivity,\n costEstimate: totalCost,\n });\n\n return totalCost;\n }\n\n propagateConstraints(\n branchPattern: number[],\n constraint: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'fan-in',\n node: this.#type,\n branchPattern,\n constraint,\n from: from?.kind ?? 'unknown',\n });\n\n if (this.#type === 'FI') {\n const updatedPattern = [0, ...branchPattern];\n /**\n * All inputs get the same branch pattern.\n * 1. They cannot contribute differing constraints to their parent inputs because they are not flipped.\n * If they were flipped this would be of type UFI.\n * 2. All inputs need to be called because they could be pinned. If they are pinned they could have constraints\n * to send to their children.\n */\n for (const input of this.#inputs) {\n input.propagateConstraints(\n updatedPattern,\n constraint,\n this,\n planDebugger,\n );\n }\n return;\n }\n\n let i = 0;\n for (const input of this.#inputs) {\n input.propagateConstraints(\n [i, ...branchPattern],\n constraint,\n this,\n planDebugger,\n );\n i++;\n }\n }\n}\n", "import type {PlannerConstraint} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\nexport class PlannerFanOut {\n readonly kind = 'fan-out' as const;\n #type: 'FO' | 'UFO';\n readonly #outputs: PlannerNode[] = [];\n readonly #input: Exclude<PlannerNode, PlannerTerminus>;\n\n constructor(input: Exclude<PlannerNode, PlannerTerminus>) {\n this.#type = 'FO';\n this.#input = input;\n }\n\n get type() {\n return this.#type;\n }\n\n addOutput(node: PlannerNode): void {\n this.#outputs.push(node);\n }\n\n get outputs(): PlannerNode[] {\n return this.#outputs;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return this.#input.closestJoinOrSource();\n }\n\n propagateConstraints(\n branchPattern: number[],\n constraint: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'fan-out',\n node: 'FO',\n branchPattern,\n constraint,\n from: from?.kind ?? 'unknown',\n });\n\n this.#input.propagateConstraints(\n branchPattern,\n constraint,\n this,\n planDebugger,\n );\n }\n\n estimateCost(\n downstreamChildSelectivity: number,\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n const ret = this.#input.estimateCost(\n downstreamChildSelectivity,\n branchPattern,\n planDebugger,\n );\n\n planDebugger?.log({\n type: 'node-cost',\n nodeType: 'fan-out',\n node: 'FO',\n branchPattern,\n downstreamChildSelectivity,\n costEstimate: ret,\n });\n\n return ret;\n }\n\n convertToUFO(): void {\n this.#type = 'UFO';\n }\n\n reset(): void {\n this.#type = 'FO';\n }\n\n /**\n * Propagate unlimiting when a parent join is flipped.\n * Fan-out propagates to its input.\n */\n propagateUnlimitFromFlippedJoin(): void {\n if (\n 'propagateUnlimitFromFlippedJoin' in this.#input &&\n typeof this.#input.propagateUnlimitFromFlippedJoin === 'function'\n ) {\n (\n this.#input as {propagateUnlimitFromFlippedJoin(): void}\n ).propagateUnlimitFromFlippedJoin();\n }\n }\n}\n", "/**\n * We do not know the value a constraint will take until runtime.\n *\n * However, we do know the column.\n *\n * E.g., we know that `issue.assignee_id` will be constrained to typeof issue.assignee_id.\n */\nexport type PlannerConstraint = Record<string, undefined>;\n\n/**\n * Multiple flipped joins will contribute extra constraints to a parent join.\n * These need to be merged.\n */\nexport function mergeConstraints(\n a: PlannerConstraint | undefined,\n b: PlannerConstraint | undefined,\n): PlannerConstraint | undefined {\n if (!a) return b;\n if (!b) return a;\n return {...a, ...b};\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport type {Condition, Ordering} from '../../../zero-protocol/src/ast.ts';\nimport {\n mergeConstraints,\n type PlannerConstraint,\n} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\n\n/**\n * Represents a connection to a source (table scan).\n *\n * # Dual State Pattern\n * Like all planner nodes, PlannerConnection separates:\n * 1. immutable structure: Ordering, filters, cost model (set at construction)\n * 2. mutable state: Pinned status, constraints (mutated during planning)\n *\n * # Cost Estimation\n * The ordering and filters determine the initial cost. As planning progresses,\n * constraints from parent joins refine the cost estimate.\n *\n * # Constraint Flow\n * When a connection is pinned as the outer loop, it reveals constraints for\n * connected joins. These constraints propagate through the graph, allowing\n * other connections to update their cost estimates.\n *\n * Example:\n *\n * ```ts\n * builder.issue.whereExists('assignee', a => a.where('name', 'Alice'))\n * ```\n *\n * ```\n * [issue] [assignee]\n * | |\n * | +-- where name = 'Alice'\n * \\ /\n * \\ /\n * [join]\n * |\n * ```\n *\n * - Initial state: Both connections have no constraints, costs are unconstrained\n * - If `issue` chosen first: Reveals constraint `assignee_id` for assignee connection\n * - If `assignee` chosen first: Reveals constraint `assignee_id` for issue connection\n * - Updated costs guide the next selection\n *\n * # Lifecycle\n * 1. Construct with immutable structure (ordering, filters, cost model)\n * 2. Wire to output node during graph construction\n * 3. Planning mutates pinned status and accumulates constraints\n * 4. reset() clears mutable state for replanning\n */\nexport class PlannerConnection {\n readonly kind = 'connection' as const;\n\n // ========================================================================\n // IMMUTABLE STRUCTURE (set during construction, never changes)\n // ========================================================================\n readonly #sort: Ordering;\n readonly #filters: Condition | undefined;\n readonly #model: ConnectionCostModel;\n readonly table: string;\n readonly name: string; // Human-readable name for debugging (defaults to table name)\n readonly #baseConstraints: PlannerConstraint | undefined; // Constraints from parent correlation\n readonly #baseLimit: number | undefined; // Original limit from query structure (never modified)\n readonly selectivity: number; // Fraction of rows passing filters (1.0 = no filtering)\n #output?: PlannerNode | undefined; // Set once during graph construction\n\n // ========================================================================\n // MUTABLE PLANNING STATE (changes during plan search)\n // ========================================================================\n /**\n * Current limit during planning. Can be cleared (set to undefined) when a\n * parent join is flipped, indicating this connection is now in an outer loop\n * and should not be limited by EXISTS semantics.\n */\n limit: number | undefined;\n\n /**\n * Constraints accumulated from parent joins during planning.\n * Key is a path through the graph (e.g., \"0,1\" for branch pattern [0,1]).\n *\n * Undefined constraints are possible when a FO converts to UFO and only\n * a single join in the UFO is flipped - other branches report undefined.\n */\n readonly #constraints: Map<string, PlannerConstraint | undefined>;\n\n readonly #isRoot: boolean;\n\n /**\n * Cached per-constraint costs to avoid redundant cost model calls.\n * Maps constraint key (branch pattern string) to computed cost.\n * Invalidated when constraints change.\n */\n #cachedConstraintCosts: Map<string, CostEstimate> = new Map();\n\n constructor(\n table: string,\n model: ConnectionCostModel,\n sort: Ordering,\n filters: Condition | undefined,\n isRoot: boolean,\n baseConstraints?: PlannerConstraint,\n limit?: number,\n name?: string,\n ) {\n this.table = table;\n this.name = name ?? table;\n this.#sort = sort;\n this.#filters = filters;\n this.#model = model;\n this.#baseConstraints = baseConstraints;\n this.#baseLimit = limit;\n this.limit = limit;\n this.#constraints = new Map();\n this.#isRoot = isRoot;\n\n // Compute selectivity for EXISTS child connections (baseLimit === 1)\n // Selectivity = fraction of rows that pass filters\n if (limit !== undefined && filters) {\n const costWithFilters = model(table, sort, filters, undefined);\n const costWithoutFilters = model(table, sort, undefined, undefined);\n this.selectivity =\n costWithoutFilters.rows > 0\n ? costWithFilters.rows / costWithoutFilters.rows\n : 1.0;\n } else {\n // Root connections or connections without filters\n this.selectivity = 1.0;\n }\n }\n\n setOutput(node: PlannerNode): void {\n this.#output = node;\n }\n\n get output(): PlannerNode {\n assert(this.#output !== undefined, 'Output not set');\n return this.#output;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return 'connection';\n }\n\n /**\n * Constraints are uniquely identified by their path through the\n * graph.\n *\n * FO represents all sub-joins as a single path.\n * UFO represents each sub-join as a separate path.\n * The first branch in a UFO will match the path of FO so no re-set needs to happen\n * when swapping from FO to UFO.\n *\n * FO swaps to UFO when a join inside FO-FI gets flipped.\n *\n * The max of the last element of the paths is the number of\n * root branches.\n */\n propagateConstraints(\n path: number[],\n c: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n const key = path.join(',');\n this.#constraints.set(key, c);\n // Constraints changed, invalidate cost caches\n this.#cachedConstraintCosts.clear();\n\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'connection',\n node: this.name,\n branchPattern: path,\n constraint: c,\n from: from?.kind ?? 'unknown',\n });\n }\n\n estimateCost(\n downstreamChildSelectivity: number,\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n // Branch pattern specified - return cost for this specific branch\n const key = branchPattern.join(',');\n\n // Check per-constraint cache first\n let cost = this.#cachedConstraintCosts.get(key);\n if (cost !== undefined) {\n return cost;\n }\n\n // Cache miss - compute and cache\n const constraint = this.#constraints.get(key);\n // Merge base constraints with propagated constraints\n const mergedConstraint = mergeConstraints(\n this.#baseConstraints,\n constraint,\n );\n const {startupCost, rows} = this.#model(\n this.table,\n this.#sort,\n this.#filters,\n mergedConstraint,\n );\n cost = {\n startupCost,\n scanEst:\n this.limit === undefined\n ? rows\n : Math.min(rows, this.limit / downstreamChildSelectivity),\n cost: 0,\n returnedRows: rows,\n selectivity: this.selectivity,\n limit: this.limit,\n };\n this.#cachedConstraintCosts.set(key, cost);\n\n planDebugger?.log({\n type: 'node-cost',\n nodeType: 'connection',\n node: this.name,\n branchPattern,\n downstreamChildSelectivity,\n costEstimate: cost,\n filters: this.#filters,\n });\n\n return cost;\n }\n\n /**\n * Remove the limit from this connection.\n * Called when a parent join is flipped, making this connection part of an\n * outer loop that should produce all rows rather than stopping at the limit.\n */\n unlimit(): void {\n if (this.#isRoot) {\n // We cannot unlimit root connections\n return;\n }\n if (this.limit !== undefined) {\n this.limit = undefined;\n // Limit changes do not impact connection costs.\n // Limit is taken into account at the join level.\n // Given that, we do not need to invalidate cost caches here.\n }\n }\n\n /**\n * Propagate unlimiting when a parent join is flipped.\n * For connections, we simply remove the limit.\n */\n propagateUnlimitFromFlippedJoin(): void {\n this.unlimit();\n }\n\n reset() {\n this.#constraints.clear();\n this.limit = this.#baseLimit;\n // Clear all cost caches\n this.#cachedConstraintCosts.clear();\n }\n\n /**\n * Capture constraint state for snapshotting.\n * Used by PlannerGraph to save/restore planning state.\n */\n captureConstraints(): Map<string, PlannerConstraint | undefined> {\n return new Map(this.#constraints);\n }\n\n /**\n * Restore constraint state from a snapshot.\n * Used by PlannerGraph to restore planning state.\n */\n restoreConstraints(\n constraints: Map<string, PlannerConstraint | undefined>,\n ): void {\n this.#constraints.clear();\n for (const [key, value] of constraints) {\n this.#constraints.set(key, value);\n }\n // Constraints changed, invalidate cost caches\n this.#cachedConstraintCosts.clear();\n }\n\n /**\n * Get current constraints for debugging.\n * Returns a copy of the constraints map.\n */\n getConstraintsForDebug(): Map<string, PlannerConstraint | undefined> {\n return new Map(this.#constraints);\n }\n\n /**\n * Get filters for debugging.\n * Returns the filters applied to this connection.\n */\n getFiltersForDebug(): Condition | undefined {\n return this.#filters;\n }\n\n /**\n * Get estimated cost for each constraint branch.\n * Returns a map of constraint key to cost estimate.\n * Forces cost calculation if not already cached.\n */\n getConstraintCostsForDebug(): Map<string, CostEstimate> {\n // Return copy of cached costs\n return new Map(this.#cachedConstraintCosts);\n }\n}\n\nexport type CostModelCost = {\n startupCost: number;\n rows: number;\n};\nexport type ConnectionCostModel = (\n table: string,\n sort: Ordering,\n filters: Condition | undefined,\n constraint: PlannerConstraint | undefined,\n) => CostModelCost;\n", "import type {Condition, Ordering} from '../../../zero-protocol/src/ast.ts';\nimport {\n PlannerConnection,\n type ConnectionCostModel,\n} from './planner-connection.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\n\nexport type {ConnectionCostModel};\n\nexport class PlannerSource {\n readonly name: string;\n readonly #model: ConnectionCostModel;\n\n constructor(name: string, model: ConnectionCostModel) {\n this.name = name;\n this.#model = model;\n }\n\n connect(\n sort: Ordering,\n filters: Condition | undefined,\n isRoot: boolean,\n baseConstraints?: PlannerConstraint,\n limit?: number,\n ): PlannerConnection {\n return new PlannerConnection(\n this.name,\n this.#model,\n sort,\n filters,\n isRoot,\n baseConstraints,\n limit,\n );\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport type {PlannerJoin} from './planner-join.ts';\nimport type {PlannerFanOut} from './planner-fan-out.ts';\nimport type {PlannerFanIn} from './planner-fan-in.ts';\nimport type {PlannerConnection} from './planner-connection.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\nimport type {PlannerNode} from './planner-node.ts';\nimport {PlannerSource, type ConnectionCostModel} from './planner-source.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\n\n/**\n * Captured state of a plan for comparison and restoration.\n */\ntype PlanState = {\n connections: Array<{limit: number | undefined}>;\n joins: Array<{type: 'semi' | 'flipped'}>;\n fanOuts: Array<{type: 'FO' | 'UFO'}>;\n fanIns: Array<{type: 'FI' | 'UFI'}>;\n connectionConstraints: Array<Map<string, PlannerConstraint | undefined>>;\n};\n\n/**\n * Maximum number of flippable joins to attempt exhaustive enumeration.\n * With n flippable joins, we explore 2^n plans.\n * 10 joins = 1024 plans (~100-200ms), 12 joins = 4096 plans (~400ms - 1 second)\n */\nconst MAX_FLIPPABLE_JOINS = 13;\n\n/**\n * Cached information about FanOut\u2192FanIn relationships.\n * Computed once during planning to avoid redundant BFS traversals.\n */\ntype FOFIInfo = {\n fi: PlannerFanIn | undefined;\n joinsBetween: PlannerJoin[];\n};\n\nexport class PlannerGraph {\n // Sources indexed by table name\n readonly #sources = new Map<string, PlannerSource>();\n\n // The final output node where constraint propagation starts\n #terminus: PlannerTerminus | undefined = undefined;\n\n // Collections of nodes with mutable planning state\n joins: PlannerJoin[] = [];\n fanOuts: PlannerFanOut[] = [];\n fanIns: PlannerFanIn[] = [];\n connections: PlannerConnection[] = [];\n\n /**\n * Reset all planning state back to initial values for another planning pass.\n * Resets only mutable planning state - graph structure is unchanged.\n *\n * This allows replanning the same query graph with different strategies.\n */\n resetPlanningState() {\n for (const j of this.joins) j.reset();\n for (const fo of this.fanOuts) fo.reset();\n for (const fi of this.fanIns) fi.reset();\n for (const c of this.connections) c.reset();\n }\n\n /**\n * Create and register a source (table) in the graph.\n */\n addSource(name: string, model: ConnectionCostModel): PlannerSource {\n assert(\n !this.#sources.has(name),\n `Source ${name} already exists in the graph`,\n );\n const source = new PlannerSource(name, model);\n this.#sources.set(name, source);\n return source;\n }\n\n /**\n * Get a source by table name.\n */\n getSource(name: string): PlannerSource {\n const source = this.#sources.get(name);\n assert(source !== undefined, `Source ${name} not found in the graph`);\n return source;\n }\n\n /**\n * Check if a source exists by table name.\n */\n hasSource(name: string): boolean {\n return this.#sources.has(name);\n }\n\n /**\n * Set the terminus (final output) node of the graph.\n * Constraint propagation starts from this node.\n */\n setTerminus(terminus: PlannerTerminus): void {\n this.#terminus = terminus;\n }\n\n /**\n * Initiate constraint propagation from the terminus node.\n * This sends constraints up through the graph to update\n * connection cost estimates.\n */\n propagateConstraints(planDebugger?: PlanDebugger): void {\n assert(\n this.#terminus !== undefined,\n 'Cannot propagate constraints without a terminus node',\n );\n this.#terminus.propagateConstraints(planDebugger);\n }\n\n /**\n * Calculate total cost of the current plan.\n * Total cost includes both startup cost (one-time, e.g., sorting) and running cost.\n */\n getTotalCost(planDebugger?: PlanDebugger): number {\n const estimate = must(this.#terminus).estimateCost(planDebugger);\n return estimate.cost + estimate.startupCost;\n }\n\n /**\n * Capture a lightweight snapshot of the current planning state.\n * Used for backtracking during multi-start greedy search.\n *\n * Captures mutable state including pinned flags, join types, and\n * constraint maps to avoid needing repropagation on restore.\n *\n * @returns A snapshot that can be restored via restorePlanningSnapshot()\n */\n capturePlanningSnapshot(): PlanState {\n return {\n connections: this.connections.map(c => ({\n limit: c.limit,\n })),\n joins: this.joins.map(j => ({type: j.type})),\n fanOuts: this.fanOuts.map(fo => ({type: fo.type})),\n fanIns: this.fanIns.map(fi => ({type: fi.type})),\n connectionConstraints: this.connections.map(c => c.captureConstraints()),\n };\n }\n\n /**\n * Restore planning state from a previously captured snapshot.\n * Used for backtracking when a planning attempt fails.\n *\n * Restores pinned flags, join types, and constraint maps, eliminating\n * the need for repropagation.\n *\n * @param state - Snapshot created by capturePlanningSnapshot()\n */\n restorePlanningSnapshot(state: PlanState): void {\n this.#validateSnapshotShape(state);\n this.#restoreConnections(state);\n this.#restoreJoins(state);\n this.#restoreFanNodes(state);\n }\n\n /**\n * Validate that snapshot shape matches current graph structure.\n */\n #validateSnapshotShape(state: PlanState): void {\n assert(\n this.connections.length === state.connections.length,\n 'Plan state mismatch: connections',\n );\n assert(\n this.joins.length === state.joins.length,\n 'Plan state mismatch: joins',\n );\n assert(\n this.fanOuts.length === state.fanOuts.length,\n 'Plan state mismatch: fanOuts',\n );\n assert(\n this.fanIns.length === state.fanIns.length,\n 'Plan state mismatch: fanIns',\n );\n assert(\n this.connections.length === state.connectionConstraints.length,\n 'Plan state mismatch: connectionConstraints',\n );\n }\n\n /**\n * Restore connection pinned flags, limits, and constraint maps.\n */\n #restoreConnections(state: PlanState): void {\n for (let i = 0; i < this.connections.length; i++) {\n this.connections[i].limit = state.connections[i].limit;\n this.connections[i].restoreConstraints(state.connectionConstraints[i]);\n }\n }\n\n /**\n * Restore join types and pinned flags.\n */\n #restoreJoins(state: PlanState): void {\n for (let i = 0; i < this.joins.length; i++) {\n const join = this.joins[i];\n const targetState = state.joins[i];\n\n // Reset to initial state first\n join.reset();\n\n // Apply target state\n if (targetState.type === 'flipped') {\n join.flip();\n }\n }\n }\n\n /**\n * Restore FanOut and FanIn types.\n */\n #restoreFanNodes(state: PlanState): void {\n for (let i = 0; i < this.fanOuts.length; i++) {\n const fo = this.fanOuts[i];\n const targetType = state.fanOuts[i].type;\n if (targetType === 'UFO' && fo.type === 'FO') {\n fo.convertToUFO();\n }\n }\n\n for (let i = 0; i < this.fanIns.length; i++) {\n const fi = this.fanIns[i];\n const targetType = state.fanIns[i].type;\n if (targetType === 'UFI' && fi.type === 'FI') {\n fi.convertToUFI();\n }\n }\n }\n\n /**\n * Main planning algorithm using exhaustive join flip enumeration.\n *\n * Enumerates all possible flip patterns for flippable joins (2^n for n flippable joins).\n * Each pattern represents a different query execution plan. We evaluate the cost of each\n * plan and select the one with the lowest cost.\n *\n * Connections are used only for cost estimation - the flip patterns determine the plan.\n * FanOut/FanIn states (FO/UFO and FI/UFI) are automatically derived from join flip states.\n *\n * @param planDebugger - Optional debugger to receive structured events during planning\n */\n plan(planDebugger?: PlanDebugger): void {\n // Get all flippable joins\n const flippableJoins = this.joins.filter(j => j.isFlippable());\n\n // Safety check: throw if too many flippable joins\n if (flippableJoins.length > MAX_FLIPPABLE_JOINS) {\n throw new Error(\n `Query has ${flippableJoins.length} EXISTS checks in a single RELATED call (or in the top level query), which would require ` +\n `${2 ** flippableJoins.length} plan evaluations. This may be very slow. ` +\n `Consider simplifying the query or increasing MAX_FLIPPABLE_JOINS (currently set to ${MAX_FLIPPABLE_JOINS}).`,\n );\n }\n\n // Build FO\u2192FI cache once to avoid redundant BFS traversals in each iteration\n const fofiCache = buildFOFICache(this);\n\n const numPatterns = 2 ** flippableJoins.length;\n let bestCost = Infinity;\n let bestPlan: PlanState | undefined = undefined;\n let bestAttemptNumber = -1;\n\n // Enumerate all flip patterns\n // try 7 and 32 (6 and 31)\n const forcePattern = undefined; // 11 14\n for (let pattern = 0; pattern < numPatterns; pattern++) {\n if (forcePattern !== undefined && pattern !== forcePattern) {\n continue;\n }\n // Reset to initial state\n this.resetPlanningState();\n\n if (planDebugger) {\n planDebugger.log({\n type: 'attempt-start',\n attemptNumber: pattern,\n totalAttempts: numPatterns,\n });\n }\n\n try {\n // Apply flip pattern (treat pattern as bitmask)\n // Bit i set to 1 means flip join i\n for (let i = 0; i < flippableJoins.length; i++) {\n if (pattern & (1 << i)) {\n flippableJoins[i].flip();\n }\n }\n\n // Derive FO/UFO and FI/UFI states from join flip states\n checkAndConvertFOFI(fofiCache);\n\n // Propagate unlimiting for flipped joins\n propagateUnlimitForFlippedJoins(this);\n\n // Propagate constraints through the graph\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'constraints-propagated',\n attemptNumber: pattern,\n connectionConstraints: this.connections.map(c => ({\n connection: c.name,\n constraints: c.getConstraintsForDebug(),\n constraintCosts: c.getConstraintCostsForDebug(),\n })),\n });\n }\n\n // Evaluate this plan\n const totalCost = this.getTotalCost(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'plan-complete',\n attemptNumber: pattern,\n totalCost,\n flipPattern: pattern, // Bitmask of which joins are flipped\n // TODO: we'll need a different way to collect these\n // nodeCosts: this.#collectNodeCosts(),\n joinStates: this.joins.map(j => {\n const info = j.getDebugInfo();\n return {\n join: info.name,\n type: info.type,\n };\n }),\n });\n }\n\n // Track best plan\n if (totalCost < bestCost) {\n bestCost = totalCost;\n bestPlan = this.capturePlanningSnapshot();\n bestAttemptNumber = pattern;\n }\n } catch (e) {\n // This flip pattern is invalid (shouldn't happen with proper isFlippable() checks)\n if (planDebugger) {\n planDebugger.log({\n type: 'plan-failed',\n attemptNumber: pattern,\n reason: `Flip pattern ${pattern.toString(2)} failed: ${e instanceof Error ? e.message : String(e)}`,\n });\n }\n continue;\n }\n }\n\n // Restore best plan\n if (bestPlan) {\n this.restorePlanningSnapshot(bestPlan);\n // Propagate constraints to ensure all derived state is consistent\n this.propagateConstraints(planDebugger);\n\n if (planDebugger) {\n planDebugger.log({\n type: 'best-plan-selected',\n bestAttemptNumber,\n totalCost: bestCost,\n flipPattern: bestAttemptNumber, // The best attempt number is also the flip pattern\n joinStates: this.joins.map(j => ({\n join: j.getName(),\n type: j.type,\n })),\n });\n }\n } else {\n // No valid plan found (all patterns failed)\n throw new Error(\n 'No valid query plan found. This should not happen - check query structure.',\n );\n }\n }\n}\n\n/**\n * Build cache of FO\u2192FI relationships and joins between them.\n * Called once at the start of planning to avoid redundant BFS traversals.\n */\nfunction buildFOFICache(graph: PlannerGraph): Map<PlannerFanOut, FOFIInfo> {\n const cache = new Map<PlannerFanOut, FOFIInfo>();\n\n for (const fo of graph.fanOuts) {\n const info = findFIAndJoins(fo);\n cache.set(fo, info);\n }\n\n return cache;\n}\n\n/**\n * Check if any joins downstream of a FanOut (before reaching FanIn) are flipped.\n * If so, convert the FO to UFO and the FI to UFI.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction checkAndConvertFOFI(fofiCache: Map<PlannerFanOut, FOFIInfo>): void {\n for (const [fo, info] of fofiCache) {\n const hasFlippedJoin = info.joinsBetween.some(j => j.type === 'flipped');\n if (info.fi && hasFlippedJoin) {\n fo.convertToUFO();\n info.fi.convertToUFI();\n }\n }\n}\n\n/**\n * Traverse from a FanOut through its outputs to find the corresponding FanIn\n * and collect all joins along the way.\n */\nfunction findFIAndJoins(fo: PlannerFanOut): FOFIInfo {\n const joinsBetween: PlannerJoin[] = [];\n let fi: PlannerFanIn | undefined = undefined;\n\n // BFS through FO outputs to find FI and collect joins\n const queue: PlannerNode[] = [...fo.outputs];\n const visited = new Set<PlannerNode>();\n\n while (queue.length > 0) {\n const node = must(queue.shift());\n if (visited.has(node)) continue;\n visited.add(node);\n\n switch (node.kind) {\n case 'join':\n joinsBetween.push(node);\n queue.push(node.output);\n break;\n case 'fan-out':\n // Nested FO - traverse its outputs\n queue.push(...node.outputs);\n break;\n case 'fan-in':\n // Found the FI - this is the boundary, don't traverse further\n fi = node;\n break;\n case 'connection':\n // Shouldn't happen in a well-formed graph\n break;\n case 'terminus':\n // Reached the end without finding FI\n break;\n }\n }\n\n return {fi, joinsBetween};\n}\n\n/**\n * Propagate unlimiting to all flipped joins in the graph.\n * When a join is flipped, its child becomes the outer loop and should no longer\n * be limited by EXISTS semantics.\n *\n * This must be called after join flipping and before propagateConstraints.\n */\nfunction propagateUnlimitForFlippedJoins(graph: PlannerGraph): void {\n for (const join of graph.joins) {\n if (join.type === 'flipped') {\n join.propagateUnlimit();\n }\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {\n mergeConstraints,\n type PlannerConstraint,\n} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\nimport type {PlannerTerminus} from './planner-terminus.ts';\n\n/**\n * Translate constraints for a flipped join from parent space to child space.\n * Matches the runtime behavior of FlippedJoin.fetch() which translates\n * parent constraints to child constraints using index-based key mapping.\n *\n * Example:\n * parentConstraint = {issueID: undefined, projectID: undefined}\n * childConstraint = {id: undefined, projectID: undefined}\n * incomingConstraint = {issueID: 5}\n * result = {id: 5} // issueID at index 0 maps to id at index 0\n */\nfunction translateConstraintsForFlippedJoin(\n incomingConstraint: PlannerConstraint | undefined,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n): PlannerConstraint | undefined {\n if (!incomingConstraint) return undefined;\n\n const parentKeys = Object.keys(parentConstraint);\n const childKeys = Object.keys(childConstraint);\n const translated: PlannerConstraint = {};\n\n for (const [key, value] of Object.entries(incomingConstraint)) {\n const index = parentKeys.indexOf(key);\n if (index !== -1) {\n // Found this key in parent at position `index`\n // Map to child key at same position\n translated[childKeys[index]] = value;\n }\n }\n\n return Object.keys(translated).length > 0 ? translated : undefined;\n}\n\n/**\n * Semi-join overhead multiplier.\n *\n * Semi-joins represent correlated subqueries (EXISTS checks) which have\n * execution overhead compared to flipped joins, even when logical row counts\n * are identical. This overhead comes from:\n * - Need to execute a separate correlation check for each parent row\n * - Cannot leverage combined constraint checking as effectively as flipped joins\n *\n * A multiplier of 1.5 means semi-joins are estimated to be ~50% more expensive\n * than equivalent flipped joins, which empirically matches observed performance\n * differences in production workloads (e.g., 1.7x in zbugs benchmarks).\n *\n * Flipped joins have a different overhead in that they become unlimited. This\n * is accounted for when propagating unlimits rather than here.\n */\n// const SEMI_JOIN_OVERHEAD_MULTIPLIER = 1.5;\n\n/**\n * Represents a join between two data streams (parent and child).\n *\n * # Dual-State Pattern\n * Like all planner nodes, PlannerJoin separates:\n * 1. IMMUTABLE STRUCTURE: Parent/child nodes, constraints, flippability\n * 2. MUTABLE STATE: Join type (semi/flipped), pinned status\n *\n * # Join Flipping\n * A join can be in two states:\n * - 'semi': Parent is outer loop, child is inner (semi-join for EXISTS)\n * - 'flipped': Child is outer loop, parent is inner\n *\n * Flipping is the key optimization: choosing which table scans first.\n * NOT EXISTS joins cannot be flipped (#flippable = false).\n *\n * # Constraint Propagation\n * - Semi-join: Sends childConstraint to child, forwards received constraints to parent\n * - Flipped join: Sends undefined to child, merges parentConstraint with received to parent\n * - Unpinned join: Only forwards constraints to parent (doesn't constrain child yet)\n *\n * # Lifecycle\n * 1. Construct with immutable structure (parent, child, constraints, flippability)\n * 2. Wire to output node during graph construction\n * 3. Planning calls flipIfNeeded() based on connection selection order\n * 4. pin() locks the join type once chosen\n * 5. reset() clears mutable state (type \u2192 'semi', pinned \u2192 false)\n */\nexport class PlannerJoin {\n readonly kind = 'join' as const;\n\n readonly #parent: Exclude<PlannerNode, PlannerTerminus>;\n readonly #child: Exclude<PlannerNode, PlannerTerminus>;\n readonly #parentConstraint: PlannerConstraint;\n readonly #childConstraint: PlannerConstraint;\n readonly #flippable: boolean;\n readonly planId: number;\n #output?: PlannerNode | undefined; // Set once during graph construction\n\n // Reset between planning attempts\n #type: 'semi' | 'flipped';\n\n constructor(\n parent: Exclude<PlannerNode, PlannerTerminus>,\n child: Exclude<PlannerNode, PlannerTerminus>,\n parentConstraint: PlannerConstraint,\n childConstraint: PlannerConstraint,\n flippable: boolean,\n planId: number,\n ) {\n this.#type = 'semi';\n this.#parent = parent;\n this.#child = child;\n this.#childConstraint = childConstraint;\n this.#parentConstraint = parentConstraint;\n this.#flippable = flippable;\n this.planId = planId;\n }\n\n setOutput(node: PlannerNode): void {\n this.#output = node;\n }\n\n get output(): PlannerNode {\n assert(this.#output !== undefined, 'Output not set');\n return this.#output;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return 'join';\n }\n\n flipIfNeeded(input: PlannerNode): void {\n if (input === this.#child) {\n this.flip();\n } else {\n assert(\n input === this.#parent,\n 'Can only flip a join from one of its inputs',\n );\n }\n }\n\n flip(): void {\n assert(this.#type === 'semi', 'Can only flip a semi-join');\n if (!this.#flippable) {\n throw new UnflippableJoinError(\n 'Cannot flip a non-flippable join (e.g., NOT EXISTS)',\n );\n }\n this.#type = 'flipped';\n }\n\n get type(): 'semi' | 'flipped' {\n return this.#type;\n }\n isFlippable(): boolean {\n return this.#flippable;\n }\n\n /**\n * Propagate unlimiting when this join is flipped.\n * When a join is flipped:\n * 1. Child becomes outer loop \u2192 produces all rows (unlimited)\n * 2. Parent is fetched once per child row \u2192 effectively unlimited\n *\n * Example: If child produces 896 rows, parent is fetched 896 times.\n * Even if each fetch returns 1 row, parent produces 896 total rows.\n *\n * Propagation rules:\n * - Connection: call unlimit()\n * - Semi-join: continue to parent (outer loop)\n * - Flipped join: stop (already unlimited when it was flipped)\n * - Fan-out/Fan-in: propagate to all inputs\n */\n propagateUnlimit(): void {\n assert(this.#type === 'flipped', 'Can only unlimit a flipped join');\n this.#parent.propagateUnlimitFromFlippedJoin();\n this.#child.propagateUnlimitFromFlippedJoin(); // Up the child chain\n }\n\n /**\n * Called when a parent join is flipped and this join is part of its child subgraph.\n * - Semi-join: continue propagation to parent (the outer loop)\n * - Flipped join: stop propagation (already unlimited when it was flipped)\n */\n propagateUnlimitFromFlippedJoin(): void {\n if (this.#type === 'semi') {\n this.#parent.propagateUnlimitFromFlippedJoin();\n }\n // For flipped joins, stop propagation\n }\n\n propagateConstraints(\n branchPattern: number[],\n constraint: PlannerConstraint | undefined,\n from?: PlannerNode,\n planDebugger?: PlanDebugger,\n ): void {\n planDebugger?.log({\n type: 'node-constraint',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n constraint,\n from: from ? getNodeName(from) : 'unknown',\n });\n\n if (this.#type === 'semi') {\n // A semi-join always has constraints for its child.\n // They are defined by the correlation between parent and child.\n this.#child.propagateConstraints(\n branchPattern,\n this.#childConstraint,\n this,\n planDebugger,\n );\n // A semi-join forwards constraints to its parent.\n this.#parent.propagateConstraints(\n branchPattern,\n constraint,\n this,\n planDebugger,\n );\n } else if (this.#type === 'flipped') {\n // A flipped join translates constraints from parent space to child space.\n // This matches FlippedJoin.fetch() runtime behavior where parent constraints\n // on join keys are translated to child constraints.\n // Example: If parent has {issueID: 5} and join maps issueID\u2192id,\n // child gets {id: 5} allowing index usage.\n const translatedConstraint = translateConstraintsForFlippedJoin(\n constraint,\n this.#parentConstraint,\n this.#childConstraint,\n );\n this.#child.propagateConstraints(\n branchPattern,\n translatedConstraint,\n this,\n planDebugger,\n );\n // A flipped join will have constraints to send to its parent.\n // - The constraints its output sent\n // - The constraints its child creates\n this.#parent.propagateConstraints(\n branchPattern,\n mergeConstraints(constraint, this.#parentConstraint),\n this,\n planDebugger,\n );\n }\n }\n\n reset(): void {\n this.#type = 'semi';\n }\n\n estimateCost(\n /**\n * This argument is to deal with consecutive `andExists` statements.\n * Each one will constrain how often a parent row passes all constraints.\n * This means that we have to scan more and more parent rows the more\n * constraints we add.\n */\n downstreamChildSelectivity: number,\n /**\n * branchPattern uniquely identifies OR branches in the graph.\n * Each path through an OR will have unique constraints to apply to the source\n * connection.\n * branchPattern allows us to correlate a path through the graph\n * to the constraints that should be applied for that path.\n *\n * Example graph:\n * UFO\n * / \\\n * J1 J2\n * \\ /\n * UFI\n *\n * J1 and J2 are joins inside an OR (FO).\n * branchPattern [0] = path through J1\n * branchPattern [1] = path through J2\n *\n * If many ORs are nested, branchPattern will have multiple elements\n * representing each level of OR.\n *\n * If no joins are flipped within the `OR`, then only a single\n * branchPattern element will be needed, as FO represents all sub-joins\n * as a single path.\n */\n branchPattern: number[],\n planDebugger?: PlanDebugger,\n ): CostEstimate {\n /**\n * downstreamChildSelectivity accumulates up a parent chain, not\n * up child chains. Child chains represent independent sub-graphs.\n * So we pass 1 for `downstreamChildSelectivity` when estimating child cost.\n * Put another way, downstreamChildSelectivity impacts how many parent\n * rows are returned.\n */\n const child = this.#child.estimateCost(1, branchPattern, planDebugger);\n /**\n * How selective is the graph from this point forward?\n * If we are _very_ selective then we must scan more parent rows\n * before finding a match.\n * E.g., if childSelectivity = 0.1 and downstreamChildSelectivity = 0.5\n * then we only pass 5% of parent rows (0.1 * 0.5 = 0.05).\n *\n * This is used to estimate how many rows will be pulled from the parent\n * when trying to satisfy downstream constraints and a limit.\n *\n * NOTE: We do not know if the probabilities are correlated so we assume independence.\n * This is a fundamental limitation of the planner.\n */\n const parent = this.#parent.estimateCost(\n // Selectivity flows up the graph from child to parent\n // so we can determine the total selectivity of all ANDed exists checks.\n child.selectivity * downstreamChildSelectivity,\n branchPattern,\n planDebugger,\n );\n\n let costEstimate: CostEstimate;\n\n if (this.type === 'semi') {\n costEstimate = {\n startupCost: parent.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows\n : Math.min(\n parent.returnedRows,\n parent.limit / downstreamChildSelectivity,\n ),\n cost:\n parent.cost + parent.scanEst * (child.startupCost + child.scanEst),\n returnedRows: parent.returnedRows * child.selectivity,\n selectivity: child.selectivity * parent.selectivity,\n limit: parent.limit,\n };\n } else {\n costEstimate = {\n startupCost: child.startupCost,\n scanEst:\n parent.limit === undefined\n ? parent.returnedRows\n : Math.min(\n parent.returnedRows * child.returnedRows,\n parent.limit / downstreamChildSelectivity,\n ),\n cost:\n child.cost + child.scanEst * (parent.startupCost + parent.scanEst),\n returnedRows:\n parent.returnedRows * child.returnedRows * child.selectivity,\n selectivity: parent.selectivity * child.selectivity,\n limit: parent.limit,\n };\n }\n\n planDebugger?.log({\n type: 'node-cost',\n nodeType: 'join',\n node: this.getName(),\n branchPattern,\n downstreamChildSelectivity,\n costEstimate,\n joinType: this.#type,\n });\n\n return costEstimate;\n }\n\n /**\n * Get a human-readable name for this join for debugging.\n * Format: \"parentName \u22C8 childName\"\n */\n getName(): string {\n const parentName = getNodeName(this.#parent);\n const childName = getNodeName(this.#child);\n return `${parentName} \u22C8 ${childName}`;\n }\n\n /**\n * Get debug information about this join's state.\n */\n getDebugInfo(): {\n name: string;\n type: 'semi' | 'flipped';\n planId: number;\n } {\n return {\n name: this.getName(),\n type: this.#type,\n planId: this.planId,\n };\n }\n}\n\nexport class UnflippableJoinError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UnflippableJoinError';\n }\n}\n\n/**\n * Get a human-readable name for any planner node.\n * Used for debugging and tracing.\n */\nfunction getNodeName(node: PlannerNode): string {\n switch (node.kind) {\n case 'connection':\n return node.name;\n case 'join':\n return node.getName();\n case 'fan-out':\n return 'FO';\n case 'fan-in':\n return 'FI';\n case 'terminus':\n return 'terminus';\n }\n}\n", "import type {PlanDebugger} from './planner-debug.ts';\nimport type {\n CostEstimate,\n JoinOrConnection,\n PlannerNode,\n} from './planner-node.ts';\n\nexport class PlannerTerminus {\n readonly kind = 'terminus' as const;\n readonly #input: Exclude<PlannerNode, PlannerTerminus>;\n\n constructor(input: Exclude<PlannerNode, PlannerTerminus>) {\n this.#input = input;\n }\n\n get pinned(): boolean {\n return true;\n }\n\n closestJoinOrSource(): JoinOrConnection {\n return this.#input.closestJoinOrSource();\n }\n\n propagateConstraints(planDebugger?: PlanDebugger): void {\n this.#input.propagateConstraints([], undefined, this, planDebugger);\n }\n\n estimateCost(planDebugger?: PlanDebugger): CostEstimate {\n // Terminus starts the cost estimation flow with empty branch pattern\n return this.#input.estimateCost(1, [], planDebugger);\n }\n\n /**\n * Propagate unlimiting when a parent join is flipped.\n * Terminus doesn't participate in unlimiting.\n */\n propagateUnlimitFromFlippedJoin(): void {\n // No-op: terminus doesn't need to unlimit anything\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {\n AST,\n Condition,\n Conjunction,\n CorrelatedSubqueryCondition,\n Disjunction,\n} from '../../../zero-protocol/src/ast.ts';\nimport {planIdSymbol} from '../../../zero-protocol/src/ast.ts';\nimport type {ConnectionCostModel} from './planner-connection.ts';\nimport type {PlannerConstraint} from './planner-constraint.ts';\nimport type {PlanDebugger} from './planner-debug.ts';\nimport {PlannerFanIn} from './planner-fan-in.ts';\nimport {PlannerFanOut} from './planner-fan-out.ts';\nimport {PlannerGraph} from './planner-graph.ts';\nimport {PlannerJoin} from './planner-join.ts';\nimport type {PlannerNode} from './planner-node.ts';\nimport {PlannerTerminus} from './planner-terminus.ts';\n\nfunction wireOutput(from: PlannerNode, to: PlannerNode): void {\n switch (from.kind) {\n case 'connection':\n case 'join':\n case 'fan-in':\n from.setOutput(to);\n break;\n case 'fan-out':\n from.addOutput(to);\n break;\n case 'terminus':\n assert(false, 'Terminus nodes cannot have outputs');\n }\n}\n\nexport type Plans = {\n plan: PlannerGraph;\n subPlans: {[key: string]: Plans};\n};\n\nexport function buildPlanGraph(\n ast: AST,\n model: ConnectionCostModel,\n isRoot: boolean,\n baseConstraints?: PlannerConstraint,\n): Plans {\n const graph = new PlannerGraph();\n let nextPlanId = 0;\n\n const source = graph.addSource(ast.table, model);\n const connection = source.connect(\n ast.orderBy ?? [],\n ast.where,\n isRoot,\n baseConstraints,\n ast.limit,\n );\n graph.connections.push(connection);\n\n let end: PlannerNode = connection;\n if (ast.where) {\n end = processCondition(\n ast.where,\n end,\n graph,\n model,\n ast.table,\n () => nextPlanId++,\n );\n }\n\n const terminus = new PlannerTerminus(end);\n wireOutput(end, terminus);\n graph.setTerminus(terminus);\n\n const subPlans: {[key: string]: Plans} = {};\n if (ast.related) {\n for (const csq of ast.related) {\n const alias = must(\n csq.subquery.alias,\n 'Related subquery must have alias',\n );\n const childConstraints = extractConstraint(\n csq.correlation.childField,\n csq.subquery.table,\n );\n subPlans[alias] = buildPlanGraph(\n csq.subquery,\n model,\n true,\n childConstraints,\n );\n }\n }\n\n return {plan: graph, subPlans};\n}\n\nfunction processCondition(\n condition: Condition,\n input: Exclude<PlannerNode, PlannerTerminus>,\n graph: PlannerGraph,\n model: ConnectionCostModel,\n parentTable: string,\n getPlanId: () => number,\n): Exclude<PlannerNode, PlannerTerminus> {\n switch (condition.type) {\n case 'simple':\n return input;\n case 'and':\n return processAnd(condition, input, graph, model, parentTable, getPlanId);\n case 'or':\n return processOr(condition, input, graph, model, parentTable, getPlanId);\n case 'correlatedSubquery':\n return processCorrelatedSubquery(\n condition,\n input,\n graph,\n model,\n parentTable,\n getPlanId,\n );\n }\n}\n\nfunction processAnd(\n condition: Conjunction,\n input: Exclude<PlannerNode, PlannerTerminus>,\n graph: PlannerGraph,\n model: ConnectionCostModel,\n parentTable: string,\n getPlanId: () => number,\n): Exclude<PlannerNode, PlannerTerminus> {\n let end = input;\n for (const subCondition of condition.conditions) {\n end = processCondition(\n subCondition,\n end,\n graph,\n model,\n parentTable,\n getPlanId,\n );\n }\n return end;\n}\n\nfunction processOr(\n condition: Disjunction,\n input: Exclude<PlannerNode, PlannerTerminus>,\n graph: PlannerGraph,\n model: ConnectionCostModel,\n parentTable: string,\n getPlanId: () => number,\n): Exclude<PlannerNode, PlannerTerminus> {\n const subqueryConditions = condition.conditions.filter(\n c => c.type === 'correlatedSubquery' || hasCorrelatedSubquery(c),\n );\n\n if (subqueryConditions.length === 0) {\n return input;\n }\n\n const fanOut = new PlannerFanOut(input);\n graph.fanOuts.push(fanOut);\n wireOutput(input, fanOut);\n\n const branches: Exclude<PlannerNode, PlannerTerminus>[] = [];\n for (const subCondition of subqueryConditions) {\n const branch = processCondition(\n subCondition,\n fanOut,\n graph,\n model,\n parentTable,\n getPlanId,\n );\n branches.push(branch);\n fanOut.addOutput(branch);\n }\n\n const fanIn = new PlannerFanIn(branches);\n graph.fanIns.push(fanIn);\n for (const branch of branches) {\n wireOutput(branch, fanIn);\n }\n\n return fanIn;\n}\n\nfunction processCorrelatedSubquery(\n condition: CorrelatedSubqueryCondition,\n input: Exclude<PlannerNode, PlannerTerminus>,\n graph: PlannerGraph,\n model: ConnectionCostModel,\n parentTable: string,\n getPlanId: () => number,\n): Exclude<PlannerNode, PlannerTerminus> {\n const {related} = condition;\n const childTable = related.subquery.table;\n\n const childSource = graph.hasSource(childTable)\n ? graph.getSource(childTable)\n : graph.addSource(childTable, model);\n\n const childConnection = childSource.connect(\n related.subquery.orderBy ?? [],\n related.subquery.where,\n false,\n undefined, // no base constraints for EXISTS/NOT EXISTS\n condition.op === 'EXISTS' ? 1 : undefined,\n );\n graph.connections.push(childConnection);\n\n let childEnd: PlannerNode = childConnection;\n if (related.subquery.where) {\n childEnd = processCondition(\n related.subquery.where,\n childEnd,\n graph,\n model,\n childTable,\n getPlanId,\n );\n }\n\n const parentConstraint = extractConstraint(\n related.correlation.parentField,\n parentTable,\n );\n const childConstraint = extractConstraint(\n related.correlation.childField,\n childTable,\n );\n\n const planId = getPlanId();\n condition[planIdSymbol] = planId;\n\n const join = new PlannerJoin(\n input,\n childEnd,\n parentConstraint,\n childConstraint,\n condition.op !== 'NOT EXISTS',\n planId,\n );\n graph.joins.push(join);\n\n wireOutput(input, join);\n wireOutput(childEnd, join);\n\n return join;\n}\n\nfunction hasCorrelatedSubquery(condition: Condition): boolean {\n if (condition.type === 'correlatedSubquery') {\n return true;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n return condition.conditions.some(hasCorrelatedSubquery);\n }\n return false;\n}\n\nfunction extractConstraint(\n fields: readonly string[],\n _tableName: string,\n): PlannerConstraint {\n return Object.fromEntries(fields.map(field => [field, undefined]));\n}\n\nfunction planRecursively(plans: Plans, planDebugger?: PlanDebugger): void {\n for (const subPlan of Object.values(plans.subPlans)) {\n planRecursively(subPlan, planDebugger);\n }\n plans.plan.plan(planDebugger);\n}\n\nexport function planQuery(\n ast: AST,\n model: ConnectionCostModel,\n planDebugger?: PlanDebugger,\n): AST {\n const plans = buildPlanGraph(ast, model, true);\n planRecursively(plans, planDebugger);\n return applyPlansToAST(ast, plans);\n}\n\nfunction applyToCondition(\n condition: Condition,\n flippedIds: Set<number>,\n): Condition {\n if (condition.type === 'simple') {\n return condition;\n }\n\n if (condition.type === 'correlatedSubquery') {\n const planId = (condition as unknown as Record<symbol, number>)[\n planIdSymbol\n ];\n const shouldFlip = planId !== undefined && flippedIds.has(planId);\n\n return {\n ...condition,\n flip: shouldFlip ? true : condition.flip,\n related: {\n ...condition.related,\n subquery: {\n ...condition.related.subquery,\n where: condition.related.subquery.where\n ? applyToCondition(condition.related.subquery.where, flippedIds)\n : undefined,\n },\n },\n };\n }\n\n return {\n ...condition,\n conditions: condition.conditions.map(c => applyToCondition(c, flippedIds)),\n };\n}\n\nexport function applyPlansToAST(ast: AST, plans: Plans): AST {\n const flippedIds = new Set<number>();\n for (const join of plans.plan.joins) {\n if (join.type === 'flipped' && join.planId !== undefined) {\n flippedIds.add(join.planId);\n }\n }\n\n return {\n ...ast,\n where: ast.where ? applyToCondition(ast.where, flippedIds) : undefined,\n related: ast.related?.map(csq => {\n const alias = must(\n csq.subquery.alias,\n 'Related subquery must have alias',\n );\n const subPlan = plans.subPlans[alias];\n return {\n ...csq,\n subquery: subPlan\n ? applyPlansToAST(csq.subquery, subPlan)\n : csq.subquery,\n };\n }),\n };\n}\n", "/* oxlint-disable @typescript-eslint/no-explicit-any */\nimport {must} from '../../../shared/src/must.ts';\nimport {\n toStaticParam,\n type Condition,\n type LiteralValue,\n type Parameter,\n type SimpleOperator,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Schema} from '../../../zero-types/src/schema.ts';\nimport type {\n AvailableRelationships,\n DestTableName,\n ExistsOptions,\n GetFilterType,\n NoCompoundTypeSelector,\n PullTableSchema,\n Query,\n} from './query.ts';\n\nexport type ParameterReference = {\n [toStaticParam](): Parameter;\n};\n\n/**\n * A factory function that creates a condition. This is used to create\n * complex conditions that can be passed to the `where` method of a query.\n *\n * @example\n *\n * ```ts\n * const condition: ExpressionFactory<User> = ({and, cmp, or}) =>\n * and(\n * cmp('name', '=', 'Alice'),\n * or(cmp('age', '>', 18), cmp('isStudent', '=', true)),\n * );\n *\n * const query = z.query.user.where(condition);\n * ```\n */\nexport interface ExpressionFactory<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> {\n (eb: ExpressionBuilder<TSchema, TTable>): Condition;\n}\n\nexport class ExpressionBuilder<\n TSchema extends Schema,\n TTable extends keyof TSchema['tables'] & string,\n> {\n readonly #exists: (\n relationship: string,\n cb?: (query: Query<TSchema, TTable>) => Query<TSchema, any>,\n options?: ExistsOptions,\n ) => Condition;\n\n constructor(\n exists: (\n relationship: string,\n cb?: (query: Query<TSchema, TTable>) => Query<TSchema, any>,\n options?: ExistsOptions,\n ) => Condition,\n ) {\n this.#exists = exists;\n this.exists = this.exists.bind(this);\n }\n\n get eb() {\n return this;\n }\n\n cmp<\n TSelector extends NoCompoundTypeSelector<PullTableSchema<TTable, TSchema>>,\n TOperator extends SimpleOperator,\n >(\n field: TSelector,\n op: TOperator,\n value:\n | GetFilterType<PullTableSchema<TTable, TSchema>, TSelector, TOperator>\n | ParameterReference,\n ): Condition;\n cmp<\n TSelector extends NoCompoundTypeSelector<PullTableSchema<TTable, TSchema>>,\n >(\n field: TSelector,\n value:\n | GetFilterType<PullTableSchema<TTable, TSchema>, TSelector, '='>\n | ParameterReference,\n ): Condition;\n cmp(\n field: string,\n opOrValue: SimpleOperator | ParameterReference | LiteralValue,\n value?: ParameterReference | LiteralValue,\n ): Condition {\n return cmp(field, opOrValue, value);\n }\n\n cmpLit(\n left: ParameterReference | LiteralValue,\n op: SimpleOperator,\n right: ParameterReference | LiteralValue,\n ): Condition {\n return {\n type: 'simple',\n left: isParameterReference(left)\n ? left[toStaticParam]()\n : {type: 'literal', value: left},\n right: isParameterReference(right)\n ? right[toStaticParam]()\n : {type: 'literal', value: right},\n op,\n };\n }\n\n and = and;\n or = or;\n not = not;\n\n exists = <TRelationship extends AvailableRelationships<TTable, TSchema>>(\n relationship: TRelationship,\n cb?: (\n query: Query<TSchema, DestTableName<TTable, TSchema, TRelationship>>,\n ) => Query<TSchema, any>,\n options?: ExistsOptions,\n ): Condition => this.#exists(relationship, cb, options);\n}\n\nexport function and(...conditions: (Condition | undefined)[]): Condition {\n const expressions = filterTrue(filterUndefined(conditions));\n\n if (expressions.length === 1) {\n return expressions[0];\n }\n\n if (expressions.some(isAlwaysFalse)) {\n return FALSE;\n }\n\n return {type: 'and', conditions: expressions};\n}\n\nexport function or(...conditions: (Condition | undefined)[]): Condition {\n const expressions = filterFalse(filterUndefined(conditions));\n\n if (expressions.length === 1) {\n return expressions[0];\n }\n\n if (expressions.some(isAlwaysTrue)) {\n return TRUE;\n }\n\n return {type: 'or', conditions: expressions};\n}\n\nexport function not(expression: Condition): Condition {\n switch (expression.type) {\n case 'and':\n return {\n type: 'or',\n conditions: expression.conditions.map(not),\n };\n case 'or':\n return {\n type: 'and',\n conditions: expression.conditions.map(not),\n };\n case 'correlatedSubquery':\n return {\n type: 'correlatedSubquery',\n related: expression.related,\n op: negateOperator(expression.op),\n };\n case 'simple':\n return {\n type: 'simple',\n op: negateOperator(expression.op),\n left: expression.left,\n right: expression.right,\n };\n }\n}\n\nexport function cmp(\n field: string,\n opOrValue: SimpleOperator | ParameterReference | LiteralValue,\n value?: ParameterReference | LiteralValue,\n): Condition {\n let op: SimpleOperator;\n if (value === undefined) {\n value = opOrValue;\n op = '=';\n } else {\n op = opOrValue as SimpleOperator;\n }\n\n return {\n type: 'simple',\n left: {type: 'column', name: field},\n right: isParameterReference(value)\n ? value[toStaticParam]()\n : {type: 'literal', value},\n op,\n };\n}\n\nfunction isParameterReference(\n value: ParameterReference | LiteralValue | null,\n): value is ParameterReference {\n return (\n value !== null && typeof value === 'object' && (value as any)[toStaticParam]\n );\n}\n\nexport const TRUE: Condition = {\n type: 'and',\n conditions: [],\n};\n\nconst FALSE: Condition = {\n type: 'or',\n conditions: [],\n};\n\nfunction isAlwaysTrue(condition: Condition): boolean {\n return condition.type === 'and' && condition.conditions.length === 0;\n}\n\nfunction isAlwaysFalse(condition: Condition): boolean {\n return condition.type === 'or' && condition.conditions.length === 0;\n}\n\nexport function simplifyCondition(c: Condition): Condition {\n if (c.type === 'simple' || c.type === 'correlatedSubquery') {\n return c;\n }\n if (c.conditions.length === 1) {\n return simplifyCondition(c.conditions[0]);\n }\n const conditions = flatten(c.type, c.conditions.map(simplifyCondition));\n if (c.type === 'and' && conditions.some(isAlwaysFalse)) {\n return FALSE;\n }\n if (c.type === 'or' && conditions.some(isAlwaysTrue)) {\n return TRUE;\n }\n return {\n type: c.type,\n conditions,\n };\n}\n\nexport function flatten(\n type: 'and' | 'or',\n conditions: readonly Condition[],\n): Condition[] {\n const flattened: Condition[] = [];\n for (const c of conditions) {\n if (c.type === type) {\n flattened.push(...c.conditions);\n } else {\n flattened.push(c);\n }\n }\n\n return flattened;\n}\n\nconst negateSimpleOperatorMap = {\n ['=']: '!=',\n ['!=']: '=',\n ['<']: '>=',\n ['>']: '<=',\n ['>=']: '<',\n ['<=']: '>',\n ['IN']: 'NOT IN',\n ['NOT IN']: 'IN',\n ['LIKE']: 'NOT LIKE',\n ['NOT LIKE']: 'LIKE',\n ['ILIKE']: 'NOT ILIKE',\n ['NOT ILIKE']: 'ILIKE',\n ['IS']: 'IS NOT',\n ['IS NOT']: 'IS',\n} as const;\n\nconst negateOperatorMap = {\n ...negateSimpleOperatorMap,\n ['EXISTS']: 'NOT EXISTS',\n ['NOT EXISTS']: 'EXISTS',\n} as const;\n\nexport function negateOperator<OP extends keyof typeof negateOperatorMap>(\n op: OP,\n): (typeof negateOperatorMap)[OP] {\n return must(negateOperatorMap[op]);\n}\n\nfunction filterUndefined<T>(array: (T | undefined)[]): T[] {\n return array.filter(e => e !== undefined);\n}\n\nfunction filterTrue(conditions: Condition[]): Condition[] {\n return conditions.filter(c => !isAlwaysTrue(c));\n}\n\nfunction filterFalse(conditions: Condition[]): Condition[] {\n return conditions.filter(c => !isAlwaysFalse(c));\n}\n", "import {assertString} from '../../../shared/src/asserts.ts';\nimport type {NonNullValue, SimplePredicateNoNull} from './filter.ts';\n\nexport function getLikePredicate(\n pattern: NonNullValue,\n flags: 'i' | '',\n): SimplePredicateNoNull {\n const op = getLikeOp(String(pattern), flags);\n return (lhs: NonNullValue) => {\n assertString(lhs);\n return op(String(lhs));\n };\n}\n\nfunction getLikeOp(pattern: string, flags: 'i' | ''): (lhs: string) => boolean {\n // if lhs does not contain '%' or '_' then it is a simple string comparison.\n // if it does contain '%' or '_' then it is a regex comparison.\n // '%' is a wildcard for any number of characters\n // '_' is a wildcard for a single character\n // Postgres SQL allows escaping using `\\`.\n\n if (!/_|%|\\\\/.test(pattern)) {\n if (flags === 'i') {\n const rhsLower = pattern.toLowerCase();\n return (lhs: string) => lhs.toLowerCase() === rhsLower;\n }\n return (lhs: string) => lhs === pattern;\n }\n const re = patternToRegExp(pattern, flags);\n return (lhs: string) => re.test(lhs);\n}\n\nconst specialCharsRe = /[$()*+.?[\\]\\\\^{|}]/;\n\nfunction patternToRegExp(source: string, flags: '' | 'i' = ''): RegExp {\n // There are a few cases:\n // % => .*\n // _ => .\n // \\x => \\x for any x except special regexp chars\n // special regexp chars => \\special regexp chars\n let pattern = '^';\n for (let i = 0; i < source.length; i++) {\n let c = source[i];\n switch (c) {\n case '%':\n pattern += '.*';\n break;\n case '_':\n pattern += '.';\n break;\n\n // @ts-expect-error fallthrough\n case '\\\\':\n if (i === source.length - 1) {\n throw new Error('LIKE pattern must not end with escape character');\n }\n i++;\n c = source[i];\n\n // fall through\n default:\n if (specialCharsRe.test(c)) {\n pattern += '\\\\';\n }\n pattern += c;\n\n break;\n }\n }\n return new RegExp(pattern + '$', flags + 'm');\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {\n Condition,\n SimpleCondition,\n SimpleOperator,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport {simplifyCondition} from '../query/expression.ts';\nimport {getLikePredicate} from './like.ts';\n\nexport type NonNullValue = Exclude<Value, null | undefined>;\nexport type SimplePredicate = (rhs: Value) => boolean;\nexport type SimplePredicateNoNull = (rhs: NonNullValue) => boolean;\n\nexport type NoSubqueryCondition =\n | SimpleCondition\n | {\n type: 'and';\n conditions: readonly NoSubqueryCondition[];\n }\n | {\n type: 'or';\n conditions: readonly NoSubqueryCondition[];\n };\n\nexport function createPredicate(\n condition: NoSubqueryCondition,\n): (row: Row) => boolean {\n if (condition.type !== 'simple') {\n const predicates = condition.conditions.map(c => createPredicate(c));\n return condition.type === 'and'\n ? (row: Row) => {\n // and\n for (const predicate of predicates) {\n if (!predicate(row)) {\n return false;\n }\n }\n return true;\n }\n : (row: Row) => {\n // or\n for (const predicate of predicates) {\n if (predicate(row)) {\n return true;\n }\n }\n return false;\n };\n }\n const {left} = condition;\n const {right} = condition;\n assert(\n right.type !== 'static',\n 'static values should be resolved before creating predicates',\n );\n assert(\n left.type !== 'static',\n 'static values should be resolved before creating predicates',\n );\n\n switch (condition.op) {\n case 'IS':\n case 'IS NOT': {\n const impl = createIsPredicate(right.value, condition.op);\n if (left.type === 'literal') {\n const result = impl(left.value);\n return () => result;\n }\n return (row: Row) => impl(row[left.name]);\n }\n }\n\n if (right.value === null || right.value === undefined) {\n return (_row: Row) => false;\n }\n\n const impl = createPredicateImpl(right.value, condition.op);\n if (left.type === 'literal') {\n if (left.value === null || left.value === undefined) {\n return (_row: Row) => false;\n }\n const result = impl(left.value);\n return () => result;\n }\n\n return (row: Row) => {\n const lhs = row[left.name];\n if (lhs === null || lhs === undefined) {\n return false;\n }\n return impl(lhs);\n };\n}\n\nfunction createIsPredicate(\n rhs: Value | readonly Value[],\n operator: 'IS' | 'IS NOT',\n): SimplePredicate {\n switch (operator) {\n case 'IS':\n return lhs => lhs === rhs;\n case 'IS NOT':\n return lhs => lhs !== rhs;\n }\n}\n\nfunction createPredicateImpl(\n rhs: NonNullValue | readonly NonNullValue[],\n operator: Exclude<SimpleOperator, 'IS' | 'IS NOT'>,\n): SimplePredicateNoNull {\n switch (operator) {\n case '=':\n return lhs => lhs === rhs;\n case '!=':\n return lhs => lhs !== rhs;\n case '<':\n return lhs => lhs < rhs;\n case '<=':\n return lhs => lhs <= rhs;\n case '>':\n return lhs => lhs > rhs;\n case '>=':\n return lhs => lhs >= rhs;\n case 'LIKE':\n return getLikePredicate(rhs, '');\n case 'NOT LIKE':\n return not(getLikePredicate(rhs, ''));\n case 'ILIKE':\n return getLikePredicate(rhs, 'i');\n case 'NOT ILIKE':\n return not(getLikePredicate(rhs, 'i'));\n case 'IN': {\n assert(Array.isArray(rhs));\n const set = new Set(rhs);\n return lhs => set.has(lhs);\n }\n case 'NOT IN': {\n assert(Array.isArray(rhs));\n const set = new Set(rhs);\n return lhs => !set.has(lhs);\n }\n default:\n operator satisfies never;\n throw new Error(`Unexpected operator: ${operator}`);\n }\n}\n\nfunction not<T>(f: (lhs: T) => boolean) {\n return (lhs: T) => !f(lhs);\n}\n\n/**\n * If the condition contains any CorrelatedSubqueryConditions, returns a\n * transformed condition which contains no CorrelatedSubqueryCondition(s) but\n * which will filter a subset of the rows that would be filtered by the original\n * condition, or undefined if no such transformation exists.\n *\n * If the condition does not contain any CorrelatedSubqueryConditions\n * returns the condition unmodified and `conditionsRemoved: false`.\n */\nexport function transformFilters(filters: Condition | undefined): {\n filters: NoSubqueryCondition | undefined;\n conditionsRemoved: boolean;\n} {\n if (!filters) {\n return {filters: undefined, conditionsRemoved: false};\n }\n switch (filters.type) {\n case 'simple':\n return {filters, conditionsRemoved: false};\n case 'correlatedSubquery':\n return {filters: undefined, conditionsRemoved: true};\n case 'and':\n case 'or': {\n const transformedConditions: NoSubqueryCondition[] = [];\n let conditionsRemoved = false;\n for (const cond of filters.conditions) {\n const transformed = transformFilters(cond);\n // If any branch of the OR ends up empty, the entire OR needs\n // to be removed.\n if (transformed.filters === undefined && filters.type === 'or') {\n return {filters: undefined, conditionsRemoved: true};\n }\n conditionsRemoved = conditionsRemoved || transformed.conditionsRemoved;\n if (transformed.filters) {\n transformedConditions.push(transformed.filters);\n }\n }\n return {\n filters: simplifyCondition({\n type: filters.type,\n conditions: transformedConditions,\n }) as NoSubqueryCondition,\n conditionsRemoved,\n };\n }\n default:\n unreachable(filters);\n }\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {\n AST,\n ColumnReference,\n CompoundKey,\n Condition,\n Conjunction,\n CorrelatedSubquery,\n CorrelatedSubqueryCondition,\n Disjunction,\n LiteralValue,\n Ordering,\n Parameter,\n SimpleCondition,\n ValuePosition,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport {Exists} from '../ivm/exists.ts';\nimport {FanIn} from '../ivm/fan-in.ts';\nimport {FanOut} from '../ivm/fan-out.ts';\nimport {\n buildFilterPipeline,\n type FilterInput,\n} from '../ivm/filter-operators.ts';\nimport {Filter} from '../ivm/filter.ts';\nimport {FlippedJoin} from '../ivm/flipped-join.ts';\nimport {Join} from '../ivm/join.ts';\nimport type {Input, InputBase, Storage} from '../ivm/operator.ts';\nimport {Skip} from '../ivm/skip.ts';\nimport type {Source, SourceInput} from '../ivm/source.ts';\nimport {Take} from '../ivm/take.ts';\nimport {UnionFanIn} from '../ivm/union-fan-in.ts';\nimport {UnionFanOut} from '../ivm/union-fan-out.ts';\nimport {planQuery} from '../planner/planner-builder.ts';\nimport type {ConnectionCostModel} from '../planner/planner-connection.ts';\nimport type {DebugDelegate} from './debug-delegate.ts';\nimport {createPredicate, type NoSubqueryCondition} from './filter.ts';\n\nexport type StaticQueryParameters = {\n authData: Record<string, JSONValue>;\n preMutationRow?: Row | undefined;\n};\n\n/**\n * Interface required of caller to buildPipeline. Connects to constructed\n * pipeline to delegate environment to provide sources and storage.\n */\nexport interface BuilderDelegate {\n readonly applyFiltersAnyway?: boolean | undefined;\n readonly debug?: DebugDelegate | undefined;\n\n /**\n * When true, allows NOT EXISTS conditions in queries.\n * Defaults to false.\n *\n * We only set this to true on the server.\n * The client-side query engine cannot support NOT EXISTS because:\n * 1. Zero only syncs a subset of data to the client\n * 2. On the client, we can't distinguish between a row not existing vs.\n * a row not being synced to the client\n * 3. NOT EXISTS requires complete knowledge of what doesn't exist\n */\n readonly enableNotExists?: boolean | undefined;\n\n /**\n * Called once for each source needed by the AST.\n * Might be called multiple times with same tableName. It is OK to return\n * same storage instance in that case.\n */\n getSource(tableName: string): Source | undefined;\n\n /**\n * Called once for each operator that requires storage. Should return a new\n * unique storage object for each call.\n */\n createStorage(name: string): Storage;\n\n decorateInput(input: Input, name: string): Input;\n\n addEdge(source: InputBase, dest: InputBase): void;\n\n decorateFilterInput(input: FilterInput, name: string): FilterInput;\n\n decorateSourceInput(input: SourceInput, queryID: string): Input;\n\n /**\n * The AST is mapped on-the-wire between client and server names.\n *\n * There is no \"wire\" for zqlite tests so this function is provided\n * to allow tests to remap the AST.\n */\n mapAst?: ((ast: AST) => AST) | undefined;\n}\n\n/**\n * Builds a pipeline from an AST. Caller must provide a delegate to create source\n * and storage interfaces as necessary.\n *\n * Usage:\n *\n * ```ts\n * class MySink implements Output {\n * readonly #input: Input;\n *\n * constructor(input: Input) {\n * this.#input = input;\n * input.setOutput(this);\n * }\n *\n * push(change: Change, _: Operator) {\n * console.log(change);\n * }\n * }\n *\n * const input = buildPipeline(ast, myDelegate, hash(ast));\n * const sink = new MySink(input);\n * ```\n */\nexport function buildPipeline(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n costModel?: ConnectionCostModel,\n): Input {\n ast = delegate.mapAst ? delegate.mapAst(ast) : ast;\n if (costModel) {\n ast = planQuery(ast, costModel);\n }\n return buildPipelineInternal(ast, delegate, queryID, '');\n}\n\nexport function bindStaticParameters(\n ast: AST,\n staticQueryParameters: StaticQueryParameters | undefined,\n) {\n const visit = (node: AST): AST => ({\n ...node,\n where: node.where ? bindCondition(node.where) : undefined,\n related: node.related?.map(sq => ({\n ...sq,\n subquery: visit(sq.subquery),\n })),\n });\n\n function bindCondition(condition: Condition): Condition {\n if (condition.type === 'simple') {\n return {\n ...condition,\n left: bindValue(condition.left),\n right: bindValue(condition.right) as Exclude<\n ValuePosition,\n ColumnReference\n >,\n };\n }\n if (condition.type === 'correlatedSubquery') {\n return {\n ...condition,\n related: {\n ...condition.related,\n subquery: visit(condition.related.subquery),\n },\n };\n }\n return {\n ...condition,\n conditions: condition.conditions.map(bindCondition),\n };\n }\n\n const bindValue = (value: ValuePosition): ValuePosition => {\n if (isParameter(value)) {\n const anchor = must(\n staticQueryParameters,\n 'Static query params do not exist',\n )[value.anchor];\n const resolvedValue = resolveField(anchor, value.field);\n return {\n type: 'literal',\n value: resolvedValue as LiteralValue,\n };\n }\n return value;\n };\n\n return visit(ast);\n}\n\nfunction resolveField(\n anchor: Record<string, JSONValue> | Row | undefined,\n field: string | string[],\n): unknown {\n if (anchor === undefined) {\n return null;\n }\n\n if (Array.isArray(field)) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n return field.reduce((acc, f) => (acc as any)?.[f], anchor) ?? null;\n }\n\n return anchor[field] ?? null;\n}\n\nfunction isParameter(value: ValuePosition): value is Parameter {\n return value.type === 'static';\n}\n\nconst EXISTS_LIMIT = 3;\nconst PERMISSIONS_EXISTS_LIMIT = 1;\n\n/**\n * Checks if a condition tree contains any NOT EXISTS operations.\n * Recursively checks AND/OR branches but does not recurse into nested subqueries\n * (those are checked when buildPipelineInternal processes them).\n */\nfunction assertNoNotExists(condition: Condition): void {\n switch (condition.type) {\n case 'simple':\n return;\n\n case 'correlatedSubquery':\n if (condition.op === 'NOT EXISTS') {\n throw new Error(\n 'not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438',\n );\n }\n return;\n\n case 'and':\n case 'or':\n for (const c of condition.conditions) {\n assertNoNotExists(c);\n }\n return;\n default:\n unreachable(condition);\n }\n}\n\nfunction buildPipelineInternal(\n ast: AST,\n delegate: BuilderDelegate,\n queryID: string,\n name: string,\n partitionKey?: CompoundKey,\n): Input {\n const source = delegate.getSource(ast.table);\n if (!source) {\n throw new Error(`Source not found: ${ast.table}`);\n }\n ast = uniquifyCorrelatedSubqueryConditionAliases(ast);\n\n if (!delegate.enableNotExists && ast.where) {\n assertNoNotExists(ast.where);\n }\n\n const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);\n const splitEditKeys: Set<string> = partitionKey\n ? new Set(partitionKey)\n : new Set();\n const aliases = new Set<string>();\n for (const csq of csqConditions) {\n aliases.add(csq.related.subquery.alias || '');\n for (const key of csq.related.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n if (ast.related) {\n for (const csq of ast.related) {\n for (const key of csq.correlation.parentField) {\n splitEditKeys.add(key);\n }\n }\n }\n const conn = source.connect(\n must(ast.orderBy),\n ast.where,\n splitEditKeys,\n delegate.debug,\n );\n\n let end: Input = delegate.decorateSourceInput(conn, queryID);\n end = delegate.decorateInput(end, `${name}:source(${ast.table})`);\n const {fullyAppliedFilters} = conn;\n\n if (ast.start) {\n const skip = new Skip(end, ast.start);\n delegate.addEdge(end, skip);\n end = delegate.decorateInput(skip, `${name}:skip)`);\n }\n\n for (const csqCondition of csqConditions) {\n // flipped EXISTS are handled in applyWhere\n if (!csqCondition.flip) {\n end = applyCorrelatedSubQuery(\n {\n ...csqCondition.related,\n subquery: {\n ...csqCondition.related.subquery,\n limit:\n csqCondition.related.system === 'permissions'\n ? PERMISSIONS_EXISTS_LIMIT\n : EXISTS_LIMIT,\n },\n },\n delegate,\n queryID,\n end,\n name,\n true,\n );\n }\n }\n\n if (ast.where && (!fullyAppliedFilters || delegate.applyFiltersAnyway)) {\n end = applyWhere(end, ast.where, delegate, name);\n }\n\n if (ast.limit !== undefined) {\n const takeName = `${name}:take`;\n const take = new Take(\n end,\n delegate.createStorage(takeName),\n ast.limit,\n partitionKey,\n );\n delegate.addEdge(end, take);\n end = delegate.decorateInput(take, takeName);\n }\n\n if (ast.related) {\n for (const csq of ast.related) {\n end = applyCorrelatedSubQuery(csq, delegate, queryID, end, name, false);\n }\n }\n\n return end;\n}\n\nfunction applyWhere(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n if (!conditionIncludesFlippedSubqueryAtAnyLevel(condition)) {\n return buildFilterPipeline(input, delegate, filterInput =>\n applyFilter(filterInput, condition, delegate, name),\n );\n }\n\n return applyFilterWithFlips(input, condition, delegate, name);\n}\n\nfunction applyFilterWithFlips(\n input: Input,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n): Input {\n let end = input;\n assert(condition.type !== 'simple', 'Simple conditions cannot have flips');\n\n switch (condition.type) {\n case 'and': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n if (withoutFlipped.length > 0) {\n end = buildFilterPipeline(input, delegate, filterInput =>\n applyAnd(\n filterInput,\n {\n type: 'and',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n );\n }\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n for (const cond of withFlipped) {\n end = applyFilterWithFlips(end, cond, delegate, name);\n }\n break;\n }\n case 'or': {\n const [withFlipped, withoutFlipped] = partitionBranches(\n condition.conditions,\n conditionIncludesFlippedSubqueryAtAnyLevel,\n );\n assert(withFlipped.length > 0, 'Impossible to have no flips here');\n\n const ufo = new UnionFanOut(end);\n delegate.addEdge(end, ufo);\n end = delegate.decorateInput(ufo, `${name}:ufo`);\n\n const branches: Input[] = [];\n if (withoutFlipped.length > 0) {\n branches.push(\n buildFilterPipeline(end, delegate, filterInput =>\n applyOr(\n filterInput,\n {\n type: 'or',\n conditions: withoutFlipped,\n },\n delegate,\n name,\n ),\n ),\n );\n }\n\n for (const cond of withFlipped) {\n branches.push(applyFilterWithFlips(end, cond, delegate, name));\n }\n\n const ufi = new UnionFanIn(ufo, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ufi);\n }\n end = delegate.decorateInput(ufi, `${name}:ufi`);\n\n break;\n }\n case 'correlatedSubquery': {\n const sq = condition.related;\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n '',\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n const flippedJoin = new FlippedJoin({\n parent: end,\n child,\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: must(\n sq.subquery.alias,\n 'Subquery must have an alias',\n ),\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, flippedJoin);\n delegate.addEdge(child, flippedJoin);\n end = delegate.decorateInput(\n flippedJoin,\n `${name}:flipped-join(${sq.subquery.alias})`,\n );\n break;\n }\n }\n\n return end;\n}\n\nfunction applyFilter(\n input: FilterInput,\n condition: Condition,\n delegate: BuilderDelegate,\n name: string,\n) {\n switch (condition.type) {\n case 'and':\n return applyAnd(input, condition, delegate, name);\n case 'or':\n return applyOr(input, condition, delegate, name);\n case 'correlatedSubquery':\n return applyCorrelatedSubqueryCondition(input, condition, delegate, name);\n case 'simple':\n return applySimpleCondition(input, delegate, condition);\n }\n}\n\nfunction applyAnd(\n input: FilterInput,\n condition: Conjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n for (const subCondition of condition.conditions) {\n input = applyFilter(input, subCondition, delegate, name);\n }\n return input;\n}\n\nexport function applyOr(\n input: FilterInput,\n condition: Disjunction,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n const [subqueryConditions, otherConditions] =\n groupSubqueryConditions(condition);\n // if there are no subquery conditions, no fan-in / fan-out is needed\n if (subqueryConditions.length === 0) {\n const filter = new Filter(\n input,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(input, filter);\n return filter;\n }\n\n const fanOut = new FanOut(input);\n delegate.addEdge(input, fanOut);\n const branches = subqueryConditions.map(subCondition =>\n applyFilter(fanOut, subCondition, delegate, name),\n );\n if (otherConditions.length > 0) {\n const filter = new Filter(\n fanOut,\n createPredicate({\n type: 'or',\n conditions: otherConditions,\n }),\n );\n delegate.addEdge(fanOut, filter);\n branches.push(filter);\n }\n const ret = new FanIn(fanOut, branches);\n for (const branch of branches) {\n delegate.addEdge(branch, ret);\n }\n fanOut.setFanIn(ret);\n return ret;\n}\n\nexport function groupSubqueryConditions(condition: Disjunction) {\n const partitioned: [\n subqueryConditions: Condition[],\n otherConditions: NoSubqueryCondition[],\n ] = [[], []];\n for (const subCondition of condition.conditions) {\n if (isNotAndDoesNotContainSubquery(subCondition)) {\n partitioned[1].push(subCondition);\n } else {\n partitioned[0].push(subCondition);\n }\n }\n return partitioned;\n}\n\nexport function isNotAndDoesNotContainSubquery(\n condition: Condition,\n): condition is NoSubqueryCondition {\n if (condition.type === 'correlatedSubquery') {\n return false;\n }\n if (condition.type === 'simple') {\n return true;\n }\n return condition.conditions.every(isNotAndDoesNotContainSubquery);\n}\n\nfunction applySimpleCondition(\n input: FilterInput,\n delegate: BuilderDelegate,\n condition: SimpleCondition,\n): FilterInput {\n const filter = new Filter(input, createPredicate(condition));\n delegate.decorateFilterInput(\n filter,\n `${valuePosName(condition.left)}:${condition.op}:${valuePosName(condition.right)}`,\n );\n delegate.addEdge(input, filter);\n return filter;\n}\n\nfunction valuePosName(left: ValuePosition) {\n switch (left.type) {\n case 'static':\n return left.field;\n case 'literal':\n return left.value;\n case 'column':\n return left.name;\n }\n}\n\nfunction applyCorrelatedSubQuery(\n sq: CorrelatedSubquery,\n delegate: BuilderDelegate,\n queryID: string,\n end: Input,\n name: string,\n fromCondition: boolean,\n) {\n // TODO: we only omit the join if the CSQ if from a condition since\n // we want to create an empty array for `related` fields that are `limit(0)`\n if (sq.subquery.limit === 0 && fromCondition) {\n return end;\n }\n\n assert(sq.subquery.alias, 'Subquery must have an alias');\n const child = buildPipelineInternal(\n sq.subquery,\n delegate,\n queryID,\n `${name}.${sq.subquery.alias}`,\n sq.correlation.childField,\n );\n\n const joinName = `${name}:join(${sq.subquery.alias})`;\n const join = new Join({\n parent: end,\n child,\n storage: delegate.createStorage(joinName),\n parentKey: sq.correlation.parentField,\n childKey: sq.correlation.childField,\n relationshipName: sq.subquery.alias,\n hidden: sq.hidden ?? false,\n system: sq.system ?? 'client',\n });\n delegate.addEdge(end, join);\n delegate.addEdge(child, join);\n return delegate.decorateInput(join, joinName);\n}\n\nfunction applyCorrelatedSubqueryCondition(\n input: FilterInput,\n condition: CorrelatedSubqueryCondition,\n delegate: BuilderDelegate,\n name: string,\n): FilterInput {\n assert(condition.op === 'EXISTS' || condition.op === 'NOT EXISTS');\n if (condition.related.subquery.limit === 0) {\n if (condition.op === 'EXISTS') {\n const filter = new Filter(input, () => false);\n delegate.addEdge(input, filter);\n return filter;\n }\n const filter = new Filter(input, () => true);\n delegate.addEdge(input, filter);\n return filter;\n }\n const existsName = `${name}:exists(${condition.related.subquery.alias})`;\n const exists = new Exists(\n input,\n delegate.createStorage(existsName),\n must(condition.related.subquery.alias),\n condition.related.correlation.parentField,\n condition.op,\n );\n delegate.addEdge(input, exists);\n return delegate.decorateFilterInput(exists, existsName);\n}\n\nfunction gatherCorrelatedSubqueryQueryConditions(\n condition: Condition | undefined,\n) {\n const csqs: CorrelatedSubqueryCondition[] = [];\n const gather = (condition: Condition) => {\n if (condition.type === 'correlatedSubquery') {\n csqs.push(condition);\n return;\n }\n if (condition.type === 'and' || condition.type === 'or') {\n for (const c of condition.conditions) {\n gather(c);\n }\n return;\n }\n };\n if (condition) {\n gather(condition);\n }\n return csqs;\n}\n\nexport function assertOrderingIncludesPK(\n ordering: Ordering,\n pk: PrimaryKey,\n): void {\n // oxlint-disable-next-line unicorn/prefer-set-has -- Array is more appropriate here for small collections\n const orderingFields = ordering.map(([field]) => field);\n const missingFields = pk.filter(pkField => !orderingFields.includes(pkField));\n\n if (missingFields.length > 0) {\n throw new Error(\n `Ordering must include all primary key fields. Missing: ${missingFields.join(\n ', ',\n )}. ZQL automatically appends primary key fields to the ordering if they are missing \n so a common cause of this error is a casing mismatch between Postgres and ZQL.\n E.g., \"userid\" vs \"userID\".\n You may want to add double-quotes around your Postgres column names to prevent Postgres from lower-casing them:\n https://www.postgresql.org/docs/current/sql-syntax-lexical.htm`,\n );\n }\n}\n\nfunction uniquifyCorrelatedSubqueryConditionAliases(ast: AST): AST {\n if (!ast.where) {\n return ast;\n }\n const {where} = ast;\n if (where.type !== 'and' && where.type !== 'or') {\n return ast;\n }\n\n let count = 0;\n const uniquifyCorrelatedSubquery = (csqc: CorrelatedSubqueryCondition) => ({\n ...csqc,\n related: {\n ...csqc.related,\n subquery: {\n ...csqc.related.subquery,\n alias: (csqc.related.subquery.alias ?? '') + '_' + count++,\n },\n },\n });\n\n const uniquify = (cond: Condition): Condition => {\n if (cond.type === 'simple') {\n return cond;\n } else if (cond.type === 'correlatedSubquery') {\n return uniquifyCorrelatedSubquery(cond);\n }\n const conditions = [];\n for (const c of cond.conditions) {\n conditions.push(uniquify(c));\n }\n return {\n type: cond.type,\n conditions,\n };\n };\n\n const result = {\n ...ast,\n where: uniquify(where),\n };\n return result;\n}\n\nexport function conditionIncludesFlippedSubqueryAtAnyLevel(\n cond: Condition,\n): boolean {\n if (cond.type === 'correlatedSubquery') {\n return !!cond.flip;\n }\n if (cond.type === 'and' || cond.type === 'or') {\n return cond.conditions.some(c =>\n conditionIncludesFlippedSubqueryAtAnyLevel(c),\n );\n }\n return false;\n}\n\nexport function partitionBranches(\n conditions: readonly Condition[],\n predicate: (c: Condition) => boolean,\n) {\n const matched: Condition[] = [];\n const notMatched: Condition[] = [];\n for (const c of conditions) {\n if (predicate(c)) {\n matched.push(c);\n } else {\n notMatched.push(c);\n }\n }\n return [matched, notMatched] as const;\n}\n", "export class NotImplementedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotImplementedError';\n }\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\nimport type {Immutable} from '../../../shared/src/immutable.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport type {TTL} from '../query/ttl.ts';\nimport type {Listener, ResultType, TypedView} from '../query/typed-view.ts';\nimport type {Change} from './change.ts';\nimport type {Input, Output} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport {applyChange} from './view-apply-change.ts';\nimport type {Entry, Format, View} from './view.ts';\n\n/**\n * Implements a materialized view of the output of an operator.\n *\n * It might seem more efficient to use an immutable b-tree for the\n * materialization, but it's not so clear. Inserts in the middle are\n * asymptotically slower in an array, but can often be done with zero\n * allocations, where changes to the b-tree will often require several allocs.\n *\n * Also the plain array view is more convenient for consumers since you can dump\n * it into console to see what it is, rather than having to iterate it.\n */\nexport class ArrayView<V extends View> implements Output, TypedView<V> {\n readonly #input: Input;\n readonly #listeners = new Set<Listener<V>>();\n readonly #schema: SourceSchema;\n readonly #format: Format;\n\n // Synthetic \"root\" entry that has a single \"\" relationship, so that we can\n // treat all changes, including the root change, generically.\n readonly #root: Entry;\n\n onDestroy: (() => void) | undefined;\n\n #dirty = false;\n #resultType: ResultType = 'unknown';\n #error: ErroredQuery | undefined;\n readonly #updateTTL: (ttl: TTL) => void;\n\n constructor(\n input: Input,\n format: Format,\n queryComplete: true | ErroredQuery | Promise<true>,\n updateTTL: (ttl: TTL) => void,\n ) {\n this.#input = input;\n this.#schema = input.getSchema();\n this.#format = format;\n this.#updateTTL = updateTTL;\n this.#root = {'': format.singular ? undefined : []};\n input.setOutput(this);\n\n if (queryComplete === true) {\n this.#resultType = 'complete';\n } else if ('error' in queryComplete) {\n this.#resultType = 'error';\n this.#error = queryComplete;\n } else {\n void queryComplete\n .then(() => {\n this.#resultType = 'complete';\n this.#fireListeners();\n })\n .catch(e => {\n this.#resultType = 'error';\n this.#error = e;\n this.#fireListeners();\n });\n }\n this.#hydrate();\n }\n\n get data() {\n return this.#root[''] as V;\n }\n\n addListener(listener: Listener<V>) {\n assert(!this.#listeners.has(listener), 'Listener already registered');\n this.#listeners.add(listener);\n\n this.#fireListener(listener);\n\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #fireListeners() {\n for (const listener of this.#listeners) {\n this.#fireListener(listener);\n }\n }\n\n #fireListener(listener: Listener<V>) {\n listener(this.data as Immutable<V>, this.#resultType, this.#error);\n }\n\n destroy() {\n this.onDestroy?.();\n }\n\n #hydrate() {\n this.#dirty = true;\n for (const node of this.#input.fetch({})) {\n applyChange(\n this.#root,\n {type: 'add', node},\n this.#schema,\n '',\n this.#format,\n );\n }\n this.flush();\n }\n\n push(change: Change): void {\n this.#dirty = true;\n applyChange(this.#root, change, this.#schema, '', this.#format);\n }\n\n flush() {\n if (!this.#dirty) {\n return;\n }\n this.#dirty = false;\n this.#fireListeners();\n }\n\n updateTTL(ttl: TTL) {\n this.#updateTTL(ttl);\n }\n}\n", "/**\n * Format descriptor for query results.\n * Describes whether a result should be singular or a list,\n * and what the format of nested relationships should be.\n */\nexport type Format = {\n singular: boolean;\n relationships: Record<string, Format>;\n};\n\nexport const defaultFormat: Format = {\n singular: false,\n relationships: {},\n} as const;\n", "/* oxlint-disable @typescript-eslint/no-explicit-any */\nimport type {Expand, ExpandRecursive} from '../../../shared/src/expand.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {type AST, type SimpleOperator} from '../../../zero-protocol/src/ast.ts';\nimport type {\n SchemaValueToTSType,\n SchemaValueWithCustomType,\n} from '../../../zero-types/src/schema-value.ts';\nimport type {\n LastInTuple,\n TableSchema,\n Schema as ZeroSchema,\n} from '../../../zero-types/src/schema.ts';\nimport type {Format, ViewFactory} from '../ivm/view.ts';\nimport type {ExpressionFactory, ParameterReference} from './expression.ts';\nimport type {CustomQueryID} from './named.ts';\nimport type {QueryDelegate} from './query-delegate.ts';\nimport type {TTL} from './ttl.ts';\nimport type {TypedView} from './typed-view.ts';\n\ntype Selector<E extends TableSchema> = keyof E['columns'];\nexport type NoCompoundTypeSelector<T extends TableSchema> = Exclude<\n Selector<T>,\n JsonSelectors<T> | ArraySelectors<T>\n>;\n\ntype JsonSelectors<E extends TableSchema> = {\n [K in keyof E['columns']]: E['columns'][K] extends {type: 'json'} ? K : never;\n}[keyof E['columns']];\n\ntype ArraySelectors<E extends TableSchema> = {\n [K in keyof E['columns']]: E['columns'][K] extends SchemaValueWithCustomType<\n any[]\n >\n ? K\n : never;\n}[keyof E['columns']];\n\nexport type QueryTable<Q> = Q extends Query<any, infer T, any> ? T : never;\nexport const delegateSymbol = Symbol('delegate');\n\nexport type ExistsOptions = {flip: boolean};\n\nexport type GetFilterType<\n TSchema extends TableSchema,\n TColumn extends keyof TSchema['columns'],\n TOperator extends SimpleOperator,\n> = TOperator extends 'IS' | 'IS NOT'\n ? // SchemaValueToTSType adds null if the type is optional, but we add null\n // no matter what for dx reasons. See:\n // https://github.com/rocicorp/mono/pull/3576#discussion_r1925792608\n SchemaValueToTSType<TSchema['columns'][TColumn]> | null\n : TOperator extends 'IN' | 'NOT IN'\n ? // We don't want to compare to null in where clauses because it causes\n // confusing results:\n // https://zero.rocicorp.dev/docs/reading-data#comparing-to-null\n readonly Exclude<SchemaValueToTSType<TSchema['columns'][TColumn]>, null>[]\n : Exclude<SchemaValueToTSType<TSchema['columns'][TColumn]>, null>;\n\nexport type AvailableRelationships<\n TTable extends string,\n TSchema extends ZeroSchema,\n> = keyof TSchema['relationships'][TTable] & string;\n\nexport type DestTableName<\n TTable extends string,\n TSchema extends ZeroSchema,\n TRelationship extends string,\n> = LastInTuple<TSchema['relationships'][TTable][TRelationship]>['destSchema'];\n\ntype DestRow<\n TTable extends string,\n TSchema extends ZeroSchema,\n TRelationship extends string,\n> = TSchema['relationships'][TTable][TRelationship][0]['cardinality'] extends 'many'\n ? PullRow<DestTableName<TTable, TSchema, TRelationship>, TSchema>\n : PullRow<DestTableName<TTable, TSchema, TRelationship>, TSchema> | undefined;\n\ntype AddSubreturn<TExistingReturn, TSubselectReturn, TAs extends string> = {\n readonly [K in TAs]: undefined extends TSubselectReturn\n ? TSubselectReturn\n : readonly TSubselectReturn[];\n} extends infer TNewRelationship\n ? undefined extends TExistingReturn\n ? (Exclude<TExistingReturn, undefined> & TNewRelationship) | undefined\n : TExistingReturn & TNewRelationship\n : never;\n\nexport type PullTableSchema<\n TTable extends string,\n TSchemas extends ZeroSchema,\n> = TSchemas['tables'][TTable];\n\nexport type PullRow<TTable extends string, TSchema extends ZeroSchema> = {\n readonly [K in keyof PullTableSchema<\n TTable,\n TSchema\n >['columns']]: SchemaValueToTSType<\n PullTableSchema<TTable, TSchema>['columns'][K]\n >;\n} & {};\n\nexport type Row<\n T extends\n | TableSchema\n | Query<ZeroSchema, string, any>\n | ((...args: any) => Query<ZeroSchema, string, any>),\n> = T extends TableSchema\n ? {\n readonly [K in keyof T['columns']]: SchemaValueToTSType<T['columns'][K]>;\n }\n : T extends\n | Query<ZeroSchema, string, any>\n | ((...args: any) => Query<ZeroSchema, string, any>)\n ? QueryRowType<T>\n : never;\n\nexport type QueryRowType<Q> = Q extends (\n ...args: any\n) => Query<any, any, infer R>\n ? R\n : Q extends Query<any, any, infer R>\n ? R\n : never;\n\nexport type ZeRow<Q> = QueryRowType<Q>;\n\nexport type QueryResultType<Q> = Q extends\n | Query<ZeroSchema, string, any>\n | ((...args: any) => Query<ZeroSchema, string, any>)\n ? HumanReadable<QueryRowType<Q>>\n : never;\n\n/**\n * A hybrid query that runs on both client and server.\n * Results are returned immediately from the client followed by authoritative\n * results from the server.\n *\n * Queries are transactional in that all queries update at once when a new transaction\n * has been committed on the client or server. No query results will reflect stale state.\n *\n * A query can be:\n * - {@linkcode materialize | materialize}\n * - awaited (`then`/{@linkcode run})\n * - {@linkcode preload | preloaded}\n *\n * The normal way to use a query would be through your UI framework's bindings (e.g., useQuery(q))\n * or within a custom mutator.\n *\n * `materialize` and `run/then` are provided for more advanced use cases.\n * Remember that any `view` returned by `materialize` must be destroyed.\n *\n * A query can be run as a 1-shot query by awaiting it. E.g.,\n *\n * ```ts\n * const result = await z.query.issue.limit(10);\n * ```\n *\n * For more information on how to use queries, see the documentation:\n * https://zero.rocicorp.dev/docs/reading-data\n *\n * @typeParam TSchema The database schema type extending ZeroSchema\n * @typeParam TTable The name of the table being queried, must be a key of TSchema['tables']\n * @typeParam TReturn The return type of the query, defaults to PullRow<TTable, TSchema>\n */\nexport interface Query<\n TSchema extends ZeroSchema,\n TTable extends keyof TSchema['tables'] & string,\n TReturn = PullRow<TTable, TSchema>,\n> {\n /**\n * Format is used to specify the shape of the query results. This is used by\n * {@linkcode one} and it also describes the shape when using\n * {@linkcode related}.\n */\n readonly format: Format;\n\n /**\n * A string that uniquely identifies this query. This can be used to determine\n * if two queries are the same.\n *\n * The hash of a custom query, on the client, is the hash of its AST.\n * The hash of a custom query, on the server, is the hash of its name and args.\n *\n * The first allows many client-side queries to be pinned to the same backend query.\n * The second ensures we do not invoke a named query on the backend more than once for the same `name:arg` pairing.\n *\n * If the query.hash was of `name:args` then `useQuery` would de-dupe\n * queries with divergent ASTs.\n *\n * QueryManager will hash based on `name:args` since it is speaking with\n * the server which tracks queries by `name:args`.\n */\n hash(): string;\n readonly ast: AST;\n readonly customQueryID: CustomQueryID | undefined;\n\n nameAndArgs(\n name: string,\n args: ReadonlyArray<ReadonlyJSONValue>,\n ): Query<TSchema, TTable, TReturn>;\n [delegateSymbol](delegate: QueryDelegate): Query<TSchema, TTable, TReturn>;\n\n /**\n * Related is used to add a related query to the current query. This is used\n * for subqueries and joins. These relationships are defined in the\n * relationships section of the schema. The result of the query will\n * include the related rows in the result set as a sub object of the row.\n *\n * ```typescript\n * const row = await z.query.users\n * .related('posts');\n * // {\n * // id: '1',\n * // posts: [\n * // ...\n * // ]\n * // }\n * ```\n * If you want to add a subquery to the related query, you can do so by\n * providing a callback function that receives the related query as an argument.\n *\n * ```typescript\n * const row = await z.query.users\n * .related('posts', q => q.where('published', true));\n * // {\n * // id: '1',\n * // posts: [\n * // {published: true, ...},\n * // ...\n * // ]\n * // }\n * ```\n *\n * @param relationship The name of the relationship\n */\n related<TRelationship extends AvailableRelationships<TTable, TSchema>>(\n relationship: TRelationship,\n ): Query<\n TSchema,\n TTable,\n AddSubreturn<\n TReturn,\n DestRow<TTable, TSchema, TRelationship>,\n TRelationship\n >\n >;\n related<\n TRelationship extends AvailableRelationships<TTable, TSchema>,\n TSub extends Query<TSchema, string, any>,\n >(\n relationship: TRelationship,\n cb: (\n q: Query<\n TSchema,\n DestTableName<TTable, TSchema, TRelationship>,\n DestRow<TTable, TSchema, TRelationship>\n >,\n ) => TSub,\n ): Query<\n TSchema,\n TTable,\n AddSubreturn<\n TReturn,\n TSub extends Query<TSchema, string, infer TSubReturn>\n ? TSubReturn\n : never,\n TRelationship\n >\n >;\n\n /**\n * Represents a condition to filter the query results.\n *\n * @param field The column name to filter on.\n * @param op The operator to use for filtering.\n * @param value The value to compare against.\n *\n * @returns A new query instance with the applied filter.\n *\n * @example\n *\n * ```typescript\n * const query = db.query('users')\n * .where('age', '>', 18)\n * .where('name', 'LIKE', '%John%');\n * ```\n */\n where<\n TSelector extends NoCompoundTypeSelector<PullTableSchema<TTable, TSchema>>,\n TOperator extends SimpleOperator,\n >(\n field: TSelector,\n op: TOperator,\n value:\n | GetFilterType<PullTableSchema<TTable, TSchema>, TSelector, TOperator>\n | ParameterReference,\n ): Query<TSchema, TTable, TReturn>;\n /**\n * Represents a condition to filter the query results.\n *\n * This overload is used when the operator is '='.\n *\n * @param field The column name to filter on.\n * @param value The value to compare against.\n *\n * @returns A new query instance with the applied filter.\n *\n * @example\n * ```typescript\n * const query = db.query('users')\n * .where('age', 18)\n * ```\n */\n where<\n TSelector extends NoCompoundTypeSelector<PullTableSchema<TTable, TSchema>>,\n >(\n field: TSelector,\n value:\n | GetFilterType<PullTableSchema<TTable, TSchema>, TSelector, '='>\n | ParameterReference,\n ): Query<TSchema, TTable, TReturn>;\n\n /**\n * Represents a condition to filter the query results.\n *\n * @param expressionFactory A function that takes a query builder and returns an expression.\n *\n * @returns A new query instance with the applied filter.\n *\n * @example\n * ```typescript\n * const query = db.query('users')\n * .where(({cmp, or}) => or(cmp('age', '>', 18), cmp('name', 'LIKE', '%John%')));\n * ```\n */\n where(\n expressionFactory: ExpressionFactory<TSchema, TTable>,\n ): Query<TSchema, TTable, TReturn>;\n\n whereExists(\n relationship: AvailableRelationships<TTable, TSchema>,\n options?: ExistsOptions,\n ): Query<TSchema, TTable, TReturn>;\n whereExists<TRelationship extends AvailableRelationships<TTable, TSchema>>(\n relationship: TRelationship,\n cb: (\n q: Query<TSchema, DestTableName<TTable, TSchema, TRelationship>>,\n ) => Query<TSchema, string>,\n options?: ExistsOptions,\n ): Query<TSchema, TTable, TReturn>;\n\n /**\n * Skips the rows of the query until row matches the given row. If opts is\n * provided, it determines whether the match is inclusive.\n *\n * @param row The row to start from. This is a partial row object and only the provided\n * fields will be used for the comparison.\n * @param opts Optional options object that specifies whether the match is inclusive.\n * If `inclusive` is true, the row will be included in the result.\n * If `inclusive` is false, the row will be excluded from the result and the result\n * will start from the next row.\n *\n * @returns A new query instance with the applied start condition.\n */\n start(\n row: Partial<PullRow<TTable, TSchema>>,\n opts?: {inclusive: boolean},\n ): Query<TSchema, TTable, TReturn>;\n\n /**\n * Limits the number of rows returned by the query.\n * @param limit The maximum number of rows to return.\n *\n * @returns A new query instance with the applied limit.\n */\n limit(limit: number): Query<TSchema, TTable, TReturn>;\n\n /**\n * Orders the results by a specified column. If multiple orderings are\n * specified, the results will be ordered by the first column, then the\n * second column, and so on.\n *\n * @param field The column name to order by.\n * @param direction The direction to order the results (ascending or descending).\n *\n * @returns A new query instance with the applied order.\n */\n orderBy<TSelector extends Selector<PullTableSchema<TTable, TSchema>>>(\n field: TSelector,\n direction: 'asc' | 'desc',\n ): Query<TSchema, TTable, TReturn>;\n\n /**\n * Limits the number of rows returned by the query to a single row and then\n * unpacks the result so that you do not get an array of rows but a single\n * row. This is useful when you expect only one row to be returned and want to\n * work with the row directly.\n *\n * If the query returns no rows, the result will be `undefined`.\n *\n * @returns A new query instance with the applied limit to one row.\n */\n one(): Query<TSchema, TTable, TReturn | undefined>;\n\n /**\n * Creates a materialized view of the query. This is a view that will be kept\n * in memory and updated as the query results change.\n *\n * Most of the time you will want to use the `useQuery` hook or the\n * `run`/`then` method to get the results of a query. This method is only\n * needed if you want to access to lower level APIs of the view.\n *\n * @param ttl Time To Live. This is the amount of time to keep the rows\n * associated with this query after `TypedView.destroy`\n * has been called.\n */\n materialize(ttl?: TTL): TypedView<HumanReadable<TReturn>>;\n /**\n * Creates a custom materialized view using a provided factory function. This\n * allows framework-specific bindings (like SolidJS, Vue, etc.) to create\n * optimized views.\n *\n * @param factory A function that creates a custom view implementation\n * @param ttl Optional Time To Live for the view's data after destruction\n * @returns A custom view instance of type {@linkcode T}\n *\n * @example\n * ```ts\n * const view = query.materialize(createSolidViewFactory, '1m');\n * ```\n */\n materialize<T>(\n factory: ViewFactory<TSchema, TTable, TReturn, T>,\n ttl?: TTL,\n ): T;\n\n /**\n * Executes the query and returns the result once. The `options` parameter\n * specifies whether to wait for complete results or return immediately,\n * and the time to live for the query.\n *\n * - `{type: 'unknown'}`: Returns a snapshot of the data immediately.\n * - `{type: 'complete'}`: Waits for the latest, complete results from the server.\n *\n * By default, `run` uses `{type: 'unknown'}` to avoid waiting for the server.\n *\n * `Query` implements `PromiseLike`, and calling `then` on it will invoke `run`\n * with the default behavior (`unknown`).\n *\n * @param options Options to control the result type.\n * @param options.type The type of result to return.\n * @param options.ttl Time To Live. This is the amount of time to keep the rows\n * associated with this query after the returned promise has\n * resolved.\n * @returns A promise resolving to the query result.\n *\n * @example\n * ```js\n * const result = await query.run({type: 'complete', ttl: '1m'});\n * ```\n */\n run(options?: RunOptions): Promise<HumanReadable<TReturn>>;\n\n /**\n * Preload loads the data into the clients cache without keeping it in memory.\n * This is useful for preloading data that will be used later.\n *\n * @param options Options for preloading the query.\n * @param options.ttl Time To Live. This is the amount of time to keep the rows\n * associated with this query after {@linkcode cleanup} has\n * been called.\n */\n preload(options?: PreloadOptions): {\n cleanup: () => void;\n complete: Promise<void>;\n };\n}\n\nexport type PreloadOptions = {\n /**\n * Time To Live. This is the amount of time to keep the rows associated with\n * this query after {@linkcode cleanup} has been called.\n */\n ttl?: TTL | undefined;\n};\n\nexport type MaterializeOptions = PreloadOptions;\n\n/**\n * A helper type that tries to make the type more readable.\n */\nexport type HumanReadable<T> = undefined extends T ? Expand<T> : Expand<T>[];\n\n/**\n * A helper type that tries to make the type more readable.\n */\n// Note: opaque types expand incorrectly.\nexport type HumanReadableRecursive<T> = undefined extends T\n ? ExpandRecursive<T>\n : ExpandRecursive<T>[];\n\n/**\n * The kind of results we want to wait for when using {@linkcode run} on {@linkcode Query}.\n *\n * `unknown` means we don't want to wait for the server to return results. The result is a\n * snapshot of the data at the time the query was run.\n *\n * `complete` means we want to ensure that we have the latest result from the server. The\n * result is a complete and up-to-date view of the data. In some cases this means that we\n * have to wait for the server to return results. To ensure that we have the result for\n * this query you can preload it before calling run. See {@link preload}.\n *\n * By default, `run` uses `{type: 'unknown'}` to avoid waiting for the server.\n *\n * The `ttl` option is used to specify the time to live for the query. This is the amount of\n * time to keep the rows associated with this query after the promise has resolved.\n */\nexport type RunOptions = {\n type: 'unknown' | 'complete';\n ttl?: TTL;\n};\n\nexport const DEFAULT_RUN_OPTIONS_UNKNOWN = {\n type: 'unknown',\n} as const;\n\nexport const DEFAULT_RUN_OPTIONS_COMPLETE = {\n type: 'complete',\n} as const;\n", "import type {Upstream} from '../../../zero-protocol/src/up.ts';\n\nexport function send(ws: WebSocket, data: Upstream) {\n ws.send(JSON.stringify(data));\n}\n", "import {resolver} from '@rocicorp/resolver';\nimport type {\n ClientGroupID,\n ClientID,\n} from '../../../replicache/src/sync/ids.ts';\nimport {BroadcastChannel} from '../../../shared/src/broadcast-channel.ts';\nimport {getBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\n\n/**\n * The prefix for the keys used for the locks and the broadcast channels.\n */\nconst keyPrefix = 'zero-active';\n\nfunction toLockName(clientGroupID: string, clientID: string): string {\n return `${keyPrefix}/${clientGroupID}/${clientID}`;\n}\n\nfunction toBroadcastChannelName(clientGroupID: string): string {\n return `${keyPrefix}/${clientGroupID}`;\n}\n\nfunction fromLockName(\n lockKey: string | undefined,\n): {clientGroupID: string; clientID: string} | undefined {\n if (!lockKey || !lockKey.startsWith(keyPrefix)) {\n return undefined;\n }\n const parts = lockKey.slice(keyPrefix.length).split('/');\n if (parts.length !== 3) {\n return undefined;\n }\n return {\n clientGroupID: parts[1],\n clientID: parts[2],\n };\n}\n\nfunction ignoreAbortError(e: unknown) {\n if (e instanceof Error && e.name === 'AbortError') {\n // Ignore the AbortError, it is expected when the signal is aborted.\n return;\n }\n throw e;\n}\n\n/**\n * A class that lists the active clients in a client group. It uses the\n * `navigator.locks` API to manage locks for each client. The class is designed\n * to be used in a browser environment where the `navigator.locks` API is\n * available.\n *\n * When navigator.locks is not available, it will return a set only containing\n * the clients in the current scripting context (window, worker, etc).\n *\n * It uses one exclusive lock per client, identified by a combination of\n * `clientGroupID` and `clientID`. Then the `query` method is used to get the\n * list of all clients that hold or are waiting for locks in the same client\n * group.\n *\n * It also tries to get a shared lock for each client in the group, so that it\n * can be notified when the exclusive lock is released. This allows the class to\n * keep track of the active clients in the group and notify when an existing\n * client is removed.\n *\n * The class also uses a `BroadcastChannel` to notify other clients in the\n * same client group when a new client is added. This allows the class to keep\n * track of the active clients in the group and notify when a new client is\n * added.\n */\nexport class ActiveClientsManager {\n readonly clientGroupID: string;\n readonly clientID: string;\n readonly #resolver = resolver<void>();\n readonly #lockManager: ClientLockManager;\n readonly #activeClients: Set<string> = new Set();\n\n /**\n * A callback that is called when a client is added to the client group.\n * It receives the client ID of the added client.\n */\n onAdd: ((clientID: string) => void) | undefined;\n\n /**\n * A callback that is called when a client is deleted from the client group.\n * It receives the client ID of the deleted client.\n */\n onDelete:\n | ((clientID: ClientID, clientGroupID: ClientGroupID) => void)\n | undefined;\n\n /**\n * Creates an instance of `ActiveClientsManager` for the specified client\n * group and client ID. It will return a promise that resolves when the\n * instance is ready to use, which means that it has successfully acquired the\n * exclusive lock for the client and has retrieved the list of active clients.\n */\n static async create(\n clientGroupID: string,\n clientID: string,\n signal: AbortSignal,\n ): Promise<ActiveClientsManager> {\n const instance = new ActiveClientsManager(clientGroupID, clientID, signal);\n await instance.#init(signal);\n return instance;\n }\n\n private constructor(\n clientGroupID: string,\n clientID: string,\n signal: AbortSignal,\n ) {\n this.clientGroupID = clientGroupID;\n this.clientID = clientID;\n this.#lockManager = getClientLockManager(signal);\n this.#activeClients.add(clientID);\n }\n\n async #init(signal: AbortSignal): Promise<void> {\n const {clientGroupID, clientID} = this;\n const name = toLockName(clientGroupID, clientID);\n\n // The BroadcastChannel is used to notify other clients in the same client\n // group when a new client is added. It listens for messages that contain\n // the lock name, which is used to identify the client. When a message is\n // received, it checks if the client belongs to the same client group and\n // adds it to the list of active clients. It also adds a shared lock for\n // the client, so that it can be notified when the exclusive lock is\n // released.\n const channel = new BroadcastChannel(toBroadcastChannelName(clientGroupID));\n channel.addEventListener(\n 'message',\n e => {\n const client = fromLockName(e.data);\n if (client?.clientGroupID === this.clientGroupID) {\n this.#addClient(client.clientID);\n }\n },\n {signal},\n );\n\n this.#lockManager\n .request(name, 'exclusive', () => this.#resolver.promise)\n .catch(ignoreAbortError);\n\n signal.addEventListener(\n 'abort',\n () => {\n this.#lockManager.release(name, () => this.#resolver.resolve());\n channel.close();\n },\n {once: true},\n );\n\n for (const clientID of await this.#getActiveClients()) {\n if (clientID !== this.clientID) {\n this.#addClient(clientID);\n }\n }\n\n if (!signal.aborted) {\n channel.postMessage(name);\n }\n }\n\n get activeClients(): ReadonlySet<string> {\n return this.#activeClients;\n }\n\n async #getActiveClients(): Promise<Set<string>> {\n const activeClients: Set<string> = new Set();\n\n for await (const lockName of this.#lockManager.queryExclusive()) {\n const client = fromLockName(lockName);\n if (client?.clientGroupID === this.clientGroupID) {\n activeClients.add(client.clientID);\n }\n }\n\n return activeClients;\n }\n\n /**\n * This gets called when a new client is added to the client group.\n *\n * It will request a shared lock for the client, and when the exclusive lock\n * is released, it will notify that the client has been deactivated.\n */\n #addSharedLockForOtherClient(clientID: string): void {\n const name = toLockName(this.clientGroupID, clientID);\n this.#lockManager\n .request(name, 'shared', () => this.#removeClient(clientID))\n .catch(ignoreAbortError);\n }\n\n #addClient(clientID: string): void {\n if (!this.#activeClients.has(clientID)) {\n this.#activeClients.add(clientID);\n this.#addSharedLockForOtherClient(clientID);\n this.onAdd?.(clientID);\n }\n }\n\n #removeClient(clientID: string): void {\n if (this.#activeClients.delete(clientID)) {\n this.onDelete?.(clientID, this.clientGroupID);\n }\n }\n}\n\nfunction getClientLockManager(signal: AbortSignal): ClientLockManager {\n const locks = getBrowserGlobal('navigator')?.locks;\n if (locks) {\n return new NativeClientLockManager(locks, signal);\n }\n return new MockClientLockManager();\n}\n\ninterface ClientLockManager {\n request(\n name: string,\n mode: 'exclusive' | 'shared',\n fn: () => MaybePromise<void>,\n ): Promise<void>;\n release(name: string, fn: () => void): void;\n queryExclusive(): AsyncIterable<string>;\n}\n\nclass NativeClientLockManager implements ClientLockManager {\n readonly #locks: LockManager;\n readonly #signal: AbortSignal;\n\n constructor(locks: LockManager, signal: AbortSignal) {\n this.#locks = locks;\n this.#signal = signal;\n }\n\n request(\n name: string,\n mode: 'exclusive' | 'shared',\n fn: () => Promise<void>,\n ): Promise<void> {\n return this.#locks.request(name, {mode, signal: this.#signal}, fn);\n }\n\n release(_name: string, fn: () => void): void {\n fn();\n }\n\n async *queryExclusive(): AsyncIterable<string> {\n const snapshot = await this.#locks.query();\n for (const lock of [\n ...(snapshot.held ?? []),\n ...(snapshot.pending ?? []),\n ]) {\n if (lock.mode === 'exclusive' && lock.name) {\n yield lock.name;\n }\n }\n }\n}\n\nconst mockLockNames = new Set<string>();\n\nconst mockListeners: Set<(name: string) => void> = new Set();\n\nclass MockClientLockManager implements ClientLockManager {\n readonly #listeners: Set<(name: string) => void> = new Set();\n\n request(\n name: string,\n mode: 'exclusive' | 'shared',\n fn: () => void | Promise<void>,\n ): Promise<void> {\n if (mode === 'exclusive') {\n mockLockNames.add(name);\n } else {\n mode satisfies 'shared';\n\n // For the mock locks we will add a listener that will notify us when the\n // lock is deleted from the `allMockLocks` set.\n const listener = (removed: string) => {\n if (removed === name) {\n mockListeners.delete(listener);\n return fn();\n }\n };\n mockListeners.add(listener);\n this.#listeners.add(listener);\n }\n return Promise.resolve();\n }\n\n release(name: string, fn: () => void): void {\n mockLockNames.delete(name);\n for (const listener of mockListeners) {\n listener(name);\n }\n for (const listener of this.#listeners) {\n mockListeners.delete(listener);\n }\n fn();\n }\n\n async *queryExclusive(): AsyncIterable<string> {\n yield* mockLockNames;\n }\n}\n", "import {type Resolver, resolver} from '@rocicorp/resolver';\nimport {Subscribable} from '../../../shared/src/subscribable.ts';\nimport {ConnectionStatus} from './connection-status.ts';\nimport {\n ClientError,\n isClientError,\n type AuthError,\n type ZeroError,\n} from './error.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\n\nconst DEFAULT_TIMEOUT_CHECK_INTERVAL_MS = 1_000;\n\n/**\n * The current connection state of the Zero instance. It can be one of the following states:\n *\n * - `connecting`: The client is actively trying to connect every 5 seconds.\n * - `attempt` counts the number of retries within the current retry window,\n * - `disconnectAt` is the epoch timestamp when the client will transition to `disconnected` state\n * - `reason` is the optional error associated with the connection attempt.\n * - `disconnected`: The client is now in an \"offline\" state. It will continue\n * to try to connect every 5 seconds.\n * - `connected`: The client has opened a successful connection to the server.\n * - `needs-auth`: Authentication is invalid or expired. No connection retries will be made\n * until the host application calls `connect({auth: token})`.\n * - `reason` is the `ZeroError` associated with the error state.\n * - `error`: A fatal error occurred. No connection retries will be made until the host\n * application calls `connect()` again.\n * - `reason` is the `ZeroError` associated with the error state.\n * - `closed`: The client was shut down (for example via `zero.close()`). This is\n * a terminal state, and a new Zero instance must be created to reconnect.\n */\nexport type ConnectionState =\n | {\n name: ConnectionStatus.Disconnected;\n reason: ZeroError;\n }\n | {\n name: ConnectionStatus.Connecting;\n attempt: number;\n disconnectAt: number;\n reason?: ZeroError | undefined;\n }\n | {\n name: ConnectionStatus.Connected;\n }\n | {\n name: ConnectionStatus.NeedsAuth;\n reason: AuthError;\n }\n | {\n name: ConnectionStatus.Error;\n reason: ZeroError;\n }\n | {\n name: ConnectionStatus.Closed;\n reason: ZeroError;\n };\n\nexport type ConnectionManagerOptions = {\n /**\n * The amount of time we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n disconnectTimeoutMs: number;\n /**\n * How frequently we check whether the connecting timeout has elapsed.\n * Defaults to 1 second.\n */\n timeoutCheckIntervalMs?: number | undefined;\n};\n\nconst TERMINAL_STATES = [\n ConnectionStatus.NeedsAuth,\n ConnectionStatus.Error,\n] as const satisfies ConnectionStatus[];\n\ntype TerminalConnectionStatus = (typeof TERMINAL_STATES)[number];\ntype TerminalConnectionState = Extract<\n ConnectionState,\n {name: TerminalConnectionStatus}\n>;\n\nexport class ConnectionManager extends Subscribable<ConnectionState> {\n #state: ConnectionState;\n\n /**\n * The timestamp when we first started trying to connect.\n * This is used to track the retry window.\n * Reset to undefined when we successfully connect or when we transition to disconnected.\n */\n #connectingStartedAt: number | undefined;\n\n /**\n * The amount of time we allow for continuous connecting attempts before\n * transitioning to disconnected state.\n */\n #disconnectTimeoutMs: number;\n\n /**\n * Handle for the timeout interval that periodically checks whether we've\n * exceeded the allowed connecting window.\n */\n #timeoutInterval: ReturnType<typeof setInterval> | undefined;\n\n /**\n * Interval duration for checking whether the connecting timeout has elapsed.\n */\n #timeoutCheckIntervalMs: number;\n\n /**\n * Resolver used to signal waiting callers when the state changes.\n */\n #stateChangeResolver: Resolver<ConnectionState> = resolver();\n\n constructor(options: ConnectionManagerOptions) {\n super();\n\n const now = Date.now();\n\n this.#disconnectTimeoutMs = options.disconnectTimeoutMs;\n this.#timeoutCheckIntervalMs =\n options.timeoutCheckIntervalMs ?? DEFAULT_TIMEOUT_CHECK_INTERVAL_MS;\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 0,\n disconnectAt: now + this.#disconnectTimeoutMs,\n };\n this.#connectingStartedAt = now;\n this.#maybeStartTimeoutInterval();\n }\n\n get state(): ConnectionState {\n return this.#state;\n }\n\n /**\n * Returns true if the current state is equal to the given status.\n */\n is(status: ConnectionStatus): boolean {\n return this.#state.name === status;\n }\n\n /**\n * Returns true if the current state is a terminal state\n * that can be recovered from by calling connect().\n */\n isInTerminalState(): boolean {\n return ConnectionManager.isTerminalState(this.#state);\n }\n\n /**\n * Returns true if the given status is a terminal state\n * that can be recovered from by calling connect().\n */\n static isTerminalState(\n state: ConnectionState,\n ): state is TerminalConnectionState {\n return (TERMINAL_STATES as readonly ConnectionStatus[]).includes(\n state.name,\n );\n }\n\n /**\n * Returns true if the run loop should continue.\n * The run loop continues in all states except closed.\n * In needs-auth and error states, the run loop pauses and waits for connect() to be called.\n */\n shouldContinueRunLoop(): boolean {\n return this.#state.name !== ConnectionStatus.Closed;\n }\n\n /**\n * Waits for the next state change.\n * @returns A promise that resolves when the next state change occurs.\n */\n waitForStateChange(): Promise<ConnectionState> {\n return this.#nextStatePromise();\n }\n\n /**\n * Transition to connecting state.\n *\n * This starts the 5-minute timeout timer, but if we've entered disconnected state,\n * we stay there and continue retrying.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connecting(reason?: ZeroError): {\n nextStatePromise: Promise<ConnectionState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // we cannot intentionally transition from disconnected to connecting\n // disconnected can transition to connected on successful connection\n // or a terminal state\n if (this.#state.name === ConnectionStatus.Disconnected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n const now = Date.now();\n\n // If we're already connecting, increment the attempt counter\n if (this.#state.name === ConnectionStatus.Connecting) {\n this.#state = {\n ...this.#state,\n attempt: this.#state.attempt + 1,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n // Starting a new connecting session\n // If #connectingStartedAt is undefined, this is a fresh start - set it to now\n // If it's already set, we're retrying within the same retry window, so keep it\n if (this.#connectingStartedAt === undefined) {\n this.#connectingStartedAt = now;\n }\n\n const disconnectAt = this.#connectingStartedAt + this.#disconnectTimeoutMs;\n\n this.#state = {\n name: ConnectionStatus.Connecting,\n attempt: 1,\n disconnectAt,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n this.#maybeStartTimeoutInterval();\n return {nextStatePromise};\n }\n\n /**\n * Transition to connected state.\n * This resets the connecting timeout timer.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n connected(): {nextStatePromise: Promise<ConnectionState>} {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already connected, no-op\n if (this.#state.name === ConnectionStatus.Connected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer on successful connection\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Connected,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to disconnected state.\n * This is called when the 5-minute timeout expires, or when we're intentionally\n * disconnecting due to an error (this will eventually be a separate state, error).\n * The run loop will continue trying to reconnect.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n disconnected(reason: ZeroError): {\n nextStatePromise: Promise<ConnectionState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already disconnected, no-op\n if (this.#state.name === ConnectionStatus.Disconnected) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // When transitioning from connected to disconnected, we've lost a connection\n // we previously had. Clear the timeout timer so we can start a fresh 5-minute window.\n if (this.#state.name === ConnectionStatus.Connected) {\n this.#connectingStartedAt = undefined;\n }\n // When transitioning from connecting to disconnected (e.g., due to timeout),\n // we keep the start time to maintain the context that we've been trying for a while.\n\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Disconnected,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to needs-auth state.\n * This pauses the run loop until connect() is called with new credentials.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n needsAuth(reason: AuthError): {\n nextStatePromise: Promise<ConnectionState>;\n } {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in needs-auth state, no-op\n if (this.#state.name === ConnectionStatus.NeedsAuth) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.NeedsAuth,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to error state.\n * This pauses the run loop until connect() is called.\n * Resets the retry window and attempt counter.\n *\n * @returns An object containing a promise that resolves on the next state change.\n */\n error(reason: ZeroError): {nextStatePromise: Promise<ConnectionState>} {\n // cannot transition from closed to any other status\n if (this.#state.name === ConnectionStatus.Closed) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Already in error state, no-op\n if (this.#state.name === ConnectionStatus.Error) {\n return {nextStatePromise: this.#nextStatePromise()};\n }\n\n // Reset the timeout timer and connecting start time\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Error,\n reason,\n };\n const nextStatePromise = this.#publishStateAndGetPromise();\n return {nextStatePromise};\n }\n\n /**\n * Transition to closed state.\n * This is terminal - no further transitions are allowed.\n */\n closed() {\n // Already closed, no-op\n if (this.#state.name === ConnectionStatus.Closed) {\n return;\n }\n\n this.#connectingStartedAt = undefined;\n this.#maybeStopTimeoutInterval();\n\n this.#state = {\n name: ConnectionStatus.Closed,\n reason: new ClientError({\n kind: ClientErrorKind.ClientClosed,\n message: 'Zero was explicitly closed by calling zero.close()',\n }),\n };\n this.#publishState();\n this.cleanup();\n return;\n }\n\n override cleanup = (): void => {\n this._listeners.clear();\n this.#resolveNextStateWaiters();\n };\n\n #resolveNextStateWaiters(): void {\n this.#stateChangeResolver.resolve(this.#state);\n this.#stateChangeResolver = resolver();\n }\n\n #publishState(): void {\n this.notify(this.#state);\n this.#resolveNextStateWaiters();\n }\n\n #nextStatePromise(): Promise<ConnectionState> {\n return this.#stateChangeResolver.promise;\n }\n\n #publishStateAndGetPromise(): Promise<ConnectionState> {\n this.#publishState();\n return this.#nextStatePromise();\n }\n\n /**\n * Check if we should transition from connecting to disconnected due to timeout.\n * Returns true if the transition happened.\n */\n #checkTimeout(): boolean {\n if (this.#state.name !== ConnectionStatus.Connecting) {\n return false;\n }\n\n const now = Date.now();\n if (now >= this.#state.disconnectAt) {\n this.disconnected(\n new ClientError({\n kind: ClientErrorKind.DisconnectTimeout,\n message: `Zero was unable to connect for ${Math.floor(this.#disconnectTimeoutMs / 1000)} seconds and was disconnected`,\n }),\n );\n return true;\n }\n\n return false;\n }\n\n #maybeStartTimeoutInterval(): void {\n if (this.#timeoutInterval !== undefined) {\n return;\n }\n this.#timeoutInterval = setInterval(() => {\n this.#checkTimeout();\n }, this.#timeoutCheckIntervalMs);\n }\n\n #maybeStopTimeoutInterval(): void {\n if (this.#timeoutInterval === undefined) {\n return;\n }\n clearInterval(this.#timeoutInterval);\n this.#timeoutInterval = undefined;\n }\n}\n\n/**\n * Used to trigger the catch block when a terminal state is reached.\n *\n * @param state - The current connection state.\n */\nexport const throwIfConnectionError = (state: ConnectionState) => {\n if (\n ConnectionManager.isTerminalState(state) ||\n state.name === ConnectionStatus.Closed ||\n ((state.name === ConnectionStatus.Connecting ||\n state.name === ConnectionStatus.Disconnected) &&\n state.reason)\n ) {\n if (\n isClientError(state.reason) &&\n (state.reason.kind === ClientErrorKind.ConnectTimeout ||\n state.reason.kind === ClientErrorKind.AbruptClose ||\n state.reason.kind === ClientErrorKind.CleanClose)\n ) {\n return;\n }\n throw state.reason;\n }\n};\n", "export class Subscribable<\n TArgs,\n TListener extends (obj: TArgs) => unknown = (obj: TArgs) => unknown,\n> {\n protected _listeners = new Set<TListener>();\n\n /**\n * Subscribe to the subscribable.\n *\n * @param listener - The listener to subscribe to.\n * @returns A function to unsubscribe from the subscribable.\n */\n subscribe = (listener: TListener): (() => void) => {\n this._listeners.add(listener);\n\n return () => {\n this._listeners.delete(listener);\n };\n };\n\n /**\n * Notify all listeners.\n *\n * @param update - The update to notify listeners with.\n */\n notify = (update: TArgs): void => {\n this._listeners.forEach(listener => listener(update));\n };\n\n hasListeners = (): boolean => this._listeners.size > 0;\n\n /**\n * Unsubscribe all listeners.\n */\n cleanup = (): void => {\n this._listeners.clear();\n };\n}\n", "import type {ConnectionManager, ConnectionState} from './connection-manager.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\nexport interface Source<T> {\n /**\n * The current state value.\n */\n readonly current: T;\n\n /**\n * Subscribe to state changes.\n *\n * @param listener - Called when the state changes with the new state value.\n * @returns A function to unsubscribe from state changes.\n */\n subscribe(listener: (state: T) => void): () => void;\n}\n\n/**\n * Connection API for managing Zero's connection lifecycle.\n */\nexport interface Connection {\n /**\n * The current connection state as a subscribable value.\n */\n readonly state: Source<ConnectionState>;\n\n /**\n * Resumes the connection from a terminal state.\n *\n * If called when not in a terminal state, this method does nothing.\n *\n * @param opts - Optional connection options\n * @param opts.auth - Token to use for authentication. If provided, this overrides\n * the stored auth credential for this connection attempt.\n * If `null` or `undefined`, the stored auth credential is cleared.\n * @returns A promise that resolves once the connection state has transitioned to connecting.\n */\n connect(opts?: {auth: string | null | undefined}): Promise<void>;\n}\n\nexport class ConnectionImpl implements Connection {\n readonly #connectionManager: ConnectionManager;\n readonly #lc: ZeroLogContext;\n readonly #source: ConnectionSource;\n readonly #setAuth: (auth: string | null | undefined) => void;\n\n constructor(\n connectionManager: ConnectionManager,\n lc: ZeroLogContext,\n setAuth: (auth: string | null | undefined) => void,\n ) {\n this.#connectionManager = connectionManager;\n this.#lc = lc;\n this.#source = new ConnectionSource(connectionManager);\n this.#setAuth = setAuth;\n }\n\n get state(): Source<ConnectionState> {\n return this.#source;\n }\n\n async connect(opts?: {auth: string | null | undefined}): Promise<void> {\n const lc = this.#lc.withContext('connect');\n\n if (opts && 'auth' in opts) {\n lc.debug?.('Updating auth credential from connect()');\n this.#setAuth(opts.auth);\n }\n\n // only allow connect() to be called from a terminal state\n if (!this.#connectionManager.isInTerminalState()) {\n lc.debug?.(\n 'connect() called but not in a terminal state. Current state:',\n this.#connectionManager.state.name,\n );\n return;\n }\n\n lc.info?.(\n `Resuming connection from state: ${this.#connectionManager.state.name}`,\n );\n\n // Transition to connecting, which will trigger the state change resolver\n // and unblock the run loop. Wait for the next state change (connected, disconnected, etc.)\n const {nextStatePromise} = this.#connectionManager.connecting();\n await nextStatePromise;\n }\n}\n\nexport class ConnectionSource implements Source<ConnectionState> {\n readonly #connectionManager: ConnectionManager;\n\n constructor(connectionManager: ConnectionManager) {\n this.#connectionManager = connectionManager;\n }\n\n get current(): ConnectionState {\n return this.#connectionManager.state;\n }\n\n get subscribe() {\n return this.#connectionManager.subscribe;\n }\n}\n", "import {compareUTF8} from 'compare-utf8';\nimport {BTreeSet} from '../../../shared/src/btree-set.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport type {Storage} from './operator.ts';\nimport type {Stream} from './stream.ts';\n\ntype Entry = [key: string, value: JSONValue];\n\nfunction comparator(a: Entry, b: Entry): number {\n return compareUTF8(a[0], b[0]);\n}\n\n/**\n * MemoryStorage is a simple in-memory implementation of `Storage` for use\n * on the client and in tests.\n */\nexport class MemoryStorage implements Storage {\n #data: BTreeSet<Entry> = new BTreeSet(comparator);\n\n set(key: string, value: JSONValue) {\n this.#data.add([key, value]);\n }\n\n get(key: string, def?: JSONValue): JSONValue | undefined {\n const r = this.#data.get([key, null]);\n if (r !== undefined) {\n return r[1];\n }\n return def;\n }\n\n del(key: string) {\n this.#data.delete([key, null]);\n }\n\n *scan(options?: {prefix: string}): Stream<[string, JSONValue]> {\n for (const entry of this.#data.valuesFrom(\n options && [options.prefix, null],\n )) {\n if (options && !entry[0].startsWith(options.prefix)) {\n return;\n }\n yield entry;\n }\n }\n\n cloneData(): Record<string, JSONValue> {\n return structuredClone(Object.fromEntries(this.#data.values()));\n }\n}\n", "import {assert} from './asserts.ts';\n\nconst MAX_NODE_SIZE = 32;\n\ntype Comparator<K> = (a: K, b: K) => number;\nexport class BTreeSet<K> {\n #root: BNode<K> = emptyLeaf as BNode<K>;\n size: number = 0;\n\n readonly comparator: Comparator<K>;\n\n constructor(comparator: Comparator<K>, entries?: IterableIterator<K>) {\n this.comparator = comparator;\n if (entries) {\n for (const key of entries) {\n this.add(key);\n }\n }\n }\n\n /** Releases the tree so that its size is 0. */\n clear() {\n this.#root = emptyLeaf as BNode<K>;\n this.size = 0;\n }\n\n clone() {\n this.#root.isShared = true;\n const ret = new BTreeSet<K>(this.comparator);\n ret.#root = this.#root;\n ret.size = this.size;\n return ret;\n }\n\n get(key: K): K | undefined {\n return this.#root.get(key, this);\n }\n\n add(key: K): this {\n if (this.#root.isShared) this.#root = this.#root.clone();\n const result = this.#root.set(key, this);\n if (result === null) return this;\n // Root node has split, so create a new root node.\n this.#root = new BNodeInternal<K>([this.#root, result]);\n return this;\n }\n\n /**\n * Returns true if the key exists in the B+ tree, false if not.\n * Use get() for best performance; use has() if you need to\n * distinguish between \"undefined value\" and \"key not present\".\n * @param key Key to detect\n * @description Computational complexity: O(log size)\n */\n has(key: K): boolean {\n return this.#root.has(key, this);\n }\n\n /**\n * Removes a single key-value pair from the B+ tree.\n * @param key Key to find\n * @returns true if a pair was found and removed, false otherwise.\n * @description Computational complexity: O(log size)\n */\n delete(key: K): boolean {\n return this.#delete(key);\n }\n\n #delete(key: K): boolean {\n let root = this.#root;\n if (root.isShared) {\n this.#root = root = root.clone();\n }\n try {\n return root.delete(key, this);\n } finally {\n let isShared;\n while (root.keys.length <= 1 && root.isInternal()) {\n isShared ||= root.isShared;\n this.#root = root =\n root.keys.length === 0 ? emptyLeaf : root.children[0];\n }\n // If any ancestor of the new root was shared, the new root must also be shared\n if (isShared) {\n root.isShared = true;\n }\n }\n }\n\n keys(): IterableIterator<K> {\n return valuesFrom(this.#root, this.comparator, undefined, true);\n }\n\n values(): IterableIterator<K> {\n return valuesFrom(this.#root, this.comparator, undefined, true);\n }\n\n valuesFrom(lowestKey?: K, inclusive: boolean = true): IterableIterator<K> {\n return valuesFrom(this.#root, this.comparator, lowestKey, inclusive);\n }\n\n valuesReversed(): IterableIterator<K> {\n return valuesFromReversed(\n this.#maxKey(),\n this.#root,\n this.comparator,\n undefined,\n true,\n );\n }\n\n valuesFromReversed(\n highestKey?: K,\n inclusive: boolean = true,\n ): IterableIterator<K> {\n return valuesFromReversed(\n this.#maxKey(),\n this.#root,\n this.comparator,\n highestKey,\n inclusive,\n );\n }\n\n /** Gets the highest key in the tree. Complexity: O(1) */\n #maxKey(): K | undefined {\n return this.#root.maxKey();\n }\n\n [Symbol.iterator](): IterableIterator<K> {\n return this.keys();\n }\n}\n\nfunction valuesFrom<K>(\n root: BNode<K>,\n comparator: Comparator<K>,\n lowestKey: K | undefined,\n inclusive: boolean,\n): IterableIterator<K> {\n const info = findPath(lowestKey, root, comparator);\n if (info === undefined) {\n return iterator<K>(() => ({done: true, value: undefined}));\n }\n\n let [nodeQueue, nodeIndex, leaf] = info;\n let i =\n lowestKey === undefined\n ? -1\n : indexOf(lowestKey, leaf.keys, 0, comparator) - 1;\n\n if (\n !inclusive &&\n i < leaf.keys.length &&\n // +1 because we did -1 above.\n comparator(leaf.keys[i + 1], lowestKey!) === 0\n ) {\n i++;\n }\n\n return iterator<K>(() => {\n for (;;) {\n if (++i < leaf.keys.length) {\n return {done: false, value: leaf.keys[i]};\n }\n\n let level = -1;\n for (;;) {\n if (++level >= nodeQueue.length) {\n return {done: true, value: undefined};\n }\n if (++nodeIndex[level] < nodeQueue[level].length) {\n break;\n }\n }\n for (; level > 0; level--) {\n nodeQueue[level - 1] = (\n nodeQueue[level][nodeIndex[level]] as BNodeInternal<K>\n ).children;\n nodeIndex[level - 1] = 0;\n }\n leaf = nodeQueue[0][nodeIndex[0]];\n i = -1;\n }\n });\n}\n\nfunction valuesFromReversed<K>(\n maxKey: K | undefined,\n root: BNode<K>,\n comparator: Comparator<K>,\n highestKey: K | undefined,\n inclusive: boolean,\n): IterableIterator<K> {\n if (highestKey === undefined) {\n highestKey = maxKey;\n if (highestKey === undefined)\n return iterator<K>(() => ({done: true, value: undefined})); // collection is empty\n }\n let [nodeQueue, nodeIndex, leaf] =\n findPath(highestKey, root, comparator) ||\n findPath(maxKey, root, comparator)!;\n assert(!nodeQueue[0] || leaf === nodeQueue[0][nodeIndex[0]]);\n let i = indexOf(highestKey, leaf.keys, 0, comparator);\n if (\n inclusive &&\n i < leaf.keys.length &&\n comparator(leaf.keys[i], highestKey) <= 0\n ) {\n i++;\n }\n\n return iterator<K>(() => {\n for (;;) {\n if (--i >= 0) {\n return {done: false, value: leaf.keys[i]};\n }\n\n let level;\n // Advance to the next leaf node\n for (level = -1; ; ) {\n if (++level >= nodeQueue.length) {\n return {done: true, value: undefined};\n }\n if (--nodeIndex[level] >= 0) {\n break;\n }\n }\n for (; level > 0; level--) {\n nodeQueue[level - 1] = (\n nodeQueue[level][nodeIndex[level]] as BNodeInternal<K>\n ).children;\n nodeIndex[level - 1] = nodeQueue[level - 1].length - 1;\n }\n leaf = nodeQueue[0][nodeIndex[0]];\n i = leaf.keys.length;\n }\n });\n}\n\nfunction findPath<K>(\n key: K | undefined,\n root: BNode<K>,\n comparator: Comparator<K>,\n): [nodeQueue: BNode<K>[][], nodeIndex: number[], leaf: BNode<K>] | undefined {\n let nextNode = root;\n const nodeQueue: BNode<K>[][] = [];\n const nodeIndex: number[] = [];\n\n if (nextNode.isInternal()) {\n for (let d = 0; nextNode.isInternal(); d++) {\n nodeQueue[d] = nextNode.children;\n nodeIndex[d] =\n key === undefined ? 0 : indexOf(key, nextNode.keys, 0, comparator);\n if (nodeIndex[d] >= nodeQueue[d].length) return; // first key > maxKey()\n nextNode = nodeQueue[d][nodeIndex[d]];\n }\n nodeQueue.reverse();\n nodeIndex.reverse();\n }\n return [nodeQueue, nodeIndex, nextNode];\n}\n\nfunction iterator<T>(next: () => IteratorResult<T>): IterableIterator<T> {\n return {\n next,\n [Symbol.iterator]() {\n return this;\n },\n };\n}\n\n/** Leaf node / base class. **************************************************/\nclass BNode<K> {\n // If this is an internal node, _keys[i] is the highest key in children[i].\n keys: K[];\n // True if this node might be within multiple `BTree`s (or have multiple parents).\n // If so, it must be cloned before being mutated to avoid changing an unrelated tree.\n // This is transitive: if it's true, children are also shared even if `isShared!=true`\n // in those children. (Certain operations will propagate isShared=true to children.)\n isShared: true | undefined;\n\n constructor(keys: K[]) {\n this.keys = keys;\n this.isShared = undefined;\n }\n\n isInternal(): this is BNodeInternal<K> {\n return false;\n }\n\n maxKey() {\n return this.keys[this.keys.length - 1];\n }\n\n minKey(): K | undefined {\n return this.keys[0];\n }\n\n clone(): BNode<K> {\n return new BNode<K>(this.keys.slice(0));\n }\n\n get(key: K, tree: BTreeSet<K>): K | undefined {\n const i = indexOf(key, this.keys, -1, tree.comparator);\n return i < 0 ? undefined : this.keys[i];\n }\n\n has(key: K, tree: BTreeSet<K>): boolean {\n const i = indexOf(key, this.keys, -1, tree.comparator);\n return i >= 0 && i < this.keys.length;\n }\n\n set(key: K, tree: BTreeSet<K>): null | BNode<K> {\n let i = indexOf(key, this.keys, -1, tree.comparator);\n if (i < 0) {\n // key does not exist yet\n i = ~i;\n tree.size++;\n\n if (this.keys.length < MAX_NODE_SIZE) {\n this.keys.splice(i, 0, key);\n return null;\n }\n // This leaf node is full and must split\n const newRightSibling = this.splitOffRightSide();\n // oxlint-disable-next-line @typescript-eslint/no-this-alias\n let target: BNode<K> = this;\n if (i > this.keys.length) {\n i -= this.keys.length;\n target = newRightSibling;\n }\n // target.#insertInLeaf(i, key);\n target.keys.splice(i, 0, key);\n\n return newRightSibling;\n }\n\n // usually this is a no-op, but some users may wish to edit the key\n this.keys[i] = key;\n return null;\n }\n\n takeFromRight(rhs: BNode<K>) {\n this.keys.push(rhs.keys.shift()!);\n }\n\n takeFromLeft(lhs: BNode<K>) {\n this.keys.unshift(lhs.keys.pop()!);\n }\n\n splitOffRightSide(): BNode<K> {\n const half = this.keys.length >> 1;\n const keys = this.keys.splice(half);\n return new BNode<K>(keys);\n }\n\n delete(key: K, tree: BTreeSet<K>): boolean {\n const cmp = tree.comparator;\n const iLow = indexOf(key, this.keys, -1, cmp);\n const iHigh = iLow + 1;\n\n if (iLow < 0) {\n return false;\n }\n\n const {keys} = this;\n for (let i = iLow; i < iHigh; i++) {\n const key = keys[i];\n\n if (key !== keys[i] || this.isShared === true) {\n throw new Error('BTree illegally changed or cloned in delete');\n }\n\n this.keys.splice(i, 1);\n tree.size--;\n return true;\n }\n\n return false;\n }\n\n mergeSibling(rhs: BNode<K>, _: number) {\n this.keys.push(...rhs.keys);\n }\n}\n\n/** Internal node (non-leaf node) ********************************************/\nclass BNodeInternal<K> extends BNode<K> {\n // Note: conventionally B+ trees have one fewer key than the number of\n // children, but I find it easier to keep the array lengths equal: each\n // keys[i] caches the value of children[i].maxKey().\n children: BNode<K>[];\n\n /**\n * This does not mark `children` as shared, so it is the responsibility of the caller\n * to ensure children are either marked shared, or aren't included in another tree.\n */\n constructor(children: BNode<K>[], keys?: K[]) {\n if (!keys) {\n keys = [];\n for (let i = 0; i < children.length; i++) {\n keys[i] = children[i].maxKey();\n }\n }\n super(keys);\n this.children = children;\n }\n\n isInternal(): this is BNodeInternal<K> {\n return true;\n }\n\n clone(): BNode<K> {\n const children = this.children.slice(0);\n for (let i = 0; i < children.length; i++) {\n children[i].isShared = true;\n }\n return new BNodeInternal<K>(children, this.keys.slice(0));\n }\n\n minKey() {\n return this.children[0].minKey();\n }\n\n get(key: K, tree: BTreeSet<K>): K | undefined {\n const i = indexOf(key, this.keys, 0, tree.comparator);\n const {children} = this;\n return i < children.length ? children[i].get(key, tree) : undefined;\n }\n\n has(key: K, tree: BTreeSet<K>): boolean {\n const i = indexOf(key, this.keys, 0, tree.comparator);\n const {children} = this;\n return i < children.length ? children[i].has(key, tree) : false;\n }\n\n set(key: K, tree: BTreeSet<K>): null | BNode<K> {\n const c = this.children;\n const cmp = tree.comparator;\n let i = Math.min(indexOf(key, this.keys, 0, cmp), c.length - 1);\n let child = c[i];\n\n if (child.isShared) {\n c[i] = child = child.clone();\n }\n if (child.keys.length >= MAX_NODE_SIZE) {\n // child is full; inserting anything else will cause a split.\n // Shifting an item to the left or right sibling may avoid a split.\n // We can do a shift if the adjacent node is not full and if the\n // current key can still be placed in the same node after the shift.\n let other: BNode<K>;\n if (\n i > 0 &&\n (other = c[i - 1]).keys.length < MAX_NODE_SIZE &&\n cmp(child.keys[0], key) < 0\n ) {\n if (other.isShared) {\n c[i - 1] = other = other.clone();\n }\n other.takeFromRight(child);\n this.keys[i - 1] = other.maxKey();\n } else if (\n (other = c[i + 1]) !== undefined &&\n other.keys.length < MAX_NODE_SIZE &&\n cmp(child.maxKey(), key) < 0\n ) {\n if (other.isShared) c[i + 1] = other = other.clone();\n other.takeFromLeft(child);\n this.keys[i] = c[i].maxKey();\n }\n }\n\n const result = child.set(key, tree);\n this.keys[i] = child.maxKey();\n if (result === null) return null;\n\n // The child has split and `result` is a new right child... does it fit?\n if (this.keys.length < MAX_NODE_SIZE) {\n // yes\n this.insert(i + 1, result);\n return null;\n }\n // no, we must split also\n const newRightSibling = this.splitOffRightSide();\n // oxlint-disable-next-line @typescript-eslint/no-this-alias\n let target: BNodeInternal<K> = this;\n if (cmp(result.maxKey(), this.maxKey()) > 0) {\n target = newRightSibling;\n i -= this.keys.length;\n }\n target.insert(i + 1, result);\n return newRightSibling;\n }\n\n /**\n * Inserts `child` at index `i`.\n * This does not mark `child` as shared, so it is the responsibility of the caller\n * to ensure that either child is marked shared, or it is not included in another tree.\n */\n insert(i: number, child: BNode<K>) {\n this.children.splice(i, 0, child);\n this.keys.splice(i, 0, child.maxKey());\n }\n\n /**\n * Split this node.\n * Modifies this to remove the second half of the items, returning a separate node containing them.\n */\n splitOffRightSide() {\n const half = this.children.length >> 1;\n return new BNodeInternal<K>(\n this.children.splice(half),\n this.keys.splice(half),\n );\n }\n\n takeFromRight(rhs: BNode<K>) {\n this.keys.push(rhs.keys.shift()!);\n this.children.push((rhs as BNodeInternal<K>).children.shift()!);\n }\n\n takeFromLeft(lhs: BNode<K>) {\n this.keys.unshift(lhs.keys.pop()!);\n this.children.unshift((lhs as BNodeInternal<K>).children.pop()!);\n }\n\n delete(key: K, tree: BTreeSet<K>): boolean {\n const cmp = tree.comparator;\n const {keys} = this;\n const {children} = this;\n let iLow = indexOf(key, this.keys, 0, cmp);\n let i = iLow;\n const iHigh = Math.min(iLow, keys.length - 1);\n if (i <= iHigh) {\n try {\n if (children[i].isShared) {\n children[i] = children[i].clone();\n }\n const result = children[i].delete(key, tree);\n // Note: if children[i] is empty then keys[i]=undefined.\n // This is an invalid state, but it is fixed below.\n keys[i] = children[i].maxKey();\n return result;\n } finally {\n // Deletions may have occurred, so look for opportunities to merge nodes.\n const half = MAX_NODE_SIZE >> 1;\n if (iLow > 0) iLow--;\n for (i = iHigh; i >= iLow; i--) {\n if (children[i].keys.length <= half) {\n if (children[i].keys.length !== 0) {\n this.tryMerge(i, MAX_NODE_SIZE);\n } else {\n // child is empty! delete it!\n keys.splice(i, 1);\n children.splice(i, 1);\n }\n }\n }\n }\n }\n return false;\n }\n\n /** Merges child i with child i+1 if their combined size is not too large */\n tryMerge(i: number, maxSize: number): boolean {\n const {children} = this;\n if (i >= 0 && i + 1 < children.length) {\n if (children[i].keys.length + children[i + 1].keys.length <= maxSize) {\n if (children[i].isShared)\n // cloned already UNLESS i is outside scan range\n children[i] = children[i].clone();\n children[i].mergeSibling(children[i + 1], maxSize);\n children.splice(i + 1, 1);\n this.keys.splice(i + 1, 1);\n this.keys[i] = children[i].maxKey();\n return true;\n }\n }\n return false;\n }\n\n /**\n * Move children from `rhs` into this.\n * `rhs` must be part of this tree, and be removed from it after this call\n * (otherwise isShared for its children could be incorrect).\n */\n mergeSibling(rhs: BNode<K>, maxNodeSize: number) {\n // assert !this.isShared;\n const oldLength = this.keys.length;\n this.keys.push(...rhs.keys);\n const rhsChildren = (rhs as unknown as BNodeInternal<K>).children;\n this.children.push(...rhsChildren);\n\n if (rhs.isShared && !this.isShared) {\n // All children of a shared node are implicitly shared, and since their new\n // parent is not shared, they must now be explicitly marked as shared.\n for (let i = 0; i < rhsChildren.length; i++) {\n rhsChildren[i].isShared = true;\n }\n }\n\n // If our children are themselves almost empty due to a mass-delete,\n // they may need to be merged too (but only the oldLength-1 and its\n // right sibling should need this).\n this.tryMerge(oldLength - 1, maxNodeSize);\n }\n}\n\n// If key not found, returns i^failXor where i is the insertion index.\n// Callers that don't care whether there was a match will set failXor=0.\nfunction indexOf<K>(\n key: K,\n keys: K[],\n failXor: number,\n comparator: Comparator<K>,\n): number {\n let lo = 0;\n let hi = keys.length;\n let mid = hi >> 1;\n while (lo < hi) {\n const c = comparator(keys[mid], key);\n if (c < 0) {\n lo = mid + 1;\n } else if (c > 0) {\n // key < keys[mid]\n hi = mid;\n } else if (c === 0) {\n return mid;\n } else {\n // c is NaN or otherwise invalid\n if (key === key) {\n // at least the search key is not NaN\n return keys.length;\n }\n throw new Error('NaN was used as a key');\n }\n mid = (lo + hi) >> 1;\n }\n return mid ^ failXor;\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nconst emptyLeaf = new BNode<any>([]);\nemptyLeaf.isShared = true;\n", "import type {Change} from '../ivm/change.ts';\nimport type {Node} from '../ivm/data.ts';\nimport {\n throwOutput,\n type FetchRequest,\n type Input,\n type Operator,\n type Output,\n} from '../ivm/operator.ts';\nimport type {SourceSchema} from '../ivm/schema.ts';\nimport type {Stream} from '../ivm/stream.ts';\nimport type {MetricsDelegate} from './metrics-delegate.ts';\n\ntype MetricName = 'query-update-client' | 'query-update-server';\n\nexport class MeasurePushOperator implements Operator {\n readonly #input: Input;\n readonly #queryID: string;\n readonly #metricsDelegate: MetricsDelegate;\n\n #output: Output = throwOutput;\n readonly #metricName: MetricName;\n\n constructor(\n input: Input,\n queryID: string,\n metricsDelegate: MetricsDelegate,\n metricName: MetricName,\n ) {\n this.#input = input;\n this.#queryID = queryID;\n this.#metricsDelegate = metricsDelegate;\n this.#metricName = metricName;\n input.setOutput(this);\n }\n\n setOutput(output: Output): void {\n this.#output = output;\n }\n\n fetch(req: FetchRequest): Stream<Node> {\n return this.#input.fetch(req);\n }\n\n cleanup(req: FetchRequest): Stream<Node> {\n return this.#input.cleanup(req);\n }\n\n getSchema(): SourceSchema {\n return this.#input.getSchema();\n }\n\n destroy(): void {\n this.#input.destroy();\n }\n\n push(change: Change): void {\n const startTime = performance.now();\n this.#output.push(change, this);\n this.#metricsDelegate.addMetric(\n this.#metricName,\n performance.now() - startTime,\n this.#queryID,\n );\n }\n}\n", "import {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {BTreeSet} from '../../../shared/src/btree-set.ts';\nimport {hasOwn} from '../../../shared/src/has-own.ts';\nimport {once} from '../../../shared/src/iterables.ts';\nimport type {\n Condition,\n Ordering,\n OrderPart,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {Row, Value} from '../../../zero-protocol/src/data.ts';\nimport type {PrimaryKey} from '../../../zero-protocol/src/primary-key.ts';\nimport type {SchemaValue} from '../../../zero-types/src/schema-value.ts';\nimport {assertOrderingIncludesPK} from '../builder/builder.ts';\nimport type {DebugDelegate} from '../builder/debug-delegate.ts';\nimport {\n createPredicate,\n transformFilters,\n type NoSubqueryCondition,\n} from '../builder/filter.ts';\nimport type {Change} from './change.ts';\nimport {\n constraintMatchesPrimaryKey,\n constraintMatchesRow,\n primaryKeyConstraintFromFilters,\n type Constraint,\n} from './constraint.ts';\nimport {\n compareValues,\n makeComparator,\n valuesEqual,\n type Comparator,\n type Node,\n} from './data.ts';\nimport {filterPush} from './filter-push.ts';\nimport {\n type FetchRequest,\n type Input,\n type Output,\n type Start,\n} from './operator.ts';\nimport type {SourceSchema} from './schema.ts';\nimport type {\n Source,\n SourceChange,\n SourceChangeAdd,\n SourceChangeEdit,\n SourceChangeRemove,\n SourceInput,\n} from './source.ts';\nimport type {Stream} from './stream.ts';\n\nexport type Overlay = {\n outputIndex: number;\n change: SourceChange;\n};\n\nexport type Overlays = {\n add: Row | undefined;\n remove: Row | undefined;\n};\n\ntype Index = {\n comparator: Comparator;\n data: BTreeSet<Row>;\n usedBy: Set<Connection>;\n};\n\nexport type Connection = {\n input: Input;\n output: Output | undefined;\n sort: Ordering;\n splitEditKeys: Set<string> | undefined;\n compareRows: Comparator;\n filters:\n | {\n condition: NoSubqueryCondition;\n predicate: (row: Row) => boolean;\n }\n | undefined;\n readonly debug?: DebugDelegate | undefined;\n};\n\n/**\n * A `MemorySource` is a source that provides data to the pipeline from an\n * in-memory data source.\n *\n * This data is kept in sorted order as downstream pipelines will always expect\n * the data they receive from `pull` to be in sorted order.\n */\nexport class MemorySource implements Source {\n readonly #tableName: string;\n readonly #columns: Record<string, SchemaValue>;\n readonly #primaryKey: PrimaryKey;\n readonly #primaryIndexSort: Ordering;\n readonly #indexes: Map<string, Index> = new Map();\n readonly #connections: Connection[] = [];\n\n #overlay: Overlay | undefined;\n\n constructor(\n tableName: string,\n columns: Record<string, SchemaValue>,\n primaryKey: PrimaryKey,\n primaryIndexData?: BTreeSet<Row>,\n ) {\n this.#tableName = tableName;\n this.#columns = columns;\n this.#primaryKey = primaryKey;\n this.#primaryIndexSort = primaryKey.map(k => [k, 'asc']);\n const comparator = makeBoundComparator(this.#primaryIndexSort);\n this.#indexes.set(JSON.stringify(this.#primaryIndexSort), {\n comparator,\n data: primaryIndexData ?? new BTreeSet<Row>(comparator),\n usedBy: new Set(),\n });\n assertOrderingIncludesPK(this.#primaryIndexSort, this.#primaryKey);\n }\n\n // Mainly for tests.\n getSchemaInfo() {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n };\n }\n\n fork() {\n const primaryIndex = this.#getPrimaryIndex();\n return new MemorySource(\n this.#tableName,\n this.#columns,\n this.#primaryKey,\n primaryIndex.data.clone(),\n );\n }\n\n get data(): BTreeSet<Row> {\n return this.#getPrimaryIndex().data;\n }\n\n #getSchema(connection: Connection): SourceSchema {\n return {\n tableName: this.#tableName,\n columns: this.#columns,\n primaryKey: this.#primaryKey,\n sort: connection.sort,\n system: 'client',\n relationships: {},\n isHidden: false,\n compareRows: connection.compareRows,\n };\n }\n\n connect(\n sort: Ordering,\n filters?: Condition,\n splitEditKeys?: Set<string>,\n ): SourceInput {\n const transformedFilters = transformFilters(filters);\n\n const input: SourceInput = {\n getSchema: () => schema,\n fetch: req => this.#fetch(req, connection),\n cleanup: req => this.#cleanup(req, connection),\n setOutput: output => {\n connection.output = output;\n },\n destroy: () => {\n this.#disconnect(input);\n },\n fullyAppliedFilters: !transformedFilters.conditionsRemoved,\n };\n\n const connection: Connection = {\n input,\n output: undefined,\n sort,\n splitEditKeys,\n compareRows: makeComparator(sort),\n filters: transformedFilters.filters\n ? {\n condition: transformedFilters.filters,\n predicate: createPredicate(transformedFilters.filters),\n }\n : undefined,\n };\n const schema = this.#getSchema(connection);\n assertOrderingIncludesPK(sort, this.#primaryKey);\n this.#connections.push(connection);\n return input;\n }\n\n #disconnect(input: Input): void {\n const idx = this.#connections.findIndex(c => c.input === input);\n assert(idx !== -1, 'Connection not found');\n this.#connections.splice(idx, 1);\n\n // TODO: We used to delete unused indexes here. But in common cases like\n // navigating into issue detail pages it caused a ton of constantly\n // building and destroying indexes.\n //\n // Perhaps some intelligent LRU or something is needed here but for now,\n // the opposite extreme of keeping all indexes for the lifetime of the\n // page seems better.\n }\n\n #getPrimaryIndex(): Index {\n const index = this.#indexes.get(JSON.stringify(this.#primaryIndexSort));\n assert(index, 'Primary index not found');\n return index;\n }\n\n #getOrCreateIndex(sort: Ordering, usedBy: Connection): Index {\n const key = JSON.stringify(sort);\n const index = this.#indexes.get(key);\n // Future optimization could use existing index if it's the same just sorted\n // in reverse of needed.\n if (index) {\n index.usedBy.add(usedBy);\n return index;\n }\n\n const comparator = makeBoundComparator(sort);\n\n // When creating these synchronously becomes a problem, a few options:\n // 1. Allow users to specify needed indexes up front\n // 2. Create indexes in a different thread asynchronously (this would require\n // modifying the BTree to be able to be passed over structured-clone, or using\n // a different library.)\n // 3. We could even theoretically do (2) on multiple threads and then merge the\n // results!\n const data = new BTreeSet<Row>(comparator);\n\n // I checked, there's no special path for adding data in bulk faster.\n // The constructor takes an array, but it just calls add/set over and over.\n for (const row of this.#getPrimaryIndex().data) {\n data.add(row);\n }\n\n const newIndex = {comparator, data, usedBy: new Set([usedBy])};\n this.#indexes.set(key, newIndex);\n return newIndex;\n }\n\n // For unit testing that we correctly clean up indexes.\n getIndexKeys(): string[] {\n return [...this.#indexes.keys()];\n }\n\n *#fetch(req: FetchRequest, from: Connection): Stream<Node> {\n const callingConnectionIndex = this.#connections.indexOf(from);\n assert(callingConnectionIndex !== -1, 'Output not found');\n const conn = this.#connections[callingConnectionIndex];\n const {sort: requestedSort, compareRows} = conn;\n const connectionComparator = (r1: Row, r2: Row) =>\n compareRows(r1, r2) * (req.reverse ? -1 : 1);\n\n const pkConstraint = primaryKeyConstraintFromFilters(\n conn.filters?.condition,\n this.#primaryKey,\n );\n // The primary key constraint will be more limiting than the constraint\n // so swap out to that if it exists.\n const fetchOrPkConstraint = pkConstraint ?? req.constraint;\n\n // If there is a constraint, we need an index sorted by it first.\n const indexSort: OrderPart[] = [];\n if (fetchOrPkConstraint) {\n for (const key of Object.keys(fetchOrPkConstraint)) {\n indexSort.push([key, 'asc']);\n }\n }\n\n // For the special case of constraining by PK, we don't need to worry about\n // any requested sort since there can only be one result. Otherwise we also\n // need the index sorted by the requested sort.\n if (\n this.#primaryKey.length > 1 ||\n !fetchOrPkConstraint ||\n !constraintMatchesPrimaryKey(fetchOrPkConstraint, this.#primaryKey)\n ) {\n indexSort.push(...requestedSort);\n }\n\n const index = this.#getOrCreateIndex(indexSort, from);\n const {data, comparator: compare} = index;\n const indexComparator = (r1: Row, r2: Row) =>\n compare(r1, r2) * (req.reverse ? -1 : 1);\n\n const startAt = req.start?.row;\n\n // If there is a constraint, we want to start our scan at the first row that\n // matches the constraint. But because the next OrderPart can be `desc`,\n // it's not true that {[constraintKey]: constraintValue} is the first\n // matching row. Because in that case, the other fields will all be\n // `undefined`, and in Zero `undefined` is always less than any other value.\n // So if the second OrderPart is descending then `undefined` values will\n // actually be the *last* row. We need a way to stay \"start at the first row\n // with this constraint value\". RowBound with the corresponding compareBound\n // comparator accomplishes this. The right thing is probably to teach the\n // btree library to support this concept.\n let scanStart: RowBound | undefined;\n\n if (fetchOrPkConstraint) {\n scanStart = {};\n for (const [key, dir] of indexSort) {\n if (hasOwn(fetchOrPkConstraint, key)) {\n scanStart[key] = fetchOrPkConstraint[key];\n } else {\n if (req.reverse) {\n scanStart[key] = dir === 'asc' ? maxValue : minValue;\n } else {\n scanStart[key] = dir === 'asc' ? minValue : maxValue;\n }\n }\n }\n } else {\n scanStart = startAt;\n }\n\n const rowsIterable = generateRows(data, scanStart, req.reverse);\n const withOverlay = generateWithOverlay(\n startAt,\n pkConstraint ? once(rowsIterable) : rowsIterable,\n // use `req.constraint` here and not `fetchOrPkConstraint` since `fetchOrPkConstraint` could be the\n // primary key constraint. The primary key constraint comes from filters and is acting as a filter\n // rather than as the fetch constraint.\n req.constraint,\n this.#overlay,\n callingConnectionIndex,\n // Use indexComparator, generateWithOverlayInner has a subtle dependency\n // on this. Since generateWithConstraint is done after\n // generateWithOverlay, the generator consumed by generateWithOverlayInner\n // does not end when the constraint stops matching and so the final\n // check to yield an add overlay if not yet yielded is not reached.\n // However, using the indexComparator the add overlay will be less than\n // the first row that does not match the constraint, and so any\n // not yet yielded add overlay will be yielded when the first row\n // not matching the constraint is reached.\n indexComparator,\n conn.filters?.predicate,\n );\n\n const withConstraint = generateWithConstraint(\n generateWithStart(withOverlay, req.start, connectionComparator),\n // we use `req.constraint` and not `fetchOrPkConstraint` here because we need to\n // AND the constraint with what could have been the primary key constraint\n req.constraint,\n );\n\n yield* conn.filters\n ? generateWithFilter(withConstraint, conn.filters.predicate)\n : withConstraint;\n }\n\n #cleanup(req: FetchRequest, connection: Connection): Stream<Node> {\n return this.#fetch(req, connection);\n }\n\n push(change: SourceChange): void {\n for (const _ of this.genPush(change)) {\n // Nothing to do.\n }\n }\n\n *genPush(change: SourceChange) {\n const primaryIndex = this.#getPrimaryIndex();\n const {data} = primaryIndex;\n const exists = (row: Row) => data.has(row);\n const setOverlay = (o: Overlay | undefined) => (this.#overlay = o);\n const writeChange = (c: SourceChange) => this.#writeChange(c);\n yield* genPushAndWriteWithSplitEdit(\n this.#connections,\n change,\n exists,\n setOverlay,\n writeChange,\n );\n }\n\n #writeChange(change: SourceChange) {\n for (const {data} of this.#indexes.values()) {\n switch (change.type) {\n case 'add': {\n const added = data.add(change.row);\n // must succeed since we checked has() above.\n assert(added);\n break;\n }\n case 'remove': {\n const removed = data.delete(change.row);\n // must succeed since we checked has() above.\n assert(removed);\n break;\n }\n case 'edit': {\n // TODO: We could see if the PK (form the index tree's perspective)\n // changed and if not we could use set.\n // We cannot just do `set` with the new value since the `oldRow` might\n // not map to the same entry as the new `row` in the index btree.\n const removed = data.delete(change.oldRow);\n // must succeed since we checked has() above.\n assert(removed);\n data.add(change.row);\n break;\n }\n default:\n unreachable(change);\n }\n }\n }\n}\n\nfunction* generateWithConstraint(\n it: Stream<Node>,\n constraint: Constraint | undefined,\n) {\n for (const node of it) {\n if (constraint && !constraintMatchesRow(constraint, node.row)) {\n break;\n }\n yield node;\n }\n}\n\nfunction* generateWithFilter(it: Stream<Node>, filter: (row: Row) => boolean) {\n for (const node of it) {\n if (filter(node.row)) {\n yield node;\n }\n }\n}\n\nexport function* genPushAndWriteWithSplitEdit(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n) {\n let shouldSplitEdit = false;\n if (change.type === 'edit') {\n for (const {splitEditKeys} of connections) {\n if (splitEditKeys) {\n for (const key of splitEditKeys) {\n if (!valuesEqual(change.row[key], change.oldRow[key])) {\n shouldSplitEdit = true;\n break;\n }\n }\n }\n }\n }\n\n if (change.type === 'edit' && shouldSplitEdit) {\n yield* genPushAndWrite(\n connections,\n {\n type: 'remove',\n row: change.oldRow,\n },\n exists,\n setOverlay,\n writeChange,\n );\n yield* genPushAndWrite(\n connections,\n {\n type: 'add',\n row: change.row,\n },\n exists,\n setOverlay,\n writeChange,\n );\n } else {\n yield* genPushAndWrite(\n connections,\n change,\n exists,\n setOverlay,\n writeChange,\n );\n }\n}\n\nfunction* genPushAndWrite(\n connections: readonly Connection[],\n change: SourceChangeAdd | SourceChangeRemove | SourceChangeEdit,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => Overlay | undefined,\n writeChange: (c: SourceChange) => void,\n) {\n for (const x of genPush(connections, change, exists, setOverlay)) {\n yield x;\n }\n writeChange(change);\n}\n\nfunction* genPush(\n connections: readonly Connection[],\n change: SourceChange,\n exists: (row: Row) => boolean,\n setOverlay: (o: Overlay | undefined) => void,\n) {\n switch (change.type) {\n case 'add':\n assert(\n !exists(change.row),\n () => `Row already exists ${stringify(change)}`,\n );\n break;\n case 'remove':\n assert(exists(change.row), () => `Row not found ${stringify(change)}`);\n break;\n case 'edit':\n assert(exists(change.oldRow), () => `Row not found ${stringify(change)}`);\n break;\n default:\n unreachable(change);\n }\n\n for (const [outputIndex, {output, filters, input}] of connections.entries()) {\n if (output) {\n setOverlay({outputIndex, change});\n const outputChange: Change =\n change.type === 'edit'\n ? {\n type: change.type,\n oldNode: {\n row: change.oldRow,\n relationships: {},\n },\n node: {\n row: change.row,\n relationships: {},\n },\n }\n : {\n type: change.type,\n node: {\n row: change.row,\n relationships: {},\n },\n };\n filterPush(outputChange, output, input, filters?.predicate);\n yield;\n }\n }\n\n setOverlay(undefined);\n}\n\nexport function* generateWithStart(\n nodes: Iterable<Node>,\n start: Start | undefined,\n compare: (r1: Row, r2: Row) => number,\n): Stream<Node> {\n if (!start) {\n yield* nodes;\n return;\n }\n let started = false;\n for (const node of nodes) {\n if (!started) {\n if (start.basis === 'at') {\n if (compare(node.row, start.row) >= 0) {\n started = true;\n }\n } else if (start.basis === 'after') {\n if (compare(node.row, start.row) > 0) {\n started = true;\n }\n }\n }\n if (started) {\n yield node;\n }\n }\n}\n\n/**\n * Takes an iterator and overlay.\n * Splices the overlay into the iterator at the correct position.\n *\n * @param startAt - if there is a lower bound to the stream. If the lower bound of the stream\n * is above the overlay, the overlay will be skipped.\n * @param rows - the stream into which the overlay should be spliced\n * @param constraint - constraint that was applied to the rowIterator and should\n * also be applied to the overlay.\n * @param overlay - the overlay values to splice in\n * @param compare - the comparator to use to find the position for the overlay\n */\nexport function* generateWithOverlay(\n startAt: Row | undefined,\n rows: Iterable<Row>,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n connectionIndex: number,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n) {\n let overlayToApply: Overlay | undefined = undefined;\n if (overlay && connectionIndex <= overlay.outputIndex) {\n overlayToApply = overlay;\n }\n const overlays = computeOverlays(\n startAt,\n constraint,\n overlayToApply,\n compare,\n filterPredicate,\n );\n yield* generateWithOverlayInner(rows, overlays, compare);\n}\n\nfunction computeOverlays(\n startAt: Row | undefined,\n constraint: Constraint | undefined,\n overlay: Overlay | undefined,\n compare: Comparator,\n filterPredicate?: (row: Row) => boolean | undefined,\n): Overlays {\n let overlays: Overlays = {\n add: undefined,\n remove: undefined,\n };\n switch (overlay?.change.type) {\n case 'add':\n overlays = {\n add: overlay.change.row,\n remove: undefined,\n };\n break;\n case 'remove':\n overlays = {\n add: undefined,\n remove: overlay.change.row,\n };\n break;\n case 'edit':\n overlays = {\n add: overlay.change.row,\n remove: overlay.change.oldRow,\n };\n break;\n }\n\n if (startAt) {\n overlays = overlaysForStartAt(overlays, startAt, compare);\n }\n\n if (constraint) {\n overlays = overlaysForConstraint(overlays, constraint);\n }\n\n if (filterPredicate) {\n overlays = overlaysForFilterPredicate(overlays, filterPredicate);\n }\n\n return overlays;\n}\n\nexport {overlaysForStartAt as overlaysForStartAtForTest};\n\nfunction overlaysForStartAt(\n {add, remove}: Overlays,\n startAt: Row,\n compare: Comparator,\n): Overlays {\n const undefinedIfBeforeStartAt = (row: Row | undefined) =>\n row === undefined || compare(row, startAt) < 0 ? undefined : row;\n return {\n add: undefinedIfBeforeStartAt(add),\n remove: undefinedIfBeforeStartAt(remove),\n };\n}\n\nexport {overlaysForConstraint as overlaysForConstraintForTest};\n\nfunction overlaysForConstraint(\n {add, remove}: Overlays,\n constraint: Constraint,\n): Overlays {\n const undefinedIfDoesntMatchConstraint = (row: Row | undefined) =>\n row === undefined || !constraintMatchesRow(constraint, row)\n ? undefined\n : row;\n\n return {\n add: undefinedIfDoesntMatchConstraint(add),\n remove: undefinedIfDoesntMatchConstraint(remove),\n };\n}\n\nfunction overlaysForFilterPredicate(\n {add, remove}: Overlays,\n filterPredicate: (row: Row) => boolean | undefined,\n): Overlays {\n const undefinedIfDoesntMatchFilter = (row: Row | undefined) =>\n row === undefined || !filterPredicate(row) ? undefined : row;\n\n return {\n add: undefinedIfDoesntMatchFilter(add),\n remove: undefinedIfDoesntMatchFilter(remove),\n };\n}\n\nexport function* generateWithOverlayInner(\n rowIterator: Iterable<Row>,\n overlays: Overlays,\n compare: (r1: Row, r2: Row) => number,\n) {\n let addOverlayYielded = false;\n let removeOverlaySkipped = false;\n for (const row of rowIterator) {\n if (!addOverlayYielded && overlays.add) {\n const cmp = compare(overlays.add, row);\n if (cmp < 0) {\n addOverlayYielded = true;\n yield {row: overlays.add, relationships: {}};\n }\n }\n\n if (!removeOverlaySkipped && overlays.remove) {\n const cmp = compare(overlays.remove, row);\n if (cmp === 0) {\n removeOverlaySkipped = true;\n continue;\n }\n }\n yield {row, relationships: {}};\n }\n\n if (!addOverlayYielded && overlays.add) {\n yield {row: overlays.add, relationships: {}};\n }\n}\n\n/**\n * A location to begin scanning an index from. Can either be a specific value\n * or the min or max possible value for the type. This is used to start a scan\n * at the beginning of the rows matching a constraint.\n */\ntype Bound = Value | MinValue | MaxValue;\ntype RowBound = Record<string, Bound>;\nconst minValue = Symbol('min-value');\ntype MinValue = typeof minValue;\nconst maxValue = Symbol('max-value');\ntype MaxValue = typeof maxValue;\n\nfunction makeBoundComparator(sort: Ordering) {\n return (a: RowBound, b: RowBound) => {\n // Hot! Do not use destructuring\n for (const entry of sort) {\n const key = entry[0];\n const cmp = compareBounds(a[key], b[key]);\n if (cmp !== 0) {\n return entry[1] === 'asc' ? cmp : -cmp;\n }\n }\n return 0;\n };\n}\n\nfunction compareBounds(a: Bound, b: Bound): number {\n if (a === b) {\n return 0;\n }\n if (a === minValue) {\n return -1;\n }\n if (b === minValue) {\n return 1;\n }\n if (a === maxValue) {\n return 1;\n }\n if (b === maxValue) {\n return -1;\n }\n return compareValues(a, b);\n}\n\nfunction* generateRows(\n data: BTreeSet<Row>,\n scanStart: RowBound | undefined,\n reverse: boolean | undefined,\n) {\n yield* data[reverse ? 'valuesFromReversed' : 'valuesFrom'](\n scanStart as Row | undefined,\n );\n}\n\nexport function stringify(change: SourceChange) {\n return JSON.stringify(change, (_, v) =>\n typeof v === 'bigint' ? v.toString() : v,\n );\n}\n", "import {MemorySource} from '../../../zql/src/ivm/memory-source.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport {wrapIterable} from '../../../shared/src/iterables.ts';\nimport {type Read, type Store} from '../../../replicache/src/dag/store.ts';\nimport {using, withRead} from '../../../replicache/src/with-transactions.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport {ENTITIES_KEY_PREFIX, sourceNameFromKey} from './keys.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {diff, DiffsMap} from '../../../replicache/src/sync/diff.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {\n InternalDiff,\n InternalDiffOperation,\n NoIndexDiff,\n} from '../../../replicache/src/btree/node.ts';\nimport {diffBinarySearch} from '../../../replicache/src/subscriptions.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport type {ZeroReadOptions} from '../../../replicache/src/replicache-options.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\n\n/**\n * Replicache needs to rebase mutations onto different\n * commits of it's b-tree. These mutations can have reads\n * in them and those reads must be run against the IVM sources.\n *\n * To ensure the reads get the correct state, the IVM\n * sources need to reflect the state of the commit\n * being rebased onto. `IVMSourceBranch` allows us to:\n * 1. fork the IVM sources\n * 2. patch them up to match the desired head\n * 3. run the reads against the forked sources\n *\n * (2) is expected to be a cheap operation as there should only\n * ever be a few outstanding diffs to apply given Zero is meant\n * to be run in a connected state.\n */\nexport class IVMSourceBranch {\n readonly #sources: Map<string, MemorySource | undefined>;\n readonly #tables: Record<string, TableSchema>;\n hash: Hash | undefined;\n\n constructor(\n tables: Record<string, TableSchema>,\n hash?: Hash,\n sources: Map<string, MemorySource | undefined> = new Map(),\n ) {\n this.#tables = tables;\n this.#sources = sources;\n this.hash = hash;\n }\n\n getSource(name: string): MemorySource | undefined {\n if (this.#sources.has(name)) {\n return this.#sources.get(name);\n }\n\n const schema = this.#tables[name];\n const source = schema\n ? new MemorySource(name, schema.columns, schema.primaryKey)\n : undefined;\n this.#sources.set(name, source);\n return source;\n }\n\n clear() {\n this.#sources.clear();\n }\n\n /**\n * Mutates the current branch, advancing it to the new head\n * by applying the given diffs.\n */\n advance(expectedHead: Hash | undefined, newHead: Hash, diffs: NoIndexDiff) {\n assert(\n this.hash === expectedHead,\n () =>\n `Expected head must match the main head. Got: ${this.hash}, expected: ${expectedHead}`,\n );\n\n applyDiffs(diffs, this);\n this.hash = newHead;\n }\n\n /**\n * Fork the branch and patch it up to match the desired head.\n */\n async forkToHead(\n store: LazyStore,\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<IVMSourceBranch> {\n const fork = this.fork();\n\n if (fork.hash === desiredHead) {\n return fork;\n }\n\n await patchBranch(desiredHead, store, fork, readOptions);\n fork.hash = desiredHead;\n return fork;\n }\n\n /**\n * Creates a new IVMSourceBranch that is a copy of the current one.\n * This is a cheap operation since the b-trees are shared until a write is performed\n * and then only the modified nodes are copied.\n *\n * IVM branches are forked when we need to rebase mutations.\n * The mutations modify the fork rather than original branch.\n */\n fork() {\n return new IVMSourceBranch(\n this.#tables,\n this.hash,\n new Map(\n wrapIterable(this.#sources.entries()).map(([name, source]) => [\n name,\n source?.fork(),\n ]),\n ),\n );\n }\n}\n\nexport async function initFromStore(\n branch: IVMSourceBranch,\n hash: Hash,\n store: Store,\n) {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const read = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for await (const entry of read.map.scan(ENTITIES_KEY_PREFIX)) {\n if (!entry[0].startsWith(ENTITIES_KEY_PREFIX)) {\n break;\n }\n diffs.push({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n });\n }\n });\n\n branch.advance(undefined, hash, diffs);\n}\n\nasync function patchBranch(\n desiredHead: Hash,\n store: LazyStore,\n fork: IVMSourceBranch,\n readOptions: ZeroReadOptions | undefined,\n) {\n const diffs = await computeDiffs(\n must(fork.hash),\n desiredHead,\n store,\n readOptions,\n );\n if (!diffs) {\n return;\n }\n applyDiffs(diffs, fork);\n}\n\nasync function computeDiffs(\n startHash: Hash,\n endHash: Hash,\n store: LazyStore,\n readOptions: ZeroReadOptions | undefined,\n): Promise<InternalDiff | undefined> {\n const readFn = (dagRead: Read) =>\n diff(\n startHash,\n endHash,\n dagRead,\n {\n shouldComputeDiffs: () => true,\n shouldComputeDiffsForIndex(_name) {\n return false;\n },\n },\n FormatVersion.Latest,\n );\n\n let diffs: DiffsMap;\n if (readOptions?.openLazySourceRead) {\n diffs = await using(store.read(readOptions.openLazySourceRead), readFn);\n } else if (readOptions?.openLazyRead) {\n diffs = await readFn(readOptions.openLazyRead);\n } else {\n diffs = await withRead(store, readFn);\n }\n\n return diffs.get('');\n}\n\nfunction applyDiffs(diffs: NoIndexDiff, branch: IVMSourceBranch) {\n for (\n let i = diffBinarySearch(diffs, ENTITIES_KEY_PREFIX, diff => diff.key);\n i < diffs.length;\n i++\n ) {\n const diff = diffs[i];\n const {key} = diff;\n if (!key.startsWith(ENTITIES_KEY_PREFIX)) {\n break;\n }\n const name = sourceNameFromKey(key);\n const source = must(branch.getSource(name));\n switch (diff.op) {\n case 'del':\n source.push({\n type: 'remove',\n row: diff.oldValue as Row,\n });\n break;\n case 'add':\n source.push({\n type: 'add',\n row: diff.newValue as Row,\n });\n break;\n case 'change':\n source.push({\n type: 'edit',\n row: diff.newValue as Row,\n oldRow: diff.oldValue as Row,\n });\n break;\n }\n }\n}\n", "import type {NoIndexDiff} from '../../../replicache/src/btree/node.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {AST} from '../../../zero-protocol/src/ast.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport type {FilterInput} from '../../../zql/src/ivm/filter-operators.ts';\nimport {MemoryStorage} from '../../../zql/src/ivm/memory-storage.ts';\nimport type {Input, Storage} from '../../../zql/src/ivm/operator.ts';\nimport type {Source, SourceInput} from '../../../zql/src/ivm/source.ts';\nimport {MeasurePushOperator} from '../../../zql/src/query/measure-push-operator.ts';\nimport type {MetricsDelegate} from '../../../zql/src/query/metrics-delegate.ts';\nimport type {\n CommitListener,\n QueryDelegate,\n} from '../../../zql/src/query/query-delegate.ts';\nimport type {RunOptions} from '../../../zql/src/query/query.ts';\nimport {type IVMSourceBranch} from './ivm-branch.ts';\nimport type {QueryManager} from './query-manager.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\nexport type AddQuery = QueryManager['addLegacy'];\nexport type AddCustomQuery = QueryManager['addCustom'];\n\nexport type UpdateQuery = QueryManager['updateLegacy'];\nexport type UpdateCustomQuery = QueryManager['updateCustom'];\nexport type FlushQueryChanges = QueryManager['flushBatch'];\n\n/**\n * ZeroContext glues together zql and Replicache. It listens to changes in\n * Replicache data and pushes them into IVM and on tells the server about new\n * queries.\n */\nexport class ZeroContext implements QueryDelegate {\n // It is a bummer to have to maintain separate MemorySources here and copy the\n // data in from the Replicache db. But we want the data to be accessible via\n // pipelines *synchronously* and the core Replicache infra is all async. So\n // that needs to be fixed.\n readonly #mainSources: IVMSourceBranch;\n readonly addServerQuery: AddQuery;\n readonly addCustomQuery: AddCustomQuery;\n readonly updateServerQuery: UpdateQuery;\n readonly updateCustomQuery: UpdateCustomQuery;\n readonly flushQueryChanges: () => void;\n readonly #batchViewUpdates: (applyViewUpdates: () => void) => void;\n readonly #commitListeners: Set<CommitListener> = new Set();\n\n readonly #lc: ZeroLogContext;\n readonly assertValidRunOptions: (options?: RunOptions) => void;\n\n /**\n * Client-side queries start out as \"unknown\" and are then updated to\n * \"complete\" once the server has sent back the query result.\n */\n readonly defaultQueryComplete = false;\n\n readonly addMetric: MetricsDelegate['addMetric'];\n\n constructor(\n lc: ZeroLogContext,\n mainSources: IVMSourceBranch,\n addQuery: AddQuery,\n addCustomQuery: AddCustomQuery,\n updateQuery: UpdateQuery,\n updateCustomQuery: UpdateCustomQuery,\n flushQueryChanges: () => void,\n batchViewUpdates: (applyViewUpdates: () => void) => void,\n addMetric: MetricsDelegate['addMetric'],\n assertValidRunOptions: (options?: RunOptions) => void,\n ) {\n this.#mainSources = mainSources;\n this.addServerQuery = addQuery;\n this.updateServerQuery = updateQuery;\n this.updateCustomQuery = updateCustomQuery;\n this.#batchViewUpdates = batchViewUpdates;\n this.#lc = lc;\n this.assertValidRunOptions = assertValidRunOptions;\n this.addCustomQuery = addCustomQuery;\n this.flushQueryChanges = flushQueryChanges;\n this.addMetric = addMetric;\n }\n\n getSource(name: string): Source | undefined {\n return this.#mainSources.getSource(name);\n }\n\n mapAst(ast: AST): AST {\n return ast;\n }\n\n createStorage(): Storage {\n return new MemoryStorage();\n }\n\n decorateInput(input: Input): Input {\n return input;\n }\n\n decorateFilterInput(input: FilterInput): FilterInput {\n return input;\n }\n\n decorateSourceInput(input: SourceInput, queryID: string): Input {\n return new MeasurePushOperator(input, queryID, this, 'query-update-client');\n }\n\n addEdge() {}\n\n onTransactionCommit(cb: CommitListener): () => void {\n this.#commitListeners.add(cb);\n return () => {\n this.#commitListeners.delete(cb);\n };\n }\n\n batchViewUpdates<T>(applyViewUpdates: () => T) {\n let result: T | undefined;\n let viewChangesPerformed = false;\n this.#batchViewUpdates(() => {\n result = applyViewUpdates();\n viewChangesPerformed = true;\n });\n assert(\n viewChangesPerformed,\n 'batchViewUpdates must call applyViewUpdates synchronously.',\n );\n return result as T;\n }\n\n processChanges(\n expectedHead: Hash | undefined,\n newHead: Hash,\n changes: NoIndexDiff,\n ) {\n this.batchViewUpdates(() => {\n try {\n this.#mainSources.advance(expectedHead, newHead, changes);\n } finally {\n this.#endTransaction();\n }\n });\n }\n\n #endTransaction() {\n for (const listener of this.#commitListeners) {\n try {\n listener();\n } catch (e) {\n // We should not fatal the inner-workings of Zero due to the user's application\n // code throwing an error.\n // Hence we wrap notifications in a try-catch block.\n this.#lc.error?.(\n ErrorKind.Internal,\n 'Failed notifying a commit listener of IVM updates',\n e,\n );\n }\n }\n }\n}\n", "import type {ReadonlyJSONObject} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {MaybePromise} from '../../../shared/src/types.ts';\nimport type {Row} from '../../../zero-protocol/src/data.ts';\nimport {\n CRUD_MUTATION_NAME,\n type CRUDMutationArg,\n type CRUDOp,\n type DeleteOp,\n type InsertOp,\n type UpdateOp,\n type UpsertOp,\n} from '../../../zero-protocol/src/push.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {\n DeleteID,\n InsertValue,\n UpdateValue,\n UpsertValue,\n} from '../../../zql/src/mutate/custom.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {toPrimaryKeyString} from './keys.ts';\nimport type {MutatorDefs, WriteTransaction} from './replicache-types.ts';\n\n/**\n * This is the type of the generated mutate.<name>.<verb> function.\n */\nexport type TableMutator<S extends TableSchema> = {\n /**\n * Writes a row if a row with the same primary key doesn't already exists.\n * Non-primary-key fields that are 'optional' can be omitted or set to\n * `undefined`. Such fields will be assigned the value `null` optimistically\n * and then the default value as defined by the server.\n */\n insert: (value: InsertValue<S>) => Promise<void>;\n\n /**\n * Writes a row unconditionally, overwriting any existing row with the same\n * primary key. Non-primary-key fields that are 'optional' can be omitted or\n * set to `undefined`. Such fields will be assigned the value `null`\n * optimistically and then the default value as defined by the server.\n */\n upsert: (value: UpsertValue<S>) => Promise<void>;\n\n /**\n * Updates a row with the same primary key. If no such row exists, this\n * function does nothing. All non-primary-key fields can be omitted or set to\n * `undefined`. Such fields will be left unchanged from previous value.\n */\n update: (value: UpdateValue<S>) => Promise<void>;\n\n /**\n * Deletes the row with the specified primary key. If no such row exists, this\n * function does nothing.\n */\n delete: (id: DeleteID<S>) => Promise<void>;\n};\n\nexport type DBMutator<S extends Schema> =\n S['enableLegacyMutators'] extends false\n ? {} // {} is needed here for intersection type identity\n : {\n [K in keyof S['tables']]: TableMutator<S['tables'][K]>;\n };\n\nexport type BatchMutator<S extends Schema> = <R>(\n body: (m: DBMutator<S>) => MaybePromise<R>,\n) => Promise<R>;\n\ntype ZeroCRUDMutate = {\n [CRUD_MUTATION_NAME]: CRUDMutate;\n};\n\n/**\n * This is the zero.mutate object part representing the CRUD operations. If the\n * queries are `issue` and `label`, then this object will have `issue` and\n * `label` properties.\n */\nexport function makeCRUDMutate<const S extends Schema>(\n schema: S,\n repMutate: ZeroCRUDMutate,\n): {mutate: DBMutator<S>; mutateBatch: BatchMutator<S>} {\n const {[CRUD_MUTATION_NAME]: zeroCRUD} = repMutate;\n\n const mutateBatch = async <R>(body: (m: DBMutator<S>) => R): Promise<R> => {\n const ops: CRUDOp[] = [];\n const m = {} as Record<string, unknown>;\n for (const name of Object.keys(schema.tables)) {\n m[name] = makeBatchCRUDMutate(name, schema, ops);\n }\n\n const rv = await body(m as DBMutator<S>);\n await zeroCRUD({ops});\n return rv;\n };\n\n const mutate: Record<string, TableMutator<TableSchema>> = {};\n for (const [name, tableSchema] of Object.entries(schema.tables)) {\n mutate[name] = makeEntityCRUDMutate(name, tableSchema.primaryKey, zeroCRUD);\n }\n return {\n mutate: mutate as DBMutator<S>,\n mutateBatch: mutateBatch as BatchMutator<S>,\n };\n}\n\n/**\n * Creates the `{insert, upsert, update, delete}` object for use outside a\n * batch.\n */\nfunction makeEntityCRUDMutate<S extends TableSchema>(\n tableName: string,\n primaryKey: S['primaryKey'],\n zeroCRUD: CRUDMutate,\n): TableMutator<S> {\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n return zeroCRUD({ops: [op]});\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n return zeroCRUD({ops: [op]});\n },\n };\n}\n\n/**\n * Creates the `{inesrt, upsert, update, delete}` object for use inside a\n * batch.\n */\nexport function makeBatchCRUDMutate<S extends TableSchema>(\n tableName: string,\n schema: Schema,\n ops: CRUDOp[],\n): TableMutator<S> {\n const {primaryKey} = schema.tables[tableName];\n return {\n insert: (value: InsertValue<S>) => {\n const op: InsertOp = {\n op: 'insert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n upsert: (value: UpsertValue<S>) => {\n const op: UpsertOp = {\n op: 'upsert',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n update: (value: UpdateValue<S>) => {\n const op: UpdateOp = {\n op: 'update',\n tableName,\n primaryKey,\n value,\n };\n ops.push(op);\n return promiseVoid;\n },\n delete: (id: DeleteID<S>) => {\n const op: DeleteOp = {\n op: 'delete',\n tableName,\n primaryKey,\n value: id,\n };\n ops.push(op);\n return promiseVoid;\n },\n };\n}\n\nexport type WithCRUD<MD extends MutatorDefs> = MD & {\n [CRUD_MUTATION_NAME]: CRUDMutator;\n};\n\nexport type CRUDMutate = (crudArg: CRUDMutationArg) => Promise<void>;\n\nexport type CRUDMutator = (\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n) => Promise<void>;\n\n// Zero crud mutators cannot function at the same\n// time as custom mutators as the rebase of crud mutators will not\n// update the IVM branch. That's ok, we're removing crud mutators\n// in favor of custom mutators.\nexport function makeCRUDMutator(schema: Schema): CRUDMutator {\n return async function zeroCRUDMutator(\n tx: WriteTransaction,\n crudArg: CRUDMutationArg,\n ): Promise<void> {\n for (const op of crudArg.ops) {\n switch (op.op) {\n case 'insert':\n await insertImpl(tx, op, schema, undefined);\n break;\n case 'upsert':\n await upsertImpl(tx, op, schema, undefined);\n break;\n case 'update':\n await updateImpl(tx, op, schema, undefined);\n break;\n case 'delete':\n await deleteImpl(tx, op, schema, undefined);\n break;\n }\n }\n };\n}\n\nfunction defaultOptionalFieldsToNull(\n schema: TableSchema,\n value: ReadonlyJSONObject,\n): ReadonlyJSONObject {\n let rv = value;\n for (const name in schema.columns) {\n if (rv[name] === undefined) {\n rv = {...rv, [name]: null};\n }\n }\n return rv;\n}\n\nexport async function insertImpl(\n tx: WriteTransaction,\n arg: InsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (!(await tx.has(key))) {\n const val = defaultOptionalFieldsToNull(\n schema.tables[arg.tableName],\n arg.value,\n );\n await tx.set(key, val);\n if (ivmBranch) {\n must(ivmBranch.getSource(arg.tableName)).push({\n type: 'add',\n row: arg.value,\n });\n }\n }\n}\n\nexport async function upsertImpl(\n tx: WriteTransaction,\n arg: InsertOp | UpsertOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n if (await tx.has(key)) {\n await updateImpl(tx, {...arg, op: 'update'}, schema, ivmBranch);\n } else {\n await insertImpl(tx, {...arg, op: 'insert'}, schema, ivmBranch);\n }\n}\n\nexport async function updateImpl(\n tx: WriteTransaction,\n arg: UpdateOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n const update = arg.value;\n const next = {...(prev as ReadonlyJSONObject)};\n for (const k in update) {\n if (update[k] !== undefined) {\n next[k] = update[k];\n }\n }\n await tx.set(key, next);\n if (ivmBranch) {\n must(ivmBranch.getSource(arg.tableName)).push({\n type: 'edit',\n oldRow: prev as Row,\n row: next,\n });\n }\n}\n\nexport async function deleteImpl(\n tx: WriteTransaction,\n arg: DeleteOp,\n schema: Schema,\n ivmBranch: IVMSourceBranch | undefined,\n): Promise<void> {\n const key = toPrimaryKeyString(\n arg.tableName,\n schema.tables[arg.tableName].primaryKey,\n arg.value,\n );\n const prev = await tx.get(key);\n if (prev === undefined) {\n return;\n }\n await tx.del(key);\n if (ivmBranch) {\n must(ivmBranch.getSource(arg.tableName)).push({\n type: 'remove',\n row: prev as Row,\n });\n }\n}\n", "import {\n WriteTransactionImpl,\n zeroData,\n} from '../../../replicache/src/transactions.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyFunction} from '../../../shared/src/sentinels.ts';\nimport type {MutationOk} from '../../../zero-protocol/src/push.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {\n ClientTransaction,\n DeleteID,\n InsertValue,\n SchemaCRUD,\n SchemaQuery,\n TableCRUD,\n Transaction,\n UpdateValue,\n UpsertValue,\n} from '../../../zql/src/mutate/custom.ts';\nimport {newQuery} from '../../../zql/src/query/query-impl.ts';\nimport {type Query, type RunOptions} from '../../../zql/src/query/query.ts';\nimport type {ClientID} from '../types/client-state.ts';\nimport {ZeroContext} from './context.ts';\nimport {deleteImpl, insertImpl, updateImpl, upsertImpl} from './crud.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport type {WriteTransaction} from './replicache-types.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\n/**\n * The shape which a user's custom mutator definitions must conform to.\n */\nexport type CustomMutatorDefs = {\n [namespaceOrKey: string]:\n | {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: CustomMutatorImpl<any>;\n }\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n | CustomMutatorImpl<any>;\n};\n\nexport type MutatorResult = {\n client: Promise<void>;\n server: Promise<MutationOk>;\n};\n\nexport type CustomMutatorImpl<\n S extends Schema,\n TWrappedTransaction = unknown,\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n TArgs = any,\n> = (\n tx: Transaction<S, TWrappedTransaction>,\n // TODO: many args. See commit: 52657c2f934b4a458d628ea77e56ce92b61eb3c6 which did have many args.\n // The issue being that it will be a protocol change to support varargs.\n args: TArgs,\n) => Promise<void>;\n\n/**\n * The shape exposed on the `Zero.mutate` instance.\n * The signature of a custom mutator takes a `transaction` as its first arg\n * but the user does not provide this arg when calling the mutator.\n *\n * This utility strips the `tx` arg from the user's custom mutator signatures.\n */\nexport type MakeCustomMutatorInterfaces<\n S extends Schema,\n MD extends CustomMutatorDefs,\n> = {\n readonly [NamespaceOrName in keyof MD]: MD[NamespaceOrName] extends (\n tx: Transaction<S>,\n ...args: infer Args\n ) => Promise<void>\n ? (...args: Args) => MutatorResult\n : {\n readonly [P in keyof MD[NamespaceOrName]]: MakeCustomMutatorInterface<\n S,\n MD[NamespaceOrName][P]\n >;\n };\n};\n\nexport type MakeCustomMutatorInterface<S extends Schema, F> = F extends (\n tx: ClientTransaction<S>,\n ...args: infer Args\n) => Promise<void>\n ? (...args: Args) => MutatorResult\n : never;\n\nexport class TransactionImpl<S extends Schema> implements ClientTransaction<S> {\n constructor(lc: ZeroLogContext, repTx: WriteTransaction, schema: S) {\n const castedRepTx = repTx as WriteTransactionImpl;\n must(repTx.reason === 'initial' || repTx.reason === 'rebase');\n this.clientID = repTx.clientID;\n this.mutationID = repTx.mutationID;\n this.reason = repTx.reason === 'initial' ? 'optimistic' : 'rebase';\n const txData = must(\n castedRepTx[zeroData],\n 'zero was not set on replicache internal options!',\n );\n this.mutate = makeSchemaCRUD(\n schema,\n repTx,\n txData.ivmSources as IVMSourceBranch,\n );\n this.query = makeSchemaQuery(\n lc,\n schema,\n txData.ivmSources as IVMSourceBranch,\n );\n this.token = txData.token;\n }\n\n readonly clientID: ClientID;\n readonly mutationID: number;\n readonly reason: 'optimistic' | 'rebase';\n readonly location = 'client';\n readonly mutate: SchemaCRUD<S>;\n readonly query: SchemaQuery<S>;\n readonly token: string | undefined;\n}\n\nexport function makeReplicacheMutator<S extends Schema, TWrappedTransaction>(\n lc: ZeroLogContext,\n mutator: CustomMutatorImpl<S, TWrappedTransaction>,\n schema: S,\n) {\n return async (\n repTx: WriteTransaction,\n args: ReadonlyJSONValue,\n ): Promise<void> => {\n const tx = new TransactionImpl(lc, repTx, schema);\n await mutator(tx, args);\n };\n}\n\nfunction makeSchemaCRUD<S extends Schema>(\n schema: S,\n tx: WriteTransaction,\n ivmBranch: IVMSourceBranch,\n) {\n // Only creates the CRUD mutators on demand\n // rather than creating them all up-front for each mutation.\n return new Proxy(\n {},\n {\n get(target: Record<string, TableCRUD<TableSchema>>, prop: string) {\n if (prop in target) {\n return target[prop];\n }\n\n target[prop] = makeTableCRUD(schema, prop, tx, ivmBranch);\n return target[prop];\n },\n },\n ) as SchemaCRUD<S>;\n}\n\nfunction assertValidRunOptions(options: RunOptions | undefined): void {\n // TODO(arv): We should enforce this with the type system too.\n assert(\n options?.type !== 'complete',\n 'Cannot wait for complete results in custom mutations',\n );\n}\n\nfunction makeSchemaQuery<S extends Schema>(\n lc: ZeroLogContext,\n schema: S,\n ivmBranch: IVMSourceBranch,\n) {\n const context = new ZeroContext(\n lc,\n ivmBranch,\n () => emptyFunction,\n () => emptyFunction,\n emptyFunction,\n emptyFunction,\n emptyFunction,\n applyViewUpdates => applyViewUpdates(),\n emptyFunction,\n assertValidRunOptions,\n );\n\n return new Proxy(\n {},\n {\n get(target: Record<string, Query<S, string>>, prop: string) {\n if (prop in target) {\n return target[prop];\n }\n\n target[prop] = newQuery(context, schema, prop);\n return target[prop];\n },\n },\n ) as SchemaQuery<S>;\n}\n\nfunction makeTableCRUD(\n schema: Schema,\n tableName: string,\n tx: WriteTransaction,\n ivmBranch: IVMSourceBranch,\n) {\n const table = must(schema.tables[tableName]);\n const {primaryKey} = table;\n return {\n insert: (value: InsertValue<TableSchema>) =>\n insertImpl(\n tx,\n {op: 'insert', tableName, primaryKey, value},\n schema,\n ivmBranch,\n ),\n upsert: (value: UpsertValue<TableSchema>) =>\n upsertImpl(\n tx,\n {op: 'upsert', tableName, primaryKey, value},\n schema,\n ivmBranch,\n ),\n update: (value: UpdateValue<TableSchema>) =>\n updateImpl(\n tx,\n {op: 'update', tableName, primaryKey, value},\n schema,\n ivmBranch,\n ),\n delete: (id: DeleteID<TableSchema>) =>\n deleteImpl(\n tx,\n {op: 'delete', tableName, primaryKey, value: id},\n schema,\n ivmBranch,\n ),\n };\n}\n", "import type {Store} from '../../../replicache/src/dag/store.ts';\nimport {\n confirmDeletedClients,\n getDeletedClients,\n type DeletedClients,\n} from '../../../replicache/src/deleted-clients.ts';\nimport type {ClientGroupID} from '../../../replicache/src/sync/ids.ts';\nimport {\n withRead,\n withWrite,\n} from '../../../replicache/src/with-transactions.ts';\nimport {promiseVoid} from '../../../shared/src/resolved-promises.ts';\nimport type {\n DeleteClientsBody,\n DeleteClientsMessage,\n} from '../../../zero-protocol/src/delete-clients.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\n/**\n * Replicache will tell us when it deletes clients from the persistent storage\n * due to GC. When this happens we tell the server about the deleted clients.\n * Replicache also store the deleted clients in IDB in case the server is\n * currently offline.\n *\n * The server will reply with the client it actually deleted. When we get that\n * we remove those IDs from our local storage.\n */\nexport class DeleteClientsManager {\n readonly #send: (msg: DeleteClientsMessage) => void;\n readonly #lc: ZeroLogContext;\n readonly #dagStore: Store;\n readonly #clientGroupID: Promise<ClientGroupID>;\n\n constructor(\n send: (msg: DeleteClientsMessage) => void,\n dagStore: Store,\n lc: ZeroLogContext,\n clientGroupID: Promise<ClientGroupID>,\n ) {\n this.#send = send;\n this.#dagStore = dagStore;\n this.#lc = lc;\n this.#clientGroupID = clientGroupID;\n }\n\n /**\n * This gets called by Replicache when it deletes clients from the persistent\n * storage.\n */\n async onClientsDeleted(deletedClients: DeletedClients): Promise<void> {\n this.#lc.debug?.('DeletedClientsManager, send:', deletedClients);\n const clientGroupID = await this.#clientGroupID;\n this.#send([\n 'deleteClients',\n {\n clientIDs: deletedClients\n .filter(dc => dc.clientGroupID === clientGroupID)\n .map(dc => dc.clientID),\n },\n ]);\n }\n\n /**\n * Zero calls this after it connects to ensure that the server knows about all\n * the clients that might have been deleted locally since the last connection.\n */\n async sendDeletedClientsToServer(): Promise<void> {\n const clientGroupID = await this.#clientGroupID;\n const deleted = await withRead(this.#dagStore, dagRead =>\n getDeletedClients(dagRead),\n );\n\n // Only send client ids that belong to this client group\n const clientIDs = deleted\n .filter(d => d.clientGroupID === clientGroupID)\n .map(d => d.clientID);\n\n if (clientIDs.length > 0) {\n this.#send(['deleteClients', {clientIDs}]);\n this.#lc.debug?.('DeletedClientsManager, send:', deleted);\n }\n }\n\n /**\n * This is called as a response to the server telling us which clients it\n * actually deleted.\n */\n clientsDeletedOnServer(deletedClients: DeleteClientsBody): Promise<void> {\n const {clientIDs = [], clientGroupIDs = []} = deletedClients;\n if (clientIDs.length > 0 || clientGroupIDs.length > 0) {\n // Get the deleted clients from the dag and remove the ones from the server.\n // then write them back to the dag.\n return withWrite(this.#dagStore, async dagWrite => {\n this.#lc.debug?.('clientsDeletedOnServer:', clientIDs, clientGroupIDs);\n await confirmDeletedClients(dagWrite, clientIDs, clientGroupIDs);\n });\n }\n return promiseVoid;\n }\n\n async getDeletedClients(): Promise<DeletedClients> {\n const deletedClients = await withRead(this.#dagStore, read =>\n getDeletedClients(read),\n );\n const clientGroupID = await this.#clientGroupID;\n return deletedClients.filter(d => d.clientGroupID === clientGroupID);\n }\n}\n", "// https://www.oreilly.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html\nconst IPV4_ADDRESS_REGEX =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n// This doesn't ensure a valid ipv6, but any ipv6 hostname will\n// match this regex, and no domain based hostnames will.\nconst IPV6_ADDRESS_HOSTNAME_REGEX = /^\\[[a-fA-F0-9:]*:[a-fA-F0-9:]*\\]$/;\n\nexport const IP_ADDRESS_HOSTNAME_REGEX = new RegExp(\n `(${IPV4_ADDRESS_REGEX.source}|${IPV6_ADDRESS_HOSTNAME_REGEX.source})`,\n);\n\nexport function shouldEnableAnalytics(\n server: string | null,\n enableAnalytics = true,\n): boolean {\n if (!enableAnalytics) {\n return false;\n }\n const serverURL = server === null ? null : new URL(server);\n const socketHostname = serverURL?.hostname;\n // If the hostname is undefined, localhost, or an ip address, then\n // this is most likely a test or local development, in which case we\n // do not want to enable analytics.\n return (\n server !== null &&\n socketHostname !== undefined &&\n socketHostname !== 'localhost' &&\n !IP_ADDRESS_HOSTNAME_REGEX.test(socketHostname)\n );\n}\n", "import {assert} from '../../../shared/src/asserts.ts';\n\nexport type HTTPString = `http${'' | 's'}://${string}`;\n\nexport type WSString = `ws${'' | 's'}://${string}`;\n\nexport function toWSString(url: HTTPString): WSString {\n return ('ws' + url.slice(4)) as WSString;\n}\n\nexport function toHTTPString(url: WSString): HTTPString {\n return ('http' + url.slice(2)) as HTTPString;\n}\n\nexport function assertHTTPString(url: string): asserts url is HTTPString {\n assert(/^https?:\\/\\//.test(url));\n}\n\nexport function assertWSString(url: string): asserts url is WSString {\n assert(/^wss?:\\/\\//.test(url));\n}\n\nexport function appendPath<T extends HTTPString | WSString>(\n url: T,\n toAppend: `/${string}`,\n): T {\n return (url + (url.endsWith('/') ? toAppend.substring(1) : toAppend)) as T;\n}\n", "import {\n TeeLogSink,\n consoleLogSink,\n type Context,\n type LogLevel,\n type LogSink,\n} from '@rocicorp/logger';\nimport {\n DatadogLogSink,\n type DatadogLogSinkOptions,\n} from '../../../datadog/src/datadog-log-sink.ts';\nimport {appendPath, type HTTPString} from './http-string.ts';\nimport {version} from './version.ts';\n\nclass LevelFilterLogSink implements LogSink {\n readonly #wrappedLogSink: LogSink;\n readonly #level: LogLevel;\n\n constructor(wrappedLogSink: LogSink, level: LogLevel) {\n this.#wrappedLogSink = wrappedLogSink;\n this.#level = level;\n }\n\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n if (this.#level === 'error' && level !== 'error') {\n return;\n }\n if (this.#level === 'info' && level === 'debug') {\n return;\n }\n this.#wrappedLogSink.log(level, context, ...args);\n }\n\n async flush() {\n await consoleLogSink.flush?.();\n }\n}\n\nconst DATADOG_LOG_LEVEL = 'info';\nconst ZERO_SASS_DOMAIN = '.reflect-server.net';\n\nexport type LogOptions = {\n readonly logLevel: LogLevel;\n readonly logSink: LogSink;\n};\n\nexport function createLogOptions(\n options: {\n consoleLogLevel: LogLevel;\n server: HTTPString | null;\n enableAnalytics: boolean;\n },\n createDatadogLogSink: (options: DatadogLogSinkOptions) => LogSink = (\n options: DatadogLogSinkOptions,\n ) => new DatadogLogSink(options),\n): LogOptions {\n const {consoleLogLevel, server, enableAnalytics} = options;\n\n if (!enableAnalytics || server === null) {\n return {\n logLevel: consoleLogLevel,\n logSink: consoleLogSink,\n };\n }\n\n const serverURL = new URL(server);\n const {hostname} = serverURL;\n const datadogServiceLabel = hostname.endsWith(ZERO_SASS_DOMAIN)\n ? hostname\n .substring(0, hostname.length - ZERO_SASS_DOMAIN.length)\n .toLowerCase()\n : hostname;\n const baseURL = new URL(appendPath(server, '/logs/v0/log'));\n const logLevel = consoleLogLevel === 'debug' ? 'debug' : 'info';\n const logSink = new TeeLogSink([\n new LevelFilterLogSink(consoleLogSink, consoleLogLevel),\n new LevelFilterLogSink(\n createDatadogLogSink({\n service: datadogServiceLabel,\n host: location.host,\n version,\n baseURL,\n }),\n DATADOG_LOG_LEVEL,\n ),\n ]);\n return {\n logLevel,\n logSink,\n };\n}\n", "import {Lock} from '@rocicorp/lock';\nimport type {Context, LogLevel, LogSink} from '@rocicorp/logger';\n\nexport interface DatadogLogSinkOptions {\n apiKey?: string | undefined;\n source?: string | undefined;\n service?: string | undefined;\n host?: string | undefined;\n version?: string | undefined;\n interval?: number | undefined;\n baseURL?: URL | undefined;\n}\n\nconst DD_BASE_URL = new URL(\n 'https://http-intake.logs.datadoghq.com/api/v2/logs',\n);\n\n// https://docs.datadoghq.com/api/latest/logs/\nexport const MAX_LOG_ENTRIES_PER_FLUSH = 1000;\nexport const FORCE_FLUSH_THRESHOLD = 250;\nconst MAX_ENTRY_BYTES = 5 * 1024 * 1024;\nconst MAX_MESSAGE_RETRIES = 2;\n\n// Conservative limit that assumes all chars are encoded as 4 UTF-8 bytes.\n// This makes the actual limit somewhere closer to 1.25 MB, which is still\n// a reasonable amount of log data to send per request.\nexport const MAX_ENTRY_CHARS = MAX_ENTRY_BYTES / 4;\n\nexport class DatadogLogSink implements LogSink {\n #messages: Message[] = [];\n readonly #apiKey: string | undefined;\n readonly #source: string | undefined;\n readonly #service: string | undefined;\n readonly #host: string | undefined;\n readonly #version: string | undefined;\n readonly #interval: number;\n readonly #baseURL: string;\n #timerID: ReturnType<typeof setTimeout> | 0 = 0;\n #flushLock = new Lock();\n\n constructor(options: DatadogLogSinkOptions) {\n const {\n apiKey,\n source,\n service,\n host,\n version,\n interval = 5_000,\n baseURL: baseUrl = DD_BASE_URL,\n } = options;\n\n this.#apiKey = apiKey;\n this.#source = source;\n this.#service = service;\n this.#host = host;\n this.#version = version;\n this.#interval = interval;\n this.#baseURL = baseUrl.toString();\n }\n\n log(level: LogLevel, context: Context | undefined, ...args: unknown[]): void {\n this.#messages.push(makeMessage(args, context, level));\n if (level === 'error' || this.#messages.length === FORCE_FLUSH_THRESHOLD) {\n // Do not await. Later calls to flush will await as needed.\n void this.flush();\n } else {\n this.#startTimer();\n }\n }\n #startTimer() {\n if (this.#timerID) {\n return;\n }\n\n this.#timerID = setTimeout(() => {\n this.#timerID = 0;\n\n void this.flush();\n }, this.#interval);\n }\n\n flush(): Promise<void> {\n return this.#flushLock.withLock(async () => {\n const {length} = this.#messages;\n if (length === 0) {\n return;\n }\n do {\n const flushTime = Date.now();\n const stringified = [];\n let totalBytes = 0;\n\n for (const m of this.#messages) {\n // As a small perf optimization, we directly mutate\n // the message rather than making a shallow copy.\n // The LOG_SINK_FLUSH_DELAY_ATTRIBUTE will be clobbered by\n // the next flush if this flush fails (which is the desired behavior).\n m.flushDelayMs = flushTime - m.date;\n\n let str = JSON.stringify(m);\n if (str.length > MAX_ENTRY_CHARS) {\n // A single message above the total payload limit will otherwise halt\n // log flushing progress. Drop and replace with a message indicating so.\n m.message = `[Dropped message of length ${str.length}]`;\n str = JSON.stringify(m);\n }\n // Calculate the totalBytes with the newline characters between messages.\n if (str.length + totalBytes + stringified.length > MAX_ENTRY_CHARS) {\n break;\n }\n totalBytes += str.length;\n stringified.push(str);\n\n if (stringified.length === MAX_LOG_ENTRIES_PER_FLUSH) {\n break;\n }\n }\n\n const body = stringified.join('\\n');\n const url = new URL(this.#baseURL);\n if (this.#apiKey !== undefined) {\n url.searchParams.set('dd-api-key', this.#apiKey);\n }\n\n if (this.#source) {\n // Both need to be set for server to treat us as the browser SDK for\n // value 'browser'.\n url.searchParams.set('ddsource', this.#source);\n url.searchParams.set('dd-evp-origin', this.#source);\n }\n\n if (this.#service) {\n url.searchParams.set('service', this.#service);\n }\n\n if (this.#host) {\n url.searchParams.set('host', this.#host);\n }\n\n if (this.#version) {\n url.searchParams.set('ddtags', `version:${this.#version}`);\n }\n\n let ok = false;\n try {\n const response = await fetch(url.toString(), {\n method: 'POST',\n body,\n keepalive: true,\n } as RequestInit);\n\n ok = response.ok;\n if (!ok) {\n // Log to console so that we might catch this in `wrangler tail`.\n // oxlint-disable-next-line no-console\n console.error(\n 'response',\n response.status,\n response.statusText,\n await response.text,\n );\n }\n } catch (e) {\n // Log to console so that we might catch this in `wrangler tail`.\n // oxlint-disable-next-line no-console\n console.error('Log flush to datadog failed', e);\n }\n\n if (ok) {\n // Remove messages that were successfully flushed.\n this.#messages.splice(0, stringified.length);\n } else {\n let numWithTooManyRetries = 0;\n for (let i = 0; i < stringified.length; i++) {\n const m = this.#messages[i];\n m.flushRetryCount = (m.flushRetryCount ?? 0) + 1;\n if (m.flushRetryCount > MAX_MESSAGE_RETRIES) {\n numWithTooManyRetries++;\n }\n }\n if (numWithTooManyRetries > 0) {\n // oxlint-disable-next-line no-console\n console.error(\n `Dropping ${numWithTooManyRetries} datadog log messages which failed to send ${\n MAX_MESSAGE_RETRIES + 1\n } times.`,\n );\n // Remove messages that have failed too many times.\n this.#messages.splice(0, numWithTooManyRetries);\n }\n }\n } while (this.#messages.length >= FORCE_FLUSH_THRESHOLD);\n // If any messages left at this point schedule another flush.\n if (this.#messages.length) {\n this.#startTimer();\n }\n });\n }\n}\n\ntype Message = Context & {\n status: LogLevel;\n date: number;\n message: unknown;\n error?: {origin: 'logger'};\n flushDelayMs?: number;\n flushRetryCount?: number;\n};\n\nfunction flattenMessage(message: unknown): unknown {\n if (Array.isArray(message) && message.length === 1) {\n return flattenMessage(message[0]);\n }\n return message;\n}\n\nfunction convertError(e: Error): {\n name: string;\n message: string;\n stack: string | undefined;\n} {\n return {\n name: e.name,\n message: e.message,\n stack: e.stack,\n };\n}\n\nfunction convertErrors(message: unknown): unknown {\n if (message instanceof Error) {\n return convertError(message);\n }\n if (message instanceof Array) {\n const convertedMessage: unknown[] = [];\n for (const item of message) {\n if (item instanceof Error) {\n convertedMessage.push(convertError(item));\n } else {\n convertedMessage.push(item);\n }\n }\n return convertedMessage;\n }\n return message;\n}\n\nconst LOG_SINK_FLUSH_RETRY_COUNT = 'flushRetryCount';\nconst LOG_SINK_FLUSH_DELAY_ATTRIBUTE = 'flushDelayMs';\n// This code assumes that no context keys will start with\n// @DATADOG_RESERVED_ (a fairly safe assumption).\nconst RESERVED_KEY_PREFIX = '@DATADOG_RESERVED_';\n// See https://docs.datadoghq.com/logs/log_configuration/attributes_naming_convention/#reserved-attributes\n// Note 'msg' and 'date' are not documented.\n// We should avoid using these as context keys. We escape them here\n// because otherwise the impact on the data dog log UI is very confusing\n// (e.g. using 'msg' as a context key results, in the context value\n// replacing the log message.)\nconst RESERVED_KEYS: ReadonlyArray<string> = [\n 'host',\n 'source',\n 'status',\n 'service',\n 'version',\n 'trace_id',\n 'message',\n 'msg', // alias for message\n 'date',\n // The following are attributes reserved by the DataDogLogSink\n // itself (as opposed to DataDog), to report on its own behavior.\n LOG_SINK_FLUSH_DELAY_ATTRIBUTE,\n LOG_SINK_FLUSH_RETRY_COUNT,\n];\n\nfunction makeMessage(\n message: unknown,\n context: Context | undefined,\n logLevel: LogLevel,\n): Message {\n let safeContext = undefined;\n if (context !== undefined) {\n for (const reservedKey of RESERVED_KEYS) {\n if (Object.hasOwn(context, reservedKey)) {\n if (safeContext === undefined) {\n safeContext = {...context};\n }\n safeContext[RESERVED_KEY_PREFIX + reservedKey] =\n safeContext[reservedKey];\n delete safeContext[reservedKey];\n }\n }\n }\n const msg: Message = {\n ...(safeContext ?? context),\n date: Date.now(),\n message: convertErrors(flattenMessage(message)),\n status: logLevel,\n };\n if (logLevel === 'error') {\n msg.error = {origin: 'logger'};\n }\n return msg;\n}\n", "// The env value should be filled in by esbuild.\n\ndeclare const process: {\n env: {\n ['ZERO_VERSION']?: string;\n };\n};\n\n/**\n * The current version of Zero.\n */\nexport const version = process.env.ZERO_VERSION ?? '0.0.0';\n", "export const TimeToConnectMs = 'time_to_connect_ms';\nexport const LastConnectError = 'last_connect_error';\nexport const TimeToConnectMsV2 = 'time_to_connect_ms_v2';\nexport const LastConnectErrorV2 = 'last_connect_error_v2';\nexport const TotalTimeToConnectMs = 'total_time_to_connect_ms';\nexport const NotConnected = 'not_connected';\n\nexport type TimeToConnectMs = typeof TimeToConnectMs;\nexport type LastConnectError = typeof LastConnectError;\nexport type TimeToConnectMsV2 = typeof TimeToConnectMsV2;\nexport type LastConnectErrorV2 = typeof LastConnectErrorV2;\nexport type TotalTimeToConnectMs = typeof TotalTimeToConnectMs;\nexport type NotConnected = typeof NotConnected;\n", "import type {MaybePromise} from '../../../shared/src/types.ts';\nimport {ClientErrorKind} from './client-error-kind.ts';\nimport {\n isClientError,\n isServerError,\n type ZeroError,\n type ZeroErrorKind,\n} from './error.ts';\nimport {MetricName} from './metric-name.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\n// This value is used to indicate that the client's last connection attempt\n// failed. We don't make this -1 because we want to stack this never connected\n// state in a graph on top of actual connection times, so it should be greater\n// than any other value.\nexport const DID_NOT_CONNECT_VALUE = 100 * 1000;\n\nexport const REPORT_INTERVAL_MS = 5_000;\n\ntype NotConnectedReason =\n | 'init'\n | 'error'\n | 'hidden'\n | 'hidden_was_init'\n | 'hidden_was_error';\n\nexport function getLastConnectErrorValue(reason: ZeroError) {\n return `${isServerError(reason) ? 'server_' : 'client_'}${camelToSnake(reason.kind)}` as const;\n}\n\n// camelToSnake is used to convert a ZeroErrorKind into a suitable\n// metric name, eg AuthInvalidated => auth_invalidated. It converts\n// both PascalCase and camelCase to snake_case.\nfunction camelToSnake(kind: ZeroErrorKind): string {\n return kind\n .split(/\\.?(?=[A-Z])/)\n .join('_')\n .toLowerCase();\n}\n\n/**\n * Returns whether an error should be reported in metrics and\n * increment the connect error count.\n *\n * Returns `true` for all server errors and client errors that represent actual\n * connection problems. Returns `false` for expected client-side disconnections\n * (user disconnect, client closed, hidden tab, clean/abrupt close).\n */\nexport function shouldReportConnectError(reason: ZeroError): boolean {\n if (!isClientError(reason)) {\n return true;\n }\n switch (reason.kind) {\n case ClientErrorKind.Hidden:\n case ClientErrorKind.ClientClosed:\n case ClientErrorKind.UserDisconnect:\n case ClientErrorKind.CleanClose:\n case ClientErrorKind.AbruptClose:\n return false;\n default:\n return true;\n }\n}\n\ntype MetricsReporter = (metrics: Series[]) => MaybePromise<void>;\n\nexport type MetricManagerOptions = {\n reportIntervalMs: number;\n host: string;\n source: string;\n reporter: MetricsReporter;\n lc: ZeroLogContext;\n};\n\n/**\n * MetricManager keeps track of the set of metrics in use and flushes them\n * to a format suitable for reporting.\n */\nexport class MetricManager {\n #reportIntervalMs: number;\n #host: string;\n #reporter: MetricsReporter;\n #lc: ZeroLogContext;\n #timerID: ReturnType<typeof setInterval> | null;\n\n constructor(opts: MetricManagerOptions) {\n this.#reportIntervalMs = opts.reportIntervalMs;\n this.#host = opts.host;\n this.#reporter = opts.reporter;\n this.#lc = opts.lc;\n\n this.tags.push(`source:${opts.source}`);\n\n this.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);\n this.#setNotConnectedReason('init');\n\n this.#timerID = setInterval(() => {\n void this.flush();\n }, this.#reportIntervalMs);\n }\n\n #metrics: Flushable[] = [];\n\n // timeToConnectMs measures the time from the call to connect() to receiving\n // the 'connected' ws message. We record the DID_NOT_CONNECT_VALUE if the previous\n // connection attempt failed for any reason.\n //\n // We set the gauge using #connectStart as follows:\n // - #connectStart is undefined if we are disconnected or connected; it is\n // defined only in the Connecting state, as a number representing the timestamp\n // at which we started connecting.\n // - #connectStart is set to the current time when connect() is called.\n // - When we receive the 'connected' message we record the time to connect and\n // set #connectStart to undefined.\n // - If disconnect() is called with a defined #connectStart then we record\n // DID_NOT_CONNECT_VALUE and set #connectStart to undefined.\n //\n // TODO It's clear after playing with the connection code we should encapsulate\n // the ConnectionState along with its state transitions and possibly behavior.\n // In that world the metric gauge(s) and bookkeeping like #connectStart would\n // be encapsulated with the ConnectionState. This will probably happen as part\n // of https://github.com/rocicorp/reflect-server/issues/255.\n readonly timeToConnectMs = this.#register(\n new Gauge(MetricName.TimeToConnectMs),\n );\n\n // lastConnectError records the last error that occurred when connecting,\n // if any. It is cleared when connecting successfully or when reported, so this\n // state only gets reported if there was a failure during the reporting period and\n // we are still not connected.\n readonly lastConnectError = this.#register(\n new State(\n MetricName.LastConnectError,\n true, // clearOnFlush\n ),\n );\n\n // notConnected records the reason why the client is not currently connected.\n // It is cleared when the client successfully connects.\n readonly #notConnected = this.#register(new State(MetricName.NotConnected));\n\n // The time from the call to connect() to receiving the 'connected' ws message\n // for the current connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect untill there is a\n // connect error, or client reports disconnected and waiting for visible.\n // Should have a value iff _notConnected has no value.\n readonly #timeToConnectMsV2 = this.#register(\n new Gauge(MetricName.TimeToConnectMsV2),\n );\n\n // lastConnectErrorV2 records the last error that occurred when connecting,\n // if any. It is cleared when the client successfully connects or\n // stops trying to connect due to being hidden.\n // Should have a value iff notConnected state is NotConnectedReason.Error.\n readonly #lastConnectErrorV2 = this.#register(\n new State(MetricName.LastConnectErrorV2),\n );\n\n // The total time it took to connect across retries for the current\n // connection. Cleared when the client is not connected.\n // TODO: Not actually currently cleared on disconnect until there is a\n // connect error, or client reports disconnected and waiting for visible.\n // See Zero.#totalToConnectStart for details of how this total is computed.\n // Should have a value iff _notConnected has no value.\n readonly #totalTimeToConnectMs = this.#register(\n new Gauge(MetricName.TotalTimeToConnectMs),\n );\n\n #setNotConnectedReason(reason: NotConnectedReason) {\n this.#notConnected.set(reason);\n }\n\n setConnected(timeToConnectMs: number, totalTimeToConnectMs: number) {\n this.#notConnected.clear();\n this.#lastConnectErrorV2.clear();\n this.#timeToConnectMsV2.set(timeToConnectMs);\n this.#totalTimeToConnectMs.set(totalTimeToConnectMs);\n }\n\n setDisconnectedWaitingForVisible() {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#lastConnectErrorV2.clear();\n let notConnectedReason: NotConnectedReason;\n switch (this.#notConnected.get()) {\n case 'init':\n notConnectedReason = 'hidden_was_init';\n break;\n case 'error':\n notConnectedReason = 'hidden_was_error';\n break;\n default:\n notConnectedReason = 'hidden';\n break;\n }\n this.#setNotConnectedReason(notConnectedReason);\n }\n\n setConnectError(reason: ZeroError) {\n this.#timeToConnectMsV2.clear();\n this.#totalTimeToConnectMs.clear();\n this.#setNotConnectedReason('error');\n this.#lastConnectErrorV2.set(getLastConnectErrorValue(reason));\n }\n\n /**\n * Tags to include in all metrics.\n */\n readonly tags: string[] = [];\n\n // Flushes all metrics to an array of time series (plural), one Series\n // per metric.\n async flush() {\n const lc = this.#lc;\n if (this.#timerID === null) {\n lc.error?.('MetricManager.flush() called but already stopped');\n return;\n }\n const allSeries: Series[] = [];\n for (const metric of this.#metrics) {\n const series = metric.flush();\n if (series !== undefined) {\n allSeries.push({\n ...series,\n host: this.#host,\n tags: this.tags,\n });\n }\n }\n if (allSeries.length === 0) {\n lc?.debug?.('No metrics to report');\n return;\n }\n try {\n await this.#reporter(allSeries);\n } catch (e) {\n lc?.error?.('Error reporting metrics', e);\n }\n }\n\n stop() {\n if (this.#timerID === null) {\n this.#lc.error?.('MetricManager.stop() called but already stopped');\n return;\n }\n clearInterval(this.#timerID);\n this.#timerID = null;\n }\n\n #register<M extends Flushable>(metric: M) {\n this.#metrics.push(metric);\n return metric;\n }\n}\n\n// These two types are influenced by Datadog's API's needs. We could change what\n// we use internally if necessary, but we'd just have to convert to/from before\n// sending to DD. So for convenience we go with their format.\n\n/** Series is a time series of points for a single metric. */\nexport type Series = {\n host: string;\n metric: string; // We call this 'name' bc 'metric' is overloaded in code.\n points: Point[];\n tags?: string[];\n};\n/**\n * A point is a second-resolution timestamp and a set of values for that\n * timestamp. A point represents exactly one second in time and the values\n * are those recorded for that second. The first element of this array\n * is the timestamp and the second element is an array of values.\n */\nexport type Point = [number, number[]];\n\nfunction makePoint(ts: number, value: number): Point {\n return [ts, [value]];\n}\n\ntype Flushable = {\n flush(): Pick<Series, 'metric' | 'points'> | undefined;\n};\n\n/**\n * Gauge is a metric type that represents a single value that can go up and\n * down. It's typically used to track discrete values or counts eg the number\n * of active users, number of connections, cpu load, etc. A gauge retains\n * its value when flushed.\n *\n * We use a Gauge to sample at the client. If we are interested in tracking\n * a metric value *per client*, the client can note the latest value in\n * a Gauge metric. The metric is periodically reported via Reporter. On the\n * server, we graph the value of the metric rolled up over the periodic\n * reporting period, that is, counted over a span of time equal to the\n * reporting period. The result is ~one point per client per reporting\n * period.\n */\nexport class Gauge implements Flushable {\n readonly #name: string;\n #value: number | undefined = undefined;\n\n constructor(name: string) {\n this.#name = name;\n }\n\n set(value: number) {\n this.#value = value;\n }\n\n get() {\n return this.#value;\n }\n\n clear() {\n this.#value = undefined;\n }\n\n flush() {\n if (this.#value === undefined) {\n return undefined;\n }\n // Gauge reports the timestamp at flush time, not at the point the value was\n // recorded.\n const points = [makePoint(t(), this.#value)];\n return {metric: this.#name, points};\n }\n}\n\nfunction t() {\n return Math.round(Date.now() / 1000);\n}\n\n/**\n * State is a metric type that represents a specific state that the system is\n * in, for example the state of a connection which may be 'open' or 'closed'.\n * The state is given a name/prefix at construction time (eg 'connection') and\n * then can be set to a specific state (eg 'open'). The prefix is prepended to\n * the set state (eg, 'connection_open') and a value of 1 is reported.\n * Unset/cleared states are not reported.\n *\n * Example:\n * const s = new State('connection');\n * s.set('open');\n * s.flush(); // returns {metric: 'connection_open', points: [[now(), [1]]]}\n */\nexport class State implements Flushable {\n readonly #prefix: string;\n readonly #clearOnFlush: boolean;\n #current: string | undefined = undefined;\n\n constructor(prefix: string, clearOnFlush = false) {\n this.#prefix = prefix;\n this.#clearOnFlush = clearOnFlush;\n }\n\n set(state: string) {\n this.#current = state;\n }\n\n get() {\n return this.#current;\n }\n\n clear() {\n this.#current = undefined;\n }\n\n flush() {\n if (this.#current === undefined) {\n return undefined;\n }\n const gauge = new Gauge([this.#prefix, this.#current].join('_'));\n gauge.set(1);\n const series = gauge.flush();\n if (this.#clearOnFlush) {\n this.clear();\n }\n return series;\n }\n}\n", "import {resolver, type Resolver} from '@rocicorp/resolver';\nimport type {\n EphemeralID,\n MutationTrackingData,\n} from '../../../replicache/src/replicache-options.ts';\nimport type {ReplicacheImpl} from '../../../replicache/src/impl.ts';\nimport type {NoIndexDiff} from '../../../replicache/src/btree/node.ts';\nimport {assert, unreachable} from '../../../shared/src/asserts.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {emptyObject} from '../../../shared/src/sentinels.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {\n mutationResultSchema,\n type MutationError,\n type MutationID,\n type MutationOk,\n type PushError,\n type PushOk,\n type PushResponseBody,\n} from '../../../zero-protocol/src/push.ts';\nimport {type ZeroError} from './error.ts';\nimport {MUTATIONS_KEY_PREFIX} from './keys.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {\n ApplicationError,\n wrapWithApplicationError,\n} from '../../../zero-protocol/src/application-error.ts';\n\ntype ErrorType =\n | MutationError\n | Omit<PushError, 'mutationIDs'>\n | Error\n | unknown;\n\nlet currentEphemeralID = 0;\nfunction nextEphemeralID(): EphemeralID {\n return ++currentEphemeralID as EphemeralID;\n}\n\n/**\n * Tracks what pushes are in-flight and resolves promises when they're acked.\n */\nexport class MutationTracker {\n readonly #outstandingMutations: Map<\n EphemeralID,\n {\n mutationID?: number | undefined;\n resolver: Resolver<MutationOk, ErrorType>;\n }\n >;\n readonly #ephemeralIDsByMutationID: Map<number, EphemeralID>;\n readonly #allMutationsAppliedListeners: Set<() => void>;\n readonly #lc: ZeroLogContext;\n\n readonly #ackMutations: (upTo: MutationID) => void;\n readonly #onFatalError: (error: ZeroError) => void;\n #clientID: string | undefined;\n #largestOutstandingMutationID: number;\n #currentMutationID: number;\n\n constructor(\n lc: ZeroLogContext,\n ackMutations: (upTo: MutationID) => void,\n onFatalError: (error: ZeroError) => void,\n ) {\n this.#lc = lc.withContext('MutationTracker');\n this.#outstandingMutations = new Map();\n this.#ephemeralIDsByMutationID = new Map();\n this.#allMutationsAppliedListeners = new Set();\n this.#largestOutstandingMutationID = 0;\n this.#currentMutationID = 0;\n this.#ackMutations = ackMutations;\n this.#onFatalError = onFatalError;\n }\n\n setClientIDAndWatch(\n clientID: string,\n experimentalWatch: ReplicacheImpl['experimentalWatch'],\n ) {\n assert(this.#clientID === undefined, 'clientID already set');\n this.#clientID = clientID;\n experimentalWatch(\n diffs => {\n this.#processMutationResponses(diffs);\n },\n {\n prefix: MUTATIONS_KEY_PREFIX + clientID + '/',\n initialValuesInFirstDiff: true,\n },\n );\n }\n\n trackMutation(): MutationTrackingData {\n const id = nextEphemeralID();\n const mutationResolver = resolver<MutationOk, ErrorType>();\n\n this.#outstandingMutations.set(id, {\n resolver: mutationResolver,\n });\n return {ephemeralID: id, serverPromise: mutationResolver.promise};\n }\n\n mutationIDAssigned(id: EphemeralID, mutationID: number): void {\n const entry = this.#outstandingMutations.get(id);\n if (entry) {\n entry.mutationID = mutationID;\n this.#ephemeralIDsByMutationID.set(mutationID, id);\n this.#largestOutstandingMutationID = Math.max(\n this.#largestOutstandingMutationID,\n mutationID,\n );\n }\n }\n\n /**\n * Reject the mutation due to an unhandled exception on the client.\n * The mutation must not have been persisted to the client store.\n */\n rejectMutation(id: EphemeralID, e: unknown): void {\n const entry = this.#outstandingMutations.get(id);\n if (entry) {\n this.#settleMutation(id, entry, 'reject', wrapWithApplicationError(e));\n }\n }\n\n /**\n * Used when zero-cache pokes down mutation results.\n */\n #processMutationResponses(diffs: NoIndexDiff): void {\n const clientID = must(this.#clientID);\n let largestLmid = 0;\n for (const diff of diffs) {\n const mutationID = Number(\n diff.key.slice(MUTATIONS_KEY_PREFIX.length + clientID.length + 1),\n );\n assert(\n !isNaN(mutationID),\n `MutationTracker received a diff with an invalid mutation ID: ${diff.key}`,\n );\n largestLmid = Math.max(largestLmid, mutationID);\n switch (diff.op) {\n case 'add': {\n const result = v.parse(diff.newValue, mutationResultSchema);\n if ('error' in result) {\n this.#processMutationError(clientID, mutationID, result);\n } else {\n this.#processMutationOk(clientID, mutationID, result);\n }\n break;\n }\n case 'del':\n break;\n case 'change':\n throw new Error('MutationTracker does not expect change operations');\n }\n }\n\n if (largestLmid > 0) {\n this.#ackMutations({\n clientID: must(this.#clientID),\n id: largestLmid,\n });\n }\n }\n\n processPushResponse(response: PushResponseBody): void {\n if ('error' in response) {\n this.#lc.error?.(\n 'Received an error response when pushing mutations',\n response,\n );\n const fatalError = this.#fatalErrorFromPushError(response);\n if (fatalError) {\n this.#onFatalError(fatalError);\n }\n } else {\n this.#processPushOk(response);\n }\n }\n\n #fatalErrorFromPushError(error: PushError): ZeroError | undefined {\n switch (error.error) {\n case 'unsupportedPushVersion':\n return new ProtocolError({\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `Unsupported push version`,\n mutationIDs: [],\n });\n case 'unsupportedSchemaVersion':\n return new ProtocolError({\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `Unsupported schema version`,\n mutationIDs: [],\n });\n case 'http':\n return new ProtocolError({\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.HTTP,\n status: error.status,\n message: `Fetch from API server returned non-OK status ${error.status}: ${error.details ?? 'unknown'}`,\n mutationIDs: [],\n });\n case 'zeroPusher':\n return new ProtocolError({\n kind: ErrorKind.PushFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `ZeroPusher error: ${error.details ?? 'unknown'}`,\n mutationIDs: [],\n });\n default:\n unreachable(error);\n }\n }\n\n /**\n * DEPRECATED: to be removed when we switch to fully driving\n * mutation resolution via poke.\n *\n * When we reconnect to zero-cache, we resolve all outstanding mutations\n * whose ID is less than or equal to the lastMutationID.\n *\n * The reason is that any responses the API server sent\n * to those mutations have been lost.\n *\n * An example case: the API server responds while the connection\n * is down. Those responses are lost.\n *\n * Mutations whose LMID is > the lastMutationID are not resolved\n * since they will be retried by the client, giving us another chance\n * at getting a response.\n *\n * The only way to ensure that all API server responses are\n * received would be to have the API server write them\n * to the DB while writing the LMID.\n */\n onConnected(lastMutationID: number) {\n this.lmidAdvanced(lastMutationID);\n }\n\n /**\n * lmid advance will:\n * 1. notify \"allMutationsApplied\" listeners if the lastMutationID\n * is greater than or equal to the largest outstanding mutation ID.\n * 2. resolve all mutations whose mutation ID is less than or equal to\n * the lastMutationID.\n */\n lmidAdvanced(lastMutationID: number): void {\n assert(\n lastMutationID >= this.#currentMutationID,\n 'lmid must be greater than or equal to current lmid',\n );\n if (lastMutationID === this.#currentMutationID) {\n return;\n }\n\n try {\n this.#currentMutationID = lastMutationID;\n this.#resolveMutations(lastMutationID);\n } finally {\n if (lastMutationID >= this.#largestOutstandingMutationID) {\n // this is very important otherwise we hang query de-registration\n this.#notifyAllMutationsAppliedListeners();\n }\n }\n }\n\n get size() {\n return this.#outstandingMutations.size;\n }\n\n #resolveMutations(upTo: number): void {\n // We resolve all mutations whose mutation ID is less than or equal to\n // the upTo mutation ID.\n for (const [id, entry] of this.#outstandingMutations) {\n if (entry.mutationID && entry.mutationID <= upTo) {\n this.#settleMutation(id, entry, 'resolve', emptyObject);\n } else {\n break; // the map is in insertion order which is in mutation ID order\n }\n }\n }\n\n #processPushOk(ok: PushOk): void {\n for (const mutation of ok.mutations) {\n if ('error' in mutation.result) {\n this.#processMutationError(\n mutation.id.clientID,\n mutation.id.id,\n mutation.result,\n );\n } else {\n this.#processMutationOk(\n mutation.id.clientID,\n mutation.id.id,\n mutation.result,\n );\n }\n }\n }\n\n #processMutationError(\n clientID: string,\n mid: number,\n error: MutationError | Omit<PushError, 'mutationIDs'>,\n ): void {\n assert(\n clientID === this.#clientID,\n 'received mutation for the wrong client',\n );\n\n const ephemeralID = this.#ephemeralIDsByMutationID.get(mid);\n if (!ephemeralID && error.error === 'alreadyProcessed') {\n return;\n }\n\n // Each tab sends all mutations for the client group\n // and the server responds back to the individual client that actually\n // ran the mutation. This means that N clients can send the same\n // mutation concurrently. If that happens, the promise for the mutation tracked\n // by this class will try to be resolved N times.\n // Every time after the first, the ephemeral ID will not be\n // found in the map. These later times, however, should always have been\n // \"mutation already processed\" events which we ignore (above).\n assert(\n ephemeralID,\n `ephemeral ID is missing for mutation error: ${error.error}.`,\n );\n\n const entry = this.#outstandingMutations.get(ephemeralID);\n assert(entry && entry.mutationID === mid);\n this.#settleMutation(\n ephemeralID,\n entry,\n 'reject',\n error.error === 'app'\n ? new ApplicationError(\n error.message ?? `Unknown application error: ${error.error}`,\n error.details ? {details: error.details} : undefined,\n )\n : new Error(\n error.error === 'alreadyProcessed'\n ? 'Mutation already processed'\n : error.error === 'oooMutation'\n ? 'Server reported an out-of-order mutation'\n : `Unknown fallback error with mutation ID ${mid}: ${error.error}`,\n ),\n );\n\n // this is included for backwards compatibility with the per-mutation fatal error responses\n if (error.error === 'oooMutation') {\n this.#onFatalError(\n new ProtocolError({\n kind: ErrorKind.InvalidPush,\n origin: ErrorOrigin.Server,\n reason: ErrorReason.Internal,\n message: 'Server reported an out-of-order mutation',\n details: error.details,\n }),\n );\n }\n }\n\n #processMutationOk(clientID: string, mid: number, result: MutationOk): void {\n assert(\n clientID === this.#clientID,\n 'received mutation for the wrong client',\n );\n\n const ephemeralID = this.#ephemeralIDsByMutationID.get(mid);\n assert(\n ephemeralID,\n 'ephemeral ID is missing. This can happen if a mutation response is received twice ' +\n 'but it should be impossible to receive a success response twice for the same mutation.',\n );\n const entry = this.#outstandingMutations.get(ephemeralID);\n assert(entry && entry.mutationID === mid);\n this.#settleMutation(ephemeralID, entry, 'resolve', result);\n }\n\n #settleMutation<Type extends 'resolve' | 'reject'>(\n ephemeralID: EphemeralID,\n entry: {\n mutationID?: number | undefined;\n resolver: Resolver<MutationOk, ErrorType>;\n },\n type: Type,\n result: 'resolve' extends Type ? MutationOk : Error,\n ): void {\n switch (type) {\n case 'resolve':\n entry.resolver.resolve(result as MutationOk);\n break;\n case 'reject':\n entry.resolver.reject(result);\n break;\n }\n\n this.#outstandingMutations.delete(ephemeralID);\n if (entry.mutationID) {\n this.#ephemeralIDsByMutationID.delete(entry.mutationID);\n }\n }\n\n /**\n * Be notified when all mutations have been included in the server snapshot.\n *\n * The query manager will not de-register queries from the server until there\n * are no pending mutations.\n *\n * The reason is that a mutation may need to be rebased. We do not want\n * data that was available the first time it was run to not be available\n * on a rebase.\n */\n onAllMutationsApplied(listener: () => void): void {\n this.#allMutationsAppliedListeners.add(listener);\n }\n\n #notifyAllMutationsAppliedListeners() {\n for (const listener of this.#allMutationsAppliedListeners) {\n listener();\n }\n }\n}\n", "import type {ReplicacheImpl} from '../../../replicache/src/replicache-impl.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {assert} from '../../../shared/src/asserts.ts';\nimport type {ReadonlyJSONValue} from '../../../shared/src/json.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport {TDigest} from '../../../shared/src/tdigest.ts';\nimport {\n mapAST,\n normalizeAST,\n type AST,\n} from '../../../zero-protocol/src/ast.ts';\nimport type {ChangeDesiredQueriesMessage} from '../../../zero-protocol/src/change-desired-queries.ts';\nimport type {ErroredQuery} from '../../../zero-protocol/src/custom-queries.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {ErrorOrigin} from '../../../zero-protocol/src/error-origin.ts';\nimport {ErrorReason} from '../../../zero-protocol/src/error-reason.ts';\nimport {ProtocolError} from '../../../zero-protocol/src/error.ts';\nimport type {UpQueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport {\n hashOfAST,\n hashOfNameAndArgs,\n} from '../../../zero-protocol/src/query-hash.ts';\nimport {\n clientToServer,\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport type {TableSchema} from '../../../zero-schema/src/table-schema.ts';\nimport type {ClientMetricMap} from '../../../zql/src/query/metrics-delegate.ts';\nimport type {CustomQueryID} from '../../../zql/src/query/named.ts';\nimport type {GotCallback} from '../../../zql/src/query/query-delegate.ts';\nimport {clampTTL, compareTTL, type TTL} from '../../../zql/src/query/ttl.ts';\nimport {type ZeroError} from './error.ts';\nimport type {InspectorDelegate} from './inspector/inspector.ts';\nimport {desiredQueriesPrefixForClient, GOT_QUERIES_KEY_PREFIX} from './keys.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\nimport type {ReadTransaction} from './replicache-types.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\ntype QueryHash = string;\n\ntype Entry = {\n // We keep track of the AST so we can use it in the inspector.\n normalized: AST;\n name: string | undefined;\n args: readonly ReadonlyJSONValue[] | undefined;\n count: number;\n gotCallbacks: GotCallback[];\n ttl: TTL;\n};\n\ntype ClientMetric = {\n [K in keyof ClientMetricMap]: TDigest;\n};\n\n/**\n * Tracks what queries the client is currently subscribed to on the server.\n * Sends `changeDesiredQueries` message to server when this changes.\n * Deduplicates requests so that we only listen to a given unique query once.\n */\nexport class QueryManager implements InspectorDelegate {\n readonly #clientID: ClientID;\n readonly #clientToServer: NameMapper;\n readonly #serverToClient: NameMapper;\n readonly #send: (change: ChangeDesiredQueriesMessage) => void;\n readonly #onFatalError: (error: ZeroError) => void;\n readonly #queries: Map<QueryHash, Entry> = new Map();\n readonly #recentQueriesMaxSize: number;\n readonly #recentQueries: Set<string> = new Set();\n readonly #gotQueries: Set<string> = new Set();\n readonly #mutationTracker: MutationTracker;\n readonly #pendingQueryChanges: UpQueriesPatchOp[] = [];\n readonly #queryChangeThrottleMs: number;\n #pendingRemovals: Array<() => void> = [];\n #batchTimer: ReturnType<typeof setTimeout> | undefined;\n readonly #lc: ZeroLogContext;\n readonly #metrics: ClientMetric = newMetrics();\n readonly #queryMetrics: Map<string, ClientMetric> = new Map();\n readonly #slowMaterializeThreshold: number;\n\n constructor(\n lc: ZeroLogContext,\n mutationTracker: MutationTracker,\n clientID: ClientID,\n tables: Record<string, TableSchema>,\n send: (change: ChangeDesiredQueriesMessage) => void,\n experimentalWatch: ReplicacheImpl['experimentalWatch'],\n recentQueriesMaxSize: number,\n queryChangeThrottleMs: number,\n slowMaterializeThreshold: number,\n onFatalError: (error: ZeroError) => void,\n ) {\n this.#lc = lc.withContext('QueryManager');\n this.#clientID = clientID;\n this.#clientToServer = clientToServer(tables);\n this.#serverToClient = serverToClient(tables);\n this.#recentQueriesMaxSize = recentQueriesMaxSize;\n this.#send = send;\n this.#mutationTracker = mutationTracker;\n this.#queryChangeThrottleMs = queryChangeThrottleMs;\n this.#slowMaterializeThreshold = slowMaterializeThreshold;\n this.#onFatalError = onFatalError;\n this.#mutationTracker.onAllMutationsApplied(() => {\n if (this.#pendingRemovals.length === 0) {\n return;\n }\n const pendingRemovals = this.#pendingRemovals;\n this.#pendingRemovals = [];\n for (const removal of pendingRemovals) {\n removal();\n }\n });\n\n experimentalWatch(\n diff => {\n for (const diffOp of diff) {\n const queryHash = diffOp.key.substring(GOT_QUERIES_KEY_PREFIX.length);\n switch (diffOp.op) {\n case 'add':\n this.#gotQueries.add(queryHash);\n this.#fireGotCallbacks(queryHash, true);\n break;\n case 'del':\n this.#gotQueries.delete(queryHash);\n this.#fireGotCallbacks(queryHash, false);\n break;\n }\n }\n },\n {\n prefix: GOT_QUERIES_KEY_PREFIX,\n initialValuesInFirstDiff: true,\n },\n );\n }\n\n getAST(queryID: string): AST | undefined {\n const ast = this.#queries.get(queryID)?.normalized;\n return ast && mapAST(ast, this.#serverToClient);\n }\n\n #fireGotCallbacks(queryHash: string, got: boolean) {\n const gotCallbacks = this.#queries.get(queryHash)?.gotCallbacks ?? [];\n for (const gotCallback of gotCallbacks) {\n gotCallback(got);\n }\n }\n\n /**\n * Get the queries that need to be registered with the server.\n *\n * An optional `lastPatch` can be provided. This is the last patch that was\n * sent to the server and may not yet have been acked. If `lastPatch` is provided,\n * this method will return a patch that does not include any events sent in `lastPatch`.\n *\n * This diffing of last patch and current patch is needed since we send\n * a set of queries to the server when we first connect inside of the `sec-protocol` as\n * the `initConnectionMessage`.\n *\n * While we're waiting for the `connected` response to come back from the server,\n * the client may have registered more queries. We need to diff the `initConnectionMessage`\n * queries with the current set of queries to understand what those were.\n */\n async getQueriesPatch(\n tx: ReadTransaction,\n lastPatch?: Map<string, UpQueriesPatchOp>,\n ): Promise<Map<string, UpQueriesPatchOp>> {\n const existingQueryHashes = new Set<string>();\n const prefix = desiredQueriesPrefixForClient(this.#clientID);\n for await (const key of tx.scan({prefix}).keys()) {\n existingQueryHashes.add(key.substring(prefix.length, key.length));\n }\n const patch: Map<string, UpQueriesPatchOp> = new Map();\n for (const hash of existingQueryHashes) {\n if (!this.#queries.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n\n for (const [hash, {normalized, ttl, name, args}] of this.#queries) {\n if (!existingQueryHashes.has(hash)) {\n patch.set(hash, {\n op: 'put',\n hash,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n // We get TTL out of the DagStore so it is possible that the TTL was written\n // with a too high TTL.\n ttl: clampTTL(ttl), // no lc here since no need to log here\n });\n }\n }\n\n if (lastPatch) {\n // if there are any `puts` in `lastPatch` that are not in `patch` then we need to\n // send a `del` event in `patch`.\n for (const [hash, {op}] of lastPatch) {\n if (op === 'put' && !patch.has(hash)) {\n patch.set(hash, {op: 'del', hash});\n }\n }\n // Remove everything from `patch` that was already sent in `lastPatch`.\n for (const [hash, {op}] of patch) {\n const lastPatchOp = lastPatch.get(hash);\n if (lastPatchOp && lastPatchOp.op === op) {\n patch.delete(hash);\n }\n }\n }\n\n return patch;\n }\n\n handleTransformErrors(errors: ErroredQuery[]) {\n for (const error of errors) {\n const queryId = error.id;\n const entry = this.#queries.get(queryId);\n\n // if we don't have the query registered, continue\n if (!entry) {\n continue;\n }\n\n if (error.error === 'app' || error.error === 'parse') {\n entry.gotCallbacks.forEach(callback => callback(false, error));\n }\n // this code path is not possible technically since errors were never implemented in the legacy query transform error\n // but is included for backwards compatibility and we have a test case for it\n else {\n this.#onFatalError(\n new ProtocolError({\n kind: ErrorKind.TransformFailed,\n origin: ErrorOrigin.ZeroCache,\n reason: ErrorReason.Internal,\n message: `Unknown error transforming queries: ${JSON.stringify(error)}`,\n queryIDs: [],\n }),\n );\n // unreachable(error); TODO(0xcadams): this should eventually be unreachable\n }\n }\n }\n\n addCustom(\n ast: AST,\n {name, args}: CustomQueryID,\n ttl: TTL,\n gotCallback?: GotCallback,\n ): () => void {\n const normalized = normalizeAST(ast);\n const queryId = hashOfNameAndArgs(name, args);\n return this.#add(queryId, normalized, name, args, ttl, gotCallback);\n }\n\n addLegacy(ast: AST, ttl: TTL, gotCallback?: GotCallback): () => void {\n const normalized = normalizeAST(ast);\n const astHash = hashOfAST(normalized);\n return this.#add(\n astHash,\n normalized,\n undefined, // name is undefined for legacy queries\n undefined, // args are undefined for legacy queries\n ttl,\n gotCallback,\n );\n }\n\n #add(\n queryId: string,\n normalized: AST,\n name: string | undefined,\n args: readonly ReadonlyJSONValue[] | undefined,\n ttl: TTL,\n gotCallback?: GotCallback,\n ) {\n assert(\n (name === undefined) === (args === undefined),\n 'If name is defined, args must be defined',\n );\n ttl = clampTTL(ttl, this.#lc);\n let entry = this.#queries.get(queryId);\n this.#recentQueries.delete(queryId);\n if (!entry) {\n normalized = mapAST(normalized, this.#clientToServer);\n\n entry = {\n normalized,\n name,\n args,\n count: 1,\n gotCallbacks: gotCallback ? [gotCallback] : [],\n ttl,\n };\n this.#queries.set(queryId, entry);\n this.#queueQueryChange({\n op: 'put',\n hash: queryId,\n ast: name === undefined ? normalized : undefined,\n name,\n args,\n ttl,\n });\n } else {\n ++entry.count;\n this.#updateEntry(entry, queryId, ttl);\n\n if (gotCallback) {\n entry.gotCallbacks.push(gotCallback);\n }\n }\n\n if (gotCallback) {\n gotCallback(this.#gotQueries.has(queryId));\n }\n\n let removed = false;\n const cleanupCb = () => {\n if (removed) {\n return;\n }\n removed = true;\n\n // We cannot remove queries while mutations are pending\n // as that could take data out of scope that is needed in a rebase\n if (this.#mutationTracker.size > 0) {\n this.#pendingRemovals.push(() =>\n this.#remove(entry, queryId, gotCallback),\n );\n return;\n }\n\n this.#remove(entry, queryId, gotCallback);\n };\n return cleanupCb;\n }\n\n updateCustom({name, args}: CustomQueryID, ttl: TTL) {\n const queryID = hashOfNameAndArgs(name, args);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n updateLegacy(ast: AST, ttl: TTL) {\n const normalized = normalizeAST(ast);\n const queryID = hashOfAST(normalized);\n const entry = must(this.#queries.get(queryID));\n this.#updateEntry(entry, queryID, ttl);\n }\n\n #updateEntry(entry: Entry, queryID: string, ttl: TTL): void {\n // If the query already exists and the new ttl is larger than the old one\n // we send a changeDesiredQueries message to the server to update the ttl.\n ttl = clampTTL(ttl, this.#lc);\n if (compareTTL(ttl, entry.ttl) > 0) {\n entry.ttl = ttl;\n this.#queueQueryChange({\n op: 'put',\n hash: queryID,\n ast: entry.name === undefined ? entry.normalized : undefined,\n name: entry.name,\n args: entry.args,\n ttl,\n });\n }\n }\n\n #queueQueryChange(op: UpQueriesPatchOp) {\n this.#pendingQueryChanges.push(op);\n this.#scheduleBatch();\n }\n\n #scheduleBatch() {\n if (this.#batchTimer === undefined) {\n this.#batchTimer = setTimeout(\n () => this.flushBatch(),\n this.#queryChangeThrottleMs,\n );\n }\n }\n\n flushBatch() {\n if (this.#batchTimer !== undefined) {\n clearTimeout(this.#batchTimer);\n this.#batchTimer = undefined;\n }\n if (this.#pendingQueryChanges.length > 0) {\n this.#send([\n 'changeDesiredQueries',\n {\n desiredQueriesPatch: [...this.#pendingQueryChanges],\n },\n ]);\n this.#pendingQueryChanges.length = 0;\n }\n }\n\n #remove(entry: Entry, astHash: string, gotCallback: GotCallback | undefined) {\n if (gotCallback) {\n const index = entry.gotCallbacks.indexOf(gotCallback);\n entry.gotCallbacks.splice(index, 1);\n }\n --entry.count;\n if (entry.count === 0) {\n this.#recentQueries.add(astHash);\n if (this.#recentQueries.size > this.#recentQueriesMaxSize) {\n const lruQueryID = this.#recentQueries.values().next().value;\n assert(lruQueryID);\n this.#queries.delete(lruQueryID);\n this.#recentQueries.delete(lruQueryID);\n this.#queryMetrics.delete(lruQueryID);\n this.#queueQueryChange({op: 'del', hash: lruQueryID});\n }\n }\n }\n\n /**\n * Gets the aggregated metrics for all queries managed by this QueryManager.\n */\n get metrics(): ClientMetric {\n return this.#metrics;\n }\n\n addMetric<K extends keyof ClientMetricMap>(\n metric: K,\n value: number,\n ...args: ClientMetricMap[K]\n ): void {\n // Only query metrics are tracked at this point.\n // If this check fails then we need to add a runtime check.\n metric satisfies `query-${string}`;\n\n // We track all materializations of queries as well as per\n // query materializations.\n this.#metrics[metric].add(value);\n\n const queryID = args[0];\n\n // Handle slow query logging for end-to-end materialization\n if (metric === 'query-materialization-end-to-end') {\n const ast = args[1];\n\n if (\n this.#slowMaterializeThreshold !== undefined &&\n value > this.#slowMaterializeThreshold\n ) {\n this.#lc.warn?.(\n 'Slow query materialization (including server/network)',\n queryID,\n ast,\n value,\n );\n } else {\n this.#lc.debug?.(\n 'Materialized query (including server/network)',\n queryID,\n ast,\n value,\n );\n }\n }\n\n // The query manager manages metrics that are per query.\n let existing = this.#queryMetrics.get(queryID);\n if (!existing) {\n existing = newMetrics();\n this.#queryMetrics.set(queryID, existing);\n }\n existing[metric].add(value);\n }\n\n getQueryMetrics(queryID: string): ClientMetric | undefined {\n return this.#queryMetrics.get(queryID);\n }\n}\n\nfunction newMetrics(): ClientMetric {\n return {\n 'query-materialization-client': new TDigest(),\n 'query-materialization-end-to-end': new TDigest(),\n 'query-update-client': new TDigest(),\n };\n}\n", "import type {LogLevel} from '@rocicorp/logger';\nimport type {StoreProvider} from '../../../replicache/src/kv/store.ts';\nimport * as v from '../../../shared/src/valita.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport type {CustomMutatorDefs} from './custom.ts';\nimport type {OnError} from './on-error.ts';\nimport {UpdateNeededReasonType} from './update-needed-reason-type.ts';\n\n/**\n * Configuration for {@linkcode Zero}.\n */\nexport interface ZeroOptions<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n> {\n /**\n * URL to the zero-cache. This can be a simple hostname, e.g.\n * - \"https://myapp-myteam.zero.ms\"\n * or a prefix with a single path component, e.g.\n * - \"https://myapp-myteam.zero.ms/zero\"\n * - \"https://myapp-myteam.zero.ms/db\"\n *\n * The latter is useful for configuring routing rules (e.g. \"/zero/\\*\") when\n * the zero-cache is hosted on the same domain as the application. **Note that\n * only a single path segment is allowed (e.g. it cannot be \"/proxy/zero/\\*\")**.\n */\n server?: string | null | undefined;\n\n /**\n * A token to identify and authenticate the user.\n *\n * Set `auth` to `null` or `undefined` if there is no logged in user.\n *\n * When a 401 or 403 HTTP status code is received from your server, Zero will\n * transition to the `needs-auth` connection state. The app should call\n * `zero.connection.connect({auth: newToken})` with a new token to reconnect.\n *\n * The call to `connect` is handled automatically by the ZeroProvider component\n * for React and SolidJS when the `auth` prop changes.\n */\n auth?: string | null | undefined;\n\n /**\n * A unique identifier for the user. Must be non-empty.\n *\n * Each userID gets its own client-side storage so that the app can switch\n * between users without losing state.\n *\n * This must match the `sub` claim of the `auth` token if\n * `auth` is provided.\n */\n userID: string;\n\n /**\n * Distinguishes the storage used by this Zero instance from that of other\n * instances with the same userID. Useful in the case where the app wants to\n * have multiple Zero instances for the same user for different parts of the\n * app.\n */\n storageKey?: string | undefined;\n\n /**\n * Determines the level of detail at which Zero logs messages about\n * its operation. Messages are logged to the `console`.\n *\n * When this is set to `'debug'`, `'info'` and `'error'` messages are also\n * logged. When set to `'info'`, `'info'` and `'error'` but not\n * `'debug'` messages are logged. When set to `'error'` only `'error'`\n * messages are logged.\n *\n * Default is `'error'`.\n */\n logLevel?: LogLevel | undefined;\n\n /**\n * This defines the schema of the tables used in Zero and their relationships\n * to one another.\n */\n schema: S;\n\n /**\n * `mutators` is a map of custom mutator definitions. The keys are\n * namespaces or names of the mutators. The values are the mutator\n * implementations. Client side mutators must be idempotent as a\n * mutation can be rebased multiple times when folding in authoritative\n * changes from the server to the client.\n */\n mutators?: MD | undefined;\n\n /**\n * Custom URL for mutation requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n mutateURL?: string | undefined;\n\n /**\n * Custom URL for query requests sent to your API server.\n * If not provided, uses the default configured in zero-cache.\n */\n getQueriesURL?: string | undefined;\n\n /**\n * `onOnlineChange` is called when the Zero instance's online status changes.\n *\n * @deprecated Use {@linkcode Connection.state.subscribe} on the Zero instance instead. e.g.\n * ```ts\n * const zero = new Zero({...});\n * zero.connection.state.subscribe((state) => {\n * console.log('Connection state:', state.name);\n * });\n * ```\n *\n * Or use a hook like {@linkcode useZeroConnectionState} to subscribe to state changes.\n */\n onOnlineChange?: ((online: boolean) => void) | undefined;\n\n /**\n * `onUpdateNeeded` is called when a client code update is needed.\n *\n * See {@link UpdateNeededReason} for why updates can be needed.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from\n * reloading automatically. You may want to display a toast to inform the end\n * user there is a new version of your app available and prompt them to\n * refresh.\n */\n onUpdateNeeded?: ((reason: UpdateNeededReason) => void) | undefined;\n\n /**\n * `onClientStateNotFound` is called when this client is no longer able\n * to sync with the zero-cache due to missing synchronization state. This\n * can be because:\n * - the local persistent synchronization state has been garbage collected.\n * This can happen if the client has no pending mutations and has not been\n * used for a while (e.g. the client's tab has been hidden for a long time).\n * - the zero-cache fails to find the server side synchronization state for\n * this client.\n *\n * The default behavior is to reload the page (using `location.reload()`).\n * Provide your own function to prevent the page from reloading automatically.\n */\n onClientStateNotFound?: (() => void) | undefined;\n\n /**\n * The number of milliseconds to wait before disconnecting a Zero\n * instance whose tab has become hidden.\n *\n * Instances in hidden tabs are disconnected to save resources.\n *\n * Default is 5_000.\n */\n hiddenTabDisconnectDelay?: number | undefined;\n\n /**\n * This gets called when the Zero instance encounters an error. The default\n * behavior is to log the error to the console. Provide your own function to\n * prevent the default behavior.\n */\n onError?: OnError | undefined;\n\n /**\n * Determines what kind of storage implementation to use on the client.\n *\n * Defaults to `'idb'` which means that Zero uses an IndexedDB storage\n * implementation. This allows the data to be persisted on the client and\n * enables faster syncs between application restarts.\n *\n * By setting this to `'mem'`, Zero uses an in memory storage and\n * the data is not persisted on the client.\n *\n * You can also set this to a function that is used to create new KV stores,\n * allowing a custom implementation of the underlying storage layer.\n */\n kvStore?: 'mem' | 'idb' | StoreProvider | undefined;\n\n /**\n * The maximum number of bytes to allow in a single header.\n *\n * Zero adds some extra information to headers on initialization if possible.\n * This speeds up data synchronization. This number should be kept less than\n * or equal to the maximum header size allowed by the zero-cache and any load\n * balancers.\n *\n * Default value: 8kb.\n */\n maxHeaderLength?: number | undefined;\n\n /**\n * The maximum amount of milliseconds to wait for a materialization to\n * complete (including network/server time) before printing a warning to the\n * console.\n *\n * Default value: 5_000.\n */\n slowMaterializeThreshold?: number | undefined;\n\n /**\n * UI rendering libraries will often provide a utility for batching multiple\n * state updates into a single render. Some examples are React's\n * `unstable_batchedUpdates`, and solid-js's `batch`.\n *\n * This option enables integrating these batch utilities with Zero.\n *\n * When `batchViewUpdates` is provided, Zero will call it whenever\n * it updates query view state with an `applyViewUpdates` function\n * that performs the actual state updates.\n *\n * Zero updates query view state when:\n * 1. creating a new view\n * 2. updating all existing queries' views to a new consistent state\n *\n * When creating a new view, that single view's creation will be wrapped\n * in a `batchViewUpdates` call.\n *\n * When updating existing queries, all queries will be updated in a single\n * `batchViewUpdates` call, so that the transition to the new consistent\n * state can be done in a single render.\n *\n * Implementations must always call `applyViewUpdates` synchronously.\n */\n batchViewUpdates?: ((applyViewUpdates: () => void) => void) | undefined;\n\n /**\n * The maximum number of recent queries, no longer subscribed to by a preload\n * or view, to continue syncing.\n *\n * Defaults is 0.\n *\n * @deprecated Use ttl instead\n */\n maxRecentQueries?: number | undefined;\n\n /**\n * Changes to queries are sent to server in batches. This option controls\n * the number of milliseconds to wait before sending the next batch.\n *\n * Defaults is 10.\n */\n queryChangeThrottleMs?: number | undefined;\n}\n\n/**\n * @deprecated Use {@link ZeroOptions} instead.\n */\nexport interface ZeroAdvancedOptions<\n S extends Schema,\n MD extends CustomMutatorDefs | undefined = undefined,\n> extends ZeroOptions<S, MD> {}\n\ntype UpdateNeededReasonBase = {\n message?: string;\n};\n\nexport type UpdateNeededReason =\n | ({type: UpdateNeededReasonType.NewClientGroup} & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.VersionNotSupported;\n } & UpdateNeededReasonBase)\n | ({\n type: UpdateNeededReasonType.SchemaVersionNotSupported;\n } & UpdateNeededReasonBase);\n\nexport const updateNeededReasonTypeSchema: v.Type<UpdateNeededReason['type']> =\n v.literalUnion(\n UpdateNeededReasonType.NewClientGroup,\n UpdateNeededReasonType.VersionNotSupported,\n UpdateNeededReasonType.SchemaVersionNotSupported,\n );\n", "import * as v from '../../../shared/src/valita.ts';\nimport {ErrorKind} from '../../../zero-protocol/src/error-kind.ts';\nimport {errorKindSchema} from '../../../zero-protocol/src/error.ts';\nimport {updateNeededReasonTypeSchema} from './options.ts';\nimport type {UpdateNeededReasonType} from './update-needed-reason-type.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\n\nexport const RELOAD_REASON_STORAGE_KEY = '_zeroReloadReason';\nexport const RELOAD_BACKOFF_STATE_KEY = '_zeroReloadBackoffState';\n\nconst reloadReasonSchema = v.tuple([\n v.union(updateNeededReasonTypeSchema, errorKindSchema),\n v.string(),\n]);\n\nconst backoffStateSchema = v.object({\n lastReloadTime: v.number().default(0),\n nextIntervalMs: v.number().default(0),\n});\n\nexport type BackoffState = v.Infer<typeof backoffStateSchema>;\n\nexport const MIN_RELOAD_INTERVAL_MS = 500;\nexport const MAX_RELOAD_INTERVAL_MS = 60_000;\n\n// For the fraction of browsers that do not support sessionStorage.\nexport const FALLBACK_RELOAD_INTERVAL_MS = 10_000;\n\nlet reloadTimer: ReturnType<typeof setTimeout> | null = null;\n\n// TODO: This should get pushed down into Replicache and used for reloads we\n// do there.\nexport function reloadWithReason(\n lc: ZeroLogContext,\n reload: () => void,\n reason: UpdateNeededReasonType | ErrorKind,\n message: string,\n) {\n if (reloadTimer) {\n lc.info?.('reload timer already scheduled');\n return;\n }\n const now = Date.now();\n const backoff = nextBackoff(lc, now);\n\n // Record state immediately so that it persists if the user manually reloads first.\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.setItem(RELOAD_BACKOFF_STATE_KEY, JSON.stringify(backoff));\n sessionStorage.setItem(\n RELOAD_REASON_STORAGE_KEY,\n JSON.stringify([reason, message]),\n );\n }\n\n const delay = backoff.lastReloadTime - now;\n lc.error?.(\n reason,\n '\\n',\n 'reloading',\n delay > 0 ? `in ${delay / 1000} seconds` : '',\n );\n reloadTimer = setTimeout(() => {\n reloadTimer = null;\n reload();\n }, delay);\n}\n\nexport function reportReloadReason(lc: ZeroLogContext) {\n if (typeof sessionStorage !== 'undefined') {\n const value = sessionStorage.getItem(RELOAD_REASON_STORAGE_KEY);\n if (value) {\n sessionStorage.removeItem(RELOAD_REASON_STORAGE_KEY);\n try {\n const parsed = JSON.parse(value);\n const [reasonType, message] = v.parse(parsed, reloadReasonSchema);\n lc.error?.(reasonType, 'Zero reloaded the page.', message);\n } catch (e) {\n lc.error?.('Zero reloaded the page.', e);\n // ignore if not able to parse\n return;\n }\n }\n }\n}\n\n/** If a reload is scheduled, do not attempt to reconnect. */\nexport function reloadScheduled() {\n return reloadTimer !== null;\n}\n\n/** Call upon a successful connection, indicating that backoff should be reset. */\nexport function resetBackoff() {\n if (typeof sessionStorage !== 'undefined') {\n sessionStorage.removeItem(RELOAD_BACKOFF_STATE_KEY);\n }\n}\n\nfunction nextBackoff(lc: ZeroLogContext, now: number): BackoffState {\n if (typeof sessionStorage === 'undefined') {\n lc.warn?.(\n `sessionStorage not supported. backing off in ${\n FALLBACK_RELOAD_INTERVAL_MS / 1000\n } seconds`,\n );\n return {\n lastReloadTime: now + FALLBACK_RELOAD_INTERVAL_MS,\n nextIntervalMs: MIN_RELOAD_INTERVAL_MS,\n };\n }\n const val = sessionStorage.getItem(RELOAD_BACKOFF_STATE_KEY);\n if (!val) {\n return {lastReloadTime: now, nextIntervalMs: MIN_RELOAD_INTERVAL_MS};\n }\n let parsed: BackoffState;\n try {\n parsed = v.parse(JSON.parse(val), backoffStateSchema, 'passthrough');\n } catch (e) {\n lc.warn?.('ignoring unparsable backoff state', val, e);\n return {lastReloadTime: now, nextIntervalMs: MIN_RELOAD_INTERVAL_MS};\n }\n const {lastReloadTime, nextIntervalMs} = parsed;\n\n // Backoff state might not have been cleared. Reset for sufficiently old state.\n if (now - lastReloadTime > MAX_RELOAD_INTERVAL_MS * 2) {\n return {lastReloadTime: now, nextIntervalMs: MIN_RELOAD_INTERVAL_MS};\n }\n if (now < lastReloadTime) {\n // If the user manually reloaded, stick to the existing schedule.\n return parsed;\n }\n const nextReloadTime = Math.max(now, lastReloadTime + nextIntervalMs);\n return {\n lastReloadTime: nextReloadTime,\n nextIntervalMs: Math.min(nextIntervalMs * 2, MAX_RELOAD_INTERVAL_MS),\n };\n}\n", "import {getBrowserGlobal} from '../../../shared/src/browser-env.ts';\nimport type {HTTPString} from './http-string.ts';\n\nfunction validateServerParam(paramName: string, server: string): HTTPString {\n const expectedProtocol = 'http';\n const forExample = (path: string = '') =>\n ` For example: \"${expectedProtocol}s://myapp-myteam.zero.ms/${path}\".`;\n\n if (\n !server.startsWith(`${expectedProtocol}://`) &&\n !server.startsWith(`${expectedProtocol}s://`)\n ) {\n throw new Error(\n `ZeroOptions.${paramName} must use the \"${expectedProtocol}\" or \"${expectedProtocol}s\" scheme.`,\n );\n }\n let url;\n try {\n url = new URL(server);\n } catch {\n throw new Error(\n `ZeroOptions.${paramName} must be a valid URL.${forExample()}`,\n );\n }\n\n const urlString = url.toString();\n\n const pathComponents = url.pathname.split('/');\n if (pathComponents[0] === '') {\n pathComponents.shift();\n }\n if (pathComponents[pathComponents.length - 1] === '') {\n pathComponents.pop();\n }\n if (pathComponents.length > 1) {\n throw new Error(\n `ZeroOptions.${paramName} may have at most one path component.${forExample(\n 'zero',\n )}`,\n );\n }\n\n for (const [property, invalidEndsWith] of [\n ['search', '?'],\n ['hash', '#'],\n ] as const) {\n if (url[property] || urlString.endsWith(invalidEndsWith)) {\n throw new Error(\n `ZeroOptions.${paramName} must not contain a ${property} component.${forExample()}`,\n );\n }\n }\n\n return urlString as HTTPString;\n}\n\nexport function getServer(\n server: string | undefined | null,\n): HTTPString | null {\n const WS = getBrowserGlobal('WebSocket');\n if (!WS) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero started in an unsupported environment, no data will be synced.',\n );\n return null;\n }\n if (server === undefined || server === null) {\n // oxlint-disable-next-line no-console\n console.warn(\n 'Zero starting up with no server URL. No data will be synced.',\n );\n return null;\n }\n return validateServerParam('server', server);\n}\n", "import {LogContext} from '@rocicorp/logger';\nimport type {OnErrorParameters} from './on-error.ts';\n\nexport const ZeroLogContext = LogContext<OnErrorParameters>;\nexport type ZeroLogContext = LogContext<OnErrorParameters>;\n", "import {Lock} from '@rocicorp/lock';\nimport type {\n PatchOperationInternal,\n PokeInternal,\n} from '../../../replicache/src/impl.ts';\nimport type {PatchOperation} from '../../../replicache/src/patch-operation.ts';\nimport type {ClientID} from '../../../replicache/src/sync/ids.ts';\nimport {getBrowserGlobalMethod} from '../../../shared/src/browser-env.ts';\nimport type {JSONValue} from '../../../shared/src/json.ts';\nimport type {\n PokeEndBody,\n PokePartBody,\n PokeStartBody,\n} from '../../../zero-protocol/src/poke.ts';\nimport type {QueriesPatchOp} from '../../../zero-protocol/src/queries-patch.ts';\nimport type {RowPatchOp} from '../../../zero-protocol/src/row-patch.ts';\nimport type {Schema} from '../../../zero-schema/src/builder/schema-builder.ts';\nimport {\n serverToClient,\n type NameMapper,\n} from '../../../zero-schema/src/name-mapper.ts';\nimport {\n toDesiredQueriesKey,\n toGotQueriesKey,\n toMutationResponseKey,\n toPrimaryKeyString,\n} from './keys.ts';\nimport type {ZeroLogContext} from './zero-log-context.ts';\nimport {unreachable} from '../../../shared/src/asserts.ts';\nimport type {MutationPatch} from '../../../zero-protocol/src/mutations-patch.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\ntype PokeAccumulator = {\n readonly pokeStart: PokeStartBody;\n readonly parts: PokePartBody[];\n readonly pokeEnd: PokeEndBody;\n};\n\n/**\n * Handles the multi-part format of zero pokes.\n * As an optimization it also debounces pokes, only poking Replicache with a\n * merged poke at most once per frame (as determined by requestAnimationFrame).\n * The client cannot control how fast the server sends pokes, and it can only\n * update the UI once per frame. This debouncing avoids wastefully\n * computing separate diffs and IVM updates for intermediate states that will\n * never been displayed to the UI.\n */\nexport class PokeHandler {\n readonly #replicachePoke: (poke: PokeInternal) => Promise<void>;\n readonly #onPokeError: () => void;\n readonly #clientID: ClientID;\n readonly #lc: ZeroLogContext;\n #receivingPoke: Omit<PokeAccumulator, 'pokeEnd'> | undefined = undefined;\n readonly #pokeBuffer: PokeAccumulator[] = [];\n #pokePlaybackLoopRunning = false;\n #lastRafPerfTimestamp = 0;\n // Serializes calls to this.#replicachePoke otherwise we can cause out of\n // order poke errors.\n readonly #pokeLock = new Lock();\n readonly #schema: Schema;\n readonly #serverToClient: NameMapper;\n readonly #mutationTracker: MutationTracker;\n\n readonly #raf =\n getBrowserGlobalMethod('requestAnimationFrame') ?? rafFallback;\n\n constructor(\n replicachePoke: (poke: PokeInternal) => Promise<void>,\n onPokeError: () => void,\n clientID: ClientID,\n schema: Schema,\n lc: ZeroLogContext,\n mutationTracker: MutationTracker,\n ) {\n this.#replicachePoke = replicachePoke;\n this.#onPokeError = onPokeError;\n this.#clientID = clientID;\n this.#schema = schema;\n this.#serverToClient = serverToClient(schema.tables);\n this.#lc = lc.withContext('PokeHandler');\n this.#mutationTracker = mutationTracker;\n }\n\n handlePokeStart(pokeStart: PokeStartBody) {\n if (this.#receivingPoke) {\n this.#handlePokeError(\n `pokeStart ${JSON.stringify(\n pokeStart,\n )} while still receiving ${JSON.stringify(\n this.#receivingPoke.pokeStart,\n )} `,\n );\n return;\n }\n this.#receivingPoke = {\n pokeStart,\n parts: [],\n };\n }\n\n handlePokePart(pokePart: PokePartBody): number | undefined {\n if (pokePart.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokePart for ${pokePart.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n this.#receivingPoke.parts.push(pokePart);\n return pokePart.lastMutationIDChanges?.[this.#clientID];\n }\n\n handlePokeEnd(pokeEnd: PokeEndBody): void {\n if (pokeEnd.pokeID !== this.#receivingPoke?.pokeStart.pokeID) {\n this.#handlePokeError(\n `pokeEnd for ${pokeEnd.pokeID}, when receiving ${\n this.#receivingPoke?.pokeStart.pokeID\n }`,\n );\n return;\n }\n if (pokeEnd.cancel) {\n this.#receivingPoke = undefined;\n return;\n }\n this.#pokeBuffer.push({...this.#receivingPoke, pokeEnd});\n this.#receivingPoke = undefined;\n if (!this.#pokePlaybackLoopRunning) {\n this.#startPlaybackLoop();\n }\n }\n\n handleDisconnect(): void {\n this.#lc.debug?.('clearing due to disconnect');\n this.#clear();\n }\n\n #startPlaybackLoop() {\n this.#lc.debug?.('starting playback loop');\n this.#pokePlaybackLoopRunning = true;\n this.#raf(this.#rafCallback);\n }\n\n #rafCallback = async () => {\n const rafLC = this.#lc.withContext('rafAt', Math.floor(performance.now()));\n if (this.#pokeBuffer.length === 0) {\n rafLC.debug?.('stopping playback loop');\n this.#pokePlaybackLoopRunning = false;\n return;\n }\n this.#raf(this.#rafCallback);\n const start = performance.now();\n rafLC.debug?.(\n 'raf fired, processing pokes. Since last raf',\n start - this.#lastRafPerfTimestamp,\n );\n this.#lastRafPerfTimestamp = start;\n await this.#processPokesForFrame(rafLC);\n rafLC.debug?.('processing pokes took', performance.now() - start);\n };\n\n #processPokesForFrame(lc: ZeroLogContext): Promise<void> {\n return this.#pokeLock.withLock(async () => {\n const now = Date.now();\n lc.debug?.('got poke lock at', now);\n lc.debug?.('merging', this.#pokeBuffer.length);\n try {\n const merged = mergePokes(\n this.#pokeBuffer,\n this.#schema,\n this.#serverToClient,\n );\n this.#pokeBuffer.length = 0;\n if (merged === undefined) {\n lc.debug?.('frame is empty');\n return;\n }\n const start = performance.now();\n lc.debug?.('poking replicache');\n await this.#replicachePoke(merged);\n lc.debug?.('poking replicache took', performance.now() - start);\n\n if (!('error' in merged.pullResponse)) {\n const lmid =\n merged.pullResponse.lastMutationIDChanges[this.#clientID];\n if (lmid !== undefined) {\n this.#mutationTracker.lmidAdvanced(lmid);\n }\n }\n } catch (e) {\n this.#handlePokeError(e);\n }\n });\n }\n\n #handlePokeError(e: unknown) {\n if (String(e).includes('unexpected base cookie for poke')) {\n // This can happen if cookie changes due to refresh from idb due\n // to an update arriving to different tabs in the same\n // client group at very different times. Unusual but possible.\n this.#lc.debug?.('clearing due to', e);\n } else {\n this.#lc.error?.('clearing due to unexpected poke error', e);\n }\n this.#clear();\n this.#onPokeError();\n }\n\n #clear() {\n this.#receivingPoke = undefined;\n this.#pokeBuffer.length = 0;\n }\n}\n\nexport function mergePokes(\n pokeBuffer: PokeAccumulator[],\n schema: Schema,\n serverToClient: NameMapper,\n):\n | (PokeInternal & {mutationResults?: MutationPatch[] | undefined})\n | undefined {\n if (pokeBuffer.length === 0) {\n return undefined;\n }\n const {baseCookie} = pokeBuffer[0].pokeStart;\n const lastPoke = pokeBuffer[pokeBuffer.length - 1];\n const {cookie} = lastPoke.pokeEnd;\n const mergedPatch: PatchOperationInternal[] = [];\n const mergedLastMutationIDChanges: Record<string, number> = {};\n const mutationResults: MutationPatch[] = [];\n\n let prevPokeEnd = undefined;\n for (const pokeAccumulator of pokeBuffer) {\n if (\n prevPokeEnd &&\n pokeAccumulator.pokeStart.baseCookie &&\n pokeAccumulator.pokeStart.baseCookie > prevPokeEnd.cookie\n ) {\n throw Error(\n `unexpected cookie gap ${JSON.stringify(prevPokeEnd)} ${JSON.stringify(\n pokeAccumulator.pokeStart,\n )}`,\n );\n }\n prevPokeEnd = pokeAccumulator.pokeEnd;\n for (const pokePart of pokeAccumulator.parts) {\n if (pokePart.lastMutationIDChanges) {\n for (const [clientID, lastMutationID] of Object.entries(\n pokePart.lastMutationIDChanges,\n )) {\n mergedLastMutationIDChanges[clientID] = lastMutationID;\n }\n }\n if (pokePart.desiredQueriesPatches) {\n for (const [clientID, queriesPatch] of Object.entries(\n pokePart.desiredQueriesPatches,\n )) {\n for (const op of queriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, hash =>\n toDesiredQueriesKey(clientID, hash),\n ),\n );\n }\n }\n }\n if (pokePart.gotQueriesPatch) {\n for (const op of pokePart.gotQueriesPatch) {\n mergedPatch.push(\n queryPatchOpToReplicachePatchOp(op, toGotQueriesKey),\n );\n }\n }\n if (pokePart.rowsPatch) {\n for (const p of pokePart.rowsPatch) {\n mergedPatch.push(\n rowsPatchOpToReplicachePatchOp(p, schema, serverToClient),\n );\n }\n }\n if (pokePart.mutationsPatch) {\n for (const op of pokePart.mutationsPatch) {\n mergedPatch.push(mutationPatchOpToReplicachePatchOp(op));\n }\n }\n }\n }\n const ret: PokeInternal & {mutationResults?: MutationPatch[] | undefined} = {\n baseCookie,\n pullResponse: {\n lastMutationIDChanges: mergedLastMutationIDChanges,\n patch: mergedPatch,\n cookie,\n },\n };\n\n // For backwards compatibility. Because we're strict on our validation,\n // zero-client must be able to parse pokes with this field before we introduce it.\n // So users can update their clients and then start using custom mutators that write responses to the db.\n if (mutationResults.length > 0) {\n ret.mutationResults = mutationResults;\n }\n return ret;\n}\n\nfunction queryPatchOpToReplicachePatchOp(\n op: QueriesPatchOp,\n toKey: (hash: string) => string,\n): PatchOperation {\n switch (op.op) {\n case 'clear':\n return op;\n case 'del':\n return {\n op: 'del',\n key: toKey(op.hash),\n };\n case 'put':\n return {\n op: 'put',\n key: toKey(op.hash),\n value: null,\n };\n default:\n unreachable(op);\n }\n}\n\nexport function mutationPatchOpToReplicachePatchOp(\n op: MutationPatch,\n): PatchOperationInternal {\n switch (op.op) {\n case 'put':\n return {\n op: 'put',\n key: toMutationResponseKey(op.mutation.id),\n value: op.mutation.result,\n };\n case 'del':\n return {\n op: 'del',\n key: toMutationResponseKey(op.id),\n };\n }\n}\n\nfunction rowsPatchOpToReplicachePatchOp(\n op: RowPatchOp,\n schema: Schema,\n serverToClient: NameMapper,\n): PatchOperationInternal {\n if (op.op === 'clear') {\n return op;\n }\n const tableName = serverToClient.tableName(op.tableName, op as JSONValue);\n switch (op.op) {\n case 'del':\n return {\n op: 'del',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n };\n case 'put':\n return {\n op: 'put',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.value),\n ),\n value: serverToClient.row(op.tableName, op.value),\n };\n case 'update':\n return {\n op: 'update',\n key: toPrimaryKeyString(\n tableName,\n schema.tables[tableName].primaryKey,\n serverToClient.row(op.tableName, op.id),\n ),\n merge: op.merge\n ? serverToClient.row(op.tableName, op.merge)\n : undefined,\n constrain: serverToClient.columns(op.tableName, op.constrain),\n };\n default:\n unreachable(op);\n }\n}\n\n/**\n * Some environments we run in don't have `requestAnimationFrame` (such as\n * Node, Cloudflare Workers).\n */\nfunction rafFallback(callback: () => void): void {\n setTimeout(callback, 0);\n}\n", "import type {\n InternalDiff,\n InternalDiffOperation,\n} from '../../../replicache/src/btree/node.ts';\nimport {readFromHash} from '../../../replicache/src/db/read.ts';\nimport type {Hash} from '../../../replicache/src/hash.ts';\nimport {withRead} from '../../../replicache/src/with-transactions.ts';\nimport type {ZeroContext} from './context.ts';\nimport * as FormatVersion from '../../../replicache/src/format-version-enum.ts';\nimport type {IVMSourceBranch} from './ivm-branch.ts';\nimport {ENTITIES_KEY_PREFIX} from './keys.ts';\nimport {must} from '../../../shared/src/must.ts';\nimport type {LazyStore} from '../../../replicache/src/dag/lazy-store.ts';\nimport type {\n EphemeralID,\n MutationTrackingData,\n ZeroOption,\n ZeroReadOptions,\n} from '../../../replicache/src/replicache-options.ts';\nimport type {MutationTracker} from './mutation-tracker.ts';\n\n// Replicache doesn't support undefined auth tokens\nconst REPLICACHE_NO_AUTH_TOKEN = '';\n\nexport const toReplicacheAuthToken = (\n auth: string | undefined | null,\n): string => auth ?? REPLICACHE_NO_AUTH_TOKEN;\n\nexport const fromReplicacheAuthToken = (auth: string): string | undefined =>\n !auth ? undefined : auth;\n\ntype TxData = {\n ivmSources: IVMSourceBranch;\n token: string | undefined;\n};\n\nexport class ZeroRep implements ZeroOption {\n readonly #context: ZeroContext;\n readonly #ivmMain: IVMSourceBranch;\n readonly #customMutatorsEnabled: boolean;\n readonly #mutationTracker: MutationTracker;\n #store: LazyStore | undefined;\n // matches replicache's auth token type\n #auth: string = REPLICACHE_NO_AUTH_TOKEN;\n\n constructor(\n context: ZeroContext,\n ivmMain: IVMSourceBranch,\n customMutatorsEnabled: boolean,\n mutationTracker: MutationTracker,\n ) {\n this.#context = context;\n this.#ivmMain = ivmMain;\n this.#customMutatorsEnabled = customMutatorsEnabled;\n this.#mutationTracker = mutationTracker;\n }\n\n set auth(auth: string) {\n this.#auth = auth;\n }\n\n async init(hash: Hash, store: LazyStore) {\n const diffs: InternalDiffOperation[] = [];\n await withRead(store, async dagRead => {\n const read = await readFromHash(hash, dagRead, FormatVersion.Latest);\n for await (const entry of read.map.scan(ENTITIES_KEY_PREFIX)) {\n if (!entry[0].startsWith(ENTITIES_KEY_PREFIX)) {\n break;\n }\n diffs.push({\n op: 'add',\n key: entry[0],\n newValue: entry[1],\n });\n }\n });\n this.#store = store;\n\n this.#context.processChanges(undefined, hash, diffs);\n }\n\n getTxData = (\n desiredHead: Hash,\n readOptions?: ZeroReadOptions,\n ): Promise<TxData> | undefined => {\n // getTxData requires some extensive testing for complete confidence\n // that it will not break. Do not enable `getTxData` unless the user\n // has opted into custom mutators.\n if (!this.#customMutatorsEnabled) {\n return;\n }\n\n return this.#ivmMain\n .forkToHead(must(this.#store), desiredHead, readOptions)\n .then(branch => ({\n ivmSources: branch,\n token: fromReplicacheAuthToken(this.#auth),\n }));\n };\n\n advance = (expectedHash: Hash, newHash: Hash, diffs: InternalDiff): void => {\n this.#context.processChanges(expectedHash, newHash, diffs);\n };\n\n trackMutation(): MutationTrackingData {\n return this.#mutationTracker.trackMutation();\n }\n mutationIDAssigned(ephemeralID: EphemeralID, mutationID: number): void {\n this.#mutationTracker.mutationIDAssigned(ephemeralID, mutationID);\n }\n rejectMutation(ephemeralID: EphemeralID, ex: unknown): void {\n this.#mutationTracker.rejectMutation(ephemeralID, ex);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,eAAsB,iBACpB,KACA,MACA,WACA,aAC2D;AAC3D,QAAM,OAAO;AAAA,IACX,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,MACjB,0BAA0B;AAAA,IAC5B;AAAA,IACA,MAAM,KAAK,UAAU,WAAW;AAAA,IAChC,QAAQ;AAAA,EACV;AACA,QAAM,UAAU,IAAI,QAAQ,KAAK,IAAI;AACrC,QAAM,WAAW,MAAM,MAAM,OAAO;AACpC,QAAM,iBAAiB,SAAS;AAChC,MAAI,mBAAmB,KAAK;AAC1B,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE;AAAA,QACA,cAAc,MAAM,SAAS,KAAK;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE;AAAA,MACA,cAAc;AAAA,IAChB;AAAA,EACF;AACF;;;ACrCA,SAAS,QAAQ,KAAc,MAAuB;AACpD,SACE,OAAO,QAAQ,YACf,QAAQ,QACP,IAAyB,UAAU;AAExC;AAIO,SAAS,gBAAgB,KAAmC;AACjE,SAAO,OAAQ,IAAyB,UAAU;AACpD;AAWO,SAAS,8BACd,GACkC;AAClC,SAAO,QAAQ,GAAG,qBAAqB;AACzC;AAWO,SAAS,8BACd,GACkC;AAClC,MAAI,CAAC,QAAQ,GAAG,qBAAqB,GAAG;AACtC,WAAO;AAAA,EACT;AAEA,QAAM,EAAC,YAAW,IAAI;AACtB,UAAQ,aAAa;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,EACX;AAEA,SAAO;AACT;AAEO,SAAS,kCACd,GAC0C;AAC1C,SAAO,8BAA8B,CAAC,CAAC;AACzC;;;ACzDO,SAAS,sBACd,GAC8B;AAC9B,eAAa,CAAC;AACd,eAAa,EAAE,cAAc;AAC7B,eAAa,EAAE,YAAY;AAC7B;;;ACsCO,SAAS,sBACd,GACuC;AACvC,cAAY,CAAC;AACb,aAAW,QAAQ,GAAG;AACpB,yBAAqB,IAAI;AAAA,EAC3B;AACF;AAEA,SAAS,qBAAqB,GAAiD;AAC7E,eAAa,CAAC;AACd,UAAQ,EAAE,IAAI;AAAA,IACZ,KAAK;AACH,mBAAa,EAAE,GAAG;AAClB,sBAAgB,EAAE,KAAK;AACvB;AAAA,IACF,KAAK;AACH,mBAAa,EAAE,GAAG;AAClB,UAAI,EAAE,UAAU,QAAW;AACzB,yBAAiB,EAAE,KAAK;AAAA,MAC1B;AACA,UAAI,EAAE,cAAc,QAAW;AAC7B,oBAAY,EAAE,SAAS;AACvB,mBAAW,OAAO,EAAE,WAAW;AAC7B,uBAAa,GAAG;AAAA,QAClB;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH,mBAAa,EAAE,GAAG;AAClB;AAAA,IACF,KAAK;AACH;AAAA,IACF;AACE,YAAM,IAAI;AAAA,QACR,sBAAsB,EAAE,EAAE;AAAA,MAC5B;AAAA,EACJ;AACF;;;AChEO,SAAS,iBAAiB,KAA8C;AAC7E,iBAAe,OACb,aACA,WACuB;AACvB,UAAM,CAAC,UAAU,eAAe,IAAI,MAAM;AAAA,MACxC,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,UAAU;AACb,aAAO,EAAC,gBAAe;AAAA,IACzB;AAEA,WAAO;AAAA,MACL,UAAU,MAAM,SAAS,KAAK;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,IAAI,MAAM;AACzB,SAAO;AACT;AAEA,IAAM,iBAAiB,oBAAI,QAAQ;AAE5B,SAAS,gBAAgB,QAAyB;AACvD,SAAO,eAAe,IAAI,MAAM;AAClC;AAEO,SAAS,qBAAqB,GAAyC;AAC5E,eAAa,CAAC;AACd,MAAI,8BAA8B,CAAC,KAAK,8BAA8B,CAAC,GAAG;AACxE;AAAA,EACF;AACA,MAAI,EAAE,WAAW,QAAW;AAC1B,iBAAa,EAAE,MAAM;AAAA,EACvB;AACA,8BAA4B,EAAE,qBAAqB;AACnD,wBAAsB,EAAE,KAAK;AAC/B;AAEA,SAAS,4BACP,uBACyD;AACzD,eAAa,qBAAqB;AAClC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,qBAAqB,GAAG;AAChE,iBAAa,GAAG;AAChB,iBAAa,KAAK;AAAA,EACpB;AACF;AAEO,SAAS,qBAAqB,GAAyC;AAC5E,eAAa,CAAC;AACd,wBAAsB,EAAE,eAAe;AACvC,MAAI,EAAE,aAAa,QAAW;AAC5B,yBAAqB,EAAE,QAAQ;AAAA,EACjC;AACF;;;ACnFA,SAAQ,gBAAe;;;ACMvB,IAAM,YAAY,oBAAI,IAAoD;AAanE,SAAS,iBACd,MAC2B;AAC3B,MAAI,UAAU,IAAI,IAAI,GAAG;AACvB,WAAO,UAAU,IAAI,IAAI;AAAA,EAC3B;AACA,SAAO,WAAW,IAAI;AACxB;AAkBO,SAAS,uBACd,MAC2B;AAC3B,SAAO,iBAAiB,IAAI,GAAG,KAAK,UAAU;AAChD;AAEO,SAAS,qBACd,MACe;AACf,QAAM,IAAI,iBAAiB,IAAI;AAC/B,MAAI,MAAM,QAAW;AACnB,UAAM,IAAI;AAAA,MACR,sDAAsD,IAAI;AAAA,IAC5D;AAAA,EACF;AACA,SAAO;AACT;;;AC5DO,IAAM,cAAc,QAAQ,QAAQ,IAAa;AACjD,IAAM,eAAe,QAAQ,QAAQ,KAAc;AACnD,IAAM,mBAAmB,QAAQ,QAAQ,MAAS;AAClD,IAAM,cAAc,QAAQ,QAAQ;AAKpC,IAAM,eAAe,IAAI,QAAe,MAAM;AAAC,CAAC;;;ACShD,IAAM,iBAAiB,OAAO;AAG9B,IAAM,gBAAN,MAAoB;AAAA,EACN,WACjB,oBAAI,IAAI;AAAA,EACD;AAAA,EAET,YAAY,MAAY;AACtB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,KAA+B;AACjC,QAAI,KAAK,MAAM,QAAQ;AACrB,aAAO,6BAA6B;AAAA,IACtC;AACA,YAAQ,KAAK,SAAS,IAAI,GAAG,GAAG;AAAA,MAC9B,KAAK;AACH,eAAO,KAAK,MAAM,IAAI,GAAG;AAAA,MAC3B,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,KAAmD;AAC3D,QAAI,KAAK,MAAM,QAAQ;AACrB,aAAO,6BAA6B;AAAA,IACtC;AACA,UAAM,IAAI,KAAK,SAAS,IAAI,GAAG;AAC/B,YAAQ,GAAG;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK,QAAW;AACd,cAAMA,KAAI,MAAM,KAAK,MAAM,IAAI,GAAG;AAClC,eAAO,yBAAyBA,EAAC;AAAA,MACnC;AAAA,MACA;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,IAAI,KAAa,OAA0B;AACzC,WACE,kCAAkC,KAAK,KAAK,MAC3C,KAAK,SAAS,IAAI,KAAK,WAAW,KAAK,CAAC,GAAG;AAAA,EAEhD;AAAA,EAEA,IAAI,KAA4B;AAC9B,WACE,kCAAkC,KAAK,KAAK,MAC3C,KAAK,SAAS,IAAI,KAAK,cAAc,GAAG;AAAA,EAE7C;AAAA,EAEA,UAAgB;AACd,SAAK,MAAM,QAAQ;AAAA,EACrB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;;;AHlEA,IAAM,UAAU,EAAC,YAAY,UAAS;AACtC,IAAM,eAAe;AAEd,IAAM,WAAN,MAAgC;AAAA,EACrC;AAAA,EACA,UAAU;AAAA,EACV,cAAc;AAAA,EAEd,YAAY,MAAc;AACxB,SAAK,MAAM,aAAa,IAAI;AAAA,EAC9B;AAAA,EAEA,OAAsB;AACpB,QAAI,KAAK,SAAS;AAChB,aAAO,uBAAuB;AAAA,IAChC;AACA,WAAO,KAAK,YAAY,QAAQ;AAAA,EAClC;AAAA,EAEA,QAAwB;AACtB,QAAI,KAAK,SAAS;AAChB,aAAO,uBAAuB;AAAA,IAChC;AACA,WAAO,KAAK,YAAY,SAAS;AAAA,EACnC;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,KAAK,MAAM,KAAK;AACtB,SAAG,MAAM;AAAA,IACX;AACA,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,YAAe,IAAwC;AAG3D,UAAM,mBAAmB,OAAO,SAAuC;AACrE,YAAM,EAAC,SAAS,SAAS,OAAM,IAAI,SAAsB;AACzD,YAAM,MAAM,UAAU,KAAK,IAAI;AAE/B,UAAI,kBAAkB,MAAM;AAC1B,cAAM,KAAK,IAAI;AACf,sBAAc,EAAE;AAChB,WAAG,MAAM;AACT,aAAK,cAAc;AACnB;AAAA,UACE,IAAI;AAAA,YACF,iCAAiC,IAAI;AAAA,UACvC;AAAA,QACF;AAAA,MACF;AAEA,UAAI,YAAY,MAAM,QAAQ,IAAI,MAAM;AACxC,UAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAEpC,YAAMC,MAAK,MAAM;AACjB,MAAAA,IAAG,kBAAkB,MAAMA,IAAG,MAAM;AACpC,aAAOA;AAAA,IACT;AASA,UAAM,KAAK,MAAM,KAAK;AAEtB,QAAI;AACF,aAAO,GAAG,EAAE;AAAA,IACd,SAAS,GAAY;AACnB,UAAI,CAAC,KAAK,WAAW,aAAa,cAAc;AAC9C,YAAI,EAAE,SAAS,qBAAqB;AAClC,eAAK,MAAM,iBAAiB,GAAG,IAAI;AACnC,gBAAM,WAAW,MAAM,KAAK;AAC5B,iBAAO,GAAG,QAAQ;AAAA,QACpB,WAAW,EAAE,SAAS,iBAAiB;AAIrC,eAAK,cAAc;AACnB,+BAAqB,WAAW,EAAE,eAAe,GAAG,IAAI;AACxD,gBAAM,IAAI;AAAA,YACR,sBAAsB,GAAG,IAAI;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,IAAM,WAAN,MAA+B;AAAA,EACpB;AAAA,EACT,UAAU;AAAA,EAEV,YAAY,IAAoB;AAC9B,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,KAA+B;AACjC,QAAI,KAAK,SAAS;AAChB,aAAO,6BAA6B;AAAA,IACtC;AACA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,MAAM,YAAY,KAAK,GAAG,EAAE,MAAM,GAAG;AAC3C,UAAI,YAAY,MAAM,QAAQ,IAAI,SAAS,CAAC;AAC5C,UAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,IACtC,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,KAAmD;AACrD,QAAI,KAAK,SAAS;AAChB,aAAO,6BAA6B;AAAA,IACtC;AACA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,MAAM,YAAY,KAAK,GAAG,EAAE,IAAI,GAAG;AACzC,UAAI,YAAY,MAAM,QAAQ,yBAAyB,IAAI,MAAM,CAAC;AAClE,UAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,IACtC,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB;AACd,SAAK,UAAU;AAAA,EAEjB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAM,YAAN,cAAwB,cAAc;AAAA,EAC3B;AAAA,EACT,UAAU;AAAA,EAEV,YAAY,IAAoB;AAC9B,UAAM,IAAI,SAAS,EAAE,CAAC;AACtB,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,SAAwB;AACtB,QAAI,KAAK,SAAS;AAChB,aAAO,6BAA6B;AAAA,IACtC;AACA,QAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,aAAO;AAAA,IACT;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,KAAK,KAAK;AAChB,YAAM,QAAQ,YAAY,EAAE;AAC5B,iBAAW,CAAC,KAAK,GAAG,KAAK,KAAK,UAAU;AACtC,YAAI,QAAQ,gBAAgB;AAC1B,gBAAM,OAAO,GAAG;AAAA,QAClB,OAAO;AACL,gBAAM,IAAI,KAAK,GAAG;AAAA,QACpB;AAAA,MACF;AACA,SAAG,aAAa,MAAM,QAAQ;AAC9B,SAAG,UAAU,MAAM,OAAO,GAAG,KAAK;AAAA,IACpC,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB;AAEd,SAAK,UAAU;AACf,UAAM,QAAQ;AAAA,EAChB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;AAEA,SAAS,UAAU,IAAwB;AACzC,QAAM,KAAK,GAAG,YAAY,cAAc,aAAa,OAAO;AAC5D,SAAO,IAAI,UAAU,EAAE;AACzB;AAEA,SAAS,SAAS,IAAuB;AACvC,QAAM,KAAK,GAAG,YAAY,cAAc,UAAU;AAClD,SAAO,IAAI,SAAS,EAAE;AACxB;AAEA,SAAS,YAAY,IAAoC;AACvD,SAAO,GAAG,YAAY,YAAY;AACpC;AAEA,SAAS,aAAa,MAAoC;AACxD,QAAM,MAAM,qBAAqB,WAAW;AAC5C,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,MAAM,IAAI,KAAK,IAAI;AACzB,QAAI,kBAAkB,MAAM;AAC1B,UAAI,OAAO,kBAAkB,YAAY;AAAA,IAC3C;AACA,QAAI,YAAY,MAAM;AACpB,YAAM,KAAK,IAAI;AAEf,SAAG,kBAAkB,MAAM,GAAG,MAAM;AACpC,cAAQ,EAAE;AAAA,IACZ;AACA,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;AAOO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,OAAO;AACT;;;AIjOO,SAAS,YAAY,MAAc,eAAgC;AACxE,SAAO,oBAAoB,MAAM,eAA6B,MAAM;AACtE;AAEA,SAAS,oBACP,MACA,eACA,eACQ;AACR,QAAM,IAAI,OAAO,IAAI,IAAI,aAAa;AACtC,SAAO,gBAAgB,GAAG,CAAC,IAAI,aAAa,KAAK;AACnD;;;ACpBO,IAAM,aAAN,cAAyB,MAAM;AAAA,EACpC,OAAO;AACT;;;ACFA,SAAQ,YAAAC,iBAAe;AAGvB,IAAMC,eAAc,QAAQ,QAAQ;AACpC,IAAMC,gBAAe,IAAI,QAAc,MAAM,MAAS;AAS/C,SAAS,MAAM,IAAY,QAAqC;AACrE,QAAM,gBAAgB,MAAM,IAAI,WAAW,SAAS;AAEpD,MAAI,QAAQ,SAAS;AACnB,WAAO,QAAQ,OAAO,cAAc,CAAC;AAAA,EACvC;AAEA,MAAI,OAAO,GAAG;AACZ,WAAOD;AAAA,EACT;AAEA,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI;AACJ,QAAI,QAAQ;AACV,oBAAc,MAAM;AAClB,qBAAa,EAAE;AACf,eAAO,cAAc,CAAC;AAAA,MACxB;AACA,aAAO,iBAAiB,SAAS,aAAa,EAAC,MAAM,KAAI,CAAC;AAAA,IAC5D;AAEA,UAAM,KAAK,WAAW,MAAM;AAC1B,cAAQ;AACR,cAAQ,oBAAoB,SAAS,WAAW;AAAA,IAClD,GAAG,EAAE;AAAA,EACP,CAAC;AACH;AAOO,SAAS,eACd,IACA,QAC6C;AAC7C,MAAI,OAAO,GAAG;AACZ,WAAO,CAACA,cAAaC,aAAY;AAAA,EACnC;AAEA,QAAM,EAAC,SAAS,gBAAgB,SAAS,eAAc,IAAIC,UAAe;AAE1E,QAAM,eAAe,IAAI,QAAc,aAAW;AAChD,UAAM,cAAc,MAAM;AACxB,mBAAa,EAAE;AACf,qBAAe;AAAA,IACjB;AAEA,UAAM,KAAK,WAAW,MAAM;AAC1B,cAAQ;AACR,aAAO,oBAAoB,SAAS,WAAW;AAAA,IACjD,GAAG,EAAE;AAEL,WAAO,iBAAiB,SAAS,aAAa,EAAC,MAAM,KAAI,CAAC;AAAA,EAC5D,CAAC;AAED,SAAO,CAAC,cAAc,cAAc;AACtC;;;ACnEO,SAAS,sBACd,aACAC,UACA,SACA,IACA,QACM;AACN,OAAK,qBAAqB,aAAaA,UAAS,SAAS,IAAI,MAAM;AACrE;AAEA,eAAe,qBACb,aACAA,UACA,SACA,IACA,QACe;AACf,MAAI,OAAO,SAAS;AAClB;AAAA,EACF;AACA,OAAK,GAAG,YAAY,qBAAqB,WAAW;AACpD,KAAG,QAAQ,UAAU;AACrB,SAAO,CAAC,OAAO,SAAS;AACtB,QAAI;AACF,YAAM,MAAM,QAAQ,GAAG,MAAM;AAAA,IAC/B,SAAS,GAAG;AACV,UAAI,EAAE,aAAa,aAAa;AAC9B,cAAM;AAAA,MACR;AAAA,IACF;AACA,QAAI,CAAC,OAAO,SAAS;AACnB,SAAG,QAAQ,SAAS;AACpB,UAAI;AACF,cAAMA,SAAQ;AAAA,MAChB,SAAS,GAAG;AACV,YAAI,OAAO,SAAS;AAClB,aAAG,QAAQ,2CAA2C,CAAC;AAAA,QACzD,OAAO;AACL,aAAG,QAAQ,kBAAkB,CAAC;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,KAAG,QAAQ,UAAU;AACvB;;;ACDO,SAAS,uBACd,aACA,WACA,UAC4B;AAC5B,SAAO,IAAI,gBAAgB,aAAa,WAAW,QAAQ,EAAE,QAAQ;AACvE;AAEA,IAAM,kBAAN,MAAsB;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,aACA,WACA,UACA;AACA,UAAM,WAAmB,CAAC;AAC1B,UAAM,WAAmB,CAAC;AAC1B,eAAW,eAAe,aAAa;AACrC,UAAI,YAAY,QAAQ,YAAY,KAAK;AACvC,oBAAY,OAAO,SAAS,KAAK,YAAY,GAAG;AAChD,oBAAY,OAAO,SAAS,KAAK,YAAY,GAAG;AAAA,MAClD;AAAA,IACF;AACA,SAAK,YAAY;AACjB,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,mBAAmB,oBAAI,IAAI;AAGhC,SAAK,0BAA0B,oBAAI,IAAI;AACvC,SAAK,kBAAkB,SAAS,mBAAmB;AACnD,SAAK,eAAe,KAAK,kBAAkB,oBAAI,IAAI,IAAI;AAAA,EACzD;AAAA,EAEA,MAAM,UAAsC;AAC1C,eAAW,KAAK,KAAK,WAAW;AAC9B,YAAM,KAAK,gBAAgB,GAAG,CAAC;AAAA,IACjC;AAKA,UAAM,QAAQ;AAAA,MACZ,MAAM;AAAA,QAAK,KAAK,WAAW,OAAO;AAAA,QAAG,UACnC,KAAK,sBAAsB,IAAI;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,KAAK,iBAAiB;AACxB,aAAO,KAAK,UAAU,cAAc;AACpC,aAAO,KAAK,YAAY;AACxB,UAAI;AACJ,SAAG;AACD,2BAAmB;AACnB,mBAAW,QAAQ,KAAK,WAAW,OAAO,GAAG;AAC3C,cACE,CAAC,KAAK,UAAU,eAAe,IAAI,KACnC,CAAC,KAAK,aAAa,IAAI,IAAI,KAC3B,KAAK,iBAAiB,IAAI,IAAI,MAAM,GACpC;AACA,kBAAM,KAAK,kBAAkB,MAAM,CAAC;AACpC,+BAAmB;AACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF,SAAS;AAAA,IACX;AAEA,eAAW,KAAK,KAAK,WAAW;AAC9B,YAAM,KAAK,gBAAgB,GAAG,EAAE;AAAA,IAClC;AAEA,QAAI,CAAC,QAAe;AAClB,iBAAW,CAAC,MAAM,MAAM,KAAK,KAAK,kBAAkB;AAClD;AAAA,UACE,UAAU;AAAA,UACV,0CAA0C,IAAI,IAAI,MAAM;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,gBAAgB,MAAY,OAA8B;AAM9D,UAAM,KAAK,sBAAsB,IAAI;AACrC,QAAI,KAAK,gBAAgB,MAAM,KAAK,GAAG;AACrC,YAAM,KAAK,kBAAkB,MAAM,KAAK;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAM,kBAAkB,MAAY,OAAe;AACjD,QAAI,SAAS,WAAW;AACtB;AAAA,IACF;AACA,UAAM,OAAO,MAAM,KAAK,UAAU,QAAQ,IAAI;AAC9C,QAAI,CAAC,QAAe;AAClB;AAAA,QACE,QAAS,KAAK,mBAAmB,CAAC,KAAK,WAAW,IAAI,IAAI;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,QAAW;AACtB,WAAK,cAAc,IAAI,IAAI;AAC3B,YAAM,KAAK,KAAK,IAAI,SAAO,KAAK,gBAAgB,KAAK,KAAK,CAAC;AAC3D,YAAM,QAAQ,IAAI,EAAE;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,sBAAsB,MAA6B;AAEjD,QAAI,IAAI,KAAK,wBAAwB,IAAI,IAAI;AAC7C,QAAI,MAAM,QAAW;AACnB,WAAK,YAAY;AACf,cAAM,QAAS,MAAM,KAAK,UAAU,YAAY,IAAI,KAAM;AAC1D,aAAK,iBAAiB,IAAI,MAAM,KAAK;AACrC,eAAO;AAAA,MACT,GAAG;AACH,WAAK,wBAAwB,IAAI,MAAM,CAAC;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,gBAAgB,MAAY,OAAwB;AAClD,UAAM,WAAW,KAAK,iBAAiB,IAAI,IAAI;AAC/C,iBAAa,QAAQ;AACrB,SAAK,iBAAiB,IAAI,MAAM,WAAW,KAAK;AAChD,WAAQ,aAAa,KAAK,UAAU,KAAO,aAAa,KAAK,UAAU;AAAA,EACzE;AACF;;;AC5LO,SAAS,aAAa,MAAoB;AAC/C,SAAO,KAAK,IAAI;AAClB;AAEO,SAAS,aAAa,MAAoB;AAC/C,SAAO,KAAK,IAAI;AAClB;AAEO,SAAS,iBAAiB,MAAoB;AACnD,SAAO,KAAK,IAAI;AAClB;AAEO,SAAS,QAAQ,MAAsB;AAC5C,SAAO,KAAK,IAAI;AAClB;;;ACEO,IAAM,YAAN,MAAiC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,IACA,aACA,iBACA;AACA,SAAK,MAAM;AACX,SAAK,eAAe;AACpB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAM,OAAsB;AAC1B,WAAO,IAAIC,UAAS,MAAM,KAAK,IAAI,KAAK,GAAG,KAAK,gBAAgB;AAAA,EAClE;AAAA,EAEA,MAAM,QAAwB;AAC5B,WAAO,IAAIC;AAAA,MACT,MAAM,KAAK,IAAI,MAAM;AAAA,MACrB,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,QAAuB;AACrB,WAAO,KAAK,IAAI,MAAM;AAAA,EACxB;AACF;AAEO,IAAMD,YAAN,MAA+B;AAAA,EACjB;AAAA,EACV;AAAA,EAET,YAAY,IAAY,iBAAuC;AAC7D,SAAK,MAAM;AACX,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,SAAS,MAA8B;AACrC,WAAO,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AAAA,EACxC;AAAA,EAEA,MAAM,SAAS,MAAwC;AACrD,UAAM,OAAO,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AAClD,QAAI,SAAS,QAAW;AACtB,aAAO;AAAA,IACT;AAEA,UAAM,UAAU,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AACrD,QAAI;AACJ,QAAI,YAAY,QAAW;AACzB,iBAAW,OAAO;AAClB,aAAO;AAAA,IACT,OAAO;AACL,aAAO,CAAC;AAAA,IACV;AACA,WAAO,IAAI,MAAM,MAAM,MAAM,IAAI;AAAA,EACnC;AAAA,EAEA,aAAa,MAA4B;AACvC,WAAO,aAAa,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,MAAM,QAAQ,MAAyC;AACrD,UAAM,OAAO,MAAM,KAAK,IAAI,IAAI,QAAQ,IAAI,CAAC;AAC7C,QAAI,SAAS,QAAW;AACtB,aAAO;AAAA,IACT;AACA,eAAW,IAAI;AACf,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,SAAK,IAAI,QAAQ;AAAA,EACnB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK,IAAI;AAAA,EAClB;AACF;AAOO,IAAMC,aAAN,cACGD,UAEV;AAAA,EAEW;AAAA,EAEA,aAAa,oBAAI,IAAU;AAAA,EAC3B,gBAAgB,oBAAI,IAAwB;AAAA,EAErD,YACE,KACA,aACA,iBACA;AACA,UAAM,KAAK,eAAe;AAC1B,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,cAAc,CAAI,MAAS,SACzB,YAAY,MAAM,MAAM,KAAK,YAAY;AAAA,EAE3C,IAAI,UAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,SAAS,GAAyB;AACtC,UAAM,EAAC,MAAM,MAAM,KAAI,IAAI;AAE3B,SAAK,gBAAgB,IAAI;AACzB,UAAM,MAAM,aAAa,IAAI;AAE7B,UAAM,KAAK,KAAK,IAAI,IAAI,KAAK,IAAyB;AACtD,QAAI;AACJ,QAAI,KAAK,SAAS,GAAG;AACnB,iBAAW,KAAK,MAAM;AACpB,aAAK,gBAAgB,CAAC;AAAA,MACxB;AACA,WAAK,KAAK,IAAI,IAAI,aAAa,IAAI,GAAG,IAAI;AAAA,IAC5C;AACA,SAAK,WAAW,IAAI,IAAI;AACxB,UAAM;AACN,UAAM;AAAA,EACR;AAAA,EAEA,QAAQ,MAAc,MAA2B;AAC/C,WAAO,KAAK,SAAS,MAAM,IAAI;AAAA,EACjC;AAAA,EAEA,WAAW,MAA6B;AACtC,WAAO,KAAK,SAAS,MAAM,MAAS;AAAA,EACtC;AAAA,EAEA,MAAM,SAAS,MAAc,MAAuC;AAClE,UAAM,UAAU,MAAM,KAAK,QAAQ,IAAI;AACvC,UAAM,KAAK,QAAQ,IAAI;AAEvB,QAAI;AACJ,QAAI,SAAS,QAAW;AACtB,WAAK,KAAK,IAAI,IAAI,EAAE;AAAA,IACtB,OAAO;AACL,WAAK,KAAK,IAAI,IAAI,IAAI,IAAI;AAAA,IAC5B;AAEA,UAAM,IAAI,KAAK,cAAc,IAAI,IAAI;AACrC,QAAI,MAAM,QAAW;AACnB,WAAK,cAAc,IAAI,MAAM,EAAC,KAAK,MAAM,KAAK,QAAO,CAAC;AAAA,IACxD,OAAO;AAEL,QAAE,MAAM;AAAA,IACV;AAEA,UAAM;AAAA,EACR;AAAA,EAEA,MAAM,SAAwB;AAC5B,UAAM,kBAAkB,MAAM;AAAA,MAC5B,KAAK,cAAc,OAAO;AAAA,MAC1B,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,KAAK,sBAAsB,eAAe;AAChD,UAAM,KAAK,IAAI,OAAO;AAAA,EACxB;AAAA,EAEA,MAAM,YAAY,MAAyC;AACzD,UAAM,QAAQ,MAAM,KAAK,IAAI,IAAI,iBAAiB,IAAI,CAAC;AACvD,QAAI,UAAU,QAAW;AACvB,aAAO;AAAA,IACT;AACA,iBAAa,KAAK;AAClB,QAAI,QAAQ,KAAK,QAAQ,SAAU,WAAW,QAAQ,IAAI;AACxD,YAAM,IAAI;AAAA,QACR,qBAAqB,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,MAAsC;AAClD,UAAM,OAAO,MAAM,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AAClD,QAAI,SAAS,QAAW;AACtB,aAAO,CAAC;AAAA,IACV;AACA,eAAW,IAAI;AACf,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,sBAAsB,eAAiD;AAC3E,UAAM,KAAsB,CAAC;AAC7B,eAAW,CAAC,MAAM,KAAK,KAAK,eAAe;AACzC,UAAI,UAAU,GAAG;AACf,WAAG,KAAK,KAAK,sBAAsB,IAAI,CAAC;AAAA,MAC1C,OAAO;AACL,cAAM,cAAc,iBAAiB,IAAI;AACzC,WAAG,KAAK,KAAK,IAAI,IAAI,aAAa,KAAK,CAAC;AAAA,MAC1C;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,EAAE;AAAA,EACtB;AAAA,EAEA,MAAM,sBAAsB,MAA2B;AACrD,UAAM,QAAQ,IAAI;AAAA,MAChB,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AAAA,MAC/B,KAAK,IAAI,IAAI,aAAa,IAAI,CAAC;AAAA,MAC/B,KAAK,IAAI,IAAI,iBAAiB,IAAI,CAAC;AAAA,IACrC,CAAC;AAED,SAAK,WAAW,OAAO,IAAI;AAAA,EAC7B;AAAA,EAEA,UAAgB;AACd,SAAK,IAAI,QAAQ;AAAA,EACnB;AACF;;;AClOO,IAAM,4BAA4B;AAWlC,IAAM,uBAAiD;AAAA,EAC1D,eAAe;AAAA,IACf,eAAe;AAAA,IACf,UAAU;AAAA,EACZ,CAAC;AACH;AAEA,SAAS,QAAQ,GAAiB,GAAyB;AACzD,QAAM,KAAK,cAAc,EAAE,eAAe,EAAE,aAAa;AACzD,MAAI,OAAO,GAAG;AACZ,WAAO;AAAA,EACT;AACA,SAAO,cAAc,EAAE,UAAU,EAAE,QAAQ;AAC7C;AAEO,SAAS,wBACd,gBACgB;AAEhB,SAAO,CAAC,GAAG,cAAc,EACtB,KAAK,OAAO,EACZ;AAAA,IACC,CAAC,MAAM,UACL,UAAU,KACV,QAAQ,MAAM,CAAC,GAAG,cAAc,EAAE,KAAK,OAAO,EAAE,QAAQ,CAAC,CAAC,MAAM;AAAA,EACpE;AACJ;AAEO,SAAS,oBACd,GACA,GACgB;AAChB,QAAM,SAAiC,CAAC;AACxC,MAAI,wBAAwB,CAAC;AAC7B,MAAI,wBAAwB,CAAC;AAC7B,WAAS,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,UAAU;AACrD,QAAI,IAAI,EAAE,WAAW,KAAK,EAAE,UAAU,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,IAAI;AAC9D,aAAO,KAAK,EAAE,CAAC,CAAC;AAChB;AAAA,IACF,WAAW,IAAI,EAAE,WAAW,KAAK,EAAE,UAAU,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,IAAI;AACrE,aAAO,KAAK,EAAE,CAAC,CAAC;AAChB;AAAA,IACF,OAAO;AAEL,aAAO,KAAK,EAAE,CAAC,CAAC;AAChB;AACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAyBA,eAAsB,kBACpB,UACA,gBACyB;AAGzB,QAAM,OAAO,wBAAwB,cAAc;AAEnD,QAAM,YAAY,WAAW,IAAI;AACjC,QAAM,QAAQ,SAAS,YAAY,WAAW,CAAC,CAAC;AAChD,QAAM,SAAS,SAAS,KAAK;AAC7B,QAAM,SAAS,QAAQ,2BAA2B,MAAM,IAAI;AAC5D,SAAO;AACT;AAEA,eAAsB,kBACpB,SACyB;AACzB,QAAM,OAAO,MAAM,QAAQ,QAAQ,yBAAyB;AAC5D,MAAI,SAAS,QAAW;AACtB,WAAO,CAAC;AAAA,EACV;AACA,QAAM,QAAQ,MAAM,QAAQ,aAAa,IAAI;AAE7C,QAAM,MAAQ,KAAK,MAAM,MAAM,oBAAoB;AACnD,MAAI,CAAC,IAAI,IAAI;AAGX,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,IAAI;AACb;AAMA,eAAsB,kBACpB,UACA,qBACyB;AACzB,QAAM,oBAAoB,MAAM,kBAAkB,QAAQ;AAE1D,SAAO;AAAA,IACL;AAAA,IACA,oBAAoB,mBAAmB,mBAAmB;AAAA,EAC5D;AACF;AAaA,eAAsB,sBACpB,UACA,kBACA,uBACyB;AACzB,QAAM,qBAAqB,IAAI,IAAI,gBAAgB;AACnD,QAAM,0BAA0B,IAAI,IAAI,qBAAqB;AAC7D,QAAM,oBAAoB,MAAM,kBAAkB,QAAQ;AAC1D,QAAM,UAAU,IAAI,IAAI,MAAM,WAAW,QAAQ,CAAC;AAClD,aAAW,YAAY,kBAAkB;AACvC,YAAQ,OAAO,QAAQ;AAAA,EACzB;AACA,aAAW,iBAAiB,uBAAuB;AACjD,eAAW,CAAC,UAAU,MAAM,KAAK,SAAS;AACxC,UAAI,OAAO,kBAAkB,eAAe;AAC1C,gBAAQ,OAAO,QAAQ;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,QAAQ;AAElC,SAAO;AAAA,IACL;AAAA,IACA,kBAAkB;AAAA,MAChB,CAAC,EAAC,eAAe,SAAQ,MACvB,CAAC,wBAAwB,IAAI,aAAa,KAC1C,CAAC,mBAAmB,IAAI,QAAQ;AAAA,IACpC;AAAA,EACF;AACF;;;AC3LA,IAAM,iBACJ,OAAO,cAAc,cAAc,YAAY;;;ACPjD,SAAQ,cAAa;;;ACId,IAAME,YAAN,MAA+B;AAAA,EAC3B;AAAA,EACA;AAAA,EACT,UAAU;AAAA,EAEV,YAAY,KAAmC,SAAqB;AAClE,SAAK,OAAO;AACZ,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,UAAU;AACR,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,KAA+B;AACjC,WACE,kCAAkC,IAAI,KACtC,QAAQ,QAAQ,KAAK,KAAK,IAAI,GAAG,CAAC;AAAA,EAEtC;AAAA,EAEA,IAAI,KAAmD;AACrD,WACE,kCAAkC,IAAI,KACtC,QAAQ,QAAQ,KAAK,KAAK,IAAI,GAAG,CAAC;AAAA,EAEtC;AACF;;;AC7BO,IAAMC,aAAN,cAAwB,cAA+B;AAAA,EACnD;AAAA,EAET,YAAY,KAAmC,SAAqB;AAClE,UAAM,IAAIC,UAAS,KAAK,OAAO,CAAC;AAChC,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,SAAwB;AACtB,QAAI,KAAK,QAAQ;AACf,aAAO,6BAA6B;AAAA,IACtC;AAGA,SAAK,SAAS,QAAQ,CAAC,OAAO,QAAQ;AACpC,UAAI,UAAU,gBAAgB;AAC5B,aAAK,KAAK,OAAO,GAAG;AAAA,MACtB,OAAO;AACL,aAAK,KAAK,IAAI,KAAK,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AACD,SAAK,SAAS,MAAM;AACpB,SAAK,QAAQ;AACb,WAAO;AAAA,EACT;AACF;;;AFpBA,IAAM,SAAS,oBAAI,IAAmB;AAM/B,SAAS,aAAa,MAA6B;AACxD,SAAO,OAAO,IAAI;AAClB,SAAO;AACT;AAgBO,IAAM,WAAN,MAAgC;AAAA,EAC5B;AAAA,EACA;AAAA,EACT,UAAU;AAAA,EAEV,YAAY,MAAc;AACxB,UAAM,QAAQ,OAAO,IAAI,IAAI;AAC7B,QAAI;AACJ,QAAI;AACJ,QAAI,OAAO;AACT,OAAC,EAAC,MAAM,IAAG,IAAI;AAAA,IACjB,OAAO;AACL,aAAO,IAAI,OAAO;AAClB,YAAM,oBAAI,IAAI;AACd,aAAO,IAAI,MAAM,EAAC,MAAM,IAAG,CAAC;AAAA,IAC9B;AACA,SAAK,UAAU;AACf,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,MAAM,OAAsB;AAC1B,uBAAmB,IAAI;AACvB,UAAM,UAAU,MAAM,KAAK,QAAQ,KAAK;AACxC,WAAO,IAAIC,UAAS,KAAK,MAAM,OAAO;AAAA,EACxC;AAAA,EAEA,MAAM,QAAwB;AAC5B,uBAAmB,IAAI;AACvB,UAAM,UAAU,MAAM,KAAK,QAAQ,MAAM;AACzC,WAAO,IAAIC,WAAU,KAAK,MAAM,OAAO;AAAA,EACzC;AAAA,EAEA,QAAuB;AACrB,SAAK,UAAU;AACf,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;;;AGzDO,IAAM,0BAAN,MAA+C;AAAA,EAC3C;AAAA,EACA;AAAA,EACT;AAAA,EACA,YAAY,IAAgB,MAAc;AACxC,SAAK,MAAM;AACX,SAAK,QAAQ;AACb,SAAK,SAAS,IAAI,SAAS,IAAI;AAAA,EACjC;AAAA,EAEA,OAAsB;AACpB,WAAO,KAAK,qBAAqB,OAAK,EAAE,KAAK,CAAC;AAAA,EAChD;AAAA,EAEA,QAAwB;AACtB,WAAO,KAAK,qBAAqB,OAAK,EAAE,MAAM,CAAC;AAAA,EACjD;AAAA,EAEA,MAAM,qBACJ,GACY;AACZ,QAAI;AACF,aAAO,MAAM,EAAE,KAAK,MAAM;AAAA,IAC5B,SAAS,GAAG;AACV,UAAI,8BAA8B,CAAC,GAAG;AAGpC,YAAI,KAAK,kBAAkB,UAAU;AACnC,eAAK,IAAI;AAAA,YACP;AAAA,UACF;AACA,eAAK,SAAS,IAAI,SAAS,KAAK,KAAK;AAAA,QACvC;AACA,eAAO,EAAE,KAAK,MAAM;AAAA,MACtB;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,QAAuB;AACrB,WAAO,KAAK,OAAO,MAAM;AAAA,EAC3B;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK,OAAO;AAAA,EACrB;AACF;AAEA,SAAS,8BAA8B,GAA+B;AACpE,SACE,UAAU,KACV,aAAa,gBACb,EAAE,SAAS,uBACX,EAAE,YACA;AAEN;AAEA,SAAS,YAAqB;AAC5B,SAAO,gBAAW,WAAW,SAAS,SAAS,KAAK;AACtD;AAEO,SAAS,2BACd,IACA,MACO;AACP,MAAI,UAAU,GAAG;AACf,WAAO,IAAI,wBAAwB,IAAI,IAAI;AAAA,EAC7C;AACA,SAAO,IAAI,SAAS,IAAI;AAC1B;AAEO,SAAS,4BAA4B,MAA6B;AACvE,MAAI,CAAC,UAAU,GAAG;AAChB,WAAO,aAAa,IAAI;AAAA,EAC1B;AACA,MAAI;AACF,WAAO,aAAa,IAAI;AAAA,EAC1B,SAAS,GAAG;AACV,QAAI,8BAA8B,CAAC,GAAG;AACpC,aAAO,aAAa,IAAI;AAAA,IAC1B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAA6B;AACjD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,MAAM,UAAU,eAAe,IAAI;AACzC,QAAI,YAAY,MAAM,QAAQ;AAC9B,QAAI,UAAU,MAAM,OAAO,IAAI,KAAK;AAAA,EACtC,CAAC;AACH;;;ACxGO,SAAS,mBACd,IACA,SACe;AACf,UAAQ,SAAS;AAAA,IACf,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,QACL,QAAQ,UAAQ,2BAA2B,IAAI,IAAI;AAAA,QACnD,MAAM;AAAA,MACR;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,QAAQ,UAAQ,IAAI,SAAS,IAAI;AAAA,QACjC,MAAM,UAAQ,aAAa,IAAI;AAAA,MACjC;AAAA,IACF;AACE,aAAO;AAAA,EACX;AACF;;;AC3BA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AASA,SAAS,iBACd,WAAqB,QACrB,WAAsB,CAAC,cAAc,GACrC,SACY;AACZ,QAAM,UACJ,SAAS,WAAW,IAAI,SAAS,CAAC,IAAI,IAAI,WAAW,QAAQ;AAC/D,SAAO,IAAI,WAAW,UAAU,SAAS,OAAO;AAClD;;;ACrBA,IAAM,wBAAwB;AAC9B,IAAM,wBAAwB,qBAAqB;AAEnD,IAAI,gBAAgB;AAab,SAAS,wBAAgC;AAC9C,SAAO,gBAAgB;AACzB;;;ACTA,IAAM,UAAU;AAChB,IAAM,iBAAiB;AAiBvB,SAAS,8BACP,OAC0C;AAC1C,eAAa,KAAK;AAClB,aAAW,CAAC,MAAM,EAAE,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,iBAAa,IAAI;AACjB,4BAAwB,EAAE;AAC1B,WAAO,SAAS,GAAG,IAAI;AAAA,EACzB;AACF;AAEA,SAAS,wBACP,OACoC;AACpC,eAAa,KAAK;AAClB,eAAa,MAAM,IAAI;AACvB,eAAa,MAAM,cAAc;AACjC,eAAa,MAAM,uBAAuB;AAC1C,eAAa,MAAM,aAAa;AAChC,MAAI,MAAM,0BAA0B,QAAW;AAC7C,iBAAa,MAAM,qBAAqB;AAAA,EAC1C;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACpB;AAAA,EAET,YAAY,eAA4B;AACtC,SAAK,WAAW,cAAc,sBAAsB,CAAC;AAAA,EACvD;AAAA,EAEA,YAAY,IAAyD;AACnE,WAAO,KAAK,aAAa,EAAC,GAAG,IAAI,uBAAuB,KAAK,IAAI,EAAC,CAAC;AAAA,EACrE;AAAA,EAEA,sBACE,IACkC;AAClC,WAAO,KAAK,aAAa,EAAE;AAAA,EAC7B;AAAA,EAEA,aAAa,IAAyD;AACpE,WAAO,UAAU,KAAK,UAAU,OAAM,UAAS;AAC7C,YAAM,cAAc,MAAM,aAAa,KAAK;AAC5C,YAAM,WAAW;AAAA,QACf,GAAG;AAAA,QACH,CAAC,GAAG,IAAI,GAAG;AAAA,MACb;AACA,YAAM,MAAM,IAAI,SAAS,QAAQ;AACjC,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,iBAAgC;AAC9B,WAAO,UAAU,KAAK,UAAU,WAAS,MAAM,IAAI,OAAO,CAAC;AAAA,EAC7D;AAAA,EAEA,gBAAgB,OAA+C;AAC7D,WAAO,UAAU,KAAK,UAAU,OAAM,UAAS;AAC7C,YAAM,cAAc,MAAM,aAAa,KAAK;AAC5C,YAAM,WAAW;AAAA,QACf,GAAG;AAAA,MACL;AACA,iBAAW,QAAQ,OAAO;AACxB,eAAO,SAAS,IAAI;AAAA,MACtB;AACA,YAAM,MAAM,IAAI,SAAS,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AAAA,EAEA,eAAiD;AAC/C,WAAO,SAAS,KAAK,UAAU,YAAY;AAAA,EAC7C;AAAA,EAEA,QAAuB;AACrB,WAAO,KAAK,SAAS,MAAM;AAAA,EAC7B;AAAA,EAEA,eAAgC;AAC9B,WAAO,UAAU,KAAK,UAAU,OAAM,UAAS;AAC7C,UAAI,YAAY,MAAM,MAAM,IAAI,cAAc;AAC9C,UAAI,cAAc,QAAW;AAE3B,oBAAY,IAAI,aAAa,CAAC;AAC9B,cAAM,MAAM,IAAI,gBAAgB,SAAS;AAAA,MAC3C;AACA,mBAAa,SAAS;AACtB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAEA,eAAe,aAAa,MAA8C;AACxE,MAAI,WAAW,MAAM,KAAK,IAAI,OAAO;AACrC,MAAI,CAAC,UAAU;AACb,eAAW,WAAW,CAAC,CAAC;AAAA,EAC1B;AACA,gCAA8B,QAAQ;AACtC,SAAO;AACT;;;AChGO,IAAM,uBAAuB,KAAK,KAAK,KAAK;AAK5C,IAAM,4BAA4B,IAAI,KAAK;AAE3C,SAAS,wBACd,mBACA,aACA,iBACA,qBACA,QACA,wBACA,kBACA,IACA,QACM;AACN,MAAI,UAAU;AACd;AAAA,IACE;AAAA,IACA,YAAY;AACV,YAAM;AAAA,QACJ;AAAA,QACA,KAAK,IAAI;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,MAAM;AACJ,UAAI,SAAS;AACX,kBAAU;AACV,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,eAAsB,oBACpB,mBACA,KACA,QACA,aACA,wBACA,kBACA,cAAc,oBACC;AACf,QAAM,YAAY,MAAM,kBAAkB,aAAa;AAEvD,QAAM,MAAM,OAAO,OAAO,SAAS;AACnC,QAAM,iBAAiB,MAAM,QAAQ;AAAA,IACnC,IAAI;AAAA,MACF,OAAM,OACJ;AAAA,QACE,GAAG;AAAA,QACH,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACJ;AAAA,EACF;AAEA,QAAM,kBAA4B,CAAC;AACnC,QAAM,gBAA0B,CAAC;AACjC,QAAM,yBAAiD,CAAC;AACxD,aAAW,CAAC,QAAQ,CAAC,YAAY,cAAc,CAAC,KAAK,gBAAgB;AACnE,QAAI,YAAY;AACd,sBAAgB,KAAK,MAAM;AAC3B,6BAAuB,KAAK,GAAG,cAAc;AAAA,IAC/C,OAAO;AACL,oBAAc,KAAK,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,EAAC,OAAM,IAAI,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,OAAO,QAAQ;AACjB,UAAM,OAAO,CAAC;AAAA,EAChB;AAEA,MAAI,uBAAuB,SAAS,GAAG;AAErC,QAAI,oBAAoC;AACxC,eAAW,QAAQ,eAAe;AAChC,YAAM,UAAU,YAAY,IAAI,GAAG,OAAM,aAAY;AACnD,cAAM,oBAAoB,MAAM;AAAA,UAC9B;AAAA,UACA;AAAA,QACF;AAEA,4BAAoB;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,2BAA2B,wBAAwB,iBAAiB;AAG1E,UAAM,iBAAiB,wBAAwB;AAAA,EACjD;AACF;AAEA,eAAe,qBACb,MACA,mBACA,aACA;AACA,QAAM,YAAY,IAAI;AACtB,QAAM,kBAAkB,gBAAgB,CAAC,IAAI,CAAC;AAChD;AAEA,eAAe,cACb,mBACA,eACA,aACiD;AAGjD,QAAM,mBAAmB,MAAM,QAAQ;AAAA,IACrC,cAAc,IAAI,OAAM,SAAQ;AAC9B,YAAM,qBAAqB,MAAM,mBAAmB,WAAW;AAC/D,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,UAAoB,CAAC;AAC3B,QAAM,SAAoB,CAAC;AAC3B,aAAW,UAAU,kBAAkB;AACrC,QAAI,OAAO,WAAW,aAAa;AACjC,cAAQ,KAAK,OAAO,KAAK;AAAA,IAC3B,OAAO;AACL,aAAO,KAAK,OAAO,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,EAAC,SAAS,OAAM;AACzB;AAEA,SAAS,mBAAmB,MAAqB;AAC/C,QAAM,aAAa,IAAI,SAAS,IAAI;AACpC,SAAO,IAAI,UAAU,YAAY,eAAe,UAAU;AAC5D;AAOA,SAAS,6BACP,IACA,KACA,QACA,wBACA,aAGA;AACA,MAAI,GAAG,0BAAwC,QAAQ;AACrD,WAAO,CAAC,KAAK;AAAA,EACf;AAGA,SAAO,GAAG,0BAA0B,MAAS;AAI7C,MAAI,MAAM,GAAG,wBAAwB,QAAQ;AAC3C,WAAO,CAAC,KAAK;AAAA,EACf;AAGA;AAAA,IACE,GAAG,4BAA0C,QAC3C,GAAG,4BAA0C,MAC7C,GAAG,4BAA0C;AAAA,EACjD;AACA,SAAO;AAAA,IACL;AAAA,IACA,YAAY,GAAG,IAAI;AAAA,EACrB;AACF;AA0CA,eAAsB,aAAa,QAAgB,MAA4B;AAC7E,QAAM,aAAa,iBAAiB,MAAM,UAAU,MAAM,UAAU;AAAA,IAClE,cAAc;AAAA,EAChB,CAAC;AACD,QAAM,kBAAkB,mBAAmB,YAAY,MAAM,OAAO;AACpE,QAAM;AAAA,IACJ;AAAA,IACA,IAAI,kBAAkB,gBAAgB,MAAM;AAAA,IAC5C,gBAAgB;AAAA,EAClB;AACF;AAQA,eAAsB,iBAAiB,MAGpC;AACD,QAAM,aAAa,iBAAiB,MAAM,UAAU,MAAM,UAAU;AAAA,IAClE,kBAAkB;AAAA,EACpB,CAAC;AACD,QAAM,kBAAkB,mBAAmB,YAAY,MAAM,OAAO;AACpE,QAAM,QAAQ,IAAI,kBAAkB,gBAAgB,MAAM;AAC1D,QAAM,YAAY,MAAM,MAAM,aAAa;AAC3C,QAAM,UAAU,OAAO,OAAO,SAAS,EAAE,IAAI,QAAM,GAAG,IAAI;AAC1D,SAAO,cAAc,OAAO,SAAS,gBAAgB,IAAI;AAC3D;AAmBA,SAAS,6CACP,wBACA,QAGA;AACA,SAAO,SAAS,QAAQ,OAAM,SAAQ;AAGpC,QAAI,wBAAwB;AAC1B,YAAM,eAAe,MAAM,gBAAgB,IAAI;AAC/C,iBAAW,eAAe,aAAa,OAAO,GAAG;AAC/C,YAAI,+BAA+B,WAAW,GAAG;AAC/C,iBAAO,CAAC,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,WAAW,IAAI;AACrC,UAAM,yBAAyB,MAAM,kBAAkB,IAAI;AAC3D,UAAM,iBAAyC,CAAC,GAAG,sBAAsB;AAGzE,eAAW,CAAC,UAAU,MAAM,KAAK,SAAS;AACxC,qBAAe,KAAK;AAAA,QAClB;AAAA,QACA,eAAe,OAAO;AAAA,MACxB,CAAC;AAAA,IACH;AAGA,WAAO,CAAC,MAAM,cAAc;AAAA,EAC9B,CAAC;AACH;;;AC/VO,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,cAAc;AACZ,UAAM,uBAAuB;AAAA,EAC/B;AACF;AAIO,SAAS,cAAc,IAAkB;AAC9C,MAAI,GAAG,QAAQ;AACb,UAAM,IAAI,uBAAuB;AAAA,EACnC;AACF;AAEO,SAAS,eAAe,IAAwC;AACrE,SAAO,GAAG,SAAS,QAAQ,OAAO,IAAI,uBAAuB,CAAC,IAAI;AACpE;;;AChBO,SAAS,gBAAgB,OAAwB;AACtD,SAAO,wBAAwB,OAAO,oBAAI,IAAI,CAAC;AACjD;AAEA,SAAS,wBAAwB,OAAgB,MAA4B;AAC3E,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,QAAI,KAAK,IAAI,KAAK,GAAG;AACnB,aAAO;AAAA,IACT;AACA,SAAK,IAAI,KAAK;AAAA,EAChB;AAEA,MAAI,iBAAiB,OAAO;AAC1B,QAAI,MAAM,SAAS;AACjB,aAAO,MAAM;AAAA,IACf;AAEA,QAAI,WAAW,OAAO;AACpB,YAAM,QAAS,MAA4B;AAC3C,UAAI,UAAU,QAAW;AACvB,cAAM,eAAe,wBAAwB,OAAO,IAAI;AACxD,YAAI,cAAc;AAChB,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MACE,OAAO,UAAU,YACjB,UAAU,QACV,aAAa,SACb,OAAQ,MAA6B,YAAY,UACjD;AACA,UAAM,UAAW,MAA4B;AAC7C,QAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI;AACF,UAAMC,QAAO,WAAW,MAAM,KAAK;AACnC,WAAO,mBAAmB,KAAK,UAAUA,KAAI,CAAC;AAAA,EAChD,SAAS,IAAI;AAAA,EAAC;AAEd,SAAO,yBAAyB,OAAO,KAAK;AAC9C;AAEO,SAAS,gBAAgB,OAA+C;AAC7E,MAAI,iBAAiB,OAAO;AAC1B,QAAI,aAAa,OAAO;AACtB,UAAI;AACF,eAAO,WAAW,MAAM,OAAO,OAAO;AAAA,MACxC,SAAS,IAAI;AAAA,MAAC;AAAA,IAChB;AAEA,QAAI,MAAM,QAAQ,MAAM,SAAS,SAAS;AACxC,aAAO,EAAC,MAAM,MAAM,KAAI;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,aAAa,OAAO;AACrE,QAAI;AACF,aAAO,WAAW,MAAO,OAAwC,OAAO;AAAA,IAC1E,SAAS,IAAI;AAAA,IAAC;AAAA,EAChB;AAEA,MAAI;AACF,WAAO,WAAW,MAAM,KAAK;AAAA,EAC/B,SAAS,IAAI;AAAA,EAAC;AAEd,SAAO;AACT;;;ACnDO,IAAM,mBAAN,cAEG,MAAM;AAAA;AAAA;AAAA;AAAA,EAIL;AAAA,EAET,YACE,SACA,SACA;AACA,UAAM,SAAS,EAAC,OAAO,SAAS,MAAK,CAAC;AACtC,SAAK,OAAO;AACZ,SAAK,WAAW,SAAS,WAAY;AAAA,EACvC;AAAA,EAEA,IAAI,UAAa;AACf,WAAO,KAAK;AAAA,EACd;AACF;AAEO,SAAS,mBAAmB,OAA2C;AAC5E,SAAO,iBAAiB;AAC1B;AAEO,SAAS,yBAEd,OAAqC;AACrC,MAAI,mBAAmB,KAAK,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,gBAAgB,KAAK;AACrC,QAAM,UAAU,gBAAgB,KAAK;AAErC,SAAO,IAAI,iBAAoB,SAAS;AAAA,IACtC,OAAO;AAAA,IACP;AAAA,EACF,CAAC;AACH;;;ACtEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIO,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,2BAA2B;AACjC,IAAM,qCACX;AACK,IAAM,yCACX;AACK,IAAM,wCACX;AACK,IAAM,iBAAiB;AACvB,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,iBAAiB;AACvB,IAAM,sBAAsB;AAC5B,IAAM,YAAY;AAClB,IAAM,SAAS;AACf,IAAM,kBAAkB;AACxB,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,4BAA4B;AAClC,IAAM,mBAAmB;AACzB,IAAM,WAAW;;;ACzBxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,SAAS;AACf,IAAM,SAAS;AACf,IAAM,YAAY;;;ACFzB;AAAA;AAAA;AAAA;AAAA,kBAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,WAAW;AACjB,IAAM,QAAQ;AACd,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAMA,YAAW;AACjB,IAAM,OAAO;AACb,IAAM,UAAU;;;ACJhB,IAAM,mBAAqB,sBAAO;AAAA,EACvC,IAAM,sBAAO;AAAA,EACb,UAAY,sBAAO;AACrB,CAAC;;;ACED,IAAM,uBAAyB;AAAA,EAC7B,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AACZ;AAEA,IAAM,uBAAyB,sBAAO;AAAA,EACpC,MAAM;AAAA,EACN,SAAW,sBAAO;AAAA;AAAA,EAElB,QAAU,aAAa,0BAAY,QAAQ,0BAAY,SAAS,EAAE,SAAS;AAC7E,CAAC;AAED,IAAM,yBAA2B;AAAA,EAC/B,wBAAU;AAAA,EACV,wBAAU;AAAA,EACV,wBAAU;AACZ;AAEA,IAAM,oBAAsB,sBAAO;AAAA,EACjC,MAAM;AAAA,EACN,SAAW,sBAAO;AAAA,EAClB,cAAgB,sBAAO,EAAE,SAAS;AAAA,EAClC,cAAgB,sBAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlC,iBAAmB,sBAAS,sBAAO,CAAC,EAAE,SAAS;AAAA,EAC/C,QAAU,uBAAQ,0BAAY,SAAS,EAAE,SAAS;AACpD,CAAC;AAED,IAAM,4BAA8B,uBAAQ,wBAAU,UAAU;AAChE,IAAM,iCAAmC,uBAAQ,wBAAU,eAAe;AAEnE,IAAM,kBAAuC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,uBAAyB,sBAAO;AAAA,EACpC,MAAM;AAAA,EACN,SAAS,WAAW,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAK7B,aAAe,qBAAM,gBAAgB;AAAA,EACrC,SAAW,sBAAO;AACpB,CAAC;AAEM,IAAM,uBAAyB;AAAA,EACpC,qBAAqB,OAAO;AAAA,IAC1B,QAAU,uBAAQ,0BAAY,MAAM;AAAA,IACpC,QAAU;AAAA,MACR,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,IACd;AAAA,EACF,CAAC;AAAA,EACD,qBAAqB,OAAO;AAAA,IAC1B,QAAU,uBAAQ,0BAAY,SAAS;AAAA,IACvC,QAAU,uBAAQ,0BAAY,IAAI;AAAA,IAClC,QAAU,sBAAO;AAAA,IACjB,aAAe,sBAAO,EAAE,SAAS;AAAA,EACnC,CAAC;AAAA,EACD,qBAAqB,OAAO;AAAA,IAC1B,QAAU,uBAAQ,0BAAY,SAAS;AAAA,IACvC,QAAU;AAAA,MACR,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAEA,IAAM,4BAA8B,sBAAO;AAAA,EACzC,MAAM;AAAA,EACN,SAAS,WAAW,SAAS;AAAA;AAAA;AAAA;AAAA,EAI7B,UAAY,qBAAQ,sBAAO,CAAC;AAAA,EAC5B,SAAW,sBAAO;AACpB,CAAC;AAEM,IAAM,4BAA8B;AAAA,EACzC,0BAA0B,OAAO;AAAA,IAC/B,QAAU,uBAAQ,0BAAY,MAAM;AAAA,IACpC,QAAU;AAAA,MACR,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,IACd;AAAA,EACF,CAAC;AAAA,EACD,0BAA0B,OAAO;AAAA,IAC/B,QAAU,uBAAQ,0BAAY,SAAS;AAAA,IACvC,QAAU,uBAAQ,0BAAY,IAAI;AAAA,IAClC,QAAU,sBAAO;AAAA,IACjB,aAAe,sBAAO,EAAE,SAAS;AAAA,EACnC,CAAC;AAAA,EACD,0BAA0B,OAAO;AAAA,IAC/B,QAAU,uBAAQ,0BAAY,SAAS;AAAA,IACvC,QAAU;AAAA,MACR,0BAAY;AAAA,MACZ,0BAAY;AAAA,MACZ,0BAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAEO,IAAM,kBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOO,IAAM,qBAA6C,qBAAM;AAAA,EAC5D,uBAAQ,OAAO;AAAA,EACjB;AACF,CAAC;AAOM,IAAM,gBAAN,cAEG,MAAM;AAAA,EACL;AAAA,EAET,YAAY,WAAc,SAAwB;AAChD,UAAM,UAAU,SAAS,OAAO;AAChC,SAAK,OAAO;AACZ,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,IAAI,OAAkB;AACpB,WAAO,KAAK,UAAU;AAAA,EACxB;AACF;AAEO,SAAS,gBAAgB,OAAwC;AACtE,SAAO,iBAAiB;AAC1B;;;AC3KO,IAAM,6BAA+B;AAAA,EACxC,sBAAO;AAAA,IACP,IAAM,sBAAO;AAAA,IACb,MAAQ,sBAAO;AAAA,IACf,MAAQ,SAAW,qBAAM,UAAU,CAAC;AAAA,EACtC,CAAC;AACH;AAGO,IAAM,yBAA2B,sBAAO;AAAA,EAC7C,IAAM,sBAAO;AAAA,EACb,MAAQ,sBAAO;AAAA,EACf,KAAK;AACP,CAAC;AAEM,IAAM,wBAA0B,sBAAO;AAAA,EAC5C,OAAS,uBAAQ,KAAK;AAAA,EACtB,IAAM,sBAAO;AAAA,EACb,MAAQ,sBAAO;AAAA;AAAA,EAEf,SAAW,sBAAO,EAAE,SAAS;AAAA,EAC7B,SAAS,WAAW,SAAS;AAC/B,CAAC;AACM,IAAM,0BAA4B,sBAAO;AAAA,EAC9C,OAAS,uBAAQ,OAAO;AAAA,EACxB,IAAM,sBAAO;AAAA,EACb,MAAQ,sBAAO;AAAA,EACf,SAAW,sBAAO;AAAA,EAClB,SAAS,WAAW,SAAS;AAC/B,CAAC;AACM,IAAM,qBAAuB;AAAA,EAClC;AAAA,EACA;AACF;AAGO,IAAM,8BAAgC;AAAA,EACzC,qBAAM,wBAAwB,kBAAkB;AACpD;AAGO,IAAM,gCAAkC,qBAAM;AAAA,EACjD,uBAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAIM,IAAM,8BAAgC,qBAAM;AAAA,EAC/C,uBAAQ,gBAAgB;AAAA,EACxB,qBAAM,kBAAkB;AAC5B,CAAC;AAGD,IAAM,+BAAiC,qBAAM;AAAA,EACzC,uBAAQ,iBAAiB;AAAA,EAC3B;AACF,CAAC;AACD,IAAM,2BAA6B,qBAAM;AAAA,EACrC,uBAAQ,aAAa;AAAA,EACvB;AACF,CAAC;AAEM,IAAM,iCAAmC;AAAA,EAC9C;AAAA,EACA;AACF;;;AClEO,SAAS,MAA4B,MAAa;AACvD,SAAO,IAAI,aAAa;AAAA,IACtB;AAAA,IACA,SAAS,CAAC;AAAA,IACV,YAAY,CAAC;AAAA,EACf,CAAC;AACH;AAEO,SAASC,UAAoC;AAClD,SAAO,IAAI,cAAc;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAASC,UAAoC;AAClD,SAAO,IAAI,cAAc;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAAS,UAAuC;AACrD,SAAO,IAAI,cAAc;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAAS,OAAwD;AACtE,SAAO,IAAI,cAAc;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAEO,SAAS,cAAgC;AAC9C,SAAO,IAAI,cAAc;AAAA,IACvB,MAAM;AAAA,IACN,UAAU;AAAA,IACV,YAAY;AAAA,EACd,CAAC;AACH;AAUO,IAAM,eAAN,MAAM,cAAyC;AAAA,EAC3C;AAAA,EACT,YAAY,QAAgB;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAgC,YAAwB;AACtD,WAAO,IAAI,cAAqB;AAAA,MAC9B,GAAG,KAAK;AAAA;AAAA;AAAA;AAAA,MAIR,YAAY,WAAW,WAAW,SAAS,IACvC,WAAW,UAAU,UAAU,MAAM,IACrC;AAAA,IACN,CAAC;AAAA,EACH;AAAA,EAEA,QACE,SAKC;AACD,UAAM,gBAAgB,OAAO;AAAA,MAC3B,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC;AAAA,IACvD;AACA,WAAO,IAAI,wBAAwB;AAAA,MACjC,GAAG,KAAK;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAEO,IAAM,0BAAN,MAAM,yBAAoD;AAAA,EACtD;AAAA,EAET,YAAY,QAAgB;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,cACK,eACH;AACA,WAAO,IAAI,yBAAwB;AAAA,MACjC,GAAG,KAAK;AAAA,MACR,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,SAAS;AACX,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ;AAIN,QAAI,KAAK,QAAQ,WAAW,WAAW,GAAG;AACxC,YAAM,IAAI,MAAM,UAAU,KAAK,QAAQ,IAAI,4BAA4B;AAAA,IACzE;AACA,UAAM,QAAQ,oBAAI,IAAY;AAC9B,eAAW,CAAC,KAAK,EAAC,WAAU,CAAC,KAAK,OAAO,QAAQ,KAAK,QAAQ,OAAO,GAAG;AACtE,YAAM,OAAO,cAAc;AAC3B,UAAI,MAAM,IAAI,IAAI,GAAG;AACnB,cAAM,IAAI;AAAA,UACR,UACE,KAAK,QAAQ,IACf,uCAAuC,IAAI;AAAA,QAC7C;AAAA,MACF;AACA,YAAM,IAAI,IAAI;AAAA,IAChB;AACA,WAAO,KAAK;AAAA,EACd;AACF;AAEA,IAAM,gBAAN,MAAM,eAA+C;AAAA,EAC1C;AAAA,EACT,YAAY,QAAgB;AAC1B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAgC,YAAwB;AACtD,WAAO,IAAI,eAA6C;AAAA,MACtD,GAAG,KAAK;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,WAAuE;AACrE,WAAO,IAAI,eAAc;AAAA,MACvB,GAAG,KAAK;AAAA,MACR,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,SAAS;AACX,WAAO,KAAK;AAAA,EACd;AACF;;;AC5JO,IAAM,kBAAuC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,qBAAuB,sBAAO;AAAA,EACzC,MAAM;AACR,CAAC;AAIM,IAAM,oBAAsB,sBAAO;AAAA,EACxC,SAAW,sBAAO,kBAAkB;AAAA;AAAA;AAAA,EAGpC,YAAc,qBAAQ,sBAAO,CAAC,EAAE,SAAS;AAC3C,CAAC;AAIM,IAAM,qBAAuB,sBAAO;AAAA,EACzC,QAAU,sBAAO,iBAAiB;AACpC,CAAC;AAID,IAAM,SAAS,CAAC,CAAC,CAAC,GAA4B,CAAC,CAAC,MAC9C,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI;AAMpB,SAAS,sBAAsB,QAAoC;AACxE,SAAO;AAAA,IACL,QAAQ;AAAA,MAAc,OAAO;AAAA,MAAQ,YACnC,OAAO,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,MAAMC,MAAK,MAAM;AAAA,QACzC;AAAA,QACA;AAAA,UACE,SAAS,cAAcA,OAAM,SAAS,OAAK,EAAE,KAAK,MAAM,CAAC;AAAA,UACzD,YAAY;AAAA,YACVA,OAAM;AAAA,YACN;AAAA,UACF,EAAE,KAAK;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACnCO,SAAS,aAKd,SAsBA;AACA,QAAM,YAAyC,CAAC;AAChD,QAAM,mBAAiE,CAAC;AACxE,QAAM,cAAc,oBAAI,IAAY;AAEpC,UAAQ,OAAO,QAAQ,CAAAC,WAAS;AAC9B,UAAM,EAAC,aAAaA,OAAM,OAAO,KAAI,IAAIA,OAAM;AAC/C,QAAI,YAAY,IAAI,UAAU,GAAG;AAC/B,YAAM,IAAI,MAAM,uCAAuC,UAAU,GAAG;AAAA,IACtE;AACA,gBAAY,IAAI,UAAU;AAC1B,QAAI,UAAUA,OAAM,OAAO,IAAI,GAAG;AAChC,YAAM,IAAI;AAAA,QACR,UAAUA,OAAM,OAAO,IAAI;AAAA,MAC7B;AAAA,IACF;AACA,cAAUA,OAAM,OAAO,IAAI,IAAIA,OAAM,MAAM;AAAA,EAC7C,CAAC;AACD,UAAQ,eAAe,QAAQ,mBAAiB;AAC9C,QAAI,iBAAiB,cAAc,IAAI,GAAG;AACxC,YAAM,IAAI;AAAA,QACR,4BAA4B,cAAc,IAAI;AAAA,MAChD;AAAA,IACF;AACA,qBAAiB,cAAc,IAAI,IAAI,cAAc;AACrD;AAAA,MACE,cAAc;AAAA,MACd,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,qBAAqB,QAAQ;AAAA,IAC7B,sBAAsB,QAAQ;AAAA,EAChC;AACF;AAEA,SAAS,kBACP,eACA,WACA,QACA;AAEA,SAAO,QAAQ,aAAa,EAAE,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM;AACrD,QAAI,SAAS,OAAO,SAAS;AAC7B,QAAI,OAAO,QAAQ,IAAI,MAAM,QAAW;AACtC,YAAM,IAAI;AAAA,QACR,iBAAiB,SAAS,MAAM,IAAI,8CAA8C,IAAI,uBAAuB,OAAO,IAAI;AAAA,MAC1H;AAAA,IACF;AACA,QAAI,QAAQ,gBAAc;AACxB,UAAI,CAAC,OAAO,WAAW,UAAU,GAAG;AAClC,cAAM,IAAI;AAAA,UACR,qBAAqB,SAAS,MAAM,IAAI,yBAAyB,WAAW,UAAU;AAAA,QACxF;AAAA,MACF;AACA,UAAI,CAAC,OAAO,QAAQ,WAAW,YAAY,CAAC,CAAC,GAAG;AAC9C,cAAM,IAAI;AAAA,UACR,qBAAqB,SAAS,MAAM,IAAI,wBAAwB,WAAW,YAAY,CAAC,CAAC,qCAAqC,OAAO,IAAI;AAAA,QAC3I;AAAA,MACF;AACA,eAAS,OAAO,WAAW,UAAU;AAAA,IACvC,CAAC;AAAA,EACH,CAAC;AACH;AAEO,SAAS,iBAAiB,QAG/B;AACA,QAAM,SAAS;AAAA,IACb,QAAQ;AAAA,MACN,OAAO;AAAA,MACP,CAAC,MAAM,EAAC,YAAY,SAAS,WAAU,MAAM;AAAA,QAC3C,cAAc;AAAA,QACd;AAAA,UACE,SAAS,WAAW,SAAS,CAACC,OAAM,EAAC,YAAAC,aAAY,KAAI,MAAM;AAAA,YACzDA,eAAcD;AAAA,YACd,EAAC,KAAI;AAAA,UACP,CAAC;AAAA,UACD,YAAY,WAAW,IAAI,OAAK,QAAQ,CAAC,EAAE,cAAc,CAAC;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,eAAe,sBAAsB,MAAM;AACjD,QAAM,OAAO,IAAI,KAAK,UAAU,YAAY,CAAC,EAAE,SAAS,EAAE;AAC1D,SAAO,EAAC,cAAc,KAAI;AAC5B;;;AC5IA,SAAQ,mBAAkB;AA+BnB,SAAS,cAAc,GAAU,GAAkB;AACxD,MAAI,mBAAmB,CAAC;AACxB,MAAI,mBAAmB,CAAC;AAExB,MAAI,MAAM,GAAG;AACX,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,MAAM,MAAM;AACd,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,WAAW;AAC1B,kBAAc,CAAC;AACf,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AACd,WAAO,IAAI;AAAA,EACb;AACA,MAAI,OAAO,MAAM,UAAU;AACzB,iBAAa,CAAC;AASd,WAAO,YAAY,GAAG,CAAC;AAAA,EACzB;AACA,QAAM,IAAI,MAAM,qBAAqB,CAAC,EAAE;AAC1C;AASO,SAAS,mBAAmB,GAA2B;AAC5D,SAAO,KAAK;AACd;AAIO,SAAS,eAAe,OAAiB,SAA+B;AAC7E,SAAO,CAAC,GAAG,MAAM;AAEf,eAAW,OAAO,OAAO;AACvB,YAAM,QAAQ,IAAI,CAAC;AACnB,YAAM,OAAO,cAAc,EAAE,KAAK,GAAG,EAAE,KAAK,CAAC;AAC7C,UAAI,SAAS,GAAG;AACd,cAAM,SAAS,IAAI,CAAC,MAAM,QAAQ,OAAO,CAAC;AAC1C,eAAO,UAAU,CAAC,SAAS;AAAA,MAC7B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAQO,SAAS,YAAY,GAAU,GAAmB;AAEvD,MAAI,KAAK,QAAQ,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AACA,SAAO,MAAM;AACf;AAEO,SAAS,aAAa,MAAY;AACvC,aAAW,UAAU,OAAO,OAAO,KAAK,aAAa,GAAG;AACtD,eAAWE,SAAQ,OAAO,GAAG;AAC3B,mBAAaA,KAAI;AAAA,IACnB;AAAA,EACF;AACF;;;ACtGO,IAAM,iBAAiB,OAAO,IAAI;AAClC,IAAM,WAAW,OAAO,IAAI;AAwD5B,SAAS,YACd,aACA,QACA,QACA,cACA,QACA,UAAU,OACJ;AACN,MAAI,OAAO,UAAU;AACnB,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AACH,mBAAW,CAACC,eAAc,QAAQ,KAAK,OAAO;AAAA,UAC5C,OAAO,KAAK;AAAA,QACd,GAAG;AACD,gBAAM,cAAc,KAAK,OAAO,cAAcA,aAAY,CAAC;AAC3D,qBAAW,QAAQ,SAAS,GAAG;AAC7B;AAAA,cACE;AAAA,cACA,EAAC,MAAM,OAAO,MAAM,KAAI;AAAA,cACxB;AAAA,cACAA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF,KAAK;AAKH;AAAA,MACF,KAAK,SAAS;AACZ,cAAM,cAAc;AAAA,UAClB,OAAO,cAAc,OAAO,MAAM,gBAAgB;AAAA,QACpD;AACA;AAAA,UACE;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA;AACE,oBAAY,MAAM;AAAA,IACtB;AAAA,EACF;AAEA,QAAM,EAAC,UAAU,eAAe,aAAY,IAAI;AAChD,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,OAAO;AACV,UAAI;AAEJ,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,YAAI,aAAa,QAAW;AAC1B;AAAA,YACE,OAAO,YAAY,UAAU,OAAO,KAAK,GAAG,MAAM;AAAA,YAClD,0BAA0B,YAAY;AAAA,UACxC;AAEA,mBAAS,cAAc;AAAA,QACzB,OAAO;AACL,qBAAW,iBAAiB,OAAO,KAAK,KAAK,QAAQ,SAAS,CAAC;AAE/D,UAAC,YAAgC,YAAY,IAAI;AAAA,QACnD;AAAA,MACF,OAAO;AACL,mBAAW;AAAA,UACT,OAAO,KAAK;AAAA,UACZ,kBAAkB,aAAa,YAAY;AAAA,UAC3C;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,UAAI,UAAU;AACZ,mBAAW,CAACA,eAAc,QAAQ,KAAK,OAAO;AAAA,UAC5C,OAAO,KAAK;AAAA,QACd,GAAG;AAED,gBAAM,cAAc,KAAK,OAAO,cAAcA,aAAY,CAAC;AAC3D,gBAAM,cAAc,aAAaA,aAAY;AAC7C,cAAI,gBAAgB,QAAW;AAC7B;AAAA,UACF;AAEA,gBAAM,UAAU,YAAY,WACxB,SACC,CAAC;AACN,mBAASA,aAAY,IAAI;AAEzB,qBAAW,QAAQ,SAAS,GAAG;AAC7B;AAAA,cACE;AAAA,cACA,EAAC,MAAM,OAAO,KAAI;AAAA,cAClB;AAAA,cACAA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,eAAO,aAAa,QAAW,qBAAqB;AACpD,cAAM,KAAK,SAAS,cAAc;AAClC,YAAI,OAAO,GAAG;AACZ,UAAC,YAAgC,YAAY,IAAI;AAAA,QACnD;AACA,iBAAS,cAAc;AAAA,MACzB,OAAO;AACL;AAAA,UACE,kBAAkB,aAAa,YAAY;AAAA,UAC3C,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,QACT;AAAA,MACF;AAEA,mBAAa,OAAO,IAAI;AACxB;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,UAAI;AACJ,UAAI,UAAU;AACZ,mBAAW,iBAAiB,aAAa,YAAY;AAAA,MACvD,OAAO;AACL,cAAM,OAAO,kBAAkB,aAAa,YAAY;AACxD,cAAM,EAAC,KAAK,MAAK,IAAIC;AAAA,UACnB;AAAA,UACA,OAAO,KAAK;AAAA,UACZ,OAAO;AAAA,QACT;AACA,eAAO,OAAO,qBAAqB;AACnC,mBAAW,KAAK,GAAG;AAAA,MACrB;AAEA,YAAM,cAAc;AAAA,QAClB,OAAO,cAAc,OAAO,MAAM,gBAAgB;AAAA,MACpD;AACA,YAAM,cAAc,OAAO,cAAc,OAAO,MAAM,gBAAgB;AACtE,UAAI,gBAAgB,QAAW;AAC7B;AAAA,UACE;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA,OAAO,MAAM;AAAA,UACb;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,UAAI,UAAU;AACZ,cAAM,WAAW,YAAY,YAAY;AACzC,wBAAgB,QAAQ;AACxB,kBAAU,UAAU,QAAQ,QAAQ,OAAO;AAAA,MAC7C,OAAO;AACL,cAAM,OAAO,kBAAkB,aAAa,YAAY;AAExD,YAAI,OAAO,YAAY,OAAO,QAAQ,KAAK,OAAO,KAAK,GAAG,MAAM,GAAG;AACjE,gBAAM,EAAC,KAAK,QAAQ,OAAO,SAAQ,IAAIA;AAAA,YACrC;AAAA,YACA,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,UACT;AACA,iBAAO,UAAU,yBAAyB;AAC1C,gBAAM,WAAW,KAAK,MAAM;AAC5B,gBAAM,EAAC,KAAK,MAAK,IAAIA;AAAA,YACnB;AAAA,YACA,OAAO,KAAK;AAAA,YACZ,OAAO;AAAA,UACT;AAOA,cACE,SAAS,cAAc,MAAM,MAC5B,QAAQ,UAAU,MAAM,MAAM,SAC/B;AACA,sBAAU,UAAU,QAAQ,QAAQ,OAAO;AAAA,UAC7C,OAAO;AAUL,qBAAS,cAAc;AACvB,gBAAI,cAAc;AAClB,gBAAI,SAAS,cAAc,MAAM,GAAG;AAClC,mBAAK,OAAO,QAAQ,CAAC;AACrB,4BAAc,SAAS,MAAM,MAAM,IAAI;AAAA,YACzC;AAEA,gBAAI;AACJ,gBAAI,OAAO;AACT,4BAAc,KAAK,WAAW;AAAA,YAChC,OAAO;AACL,mBAAK,OAAO,aAAa,GAAG,QAAQ;AACpC,4BAAc;AACd,kBAAI,SAAS,cAAc,IAAI,GAAG;AAChC,sBAAM,eAAe,EAAC,GAAG,SAAQ;AACjC,qBAAK,MAAM,IAAI;AAAA,cACjB;AAAA,YACF;AACA,wBAAY,cAAc;AAC1B,sBAAU,aAAa,QAAQ,QAAQ,OAAO;AAAA,UAChD;AAAA,QACF,OAAO;AAEL,gBAAM,EAAC,KAAK,MAAK,IAAIA;AAAA,YACnB;AAAA,YACA,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,UACT;AACA,iBAAO,OAAO,qBAAqB;AACnC,oBAAU,KAAK,GAAG,GAAG,QAAQ,QAAQ,OAAO;AAAA,QAC9C;AAAA,MACF;AAEA;AAAA,IACF;AAAA,IACA;AACE,kBAAY,MAAM;AAAA,EACtB;AACF;AAEA,SAAS,UACP,UACA,QACA,QACA,SACA;AACA,SAAO,OAAO,UAAU,OAAO,KAAK,GAAG;AACvC,MAAI,SAAS;AACX,aAAS,QAAQ,IAAI,OAAO,OAAO,KAAK,KAAK,MAAM;AAAA,EACrD;AACF;AAEA,SAAS,IACP,KACA,MACA,QACA,SACuB;AACvB,QAAM,EAAC,KAAK,MAAK,IAAIA,cAAa,MAAM,KAAK,OAAO,WAAW;AAE/D,MAAI,OAAO;AACT,SAAK,GAAG,EAAE,cAAc;AACxB,WAAO;AAAA,EACT;AACA,QAAM,WAAW,iBAAiB,KAAK,QAAQ,SAAS,CAAC;AACzD,OAAK,OAAO,KAAK,GAAG,QAAQ;AAC5B,SAAO;AACT;AAEA,SAAS,wBACP,MACA,KACA,aACW;AACX,QAAM,EAAC,KAAK,MAAK,IAAIA,cAAa,MAAM,KAAK,WAAW;AACxD,SAAO,OAAO,qBAAqB;AACnC,QAAM,WAAW,KAAK,GAAG;AACzB,QAAM,KAAK,SAAS,cAAc;AAClC,MAAI,OAAO,GAAG;AACZ,SAAK,OAAO,KAAK,CAAC;AAAA,EACpB;AACA,WAAS,cAAc;AAEvB,SAAO;AACT;AAGA,SAASA,cACP,MACA,QACAC,aACA;AACA,MAAI,MAAM;AACV,MAAI,OAAO,KAAK,SAAS;AACzB,SAAO,OAAO,MAAM;AAClB,UAAM,MAAO,MAAM,SAAU;AAC7B,UAAM,aAAaA,YAAW,KAAK,GAAG,GAAU,MAAa;AAC7D,QAAI,aAAa,GAAG;AAClB,YAAM,MAAM;AAAA,IACd,WAAW,aAAa,GAAG;AACzB,aAAO,MAAM;AAAA,IACf,OAAO;AACL,aAAO,EAAC,KAAK,KAAK,OAAO,KAAI;AAAA,IAC/B;AAAA,EACF;AACA,SAAO,EAAC,KAAK,KAAK,OAAO,MAAK;AAChC;AAEA,SAAS,kBACP,aACA,cACe;AACf,QAAM,OAAO,YAAY,YAAY;AACrC,cAAY,IAAI;AAChB,SAAO;AACT;AAEA,SAAS,gBAAgB,GAAoC;AAC3D,eAAc,EAAyB,cAAc,CAAC;AACxD;AAEA,SAAS,iBAAiB,aAAoB,cAAiC;AAC7E,QAAM,IAAI,YAAY,YAAY;AAClC,eAAc,EAAyB,cAAc,CAAC;AACtD,SAAO;AACT;AAEA,SAAS,iBACP,KACA,QACA,SACA,IACW;AACX,MAAI,SAAS;AACX,WAAO,EAAC,GAAG,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,QAAQ,GAAG,OAAO,KAAK,MAAM,EAAC;AAAA,EACvE;AACA,SAAO,EAAC,GAAG,KAAK,CAAC,cAAc,GAAG,GAAE;AACtC;AACA,SAAS,OAAO,KAAU,QAAsB;AAE9C,MAAI,OAAO,WAAW,WAAW,GAAG;AAClC,WAAO,KAAK,UAAU,IAAI,OAAO,WAAW,CAAC,CAAC,CAAC;AAAA,EACjD;AACA,SAAO,KAAK,UAAU,OAAO,WAAW,IAAI,OAAK,IAAI,CAAC,CAAC,CAAC;AAC1D;;;AClaA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAAC;AAAA,EAAA,sBAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,cAAc;AACpB,IAAM,aAAa;AACnB,IAAM,eAAe;AACrB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,uBAAuB;AAC7B,IAAM,cAAc;AACpB,IAAM,cAAc;AACpB,IAAM,SAAS;AACf,IAAM,iBAAiB;AACvB,IAAMA,kBAAiB;AACvB,IAAM,iBAAiB;AACvB,IAAMD,YAAW;;;ACZxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAAAE;AAAA,EAAA;AAAA;AAAO,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,YAAY;AAClB,IAAM,YAAY;AAClB,IAAMA,SAAQ;AACd,IAAM,SAAS;;;ACmCf,IAAM,cAAN,cAKG,MAAM;AAAA,EACL;AAAA,EAET,YAAY,WAAc,SAAwB;AAChD,UAAM,UAAU,SAAS,OAAO;AAChC,SAAK,OAAO;AACZ,SAAK,YAAY,EAAC,GAAG,WAAW,QAAQ,0BAAY,OAAM;AAAA,EAC5D;AAAA,EAEA,IAAI,OAAkB;AACpB,WAAO,KAAK,UAAU;AAAA,EACxB;AACF;AAEO,SAAS,cAAc,IAA6C;AACzE,SACE,gBAAgB,EAAE,MACjB,GAAG,UAAU,WAAW,0BAAY,UACnC,GAAG,UAAU,WAAW,0BAAY;AAE1C;AAEO,SAAS,YAAY,IAA8B;AACxD,MAAI,cAAc,EAAE,GAAG;AACrB,QACE,GAAG,SAAS,wBAAU,mBACtB,GAAG,SAAS,wBAAU,cACtB;AACA,aAAO;AAAA,IACT;AACA,SACG,GAAG,UAAU,SAAS,wBAAU,cAC/B,GAAG,UAAU,SAAS,wBAAU,oBAClC,GAAG,UAAU,WAAW,0BAAY,SACnC,GAAG,UAAU,WAAW,OAAO,GAAG,UAAU,WAAW,MACxD;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,iBAAiB,OAA2C;AAC1E,MAAI,cAAc,KAAK,GAAG;AACxB,YAAQ,MAAM,UAAU,MAAM;AAAA,MAC5B,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AACb,eAAO,MAAM;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,cAAc,IAAiD;AAC7E,SACE,cAAc,eAAe,GAAG,UAAU,WAAW,0BAAY;AAErE;AAEO,IAAM,uBAAuB;AAa7B,SAAS,6BACd,IAC2B;AAE3B,MAAI,YAAY,EAAE,GAAG;AACnB,WAAO;AAAA,MACL,QAAQ,+BAAiB;AAAA,MACzB,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,cAAc,EAAE,GAAG;AACrB,YAAQ,GAAG,MAAM;AAAA;AAAA,MAEf,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AACnB,eAAO,EAAC,QAAQ,sBAAsB,QAAQ,GAAE;AAAA;AAAA,MAGlD,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AAAA,MACrB,KAAK,+BAAgB;AACnB,eAAO,EAAC,QAAQ,+BAAiB,OAAO,QAAQ,GAAE;AAAA;AAAA,MAGpD,KAAK,+BAAgB;AACnB,eAAO,EAAC,QAAQ,+BAAiB,cAAc,QAAQ,GAAE;AAAA;AAAA,MAG3D,KAAK,+BAAgB;AACnB,eAAO,EAAC,QAAQ,+BAAiB,QAAQ,QAAQ,GAAE;AAAA,MAErD;AACE,oBAAY,GAAG,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,MAAI,cAAc,EAAE,GAAG;AACrB,YAAQ,GAAG,MAAM;AAAA;AAAA,MAEf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA;AAAA;AAAA,MAGf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AACb,eAAO,EAAC,QAAQ,+BAAiB,OAAO,QAAQ,GAAE;AAAA;AAAA,MAGpD,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AACb,eAAO,EAAC,QAAQ,sBAAsB,QAAQ,GAAE;AAAA;AAAA,MAGlD,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AACb,eAAO;AAAA,UACL,QAAQ,+BAAiB;AAAA,UACzB,QAAQ;AAAA,QACV;AAAA;AAAA,MAGF,KAAK,wBAAU;AAAA,MACf,KAAK,wBAAU;AACb,eAAO,EAAC,QAAQ,sBAAsB,QAAQ,GAAE;AAAA,MAElD;AACE,oBAAY,GAAG,IAAI;AAAA,IACvB;AAAA,EACF;AAIA,SAAO;AAAA,IACL,QAAQ,+BAAiB;AAAA,IACzB,QAAQ,IAAI,YAAY;AAAA,MACtB,MAAM,+BAAgB;AAAA,MACtB,SACE,iCACC,cAAc,QACX,GAAG,UACH,OAAO,OAAO,WACZ,KACA,OAAO,MAAM,eAAe;AAAA,IACtC,CAAC;AAAA,EACH;AACF;;;AC5NA;AAAA;AAAA;AAAA,mCAAAC;AAAA,EAAA,2BAAAC;AAAA;AAKO,IAAM,iBAAiB;AAOvB,IAAMA,uBAAsB;AAO5B,IAAMD,6BAA4B;;;ACnBzC,OAA0C;AAC1C,SAAuB,YAAAE,kBAAe;;;ACDtC,SAAQ,YAAW;AACnB,SAAQ,kBAAAC,uBAAiC;AACzC,SAAQ,YAAAC,iBAAe;;;ACFvB,SAAQ,YAAAC,iBAAe;AAOhB,SAAS,6BACd,KACA,kBACA,QAC2B;AAC3B,SAAO,MACH,IAAI,8BAA8B,KAAK,kBAAkB,MAAM,IAC/D,IAAI,+BAA+B;AACzC;AAQA,IAAM,gCAAN,MAAyE;AAAA,EAC9D;AAAA,EACA;AAAA,EACT,aAAgD;AAAA;AAAA;AAAA;AAAA,EAKhD;AAAA,EAES,YAAY,oBAAI,IAGtB;AAAA,EAEH,YACE,KACA,kBACA,QACA;AACA,SAAK,OAAO;AACZ,SAAK,oBAAoB;AACzB,SAAK,kBAAkB,IAAI;AAG3B,SAAK,KAAK,iBAAiB,oBAAoB,KAAK,qBAAqB;AAAA,MACvE;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,sBAAsB,MAAM;AAC1B,QAAI,KAAK,KAAK,oBAAoB,WAAW;AAC3C,mBAAa,KAAK,UAAU;AAC5B,WAAK,oBAAoB,SAAS;AAAA,IACpC,OAAO;AACL,WAAK,aAAa,WAAW,MAAM;AACjC,aAAK,oBAAoB,QAAQ;AAAA,MACnC,GAAG,KAAK,iBAAiB;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,oBAAoB,iBAA0C;AAC5D,QAAI,oBAAoB,KAAK,iBAAiB;AAC5C;AAAA,IACF;AACA,SAAK,kBAAkB;AACvB,eAAW,SAAS,KAAK,WAAW;AAClC,YAAM,EAAC,SAAS,MAAK,IAAI;AACzB,UAAI,UAAU,iBAAiB;AAC7B,gBAAQ;AACR,aAAK,UAAU,OAAO,KAAK;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAAmC;AACjC,WAAO,KAAK,SAAS,SAAS;AAAA,EAChC;AAAA,EAEA,gBAAkC;AAChC,WAAO,KAAK,SAAS,QAAQ;AAAA,EAC/B;AAAA,EAEA,SAAS,OAAkD;AACzD,QAAI,KAAK,oBAAoB,OAAO;AAClC,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,UAAM,EAAC,SAAS,QAAO,IAAIA,UAAS;AACpC,SAAK,UAAU,IAAI,EAAC,SAAS,MAAK,CAAC;AACnC,WAAO;AAAA,EACT;AACF;AAEA,IAAM,kBAAkB,QAAQ,QAAQ;AACxC,IAAM,2BAA2B,IAAI,QAAQ,MAAM,MAAS;AAE5D,IAAM,iCAAN,MAA0E;AAAA,EAC/D,kBAA2C;AAAA,EACpD,iBAAmC;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,gBAAkC;AAChC,WAAO;AAAA,EACT;AACF;;;AC1GA,IAAM,6BAAN,MAAiC;AAAA,EACtB;AAAA,EACA;AAAA;AAAA;AAAA,EAIA,iBAAiB;AAAA,EAE1B,YAAY,KAAqB,YAAoC;AACnE,SAAK,MAAM;AACX,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,IAAI,eAAe;AAAA,EACjC;AAAA,EAEA,IAAI,aAAqB;AACvB,WAAO,KAAK,IAAI,eAAe;AAAA,EACjC;AACF;AAEO,IAAM,eAAN,cACG,2BAEV;AAAA,EACW,gBAAgB;AAAA,EAEzB,IAAI,gBAA+B;AACjC,WAAO,KAAK,IAAI;AAAA,EAClB;AACF;AAEO,IAAM,eAAN,cACG,2BAEV;AAAA,EACE,IAAI,gBAAwB;AAC1B,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,gBAAgB;AAClB;;;AC5CA,SAAQ,YAAAC,iBAAe;AAMhB,IAAM,eAAe;AACrB,IAAM,eAAe;AAcrB,IAAM,iBAAN,MAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8B1B,mBAAmBC,UAAe;AAAA;AAAA;AAAA;AAAA,EAKlC,sBAAsBA,UAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,gBAAgBA,UAAuC;AAAA,EAE9C;AAAA,EACT,UAAU;AAAA,EACV,eAAe,IAAI,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnC,eAAe;AAAA,EACN;AAAA,EACA;AAAA,EAET,YACE,IACA,UACA,mBACA;AACA,SAAK,MAAM;AACX,SAAK,YAAY;AACjB,SAAK,qBAAqB;AAC1B,SAAK,KAAK,IAAI;AAAA,EAChB;AAAA,EAEA,QAAc;AACZ,SAAK,UAAU;AACf,SAAK,aAAa,MAAM;AACxB,QAAI,KAAK,eAAe,GAAG;AACzB,WAAK,cAAc,QAAQ,EAAC,OAAO,WAAW,EAAC,CAAC;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAK,KAAqD;AAC9D,QAAI,KAAK,SAAS;AAChB,aAAO,EAAC,OAAO,WAAW,EAAC;AAAA,IAC7B;AACA,SAAK;AACL,SAAK,IAAI,QAAQ,QAAQ,GAAG;AAC5B,QAAI,KAAK;AACP,WAAK,oBAAoB,QAAQ;AAAA,IACnC,OAAO;AACL,YAAM,KAAK,oBAAoB,eAAe;AAAA,IAChD;AAEA,SAAK,iBAAiB,QAAQ;AAE9B,UAAM,SAAS,MAAM,KAAK,cAAc;AACxC,SAAK;AACL,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,cAA4B,CAAC;AAEnC,QAAI,kBAAkBA,UAAS;AAC/B,QAAI;AAGJ,QAAI,UAAU;AACd,UAAM,WAAW,KAAK;AACtB,UAAM,EAAC,MAAK,IAAI,KAAK;AACrB,QAAI,QAAQ;AAEZ,YAAQ,0BAA0B;AAElC,UAAM,iBAA+B,QACnC,QAAQ,KAAK,CAAC,KAAK,oBAAoB,SAAS,MAAM,EAAE,CAAC,CAAC;AAE5D,WAAO,CAAC,KAAK,SAAS;AACpB;AAAA,QACE,uBAAuB,WAAW,IAC9B,sCACA;AAAA,MACN;AAGA,YAAM,QAAQ,CAAC,KAAK,iBAAiB,OAAO;AAC5C,YAAMC,KAAI,SAAS;AACnB,UAAIA,OAAM,MAAM;AAEd,cAAM,KAAK,MAAMA,IAAG,KAAK,aAAa,MAAM,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC,CAAC;AAAA,MAC/D;AACA,YAAM,QAAQ,KAAK,KAAK;AACxB,UAAI,KAAK,QAAS;AAElB,cAAQ,sBAAsB;AAC9B,YAAM,eAAe,SAAS,aAAa;AAC3C,UAAI,KAAK,QAAS;AAClB,cAAQ,WAAW;AAGnB,WAAK,mBAAmBD,UAAS;AAEjC,UAAI,WAAW,SAAS,gBAAgB;AACtC,gBAAQ,2DAA2D;AACnE,cAAM,KAAK,8BAA8B;AACzC,YAAI,KAAK,QAAS;AAClB,gBAAQ,aAAa;AAAA,MACvB;AAIA,UAAI,UAAU,KAAK,uBAAuB,WAAW,GAAG;AACtD,gBAAQ,+BAA+B,OAAO,UAAU,WAAW;AACnE;AAAA,UACE,uBAAuB,WAAW,IAC9B,0CACA,2CACE,UACA;AAAA,UACN;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AAKL,gBAAQ;AAAA,MACV;AAEA,YAAM,eAAe,KAAK;AAAA,QACxB,SAAS;AAAA,QACT,KAAK,IAAI,SAAS,YAAY,KAAK;AAAA,MACrC;AACA,UAAI,iBAAiB,QAAW;AAC9B,cAAM,oBAAoB,KAAK,IAAI,IAAI;AACvC,YAAI,eAAe,mBAAmB;AACpC,gBAAM,QAAQ,KAAK;AAAA,YACjB,eAAe,eAAe,iBAAiB;AAAA,YAC/C,gBAAgB;AAAA,UAClB,CAAC;AACD,cAAI,KAAK,QAAS;AAAA,QACpB;AAAA,MACF;AAEA;AACA,YAAM,YAAY;AAChB,cAAM,QAAQ,KAAK,IAAI;AACvB,YAAI;AACJ,YAAI;AACJ,YAAI;AACF,yBAAe;AACf,kBAAQ,iBAAiB;AACzB,eAAK,sBAAsBA,UAAS;AACpC,eAAK,MAAM,SAAS,WAAW;AAC/B,kBAAQ,iBAAiB,EAAE;AAAA,QAC7B,SAAS,GAAG;AACV,kBAAQ,eAAe,CAAC;AACxB,kBAAQ;AACR,eAAK;AAAA,QACP;AACA,YAAI,KAAK,SAAS;AAChB,kBAAQ,yBAAyB;AACjC;AAAA,QACF;AACA,gBAAQ,gBAAgB,EAAC,UAAU,KAAK,IAAI,IAAI,OAAO,GAAE,CAAC;AAC1D,oBAAY,KAAK,EAAC,UAAU,KAAK,IAAI,IAAI,OAAO,GAAE,CAAC;AACnD,YAAI,UAAU,WAAW,GAAG;AAC1B,0BAAgB,QAAQ;AACxB,4BAAkBA,UAAS;AAAA,QAC7B;AACA;AACA,aAAK,qBAAqB;AAC1B,cAAM,eAAe,KAAK;AAC1B,aAAK,gBAAgBA,UAAS;AAC9B,YAAI,OAAO;AACT,uBAAa,QAAQ,EAAC,MAAK,CAAC;AAAA,QAC9B,OAAO;AACL,uBAAa,QAAQ,MAAS;AAAA,QAChC;AACA,YAAI,CAAC,IAAI;AAEP,eAAK,iBAAiB,QAAQ;AAAA,QAChC;AAAA,MACF,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAEA,4BAAsD;AAAA,EAEtD,uBAAuB;AACrB,QAAI,KAAK,2BAA2B;AAClC,YAAM,UAAU,KAAK;AACrB,WAAK,4BAA4B;AACjC,cAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,gCAAgC;AAC9B,UAAM,EAAC,SAAS,QAAO,IAAIA,UAAS;AACpC,SAAK,4BAA4B;AACjC,WAAO;AAAA,EACT;AACF;AAGA,IAAM,0BAA0B;AAEhC,SAAS,aAAa;AACpB,SAAO,IAAI,MAAM,QAAQ;AAC3B;AAMA,SAAS,+BACP,OACA,UACA,aACQ;AACR,QAAM,EAAC,OAAM,IAAI;AACjB,MAAI,WAAW,GAAG;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,EAAC,GAAE,IAAI,YAAY,YAAY,SAAS,CAAC;AAC/C,QAAM,EAAC,gBAAgB,WAAU,IAAI;AAErC,MAAI,CAAC,IAAI;AACP,WAAO,UAAU,IAAI,aAAa,QAAQ;AAAA,EAC5C;AAEA,MAAI,SAAS,GAAG;AAEd,UAAM,WAAuB,YAAY,YAAY,SAAS,CAAC;AAG/D,WAAO,YAAY,SAAS,yBAAyB;AACnD,kBAAY,MAAM;AAAA,IACpB;AAEA,QAAI,MAAM,CAAC,SAAS,IAAI;AAEtB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,MAAM;AAAA,IACV,YAAY,OAAO,CAAC,EAAC,IAAAE,IAAE,MAAMA,GAAE,EAAE,IAAI,CAAC,EAAC,SAAQ,MAAM,QAAQ;AAAA,EAC/D;AAEA,SAAQ,MAAM,iBAAkB;AAClC;AAEA,SAAS,OAAO,QAAkB;AAChC,SAAO,KAAK;AACZ,QAAM,EAAC,OAAM,IAAI;AACjB,QAAM,OAAO,UAAU;AACvB,MAAI,SAAS,MAAM,GAAG;AACpB,WAAO,OAAO,IAAI;AAAA,EACpB;AACA,UAAQ,OAAO,OAAO,CAAC,IAAI,OAAO,IAAI,KAAK;AAC7C;AAEA,SAAS,uBAAuB,aAA2B;AACzD,SAAO,YAAY,SAAS,KAAK,CAAC,YAAY,YAAY,SAAS,CAAC,EAAE;AACxE;AAEA,SAAS,UAAU,aAA2B;AAC5C,SACE,YAAY,SAAS,KACrB,CAAC,YAAY,YAAY,SAAS,CAAC,EAAE,MACrC,YAAY,YAAY,SAAS,CAAC,EAAE;AAExC;;;AClVA,SAAQ,UAAAC,eAAa;AAyDd,IAAM,YAAN,MAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsB7B,UAAU,IAAIC,QAAO;AAAA,EACrB,SAAS,oBAAI,IAAkB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGU,iBAAiB,oBAAI,IAAiB;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqDA,aAAa,oBAAI,IAAkB;AAAA,EACnC,QAAQ,oBAAI,IAA2B;AAAA,EAE1D,YACE,aACA,sBACA,aACA,iBACA,iBAA2C,gBAC3C;AACA,SAAK,qBAAqB,IAAI;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,SAAK,eAAe;AACpB,SAAK,eAAe;AACpB,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,MAAM,KAAK,YAAsC;AAC/C,UAAM,UAAU,MAAM,KAAK,QAAQ,KAAK;AACxC,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAA4B;AAChC,UAAM,UAAU,MAAM,KAAK,QAAQ,MAAM;AACzC,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,QAAuB;AACrB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,WAA0B;AACjC,WACE,KAAK,mBAAmB,sBAAsB,SAAS,MAAM;AAAA,EAEjE;AAAA,EAEA,yCACE,IACY;AACZ,WAAO,KAAK,mBAAmB,8BAA8B,EAAE;AAAA,EACjE;AACF;AAEO,IAAM,WAAN,MAA+B;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACnB,cAAyC;AAAA,EAChC;AAAA,EACT,UAAU;AAAA,EACD;AAAA,EACA;AAAA,EAET,YACE,OACA,eACA,mBACA,aACA,SACA,iBAKA,YACA;AACA,SAAK,SAAS;AACd,SAAK,iBAAiB;AACtB,SAAK,qBAAqB;AAC1B,SAAK,eAAe;AACpB,SAAK,WAAW;AAChB,SAAK,kBAAkB;AACvB,SAAK,cACH,eAAe,SAAY,QAAQ,QAAQ,UAAU,IAAI;AAC3D,SAAK,2BAA2B,eAAe;AAAA,EACjD;AAAA,EAEA,mBAAmB,MAAqB;AACtC,WAAO,KAAK,eAAe,IAAI,IAAI;AAAA,EACrC;AAAA,EAEA,MAAM,SAAS,MAA8B;AAC3C,WAAQ,MAAM,KAAK,SAAS,IAAI,MAAO;AAAA,EACzC;AAAA,EAEA,MAAM,SAAS,MAAwC;AACrD,UAAM,eAAe,KAAK,eAAe,IAAI,IAAI;AACjD,QAAI,iBAAiB,QAAW;AAC9B,aAAO;AAAA,IACT;AACA,QAAI,QAAQ,KAAK,mBAAmB,IAAI,IAAI;AAC5C,QAAI,UAAU,QAAW;AACvB,cAAQ,OAAO,MAAM,KAAK,eAAe,GAAG,SAAS,IAAI;AACzD,UAAI,UAAU,QAAW;AACvB,aAAK,mBAAmB,IAAI,KAAK;AAAA,MACnC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,MAA4B;AACvC,WAAO,aAAa,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,QAAQ,MAAyC;AAC/C,WAAO,QAAQ,QAAQ,KAAK,OAAO,IAAI,IAAI,CAAC;AAAA,EAC9C;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,SAAS;AACjB,WAAK,SAAS;AACd,UAAI,CAAC,KAAK,0BAA0B;AAClC,aAAK,aACD,KAAK,UAAQ,KAAK,QAAQ,CAAC,EAG5B,MAAM,OAAK;AAAA,QAAC,CAAC;AAAA,MAClB;AACA,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEU,iBAAgC;AACxC,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,cAAc,KAAK,aAAa,KAAK;AAAA,IAC5C;AACA,WAAO,KAAK;AAAA,EACd;AACF;AAEO,IAAM,YAAN,cACG,SAEV;AAAA,EACW;AAAA,EACA;AAAA,EACA;AAAA,EACU,sBAAsB,oBAAI,IAAwB;AAAA,EAClD,wBAAwB,oBAAI,IAAiB;AAAA,EAC7C,uBAAuB,oBAAI,IAG5C;AAAA,EACO,iBAAiB,oBAAI,IAAU;AAAA,EAExC,YACE,OACA,eACA,mBACA,aACA,WACA,MACA,SACA,aACA,iBACA;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,cAAc,CAAI,MAAS,SAAyB;AAClD,UAAM,QAAQ,YAAY,MAAM,MAAM,KAAK,YAAY;AACvD,SAAK,eAAe,IAAI,MAAM,IAAI;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,SAAY,GAAa,MAA8B;AACrD,UAAM,EAAC,MAAM,KAAI,IAAI;AACrB,SAAK,gBAAgB,IAAI;AACzB,QAAI,KAAK,SAAS,GAAG;AACnB,iBAAW,KAAK,MAAM;AACpB,aAAK,gBAAgB,CAAC;AAAA,MACxB;AAAA,IACF;AACA,QAAI,KAAK,eAAe,IAAI,IAAI,KAAK,KAAK,mBAAmB,IAAI,GAAG;AAClE,WAAK,sBAAsB,IAAI,MAAM,CAAC;AAAA,IACxC,OAAO;AACL,WAAK,qBAAqB,IAAI,MAAM,EAAC,OAAO,GAAG,MAAM,QAAQ,GAAE,CAAC;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,MAAc,MAA2B;AACrD,UAAM,KAAK,SAAS,MAAM,IAAI;AAAA,EAChC;AAAA,EAEA,MAAM,WAAW,MAA6B;AAC5C,UAAM,KAAK,SAAS,MAAM,MAAS;AAAA,EACrC;AAAA,EAEA,MAAM,SAAS,MAAc,MAAuC;AAClE,UAAM,UAAU,MAAM,KAAK,QAAQ,IAAI;AACvC,UAAM,IAAI,KAAK,oBAAoB,IAAI,IAAI;AAC3C,QAAI,MAAM,QAAW;AACnB,WAAK,oBAAoB,IAAI,MAAM,EAAC,KAAK,MAAM,KAAK,QAAO,CAAC;AAAA,IAC9D,OAAO;AAEL,QAAE,MAAM;AAAA,IACV;AAAA,EACF;AAAA,EAES,mBAAmB,MAAqB;AAC/C,WACE,KAAK,sBAAsB,IAAI,IAAI,KAAK,MAAM,mBAAmB,IAAI;AAAA,EAEzE;AAAA,EAEA,MAAe,SAAS,MAAwC;AAC9D,UAAM,sBAAsB,KAAK,sBAAsB,IAAI,IAAI;AAC/D,QAAI,wBAAwB,QAAW;AACrC,aAAO;AAAA,IACT;AACA,UAAM,eAAe,KAAK,eAAe,IAAI,IAAI;AACjD,QAAI,iBAAiB,QAAW;AAC9B,aAAO;AAAA,IACT;AAIA,UAAM,qBAAqB,KAAK,qBAAqB,IAAI,IAAI;AAC7D,QAAI,uBAAuB,QAAW;AACpC,aAAO,mBAAmB;AAAA,IAC5B;AACA,QAAI,QAAQ,KAAK,mBAAmB,IAAI,IAAI;AAC5C,QAAI,UAAU,QAAW;AACvB,cAAQ,OAAO,MAAM,KAAK,eAAe,GAAG,SAAS,IAAI;AACzD,UAAI,UAAU,QAAW;AACvB,aAAK,qBAAqB,IAAI,MAAM,MAAM,EAAC,OAAO,MAAM,GAAE,CAAC;AAAA,MAC7D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAES,QAAQ,MAAyC;AACxD,UAAM,aAAa,KAAK,oBAAoB,IAAI,IAAI;AACpD,QAAI,YAAY;AACd,aAAO,QAAQ,QAAQ,WAAW,GAAG;AAAA,IACvC;AACA,WAAO,MAAM,QAAQ,IAAI;AAAA,EAC3B;AAAA,EAEA,MAAM,SAAwB;AAC5B,UAAM,gBAAgB,IAAI;AAAA,MACxB;AAAA,QACE,KAAK,sBAAsB,KAAK;AAAA,QAChC,KAAK,qBAAqB,KAAK;AAAA,MACjC;AAAA,IACF;AACA,UAAM,kBAAkB,MAAM;AAAA,MAC5B,KAAK,oBAAoB,OAAO;AAAA,MAChC;AAAA,MACA;AAAA,IACF;AAEA,eAAW,CAAC,MAAM,KAAK,KAAK,iBAAiB;AAC3C,UAAI,KAAK,mBAAmB,IAAI,GAAG;AACjC,YAAI,UAAU,GAAG;AACf,eAAK,WAAW,OAAO,IAAI;AAC3B,eAAK,eAAe,OAAO,IAAI;AAC/B,eAAK,MAAM,OAAO,IAAI;AAAA,QACxB,OAAO;AACL,eAAK,WAAW,IAAI,MAAM,KAAK;AAC/B,gBAAM,QAAQ,KAAK,sBAAsB,IAAI,IAAI;AACjD,cAAI,OAAO;AACT,iBAAK,MAAM,IAAI,MAAM,MAAM,IAAI;AAC/B,iBAAK,eAAe,IAAI,MAAM,KAAK;AAAA,UACrC;AAAA,QACF;AACA,wBAAgB,OAAO,IAAI;AAAA,MAC7B;AAAA,IACF;AAEA,SAAK,mBAAmB;AAAA,MACtB,KAAK;AAAA,MACL;AAAA,IACF;AAEA,eAAW,CAAC,MAAM,UAAU,KAAK,KAAK,qBAAqB;AACzD,UAAI,WAAW,KAAK;AAClB,aAAK,OAAO,IAAI,MAAM,WAAW,GAAG;AAAA,MACtC,OAAO;AACL,aAAK,OAAO,OAAO,IAAI;AAAA,MACzB;AAAA,IACF;AAEA,SAAK,sBAAsB,MAAM;AACjC,SAAK,qBAAqB,MAAM;AAChC,SAAK,oBAAoB,MAAM;AAC/B,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,YAAY,MAAgC;AAC1C,WAAO,KAAK,WAAW,IAAI,IAAI;AAAA,EACjC;AAAA,EAEA,QAAQ,MAAyC;AAC/C,UAAM,sBAAsB,KAAK,sBAAsB,IAAI,IAAI;AAC/D,QAAI,qBAAqB;AACvB,aAAO,oBAAoB;AAAA,IAC7B;AACA,UAAM,eAAe,KAAK,eAAe,IAAI,IAAI;AACjD,QAAI,cAAc;AAChB,aAAO,aAAa;AAAA,IACtB;AACA,UAAM,qBAAqB,KAAK,qBAAqB,IAAI,IAAI;AAC7D,QAAI,uBAAuB,QAAW;AACpC,aAAO,mBAAmB,MAAM;AAAA,IAClC;AACA,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,eAAe,MAAqB;AAClC,WAAO,KAAK,MAAM,IAAI,IAAI;AAAA,EAC5B;AAAA,EAEA,gBAAgB,aAAoC;AAClD,UAAM,gBAAgB,CAAC;AACvB,eAAW,aAAa,aAAa;AACnC,YAAM,QAAQ,KAAK,eAAe,IAAI,SAAS;AAC/C,UAAI,OAAO;AACT,aAAK,eAAe,OAAO,SAAS;AACpC,sBAAc,KAAK,KAAK;AAAA,MAC1B;AAAA,IACF;AACA,SAAK,mBAAmB,UAAU,aAAa;AAAA,EACjD;AACF;AAOA,IAAM,cAAN,MAAkB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,QAAQ;AAAA,EACR,6BAA6B;AAAA,EACpB,oBAA4B,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,eAAe,oBAAI,IAAsB;AAAA,EAElD,YACE,gBACA,gBACA,WACA,MACA;AACA,SAAK,kBAAkB;AACvB,SAAK,kBAAkB;AACvB,SAAK,aAAa;AAClB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,MAA+B;AACjC,UAAM,aAAa,KAAK,aAAa,IAAI,IAAI;AAC7C,QAAI,YAAY;AAEd,WAAK,aAAa,OAAO,IAAI;AAC7B,WAAK,aAAa,IAAI,MAAM,UAAU;AAAA,IACxC;AACA,WAAO,YAAY;AAAA,EACrB;AAAA,EAEA,sBAAsB,MAA+B;AACnD,WAAO,KAAK,aAAa,IAAI,IAAI,GAAG;AAAA,EACtC;AAAA,EAEA,IAAI,OAAoB;AACtB,UAAM,EAAC,KAAI,IAAI;AAGf,UAAM,gBAAgB,KAAK,aAAa,IAAI,IAAI;AAChD,QAAI,eAAe;AACjB,WAAK,aAAa,OAAO,IAAI;AAC7B,WAAK,aAAa,IAAI,MAAM,aAAa;AACzC;AAAA,IACF;AAGA,UAAM,WAAW,KAAK,WAAW,IAAI,IAAI;AACzC,QAAI,aAAa,UAAa,WAAW,GAAG;AAC1C;AAAA,IACF;AACA,QAAI,CAAC,KAAK,YAAY,KAAK,GAAG;AAC5B;AAAA,IACF;AACA,QAAI,CAAC,KAAK,MAAM,IAAI,IAAI,GAAG;AACzB,iBAAW,WAAW,MAAM,MAAM;AAChC,aAAK,WAAW,IAAI,UAAU,KAAK,WAAW,IAAI,OAAO,KAAK,KAAK,CAAC;AAAA,MACtE;AACA,WAAK,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,IACjC;AAEA,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,wBAAwB;AACtB,QAAI,KAAK,4BAA4B;AACnC;AAAA,IACF;AACA,eAAW,SAAS,KAAK,aAAa,OAAO,GAAG;AAC9C,UAAI,KAAK,SAAS,KAAK,iBAAiB;AACtC;AAAA,MACF;AACA,WAAK,OAAO,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,YAAY,OAAc,MAAwB;AAChD,UAAM,YAAY,QAAQ,KAAK,gBAAgB,KAAK;AACpD,QAAI,YAAY,KAAK,iBAAiB;AAIpC,aAAO;AAAA,IACT;AACA,SAAK,SAAS;AACd,SAAK,aAAa,IAAI,MAAM,MAAM,EAAC,OAAO,MAAM,UAAS,CAAC;AAC1D,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,YAA8B;AACnC,UAAM,EAAC,KAAI,IAAI,WAAW;AAC1B,SAAK,SAAS,WAAW;AACzB,SAAK,aAAa,OAAO,IAAI;AAAA,EAC/B;AAAA,EAEA,mBAAmB,MAAkB;AACnC,SAAK,WAAW,OAAO,IAAI;AAC3B,SAAK,MAAM,OAAO,IAAI;AACtB,UAAM,aAAa,KAAK,aAAa,IAAI,IAAI;AAC7C,QAAI,YAAY;AACd,WAAK,SAAS,WAAW;AACzB,WAAK,aAAa,OAAO,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,gBACE,aACA,iBACM;AACN,eAAW,CAAC,MAAM,KAAK,KAAK,iBAAiB;AAC3C,UAAI,UAAU,GAAG;AACf,YAAI,CAAC,KAAK,4BAA4B;AACpC,eAAK,mBAAmB,IAAI;AAAA,QAC9B,OAAO;AACL,eAAK,WAAW,IAAI,MAAM,CAAC;AAC3B,eAAK,kBAAkB,KAAK,IAAI;AAAA,QAClC;AAAA,MACF,OAAO;AACL,aAAK,WAAW,IAAI,MAAM,KAAK;AAC/B,cAAM,eAAe,YAAY,IAAI,IAAI;AACzC,YAAI,cAAc;AAChB,gBAAM,EAAC,OAAO,KAAI,IAAI;AACtB,gBAAM,gBAAgB,KAAK,aAAa,IAAI,IAAI;AAChD,cAAI,eAAe;AAIjB,iBAAK,aAAa,OAAO,IAAI;AAC7B,iBAAK,aAAa,IAAI,MAAM,aAAa;AAAA,UAC3C,OAAO;AACL,iBAAK,YAAY,OAAO,SAAS,KAAK,OAAO,MAAS;AACtD,iBAAK,MAAM,IAAI,MAAM,MAAM,IAAI;AAAA,UACjC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,UAAU,QAAyB;AACjC,eAAW,SAAS,QAAQ;AAC1B,WAAK,YAAY,KAAK;AAAA,IACxB;AACA,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,MAAM,8BACJ,IACY;AACZ,SAAK,6BAA6B;AAClC,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,UAAE;AACA,WAAK,6BAA6B;AAClC,iBAAW,QAAQ,KAAK,mBAAmB;AACzC,YAAI,KAAK,WAAW,IAAI,IAAI,MAAM,GAAG;AACnC,eAAK,mBAAmB,IAAI;AAAA,QAC9B;AAAA,MACF;AACA,WAAK,sBAAsB;AAAA,IAC7B;AAAA,EACF;AACF;;;ACzqBA,SAAQ,eAAAC,oBAAkB;;;ACD1B,SAAQ,mBAAkB;;;AC6DnB,SAAS,mBACd,SAC6B;AAC7B,SAAQ,QAA6B,cAAc;AACrD;AAwBO,SAAS,mCACd,UAC4D;AAC5D,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO,CAAC,QAAQ;AAAA,EAClB;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,SAAsC;AACpE,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC;AAAA,EACV;AACA,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,OAAO;AACjB,KAAC,EAAC,KAAK,UAAS,IAAI,QAAQ;AAC5B,QAAK,QAA2B,WAAW;AACzC,UAAI,OAAO,QAAQ,UAAU;AAC3B,oBAAY;AAAA,MACd,OAAO;AACL,oBAAY,IAAI,CAAC;AACjB,kBAAU,IAAI,CAAC;AAAA,MACjB;AAAA,IACF,OAAO;AACL,gBAAU;AAAA,IACZ;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,mBAAmB;AAAA,IACnB,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,OAAO,QAAQ;AAAA,IACf,WAAY,QAA2B;AAAA,EACzC;AACF;;;ADrGO,IAAM,iBAAN,MAEP;AAAA,EACW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,MACA,SACA,mBACA,YACA;AACA,SAAK,QAAQ;AACb,SAAK,WAAW;AAChB,SAAK,qBAAqB;AAC1B,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA,EAGA,CAAC,OAAO,aAAa,IAAqC;AACxD,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA,EAGA,SAA0C;AACxC,WAAO,IAAI;AAAA,MACT,KAAK,aAAa,OAAK,EAAE,CAAC,CAAM;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAqE;AAEnE,WAAO,IAAI;AAAA,MACT,KAAK,aAAgB,OAAK,EAAE,CAAC,CAAM;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAEE;AAGA,WAAO,IAAI;AAAA,MACT,KAAK,aAAoB,OAAK,CAAC,EAAE,CAAC,GAAU,EAAE,CAAC,CAAM,CAAC;AAAA,IACxD;AAAA,EACF;AAAA;AAAA,EAGA,UAAwB;AACtB,WAAO,KAAK,OAAO,EAAE,QAAQ;AAAA,EAC/B;AAAA,EAEA,aAAgB,SAAwD;AACtE,WAAO;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AACF;AA0CA,IAAM,0CAAN,MAEA;AAAA,EACW;AAAA,EAET,YAAY,IAA8B;AACxC,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,OAAO;AACL,WAAO,KAAK,IAAI,KAAK;AAAA,EACvB;AAAA,EAEA,CAAC,OAAO,aAAa,IAA8B;AACjD,WAAO,KAAK,IAAI,OAAO,aAAa,EAAE;AAAA,EACxC;AAAA,EAEA,UAAwB;AACtB,WAAO,qBAAqB,KAAK,GAAG;AAAA,EACtC;AACF;AAEA,gBAAgB,aACd,SACA,MACA,SACA,QACA,YAC8B;AAC9B,gBAAc,MAAM;AAEpB,MAAI,EAAC,QAAQ,SAAQ,IAAI;AACzB,QAAM,EAAC,SAAS,GAAE,IAAI;AACtB,MAAI,YAAY,QAAQ,OAAO;AAE/B,QAAM,cAAc,mBAAmB,OAAO;AAG9C,mBAAiB,SAAS,MAAM;AAC9B,UAAM,MAAM,MAAM,CAAC;AACnB,UAAM,aAAqB,cAAc,IAAI,CAAC,IAAK;AACnD,QAAI,CAAC,WAAW,WAAW,MAAM,GAAG;AAClC;AAAA,IACF;AAEA,QAAI,WAAW;AACb,kBAAY;AACZ,UAAI,aAAa;AAEf,YAAI,oBAAoB,KAAiB,QAAQ,MAAO,GAAG,GAAG;AAC5D;AAAA,QACF;AAAA,MACF,OAAO;AAEL,YAAI,uBAAuB,KAAe,QAAQ,MAAO,GAAG,GAAG;AAC7D;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK;AAEnB,QAAI,EAAE,UAAU,GAAG;AAEjB,UAAI,CAAC,aAAa;AAChB,mBAAW,GAAa;AAAA,MAC1B;AACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,oBACP,KACA,UACS;AACT,QAAM,CAAC,mBAAmB,eAAe,IACvC,mCAAmC,QAAQ;AAC7C,QAAM,CAAC,cAAc,UAAU,IAAI,mCAAmC,GAAG;AACzE,MAAI,iBAAiB,mBAAmB;AACtC,WAAO;AAAA,EACT;AACA,MAAI,oBAAoB,QAAW;AACjC,WAAO;AAAA,EACT;AACA,SAAO,eAAe;AACxB;AAEA,SAAS,uBAAuB,KAAa,UAA2B;AACtE,SAAO,QAAQ;AACjB;AA6HO,SAAS,4BAA4B,SAAmC;AAC7E,QAAM,EAAC,QAAQ,MAAK,IAAI;AACxB,MAAI,UAAU;AACd,MAAI,WAAW,QAAW;AACxB,cAAU,mBAAmB,QAAQ,MAAS;AAAA,EAChD;AACA,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,EAAC,IAAG,IAAI;AACd,QAAM,CAAC,WAAW,OAAO,IAAI,mCAAmC,GAAG;AACnE,QAAM,WAAW,mBAAmB,WAAW,OAAO;AAEtD,MAAI,YAAY,UAAU,OAAO,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ADjRA,IAAI,uBAAuB;AAEpB,IAAM,sBAAN,MAAqD;AAAA,EACjD;AAAA,EACA;AAAA,EACU;AAAA;AAAA;AAAA;AAAA,EAKV;AAAA;AAAA,EAEA;AAAA,EAET,YACE,UACA,QACA,IACA,UAAU,uBACV;AACA,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,MAAM,GACR,YAAY,OAAO,EACnB,YAAY,QAAQ,sBAAsB;AAC7C,SAAK,cAAc;AACnB,SAAK,WAAW;AAAA,EAClB;AAAA,EAGA,IAAyB,KAAmD;AAC1E,WACE,eAAe,KAAK,IAAI,KACvB,KAAK,KAAK,IAAI,GAAG;AAAA,EAEtB;AAAA;AAAA,EAGA,MAAM,IAAI,KAA+B;AACvC,kBAAc,KAAK,IAAI;AACvB,WAAO,KAAK,KAAK,IAAI,GAAG;AAAA,EAC1B;AAAA;AAAA,EAGA,MAAM,UAA4B;AAChC,kBAAc,KAAK,IAAI;AACvB,WAAO,KAAK,KAAK,QAAQ;AAAA,EAC3B;AAAA,EAgBA,KACE,SACkD;AAClD,WAAO,KAAK,SAAS,KAAK,MAAM,IAAI;AAAA,EACtC;AACF;AAEA,SAAS,KAAK,GAAkB;AAEhC;AAEA,SAAS,KACP,SACA,QACA,YAC+C;AAC/C,QAAM,OAAO,gBAA4B,QAAQ,OAAO;AACxD,SAAO;AAAA,IACL;AAAA,IACA,WAAY,CAAC;AAAA,IACb;AAAA,IACA;AAAA,EACF;AACF;AAIO,IAAM,iCAAN,MAAgE;AAAA,EAC5D,QAAqB,oBAAI,IAAI;AAAA,EAC7B,SAAiC,CAAC;AAAA,EAClC;AAAA,EAET,YAAY,IAAyB;AACnC,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,IAAI,cAAmC;AACrC,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,IAAI,WAAgC;AAClC,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,IAAI;AAAA,EAClB;AAAA,EAEA,UAA4B;AAE1B,SAAK,OAAO,KAAK,EAAC,SAAS,CAAC,EAAC,CAAC;AAC9B,WAAO,KAAK,IAAI,QAAQ;AAAA,EAC1B;AAAA,EAGA,IAAyB,KAAmD;AAC1E,SAAK,MAAM,IAAI,GAAG;AAClB,WAAO,KAAK,IAAI,IAAI,GAAG;AAAA,EACzB;AAAA,EAEA,IAAI,KAA+B;AACjC,SAAK,MAAM,IAAI,GAAG;AAClB,WAAO,KAAK,IAAI,IAAI,GAAG;AAAA,EACzB;AAAA,EAgBA,KACE,SACkD;AAClD,UAAM,WAAiC;AAAA,MACrC,SAAS,gBAAgB,OAAO;AAAA,MAChC,mBAAmB;AAAA,IACrB;AACA,SAAK,OAAO,KAAK,QAAQ;AACzB,WAAO,KAAK,SAAS,KAAK,IAAI,MAAM,uBAAqB;AACvD,eAAS,oBAAoB;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,OAA4B;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,QAAgC;AAClC,WAAO,KAAK;AAAA,EACd;AACF;AAsCO,IAAM,WAAW,OAAO;AAExB,IAAM,uBAAN,cACG,oBAEV;AAAA,EAGW;AAAA,EACA;AAAA,EACT,CAAU,QAAQ;AAAA,EAElB,YACE,UACA,YACA,QACA,OACA,SACA,IACA,UAAU,wBACV;AACA,UAAM,UAAU,SAAS,IAAI,OAAO;AACpC,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,QAAQ,IAAI;AAAA,EACnB;AAAA,EAEA,IAAI,KAAa,OAAyC;AACxD,WAAO,KAAK,IAAI,KAAK,KAAK;AAAA,EAC5B;AAAA,EAEA,MAAM,IAAI,KAAa,OAAyC;AAC9D,kBAAc,KAAK,IAAI;AACvB,UAAM,KAAK,KAAK,IAAI,KAAK,KAAK,KAAK,WAAW,KAAK,CAAC;AAAA,EACtD;AAAA,EAEA,IAAI,KAA+B;AACjC,WAAO,eAAe,KAAK,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,GAAG;AAAA,EACjE;AACF;AAeA,SAAS,gBACP,QACA,SAC4C;AAC5C,MAAI,WAAW,mBAAmB,OAAO,GAAG;AAC1C,WAAO,2BAA2B,QAAQ,OAAO;AAAA,EAGnD;AAEA,SAAO,OAAO,IAAI,KAAK,uBAAuB,OAAO,CAAC;AAGxD;AAEO,SAAS,uBACd,SACQ;AACR,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,QAAM,EAAC,SAAS,IAAI,MAAK,IAAI;AAC7B,MAAI,SAASC,aAAY,MAAM,KAAK,MAAM,GAAG;AAC3C,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAEA,SAAS,uCAIP,MACA,SACA,QACA,YAC+C;AAC/C,SAAO,IAAI,eAAe,MAAM,SAAS,QAAQ,UAAU;AAC7D;AAEA,gBAAgB,2BACd,QACA,SACiD;AACjD,QAAM,MAAM,OAAO,eAAe,QAAQ,SAAS;AACnD,mBAAiB,SAAS,IAAI,KAAK,4BAA4B,OAAO,CAAC,GAAG;AACxE,UAAM,CAAC,eAAe,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AAAA,EAC3C;AACF;;;AGjYA,eAAe,eACb,UACA,UACA,WACA,UACA,IACA,kBACA,eACAC,WACgB;AAChB,QAAM,YAAY,SAAS;AAC3B,QAAM,OAAO,UAAU;AACvB,MAAI,gBAAgB,SAAS,GAAG;AAC9B;AAAA,MACE,UAAU,aAAa;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACA,QAAM,mBAAmB,SAAS,IAAI;AACtC,MAAI,CAAC,kBAAkB;AASrB,OAAG,QAAQ,iCAAiC,IAAI,EAAE;AAAA,EACpD;AACA,QAAM,cACJ,qBACC,YAAY;AAAA,EAEb;AAEF,QAAM,OAAO,UAAU;AAEvB,QAAM,cAAc,MAAM,eAAe,WAAW,QAAQ;AAC5D,QAAM,iBAAiB,MAAM,YAAY;AAAA,IACvC;AAAA,IACA;AAAA,EACF;AACA,MAAI,mBAAmB,UAAU,YAAY;AAC3C,UAAM,IAAI;AAAA,MACR,uCAAuC,UAAU,UAAU,WAAW,cAAc,wBAAwB,gBAAgB,iBAAiB,IAAI;AAAA,IACnJ;AAAA,EACF;AAEA,MAAI,iBAA+B,MAAM;AACvC,wBAAoB,SAAS;AAAA,EAC/B;AAEA,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,MAAM;AAAA,IACf;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,EACF;AAEA,QAAM,KAAK,IAAI;AAAA,IACb;AAAA,IACA,MAAM,QAAQ,cAAc;AAAA,IAC5B;AAAA,IACAA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,YAAY,IAAI,IAAI;AAC1B,SAAO;AACT;AAEA,eAAsB,2BACpB,UACA,UACA,OACA,UACA,IAGA,kBACA,eACAA,WACuB;AACvB,QAAM,KAAK,MAAM;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACAA;AAAA,EACF;AACA,SAAO,GAAG,UAAU;AACtB;AAEA,eAAsB,wBACpB,UACA,UACA,OACA,UACA,UACA,IAGA,kBACA,eACAA,WACe;AACf,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACAA;AAAA,EACF;AACA,SAAO,QAAQ,OAAO,QAAQ;AAChC;;;ACzIO,SAAS,iBAAiB,KAA8C;AAC7E,iBAAe,OACb,aACA,WACuB;AACvB,UAAM,CAAC,UAAU,eAAe,IAAI,MAAM;AAAA,MACxC,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,UAAU;AACb,aAAO,EAAC,gBAAe;AAAA,IACzB;AAEA,UAAM,KAAmB;AAAA,MACvB;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,eAAS,MAAM,SAAS,KAAK;AAAA,IAC/B,QAAQ;AAEN,aAAO;AAAA,IACT;AAEA,QACE,8BAA8B,MAAM,KACpC,8BAA8B,MAAM,GACpC;AACA,SAAG,WAAW;AAAA,IAChB;AAEA,WAAO;AAAA,EACT;AAEA,iBAAe,IAAI,MAAM;AACzB,SAAO;AACT;AAEA,IAAM,iBAAiB,oBAAI,QAAQ;AAE5B,SAAS,gBAAgB,QAAyB;AACvD,SAAO,eAAe,IAAI,MAAM;AAClC;;;ACxDO,IAAM,yBAAyB;;;ACG/B,IAAM,cAAN,cAA0B,MAAM;AAAC;;;ACHjC,SAAS,QAAQ,GAAmB;AACzC,MAAI,aAAa,OAAO;AACtB,WAAO;AAAA,EACT;AACA,SAAO,IAAI,MAAM,OAAO,CAAC,CAAC;AAC5B;;;ACLO,IAAM,UAAU;AAChB,IAAM,OAAO;AACb,IAAM,iBAAiB;;;ACmB9B,eAAsB,MACpB,IACA,SACA,OACe;AACf,aAAW,KAAK,OAAO;AACrB,YAAQ,EAAE,IAAI;AAAA,MACZ,KAAK,OAAO;AACV,cAAM,SAAS,WAAW,EAAE,KAAK;AACjC,cAAM,QAAQ,IAAI,IAAI,EAAE,KAAK,MAAM;AACnC;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,cAAM,WAAW,MAAM,QAAQ,IAAI,EAAE,GAAG;AACxC,cAAM,UAGA,CAAC;AACP,cAAM,eAAe,CAAC,UAAiD;AACrE,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,gBACE,CAAC,EAAE,aACH,EAAE,UAAU,WAAW,KACvB,EAAE,UAAU,QAAQ,GAAG,IAAI,IAC3B;AACA,sBAAQ,KAAK,CAAC,KAAK,KAAK,CAAC;AAAA,YAC3B;AAAA,UACF;AAAA,QACF;AACA,YAAI,aAAa,QAAW;AAC1B,uBAAa,QAAQ;AACrB,uBAAa,QAAQ;AAAA,QACvB;AACA,YAAI,EAAE,OAAO;AACX,uBAAa,EAAE,KAAK;AAAA,QACtB;AACA,cAAM,SAAS,WAAW,OAAO,YAAY,OAAO,CAAC;AACrD,cAAM,QAAQ,IAAI,IAAI,EAAE,KAAK,MAAM;AAEnC;AAAA,MACF;AAAA,MACA,KAAK,OAAO;AACV,cAAM,WAAW,MAAM,QAAQ,IAAI,EAAE,GAAG;AACxC,YAAI,aAAa,QAAW;AAC1B;AAAA,QACF;AACA,cAAM,QAAQ,IAAI,IAAI,EAAE,GAAG;AAC3B;AAAA,MACF;AAAA,MACA,KAAK;AACH,cAAM,QAAQ,MAAM;AACpB;AAAA,IACJ;AAAA,EACF;AACF;;;ACvEO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKP;AAAA,EACA,YAAY,UAAkB;AAC5B,UAAM,gBAAgB;AACtB,SAAK,WAAW;AAAA,EAClB;AACF;;;ACfO,IAAM,iBAAiB;;;ACgDvB,IAAM,oBAAoB;AAkCjC,eAAsB,YACpB,WACA,UACA,eACA,eACA,QACA,WACA,OACA,eACA,IACA,mBAAmB,MACW;AAC9B,QAAM,aAAa,MAAM,SAAS,OAAO,OAAM,YAAW;AACxD,UAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,UAAM,eAAe,MAAM,qBAAqB,cAAc,OAAO;AACrE,UAAM,mBAAmB,aAAa;AACtC,2BAAuB,gBAAgB;AACvC,WAAO,iBAAiB;AAAA,EAC1B,CAAC;AAED,QAAM,UAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,aAAa;AAAA,IACb;AAAA,EACF;AAEA,QAAM,EAAC,UAAU,gBAAe,IAAI,MAAM;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,MAAI,CAAC,oBAAoB,gBAAgB,QAAQ,GAAG;AAClD,WAAO;AAAA,MACL;AAAA,MACA,cAAc;AAAA,MACd,UAAU;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,SAAS,MAAM;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,cAAc;AAAA,IACd,UACE,OAAO,SAAsC,UACzC,OAAO,WACP;AAAA,EACR;AACF;AAEA,eAAe,WACb,IACA,QACA,SACA,WACuB;AACvB,KAAG,QAAQ,kBAAkB;AAC7B,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,OAAO,SAAS,SAAS;AAC9C,OAAG;AAAA,MACD,WAAW,aAAa,WAAW,aAAa,QAAQ;AAAA,MACxD,KAAK,IAAI,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF,SAAS,GAAG;AACV,UAAM,IAAI,UAAU,QAAQ,CAAC,CAAC;AAAA,EAChC;AACA,MAAI;AACF,yBAAqB,YAAY;AACjC,WAAO;AAAA,EACT,SAAS,GAAG;AACV,UAAM,IAAI,YAAY,yBAAyB,QAAQ,CAAC,CAAC;AAAA,EAC3D;AACF;AAaA,SAAS,gBACP,MACA,eACA,mBACA;AACA,SAAO,YAAY,IAAI,IAAI,aAAa,4BAA4B,IAAI,IAAI,iBAAiB;AAC/F;AAEO,SAAS,qBACd,IACA,OACA,oBACA,UACA,UACA,eACmC;AAGnC,SAAO,0BAA0B,OAAO,OAAM,aAAY;AACxD,UAAM,UAAU;AAChB,UAAM,WAAW,MAAM,QAAQ,QAAQ,iBAAiB;AACxD,QAAI,aAAa,QAAW;AAC1B,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAM,eAAe,MAAM,qBAAqB,UAAU,OAAO;AACjE,UAAM,mBAAmB,aAAa;AACtC,2BAAuB,gBAAgB;AACvC,UAAM,aAAa,iBAAiB;AAOpC,QAAI,CAAC,UAAU,oBAAoB,UAAU,GAAG;AAC9C,SAAG;AAAA,QACD;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAmC;AAAA,MACrC;AAAA,IACF;AAGA,eAAW,CAACC,WAAU,UAAU,KAAK,OAAO;AAAA,MAC1C,SAAS;AAAA,IACX,GAAG;AACD,YAAM,iBAAiB,iBAAiB,gBAAgBA,SAAQ;AAChE,UAAI,mBAAmB,UAAa,aAAa,gBAAgB;AAC/D,cAAM,IAAI;AAAA,UACR;AAAA,YACE,GAAGA,SAAQ;AAAA,YACX,OAAO,UAAU;AAAA,YACjB,OAAO,cAAc;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,uBAAuB,WAAW,SAAS,MAAM;AACvD,QAAI,eAAe,sBAAsB,UAAU,IAAI,GAAG;AACxD,YAAM,IAAI;AAAA,QACR;AAAA,UACE;AAAA,UACA,KAAK,UAAU,oBAAoB;AAAA,UACnC,KAAK,UAAU,UAAU;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,UAAU,sBAAsB,UAAU,GAAG;AAC/C,UAAI,SAAS,MAAM,SAAS,GAAG;AAC7B,WAAG;AAAA,UACD,8BAA8B,KAAK;AAAA,YACjC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AACA,UAAI,OAAO,KAAK,SAAS,qBAAqB,EAAE,SAAS,GAAG;AAC1D,WAAG;AAAA,UACD,8BAA8B,KAAK;AAAA,YACjC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAmC;AAAA,MACrC;AAAA,IACF;AAEA,UAAM,UAAU,MAAM;AAAA,MACpB,aAAa,MAAM;AAAA,MACnB,EAAC,GAAG,iBAAiB,iBAAiB,GAAG,SAAS,sBAAqB;AAAA,MACvE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAY,MAAM,IAAI,SAAS,SAAS,KAAK;AAE7C,WAAO;AAAA,MACL,MAAmC;AAAA,MACnC,UAAU,MAAM,QAAQ,OAAO,cAAc;AAAA,IAC/C;AAAA,EACF,CAAC;AACH;AAEO,SAAS,aACd,OACA,IACA,kBACA,UACA,YACA,eAOC;AACD,SAAO,0BAA0B,OAAO,OAAM,aAAY;AACxD,UAAM,UAAU;AAEhB,UAAM,eAAe,MAAM,QAAQ,QAAQ,cAAc;AACzD,QAAI,iBAAiB,QAAW;AAC9B,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AACA,QAAI,iBAAiB,kBAAkB;AACrC,SAAG;AAAA,QACD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AAKA,UAAM,eAAe,MAAM,qBAAqB,cAAc,OAAO;AACrE,UAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,QAAI,iBAAiB,QAAW;AAC9B,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AACA,UAAM,eAAe,MAAM,qBAAqB,cAAc,OAAO;AAErE,UAAM,EAAC,KAAI,IAAI;AACf,UAAM,oBAAoB,KAAK;AAC/B,QAAI,iBAAiB,MAAM;AACzB,YAAM,IAAI,MAAM,6BAA6B;AAAA,IAC/C;AACA,QAAI,sBAAsB,aAAa,MAAM,MAAM;AACjD,YAAM,IAAI,MAAM,mBAAmB;AAAA,IACrC;AAIA,UAAM,WAAW,MAAM,eAAe,cAAc,OAAO;AAC3D,UAAM,UAAuB,CAAC;AAC9B,UAAMC,kBAAiB,MAAM,eAAiB,cAAc,OAAO;AACnE,eAAW,UAAUA,iBAAgB;AACnC,UAAI,MAAM;AACV,aAAO,kBAAkB,MAAM,CAAC;AAChC,YAAM,OAAO,KAAK;AAElB,UACG,MAAM,OAAO,cAAc,KAAK,OAAO,IACvC,MAAM,SAAS,cAAc,KAAK,OAAO,GAC1C;AAEA,gBAAQ,KAAK,MAAmB;AAAA,MAClC;AAAA,IACF;AAGA,YAAQ,QAAQ;AAIhB,UAAM,WAAW,IAAI,SAAS;AAG9B,QAAI,QAAQ,SAAS,GAAG;AACtB,aAAO;AAAA,QACL,UAAU;AAAA,QACV,aAAa;AAAA,QACb,UAAU;AAAA,QACV,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,QAKjB,OAAO;AAAA,MACT;AAAA,IACF;AAKA,UAAM,WAAW,MAAM,eAAe,cAAc,OAAO;AAC3D,QAAI,WAAW,mBAAmB,GAAG;AACnC,YAAM,cAAc,IAAI;AAAA,QACtB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX;AACA,YAAM,cAAc,IAAI;AAAA,QACtB;AAAA,QACA;AAAA,QACA,SAAS;AAAA,MACX;AACA,YAAM,YAAY,MAAM,KAAK,aAAa,WAAW;AACrD,eAAS,IAAI,IAAI,SAAS;AAC1B,YAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAGA,UAAM,QAAQ,IAAI;AAAA,MAChB,SAAS,QAAQ,mBAAmB,YAAY;AAAA,MAChD,SAAS,WAAW,cAAc;AAAA,IACpC,CAAC;AACD,UAAM,SAAS,OAAO;AAEtB,UAAM,kBAAkB;AAExB,QAAI,GAAG,OAAO;AACZ,YAAM,CAAC,mBAAmB,SAAS,IAAI;AAAA,QACrC;AAAA,QACA;AAAA,MACF;AACA,YAAM,CAAC,mBAAmB,SAAS,IAAI;AAAA,QACrC;AAAA,QACA;AAAA,MACF;AACA,SAAG;AAAA,QACD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,aAAa;AAAA,MACf;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU;AAAA,MACV,aAAa;AAAA,MACb,UAAU;AAAA,MACV,iBAAiB,CAAC;AAAA,MAClB,OAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;;;AC1bO,SAAS,mBAAmB,GAAuC;AACxE,eAAa,CAAC;AACd,wBAAsB,EAAE,eAAe;AACvC,MAAI,EAAE,aAAa,QAAW;AAC5B,uBAAmB,EAAE,QAAQ;AAAA,EAC/B;AACF;AAEA,SAAS,mBAAmB,GAAuC;AACjE,MAAI,8BAA8B,CAAC,GAAG;AACpC;AAAA,EACF;AACA,oCAAkC,CAAC;AACrC;AAqBO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAKP;AAAA,EACA,YAAY,UAAkB;AAC5B,UAAM,gBAAgB;AACtB,SAAK,WAAW;AAAA,EAClB;AACF;;;ACxCO,IAAM,oBAAoB;AAejC,IAAM,mBAAmD,eAAe;AAAA,EACtE,IAAW,sBAAO;AAAA,EAClB,MAAa,sBAAO;AAAA,EACpB,MAAM;AAAA,EACN,WAAkB,sBAAO;AAAA,EACzB,UAAU;AACZ,CAAC;AAoBD,IAAM,sBAA6B,sBAAO;AAAA,EACxC,aAAoB,uBAAQ,CAAC;AAAA,EAC7B,eAAsB,sBAAO;AAAA,EAC7B,WAAkB,sBAAO;AAAA,EACzB,eAAe;AAAA,EACf,WAAkB,qBAAM,gBAAgB;AAC1C,CAAC;AAqBD,SAAS,YAAY,IAAqC;AACxD,SAAO;AAAA,IACL,IAAI,GAAG;AAAA,IACP,MAAM,GAAG;AAAA,IACT,MAAM,GAAG;AAAA,IACT,WAAW,GAAG;AAAA,IACd,UAAU,GAAG;AAAA,EACf;AACF;AAEA,eAAsB,KACpB,WACA,OACA,IACA,WACA,eACA,WACA,QACA,eACA,aACmC;AAGnC,QAAM,UAAU,MAAM,SAAS,OAAO,OAAM,YAAW;AACrD,UAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,WAAO,eAAe,cAAc,OAAO;AAAA,EAE7C,CAAC;AAED,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAIA,UAAQ,QAAQ;AAEhB,SAAO,gBAAgB,iBAAiB;AAExC,QAAM,gBAAoC,CAAC;AAC3C,aAAW,UAAU,SAAS;AAC5B,QAAI,kBAAkB,MAAM,GAAG;AAC7B,oBAAc,KAAK,YAAY,OAAO,IAAI,CAAC;AAAA,IAC7C,OAAO;AACL,YAAM,IAAI,MAAM,mCAAmC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,aAAa;AACpB,QAAM,UAAyB;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb;AAAA,EACF;AAEA,KAAG,QAAQ,kBAAkB;AAC7B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,eAAe,MAAM,WAAW,QAAQ,SAAS,SAAS;AAChE,KAAG,QAAQ,wBAAwB,KAAK,IAAI,IAAI,WAAW,IAAI;AAC/D,SAAO;AACT;AAEA,eAAe,WACb,QACA,MACA,WACuB;AACvB,MAAI;AACJ,MAAI;AACF,mBAAe,MAAM,OAAO,MAAM,SAAS;AAAA,EAC7C,SAAS,GAAG;AACV,UAAM,IAAI,UAAU,QAAQ,CAAC,CAAC;AAAA,EAChC;AACA,MAAI;AACF,uBAAmB,YAAY;AAC/B,WAAO;AAAA,EACT,SAAS,GAAG;AACV,UAAM,IAAI,YAAY,yBAAyB,QAAQ,CAAC,CAAC;AAAA,EAC3D;AACF;;;AC7IA,IAAM,6DAA6D,KAAK,KAAK;;;ACtC7E,IAAM,uBAAN,MAAuD;AAAA,EAC5C;AAAA,EAET,YACE;AAAA,EAEF,iBAEW;AAAA,EAEX,YAAY,MAAc;AACxB,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,mBAAyB;AAAA,EAEzB;AAAA,EACA,sBAA4B;AAAA,EAE5B;AAAA,EACA,gBAAyB;AACvB,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AAAA,EAEd;AAAA,EAEA,cAAoB;AAAA,EAEpB;AACF;AAEA,IAAM,KACJ,OAAO,qBAAqB,cACxB,uBACA;;;AC9BN,SAAS,kBAAkB,gBAAgC;AACzD,SAAO,+BAA+B,cAAc;AACtD;AAOA,SAAS,kBAAkB,gBAAgC;AACzD,SAAO,kCAAkC,cAAc;AACzD;AAUA,SAAS,4BACP,SACsC;AACtC,SACE,OAAO,YAAY,YACnB,OAAQ,QAAqC,kBAAkB,YAC/D,OAAQ,QAA+B,YAAY;AAEvD;AAEO,SAAS,qBACd,gBACA,SACA,QACA,eACA,kBACA,gBACA,QACA;AACA,MAAI,OAAO,SAAS;AAClB;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;AACxE,MAAI,kBAAkB;AACpB,cAAU,YAAY,EAAC,eAAe,QAAO,CAAC;AAE9C,UAAM,YAAY,IAAI,GAAiB,kBAAkB,cAAc,CAAC;AACxE,cAAU,YAAY,CAAC,aAAa,CAAC;AACrC,cAAU,MAAM;AAAA,EAClB;AAEA,YAAU,YAAY,OAAO,MAAoB;AAC/C,UAAM,EAAC,KAAI,IAAI;AACf,QAAI,4BAA4B,IAAI,GAAG;AACrC,YAAM,EAAC,eAAe,kBAAkB,SAAS,iBAAgB,IAAI;AACrE,UAAI,qBAAqB,eAAe;AACtC,YAAI,qBAAqB,SAAS;AAShC,gBAAM,eAAe,MAAM;AAAA,YACzB;AAAA,YACA,OAAO,eACJ,MAAM,eAAe,kBAAkB,UAAU,MAClD;AAAA,UACJ;AACA,cAAI,cAAc;AAChB,2BAAe;AAAA,UACjB;AAAA,QACF,OAAO;AAaL,yBAAe;AACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,iBAAiB,SAAS,MAAM,UAAU,MAAM,GAAG,EAAC,MAAM,KAAI,CAAC;AACxE;;;ACrGA,SAAS,gBAAgB,gBAAgC;AACvD,SAAO,yBAAyB,cAAc;AAChD;AAWA,SAAS,kBAAkB,OAA8C;AACvE,eAAa,KAAK;AAClB,eAAa,MAAM,aAAa;AAChC,eAAa,MAAM,QAAQ;AAC7B;AAEO,SAAS,qBACd,gBACA,QACA,eACW;AACX,MAAI,OAAO,SAAS;AAClB,WAAO,MAAM;AAAA,EACf;AACA,QAAM,UAAU,IAAI,GAAiB,gBAAgB,cAAc,CAAC;AAEpE,UAAQ,YAAY,OAAK;AACvB,UAAM,EAAC,KAAI,IAAI;AACf,sBAAkB,IAAI;AACtB,kBAAc;AAAA,MACZ,eAAe,KAAK;AAAA,MACpB,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,SAAO,iBAAiB,SAAS,MAAM,QAAQ,MAAM,GAAG,EAAC,MAAM,KAAI,CAAC;AAEpE,SAAO,CAAC,gBAA6B;AACnC,QAAI,OAAO,SAAS;AAClB;AAAA,IACF;AACA,YAAQ,YAAY,WAAW;AAC/B,kBAAc,WAAW;AAAA,EAC3B;AACF;;;ACpCA,eAAsB,uBACpB,SACqC;AACrC,QAAM,eAAe,MAAM,gBAAgB,mBAAmB,OAAO;AACrE,QAAM,UAAU,MAAM,mBAAmB,cAAc,OAAO;AAC9D,SAAO,QACJ,IAAI,QAAM;AAAA,IACT,IAAI,EAAE,KAAK;AAAA,IACX,MAAM,EAAE,KAAK;AAAA,IACb,MAAM,EAAE,KAAK;AAAA,IACb,UAAU,EAAE,KAAK;AAAA,EACnB,EAAE,EACD,QAAQ;AACb;;;ACXO,IAAM,2BAA2B,KAAK,KAAK,KAAK;AAKhD,IAAM,cAAc,IAAI,KAAK;AAEpC,IAAI;AAKG,SAAS,aACd,UACA,UACA,uBACA,YACA,kBACA,IACA,QACM;AACN;AAAA,IACE;AAAA,IACA,MAAM;AACJ,uBAAiB;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,UACP,UACA,UACA,uBACA,kBACoB;AACpB,SAAO,UAAU,UAAU,OAAM,aAAY;AAC3C,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,UAAU,MAAM,WAAW,QAAQ;AACzC,UAAM,iBAAyC,CAAC;AAChD,UAAM,aAAoC,oBAAI,IAAI;AAClD,eAAW,CAAC,IAAI,MAAM,KAAK,SAAS;AAClC,UACE,OAAO,YACP,MAAM,OAAO,wBAAwB,uBACrC;AACA,mBAAW,IAAI,IAAI,MAAM;AAAA,MAC3B,OAAO;AACL,uBAAe,KAAK;AAAA,UAClB,eAAe,OAAO;AAAA,UACtB,UAAU;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,WAAW,SAAS,QAAQ,MAAM;AACpC,aAAO;AAAA,IACT;AACA,UAAM,WAAW,YAAY,QAAQ;AACrC,UAAM,2BAA2B,MAAM;AAAA,MACrC;AAAA,MACA;AAAA,IACF;AACA,UAAM,iBAAiB,wBAAwB;AAC/C,WAAO;AAAA,EACT,CAAC;AACH;;;AC9EA,IAAM,iBAAiB,IAAI,KAAK;AAEhC,IAAIC;AAKG,SAAS,kBACd,UACA,wBACA,IACA,QACM;AACN;AAAA,IACE;AAAA,IACA,MAAM;AACJ,MAAAC,kBAAiB,eAAe,UAAU,sBAAsB;AAChE,aAAOA;AAAA,IACT;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAQO,SAAS,eACd,UACA,wBACyB;AACzB,SAAO,UAAU,UAAU,OAAM,OAAM;AACrC,UAAM,UAAU,MAAM,WAAW,EAAE;AACnC,UAAM,iBAAiB,oBAAI,IAAI;AAC/B,eAAW,UAAU,QAAQ,OAAO,GAAG;AACrC,qBAAe,IAAI,OAAO,aAAa;AAAA,IACzC;AACA,UAAM,eAAe,oBAAI,IAAI;AAC7B,UAAM,qBAAyC,oBAAI,IAAI;AACvD,eAAW,CAAC,eAAe,WAAW,KAAK,MAAM,gBAAgB,EAAE,GAAG;AACpE,UACE,eAAe,IAAI,aAAa,KAC/B,0BAA0B,+BAA+B,WAAW,GACrE;AACA,qBAAa,IAAI,eAAe,WAAW;AAAA,MAC7C,OAAO;AACL,2BAAmB,IAAI,aAAa;AAAA,MACtC;AAAA,IACF;AACA,UAAM,gBAAgB,cAAc,EAAE;AAEtC,WAAO;AAAA,EACT,CAAC;AACH;;;AC1DO,IAAM,qBAAqB,KAAK;AAEhC,IAAI;AAEJ,SAAS,gBACd,UACA,UACA,uBACA,qBACA,IACA,QACM;AACN;AAAA,IACE;AAAA,IACA,YAAY;AACV,8BAAwB,eAAe,UAAU,QAAQ;AACzD,UAAI;AACF,eAAO,MAAM;AAAA,MACf,SAAS,GAAG;AACV,YAAI,aAAa,0BAA0B;AACzC,gCAAsB;AACtB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,eACd,UACA,UACoB;AACpB,SAAO,UAAU,UAAU,OAAM,aAAY;AAC3C,UAAM,UAAU,MAAM,WAAW,QAAQ;AACzC,UAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,yBAAyB,QAAQ;AAAA,IAC7C;AAEA,UAAM,YAAY;AAAA,MAChB,GAAG;AAAA,MACH,sBAAsB,KAAK,IAAI;AAAA,IACjC;AACA,UAAM,aAAa,IAAI,IAAI,OAAO,EAAE,IAAI,UAAU,SAAS;AAE3D,UAAM,WAAW,YAAY,QAAQ;AACrC,WAAO;AAAA,EACT,CAAC;AACH;;;ACzDO,IAAM,UAAN,MAAc;AAAA,EACnB,QAAmB,oBAAI,IAAI;AAAA,EAC3B;AAAA,EAEA,YAAY,SAAuB;AACjC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM,MAAM,GAAS;AACnB,QAAI,KAAK,MAAM,IAAI,CAAC,GAAG;AACrB;AAAA,IACF;AACA,SAAK,MAAM,IAAI,CAAC;AAChB,UAAM,QAAQ,MAAM,KAAK,SAAS,aAAa,CAAC;AAChD,UAAM,KAAK,WAAW,KAAK;AAAA,EAC7B;AAAA,EAEA,MAAM,WAAW,OAAuB;AACtC,UAAM,QAAQ,IAAI,MAAM,KAAK,IAAI,SAAO,KAAK,MAAM,GAAG,CAAC,CAAC;AAAA,EAC1D;AACF;;;ACrBO,IAAM,0BAAN,cAAsC,QAAQ;AAAA,EAC1C,kBAAoC,oBAAI,IAAI;AAAA,EAC5C;AAAA,EAET,YAAY,SAAmB;AAC7B,UAAM,OAAO;AACb,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,IAAI,iBAA2C;AAC7C,WAAO,KAAK;AAAA,EACd;AAAA,EAES,MAAM,GAAwB;AACrC,QAAI,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAG;AAEzC,aAAO;AAAA,IACT;AACA,WAAO,MAAM,MAAM,CAAC;AAAA,EACtB;AAAA,EAES,WAAW,OAA6B;AAC/C,SAAK,gBAAgB,IAAI,MAAM,MAAM,KAAK;AAC1C,WAAO,MAAM,WAAW,KAAK;AAAA,EAC/B;AACF;;;AC6BA,eAAsB,YACpB,IACA,UACA,QACA,QACA,UACA,QACA,eACA,aACA,+BAA+B,MAAM,QAAQ,QAAQ,GACtC;AACf,MAAI,OAAO,GAAG;AACZ;AAAA,EACF;AAEA,QAAM,CAAC,YAAY,oBAAoB,iBAAiB,IAAI,MAAM;AAAA,IAChE;AAAA,IACA,OAAM,eAAc;AAClB,YAAM,qBAAqB,UAAU,UAAU;AAC/C,YAAMC,qBAAoB,MAAM;AAAA,QAC9B;AAAA,QACA;AAAA,MACF;AACA;AAAA,QACEA;AAAA,QACA,sCAAsC,QAAQ;AAAA,MAChD;AACA,YAAM,CAAC,EAAE,+BAA+B,IAAI,MAAM;AAAA,QAChD;AAAA,QACAA;AAAA,MACF;AACA,YAAMC,cAAa,MAAM,gCAAgC;AAAA,QACvD;AAAA,QACA;AAAA,MACF;AACA,YAAMC,sBAAqB,MAAM;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AACA,+BAAyBA,mBAAkB;AAC3C,aAAO,CAACD,aAAYC,qBAAoBF,kBAAiB;AAAA,IAC3D;AAAA,EACF;AAEA,MAAI,OAAO,GAAG;AACZ;AAAA,EACF;AACA,QAAM,CAAC,oBAAoB,oBAAoB,cAAc,IAC3D,MAAM,SAAS,QAAQ,OAAM,eAAc;AACzC,UAAM,mBAAmB,MAAM;AAAA,MAC7B;AAAA,MACA;AAAA,IACF;AACA,UAAM,eAAe,MAAM;AAAA,MACzB;AAAA,MACA,EAAC,CAAC,QAAQ,GAAG,cAAc,EAAC;AAAA,MAC5B;AAAA,IACF;AACA,UAAMG,sBAAqB,MAAM;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AACA,6BAAyBA,mBAAkB;AAE3C,QAAIC;AACJ,QACE,2BAA2BD,qBAAoB,kBAAkB,IAAI,GACrE;AACA,YAAM,6BAA6B;AAGnC,YAAM,yBAAyBA,oBAAmB,MAAM;AAExD,YAAM,UAAU,IAAI,wBAAwB,UAAU;AACtD,YAAM,QAAQ,MAAM,sBAAsB;AAC1C,MAAAC,kBAAiB,QAAQ;AAAA,IAC3B;AAEA,WAAO,CAAC,cAAcD,qBAAoBC,eAAc;AAAA,EAC1D,CAAC;AAEH,MAAI,OAAO,GAAG;AACZ;AAAA,EACF;AAEA,MAAI,8BAA8B;AAClC,QAAM,gCACJ,eAAgB,MAAM,YAAY,mBAAmB,MAAM,IAAI;AAEjE,QAAM,UAAU,QAAQ,OAAM,gBAAe;AAC3C,UAAM,CAAC,iBAAiB,qCAAqC,IAC3D,MAAM,mBAAmB,aAAa,iBAAiB;AAMzD,QAAI,6BACF,sCAAsC,MAAM;AAC9C,QAAI,cAAwC;AAAA,MAC1C,GAAG,gBAAgB;AAAA,IACrB;AACA,QAAI,EAAC,0BAAyB,IAAI;AAElC,QAAI,gBAAgB;AAGlB,YAAM,SAAS,MAAM,cAAc,UAAU,WAAW;AACxD,qBAAe,MAAM;AAErB,YAAM,2BAA2B,MAAM;AAAA,QACrC;AAAA,QACA;AAAA,MACF;AACA,+BAAyB,wBAAwB;AAGjD,UACE;AAAA,QACE;AAAA,QACA;AAAA,MACF,IAAI,GACJ;AAEA,sCAA8B;AAC9B,cAAM,QAAQ;AAAA,UACZ,MAAM,KAAK,eAAe,OAAO,GAAG,OAAK,YAAY,SAAS,CAAC,CAAC;AAAA,QAClE;AAEA,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,YACE,GAAG;AAAA,YACH,aAAa,mBAAmB,MAAM;AAAA,UACxC;AAAA,UACA;AAAA,QACF;AAGA,qCAA6B,mBAAmB,MAAM;AACtD,cAAM,gCAAgC,MAAM;AAAA,UAC1C,gBAAgB;AAAA,UAChB;AAAA,QACF;AAEA,oCAA4B,mBAAmB,KAAK;AACpD,sBAAc,EAAC,GAAG,0BAAyB;AAE3C,qCAA6B,MAAM;AAAA,UACjC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,CAAC,6BAA6B;AAChC,oCACE,eACC,MAAM,YAAY,4BAA4B;AAAA,QAC7C,oBAAoB;AAAA,MACtB,CAAC;AAAA,IACL;AAGA,iCAA6B,MAAM;AAAA,MACjC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,+BAA+B;AAAA,IACjC;AAEA,UAAM,qBAAqB;AAAA,MACzB,GAAG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,MACA;AAAA,IACF;AAEA,UAAM,eAAe,mBAAmB,oBAAoB,WAAW;AAAA,EACzE,CAAC;AAED,MAAI,kBAAkB,6BAA6B;AACjD,UAAM;AAAA,MAAU;AAAA,MAAQ,iBACtB,YAAY,gBAAgB,CAAC,GAAG,eAAe,KAAK,CAAC,CAAC;AAAA,IACxD;AAAA,EACF;AACF;AAEA,eAAe,mBACb,YACA,eACsC;AACtC,QAAM,cAAc,MAAM,eAAe,eAAe,UAAU;AAClE,SAAO,aAAa,sCAAsC,aAAa,EAAE;AACzE,SAAO,CAAC,aAAa,MAAM,eAAe,YAAY,UAAU,UAAU,CAAC;AAC7E;AAEA,eAAe,OACb,WACA,OACA,OACA,UACA,aACA,IACA,eACAC,WACe;AACf,WAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;AAC9C,UAAM,iBAAiB,UAAU,CAAC;AAClC,UAAM,EAAC,KAAI,IAAI;AACf,UAAM,cAAc,MAAM,eAAe,OAAO,KAAK;AACrD,QACG,MAAM,eAAe,cAAc,KAAK,UAAU,KAAK,IACvD,MAAM,YAAY,cAAc,KAAK,UAAU,KAAK,GACrD;AACA,kBAAY,KAAK,QAAQ,IAAI,KAAK;AAClC,eACE,MAAM;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACAA;AAAA,MACF,GACA,MAAM;AAAA,IACV;AAAA,EACF;AACA,SAAO;AACT;;;ACpSO,IAAM,yBAAN,cAAqC,QAAQ;AAAA,EACzC,kBAA4C,oBAAI,IAAI;AAAA,EAC7D,2BAA2B;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,SACA,WACA,iBACA,iBAA2C,gBAC3C;AACA,UAAM,OAAO;AACb,SAAK,aAAa;AAClB,SAAK,mBAAmB;AACxB,SAAK,kBAAkB;AAAA,EACzB;AAAA,EAEA,IAAI,iBAAmD;AACrD,WAAO,KAAK;AAAA,EACd;AAAA,EAES,MAAM,GAAwB;AACrC,QACE,KAAK,4BAA4B,KAAK,oBACtC,KAAK,WAAW,SAAS,CAAC,GAC1B;AACA,aAAO;AAAA,IACT;AACA,WAAO,MAAM,MAAM,CAAC;AAAA,EACtB;AAAA,EAES,WAAW,OAA6B;AAC/C,QAAI,KAAK,2BAA2B,KAAK,kBAAkB;AACzD,YAAM,OAAO,KAAK,gBAAgB,KAAK;AACvC,WAAK,gBAAgB,IAAI,MAAM,MAAM,EAAC,OAAO,KAAI,CAAC;AAClD,WAAK,4BAA4B;AAAA,IACnC;AAEA,WAAO,MAAM,WAAW,KAAK;AAAA,EAC/B;AACF;;;ACPA,IAAM,oBAAoB,IAAI,KAAK;AACnC,IAAM,WAAW;AAmBjB,eAAsB,QACpB,IACA,QACA,QACA,UACA,UACA,YACA,QACA,eACA,MACsE;AACtE,MAAI,OAAO,GAAG;AACZ;AAAA,EACF;AACA,QAAM,qBAAqB,MAAM;AAAA,IAAS;AAAA,IAAQ,gBAChD,qBAAqB,mBAAmB,UAAU;AAAA,EACpD;AACA,2BAAyB,kBAAkB;AAmB3C,QAAM,SACJ,MAAM,OAAO,yCAAyC,YAAY;AAChE,UAAM,oBAAmD,MAAM;AAAA,MAC7D;AAAA,MACA,OAAM,gBAAe;AACnB,cAAM,cAAc,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AACA,YAAI,CAAC,aAAa;AAChB,gBAAM,IAAI,yBAAyB,QAAQ;AAAA,QAC7C;AAEA,cAAMC,6BAA4B,YAAY;AAC9C,cAAM,8BAA8B,MAAM;AAAA,UACxCA;AAAA,UACA;AAAA,QACF;AACA,cAAMC,cAAa,MAAM,4BAA4B;AAAA,UACnD;AAAA,UACA;AAAA,QACF;AAOA,cAAM,SAAS,MAAM,cAAc,UAAU,WAAW;AACxD,uBAAe,MAAM;AACrB,cAAMC,iCAAgC,MAAM;AAAA,UAC1CF;AAAA,UACA;AAAA,QACF;AACA,iCAAyBE,8BAA6B;AACtD,YACE;AAAA,UACE;AAAA,UACAA;AAAA,UACAF;AAAA,QACF,GACA;AACA,iBAAO;AAAA,QACT;AAIA,cAAM,UAAU,IAAI;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,QAAQ,MAAMA,0BAAyB;AAC7C,cAAM,EAAC,gBAAAG,gBAAc,IAAI;AAEzB,cAAM,mBAAmB,IAAI,IAAI,OAAO,aAAa;AACrD,yBAAiB,IAAIH,0BAAyB;AAE9C,cAAM,YAAsB;AAAA,UAC1B,GAAG;AAAA,UACH,eAAe,CAAC,GAAG,gBAAgB;AAAA,QACrC;AAEA,cAAM,UAAU,UAAU,WAAW,WAAW;AAChD,eAAO;AAAA,UACLA;AAAA,UACAE;AAAA,UACAD;AAAA,UACAE;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,CAAC,mBAAmB;AAClC,aAAO;AAAA,QACL,MAAM;AAAA,MACR;AAAA,IACF;AAQA,UAAM,MAAM,QAAQ;AACpB,QAAI,OAAO,GAAG;AACZ,aAAO;AAAA,QACL,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AACJ,WAAO,UAAU,QAAQ,OAAM,gBAAe;AAC5C,YAAM,mBAAmB,MAAM;AAAA,QAC7B;AAAA,QACA;AAAA,MACF;AACA,YAAMC,sBAAqB,MAAM;AAAA,QAC/B;AAAA,QACA;AAAA,MACF;AACA,+BAAyBA,mBAAkB;AAC3C,UACE;AAAA,QACEA;AAAA,QACA;AAAA,QACA;AAAA,MACF,GACA;AACA,eAAO;AAAA,UACL,MAAM;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAEA,YAAM,qBAAqB,MAAM;AAAA,QAC/B;AAAA,QACA,EAAC,CAAC,QAAQ,GAAG,WAAU;AAAA,QACvB;AAAA,MACF;AACA,YAAM,KAAK,CAAC;AACZ,iBAAW,EAAC,OAAO,KAAI,KAAK,eAAe,OAAO,GAAG;AACnD,WAAG,KAAK,YAAY,SAAS,OAAO,IAAI,CAAC;AAAA,MAC3C;AACA,YAAM,QAAQ,IAAI,EAAE;AAEpB,UAAI,oBAAoB;AACxB,UAAI,mBAAmB,SAAS,GAAG;AACjC,cAAMC,YAAW,MAAM,MAAM,YAAY,mBAAmB;AAAA,UAC1D,cAAc;AAAA,QAChB,CAAC;AACD,iBAAS,IAAI,mBAAmB,SAAS,GAAG,KAAK,GAAG,KAAK;AACvD,+BACE,MAAM;AAAA,YACJ,mBAAmB,CAAC;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,mBAAmB,CAAC,EAAE,KAAK;AAAA,YAC3B;AAAA,YACAA;AAAA,UACF,GACA,MAAM;AAAA,QACV;AAAA,MACF;AAEA,YAAM,sBAAsB,MAAM;AAAA,QAChC;AAAA,QACA;AAAA,MACF;AACA,YAAM,QAAQ,MAAM;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,YAAY,QAAQ,mBAAmB,iBAAiB;AAC9D,aAAO;AAAA,QACL,MAAM;AAAA,QACN;AAAA,QACA,SAAS,iBAAiB,MAAM;AAAA,QAChC,SAAS;AAAA,QACT,yBAAyB;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AAEH,MAAI,OAAO,GAAG;AACZ;AAAA,EACF;AAEA,QAAM,mBAAmB,CAAC,kBACxB,UAAU,QAAQ,OAAM,gBAAe;AACrC,UAAM,SAAS,MAAM,cAAc,UAAU,WAAW;AACxD,UAAM,YAAY;AAAA,MAChB,GAAG;AAAA,MACH;AAAA,IACF;AAIA,UAAM,UAAU,UAAU,WAAW,WAAW;AAAA,EAClD,CAAC;AAEH,MAAI,OAAO,SAAS,WAAW;AAC7B,QAAI,OAAO,wBAAwB;AACjC,YAAM,iBAAiB,OAAO,sBAAsB;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAKA,QAAM,QAAQ,OAAO,SAAS,OAAO,SAAS,OAAO,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC;AACxE,QAAM,iBAAiB,CAAC,OAAO,uBAAuB,CAAC;AACvD,SAAO;AAAA,IACL,SAAS,OAAO;AAAA,IAChB,SAAS,OAAO;AAAA,IAChB,OAAO,OAAO;AAAA,EAChB;AACF;AAEA,SAAS,mBACP,oBACA,+BACA,2BACS;AACT,QAAM,kCAAkC;AAAA,IACtC;AAAA,IACA;AAAA,EACF;AACA,SACE,kCAAkC,KACjC,oCAAoC,KACnC,8BAA8B,8BAA8B,MAAM;AAExE;;;ACzUA,SAAuB,YAAAC,iBAAe;;;ACU/B,SAAS,YAAY,SAAgC;AAC1D,SAAO,IAAI,QAAQ,aAAW;AAC5B,QAAI,OAAO,wBAAwB,YAAY;AAC7C,0BAAoB,MAAM,QAAQ,GAAG,EAAC,QAAO,CAAC;AAAA,IAChD,OAAO;AACL,iBAAW,MAAM,QAAQ,GAAG,OAAO;AAAA,IACrC;AAAA,EACF,CAAC;AACH;;;ADZO,IAAM,mBAAN,MAAuB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,qBAAiD;AAAA,EACjD,eAA2C;AAAA;AAAA,EAE3C,cAAc,QAAQ,QAAQ;AAAA;AAAA,EAE9B,mBAAmB,QAAQ,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAenC,YACEC,UACA,eACA,YACA,aACAC,eAAc,aACd;AACA,SAAK,WAAWD;AAChB,SAAK,iBAAiB;AACtB,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,eAAeC;AACpB,SAAK,aAAa;AAAA,MAChB;AAAA,MACA,MAAM;AACJ,cAAM,aAAa,IAAI,WAAW,SAAS;AAC3C,aAAK,cAAc,OAAO,UAAU;AACpC,aAAK,oBAAoB,OAAO,UAAU;AAC1C,aAAK,eAAe;AACpB,aAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,EAAC,MAAM,KAAI;AAAA,IACb;AAAA,EACF;AAAA,EAEA,WAA0B;AACxB,QAAI,KAAK,aAAa,SAAS;AAC7B,aAAO,QAAQ,OAAO,IAAI,WAAW,SAAS,CAAC;AAAA,IACjD;AACA,QAAI,KAAK,oBAAoB;AAC3B,aAAO,KAAK,mBAAmB;AAAA,IACjC;AACA,SAAK,qBAAqBC,UAAS;AACnC,SAAK,KAAK,kBAAkB;AAC5B,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA,EAEA,MAAM,oBAAmC;AACvC,QAAI;AACF,YAAM,KAAK;AAAA,IAIb,QAAQ;AAAA,IAAC;AACT,UAAM,KAAK;AACX,QAAI,CAAC,KAAK,oBAAoB;AAC5B;AAAA,IACF;AACA,UAAM,KAAK,aAAa,KAAK,cAAc;AAC3C,QAAI,CAAC,KAAK,oBAAoB;AAC5B;AAAA,IACF;AACA,SAAK,mBAAmB,SAAS,KAAK,aAAa,KAAK,YAAY;AACpE,SAAK,eAAe,KAAK;AACzB,SAAK,qBAAqB;AAC1B,QAAI;AACF,WAAK,cAAc,KAAK,SAAS;AACjC,YAAM,KAAK;AACX,WAAK,cAAc,QAAQ;AAAA,IAC7B,SAAS,GAAG;AACV,WAAK,cAAc,OAAO,CAAC;AAAA,IAC7B;AACA,SAAK,eAAe;AAAA,EACtB;AACF;AAEA,eAAe,SACb,QACA,aACe;AACf,MAAI;AACF,UAAM,MAAM,QAAQ,WAAW;AAAA,EACjC,SAAS,GAAG;AACV,WAAO,aAAa,UAAU;AAAA,EAChC;AACF;;;AE3GO,SAAS,sBACd,IACA,IACA,QACM;AACN,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,WAAW,YAAY,IAAI,EAAE;AACnC,WAAO,iBAAiB,SAAS,MAAM;AACrC,oBAAc,QAAQ;AAAA,IACxB,CAAC;AAAA,EACH;AACF;;;ACVA,SAAQ,eAAAC,cAAa,eAAAC,cAAa,UAAU,kBAAiB;;;ACDtD,IAAM,aAAa;AACnB,IAAM,UAAU;;;AD+CvB,IAAM,WAAgC,oBAAI,IAAI;AAE9C,IAAM,uBAAuB,OAAO;AAG7B,IAAM,mBAAN,MAAqD;AAAA,EACjD;AAAA,EACA;AAAA,EACT,aAAuC;AAAA,EACvC,QAAQ;AAAA,EACR,SAAoD,CAAC;AAAA,EAE5C;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,MACA,QACA,SACA,QAEA,UAAmC,WACnC;AACA,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,qBAAqB,WAA4B;AAC/C,eAAWC,SAAQ,KAAK,QAAQ;AAC9B,UAAIA,MAAK,QAAQ,cAAc,WAAW;AACxC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OACE,IACA,OACA,QACY;AACZ,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,QAAQ,OAA0B;AAChC,eAAW,CAAC,WAAWC,KAAI,KAAK,OAAO;AACrC,UAAI,wBAAwB,KAAK,OAAO,KAAK,QAAQ,WAAWA,KAAI,GAAG;AACrE,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,WACE,MACA,OACM;AACN,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,OAAO,QAAiB;AACtB,QACE,KAAK,eAAe,wBACpB,CAAC,KAAK,SAAS,KAAK,YAAY,MAAM,GACtC;AACA,WAAK,aAAa;AAClB,WAAK,QAAQ,MAAM;AAAA,IACrB;AAAA,EACF;AACF;AAgEO,IAAM,oBAAN,MAAkE;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,UAAkD;AAAA,EAClD,SAAmC;AAAA,EAE5C,YAAY,UAAyB,SAAwB;AAC3D,SAAK,YAAY;AACjB,SAAK,UAAU,SAAS,UAAU;AAClC,SAAK,aAAc,SAA+B;AAClD,SAAK,4BAA4B,SAAS,4BAA4B;AAAA,EACxE;AAAA,EAEA,qBAAqB,WAA4B;AAC/C,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,OAAO,QAAgC;AACrC,QAAI,WAAW,QAAW;AACxB,WAAK,UAAU,MAAM;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,OACE,IACA,MACA,OAC2B;AAC3B,UAAM,SAAS,OACb,WACA,QACA,YACA,wBAGuD;AACvD,UAAIC;AACJ,UAAI,SAAoB,YAAY;AAClC,YAAI,CAAC,KAAK,2BAA2B;AAGnC,iBAAO;AAAA,QACT;AAGA,eAAO,UAAU,MAAS;AAE1B,cAAMC,WAAgC,CAAC;AACvC,yBAAiB,SAAS,GAAG,KAAK,EAAC,QAAQ,UAAS,CAAC,EAAE,QAAQ,GAAG;AAChE,UAAAA,SAAQ,KAAK;AAAA,YACX,IAAI;AAAA,YACJ,KAAK,MAAM,CAAC;AAAA,YACZ,UAAU,MAAM,CAAC;AAAA,UACnB,CAAC;AAAA,QACH;AACA,QAAAD,QAAOC;AAAA,MACT,OAAO;AACL,eAAO,KAAK;AACZ,cAAM,YAAY,MAAM,IAAI,aAAa,EAAE,KAAK,CAAC;AACjD,QAAAD,QAAO,oBAAoB,SAAS;AAAA,MACtC;AACA,YAAM,UAAgC,CAAC;AACvC,YAAM,EAAC,OAAM,IAAIA;AACjB,eACM,IAAI,iBAAiBA,OAAM,QAAQ,UAAU,GACjD,IAAI,QACJ,KACA;AACA,YAAI,WAAWA,MAAK,CAAC,CAAC,EAAE,WAAW,MAAM,GAAG;AAC1C,kBAAQ,KAAKA,MAAK,CAAC,CAAC;AAAA,QACtB,OAAO;AACL;AAAA,QACF;AAAA,MACF;AAGA,aAAO,SAAoB,cAAc,QAAQ,SAAS,IACtD,UACA;AAAA,IACN;AAEA,QAAI,KAAK,YAAY;AACnB,aAAO;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,CAAAA,UAAQA,MAAK,IAAI,CAAC;AAAA,QAClB,kBAAgB,kBAAkB,cAAc,cAAc;AAAA,MAChE;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL,CAAAA,UAAQA,MAAK;AAAA,MACb,kBAAgB,kBAAkB,cAAc,OAAK,CAAC;AAAA,IACxD;AAAA,EACF;AAAA,EAEA,QAAQ,OAA0B;AAChC,UAAMA,QAAO,MAAM,IAAI,KAAK,cAAc,EAAE;AAC5C,QAAIA,UAAS,QAAW;AACtB,aAAO;AAAA,IACT;AAEA,WAAO,mBAAmBA,OAAM,KAAK,SAAS,KAAK,UAAU;AAAA,EAC/D;AAAA,EAEA,WACE,OACA,QACM;AAAA,EAER;AACF;AAEA,SAAS,kBACPA,OACA,YACsB;AACtB,SAAOA,MAAK,IAAI,QAAM;AACpB,UAAM,MAAM,WAAW,GAAG,GAAG;AAC7B,YAAQ,GAAG,IAAI;AAAA,MACb,KAAK;AACH,eAAO;AAAA,UACL,IAAI;AAAA,UACJ;AAAA,UACA,UAAU,GAAG;AAAA,QACf;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,IAAI;AAAA,UACJ;AAAA,UACA,UAAU,GAAG;AAAA,UACb,UAAU,GAAG;AAAA,QACf;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,IAAI;AAAA,UACJ;AAAA,UACA,UAAU,GAAG;AAAA,QACf;AAAA,IACJ;AAAA,EACF,CAAC;AACH;AAwCO,IAAM,2BAAN,MAA+D;AAAA,EAC3D,iBAAkC,oBAAI,IAAI;AAAA,EAC1C,wBAAyC,oBAAI,IAAI;AAAA,EACjD;AAAA,EACA;AAAA,EACT,6BAA6B;AAAA,EACpB;AAAA,EAET,YACE,eACA,IACA,QACA;AACA,SAAK,iBAAiB;AACtB,SAAK,MAAM;AACX,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAO,cAA2C;AAChD,SAAK,eAAe,IAAI,YAAmC;AAC3D,SAAK,KAAK;AAAA,MACR;AAAA,IACF;AACA,WAAO,MACL,KAAK,eAAe,OAAO,YAAmC;AAAA,EAClE;AAAA,EAEA,QAAc;AACZ,eAAW,gBAAgB,KAAK,gBAAgB;AAC9C,mBAAa,SAAS;AAAA,IACxB;AACA,SAAK,eAAe,MAAM;AAAA,EAC5B;AAAA,EAEA,KAAK,OAAgC;AACnC,UAAM,gBAAgB,sBAAsB,KAAK,gBAAgB,KAAK;AACtE,WAAO,KAAK,mBAAmB,eAA0B,SAAS,KAAK;AAAA,EACzE;AAAA,EAEA,MAAM,mBACJ,eACA,MACA,OACA;AACA,QAAI,KAAK,QAAQ,SAAS;AACxB;AAAA,IACF;AAEA,UAAM,OAAO,CAAC,GAAG,aAAa;AAC9B,QAAI,KAAK,WAAW,GAAG;AACrB;AAAA,IACF;AAGA,UAAM,UAAU,MAAM,KAAK;AAAA,MAAe,QACxC,QAAQ;AAAA,QACN,KAAK,IAAI,OAAM,MAAK;AAClB,gBAAM,MAAM,IAAI,+BAA+B,EAAE;AACjD,cAAI;AACF,mBAAO,MAAM,EAAE,OAAO,KAAK,MAAM,KAAK;AAAA,UACxC,UAAE;AAIA,cAAE,WAAW,IAAI,MAAM,IAAI,KAAK;AAAA,UAClC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,SAAK,cAAc,MAAM,OAAO;AAAA,EAClC;AAAA;AAAA,EAGA,cACE,MACA,SACA;AACA,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,IAAI,KAAK,CAAC;AAChB,YAAM,SAAS,QAAQ,CAAC;AACxB,UAAI,OAAO,WAAW,aAAa;AACjC,UAAE,OAAO,OAAO,KAAK;AAAA,MACvB,OAAO;AACL,YAAI,EAAE,SAAS;AACb,YAAE,QAAQ,OAAO,MAAM;AAAA,QACzB,OAAO;AACL,eAAK,IAAI,QAAQ,+BAA+B,OAAO,MAAM;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gCAAgC,GAAwB;AAC5D,SAAK,sBAAsB,IAAI,CAAC;AAEhC,QAAI,CAAC,KAAK,4BAA4B;AACpC,WAAK,6BAA6B;AAClC,YAAM,QAAQ,QAAQ;AACtB,WAAK,6BAA6B;AAClC,YAAM,gBAAgB,CAAC,GAAG,KAAK,qBAAqB;AACpD,WAAK,sBAAsB,MAAM;AACjC,YAAM,KAAK;AAAA,QACT;AAAA,QACW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,qBAA8B;AAC5B,WAAO,KAAK,eAAe,OAAO;AAAA,EACpC;AAAA,EAEA,2BAA2B,WAA4B;AACrD,eAAW,KAAK,KAAK,gBAAgB;AACnC,UAAI,EAAE,qBAAqB,SAAS,GAAG;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAOA,SAAS,wBACP,MACA,OACA,WACAA,OACS;AAET,MAAI,cAAc,IAAI;AACpB,eAAW,aAAaA,OAAM;AAC5B,UAAI,KAAK,IAAI,UAAU,GAAG,GAAG;AAC3B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,aAAW,YAAY,OAAO;AAC5B,QAAI,oBAAoB,UAAU,WAAWA,KAAI,GAAG;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBACP,UACA,iBACAA,OACS;AAET,aAAW,aAAaA,OAAM;AAC5B,QAAI,mBAAmB,UAAU,iBAAiB,UAAU,GAAG,GAAG;AAChE,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,mBACd,UACA,iBACA,YACS;AACT,QAAM;AAAA,IACJ,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,SAAS;AAEb,MAAI,oBAAoB,WAAW;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,WAAW;AAEd,QAAI,UAAU,UAAa,SAAS,GAAG;AACrC,aAAO;AAAA,IACT;AAIA,QAAI,CAAC,UAAU,CAAC,UAAU;AACxB,aAAO;AAAA,IACT;AAEA,QACE,WACC,CAAC,WAAW,WAAW,MAAM,KAC5B,wBAAwB,UAAU,UAAU,IAC9C;AACA,aAAO;AAAA,IACT;AAEA,QACE,aACE,kBAAkB,WAAW,YAAY,QAAQ,KACjD,SAAS,YAAY,QAAQ,KAC7B,wBAAwB,UAAU,UAAU,IAC9C;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAIA,MAAI,CAAC,UAAU,CAAC,YAAY,CAAC,mBAAmB;AAC9C,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,qBAAqB,iBAAiB,IAAI,eAAe,UAAU;AAE1E,MAAI,QAAQ;AACV,QAAI,CAAC,oBAAoB,WAAW,MAAM,GAAG;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MACE,sBACE,kBAAkB,WAAW,qBAAqB,iBAAiB,KACnE,SAAS,qBAAqB,iBAAiB,IACjD;AACA,WAAO;AAAA,EACT;AAEA,MACE,aACE,kBAAkB,WAAW,mBAAmB,QAAQ,KACxD,SAAS,mBAAmB,QAAQ,IACtC;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,wBACP,UACA,YACS;AACT,QAAM,EAAC,kBAAiB,IAAI;AAC5B,SACE,SAAS,QAAQ,UAAU,UAC3B,sBAAsB,UACtBE,aAAY,YAAY,iBAAiB;AAE7C;AAEA,UAAU,sBACR,eACA,OAC4B;AAC5B,aAAW,gBAAgB,eAAe;AACxC,QAAI,aAAa,QAAQ,KAAK,GAAG;AAC/B,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,SAAS,mBACPF,OACA,QACA,WACS;AACT,MAAI,WAAW,IAAI;AACjB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,YACf,CAAC,WAAkC,eAAe,OAAO,GAAG,EAAE,CAAC,IAC/D,CAAC,WAAkC,OAAO;AAC9C,QAAM,IAAI,iBAAiBA,OAAM,QAAQ,UAAU;AACnD,SAAO,IAAIA,MAAK,UAAU,WAAWA,MAAK,CAAC,CAAC,EAAE,WAAW,MAAM;AACjE;AAEO,SAAS,iBACdA,OACA,QACA,YACQ;AACR,SAAO;AAAA,IAAaA,MAAK;AAAA,IAAQ,OAC/BG,aAAY,QAAQ,WAAWH,MAAK,CAAC,CAAC,CAAC;AAAA,EACzC;AACF;;;AE3pBA,IAAI,YAAY;AAChB,SAAS,eAAe;AACtB,MAAI,cAAc,IAAI;AACpB,UAAM,MAAM,IAAI,WAAW,CAAC;AAC5B,6BAAyB,GAAG;AAC5B,gBAAY,MAAM,KAAK,KAAK,OAAK,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,IAAM,mBAAwC,oBAAI,IAAI;AAS/C,SAAS,aAAa,UAA4B;AACvD,QAAM,UAAU,iBAAiB,IAAI,QAAQ,KAAK;AAClD,mBAAiB,IAAI,UAAU,UAAU,CAAC;AAC1C,SAAO,GAAG,QAAQ,IAAI,aAAa,CAAC,IAAI,OAAO;AACjD;;;ACfO,IAAM,UAAkB;;;AvCkI/B,IAAM,mBAAmB;AAEzB,IAAM,0BAA0B;AAChC,IAAM,0BAA0B;AAEhC,IAAM,sBAAsB;AAC5B,IAAM,sBAAsB;AAE5B,IAAM,2CAA2C,MAAM,KAAK;AAE5D,IAAM,gCAAgC,IAAI,KAAK;AAE/C,IAAMI,QAAO,MAAM;AAEnB;AAEA,IAAM,mCAAuD;AAAA,EAC3D,MAAM;AACR;AAqDO,IAAM,iBAAN,MAAkD;AAAA;AAAA,EAEvD;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGS;AAAA,EAEA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMT,wBAAwB;AAAA,EAEf;AAAA,EAET,iBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMzB,IAAI,UAAkB;AACpB,WAAO,YAAY,KAAK,MAAM,KAAK,aAAa;AAAA,EAClD;AAAA,EAEA,IAAI,KAAK,MAAc;AACrB,QAAI,KAAK,OAAO;AACd,WAAK,MAAM,OAAO;AAAA,IACpB;AAEA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGS;AAAA,EAET,IAAI,eAAkC;AACpC,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,gBAAgB,KAAK;AAAA,MACrB,yBAAuC;AAAA,MACvC,eAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACD,YAAY,aAAa;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAgC,CAAC;AAAA;AAAA;AAAA;AAAA,EAKjC;AAAA;AAAA,EAGT,eAAe;AAAA,EACf,eAAe;AAAA,EAEf;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA,EAES;AAAA;AAAA;AAAA;AAAA,EAKT;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAES;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,wBAAwB,IAAI,gBAAgB;AAAA,EAE5C,eAAe,IAAI,KAAK;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACT,oBAAoB,IAAI;AAAA,IACtB,MAAM,KAAK,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA,KAAK,sBAAsB;AAAA,EAC7B;AAAA,EACS;AAAA,EACT,oBAAoB,IAAI;AAAA,IACtB,MAAM,KAAK,QAAQ;AAAA,IACnB;AAAA,IACA;AAAA,IACA,KAAK,sBAAsB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,iBAA2C;AAC7C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,SAA8C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW9C,wBAA6C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqB7C,iBAAgE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhE,UACE;AAAA;AAAA,EAGF,gBAAgB,MAAM;AAAA,EACtB,cAAc,MAAM;AAAA,EACpB,qBAAqB,CAAC,MAAwB;AAAA,EAE9C,YACE,SACA,cAAqC,CAAC,GACtC;AACA,oBAAgB,OAAO;AACvB,UAAM;AAAA,MACJ;AAAA,MACA,WAAW;AAAA,MACX,WAAW,CAACC,eAAc;AAAA,MAC1B,UAAU;AAAA,MACV;AAAA,MACA,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,eAAe;AAAA,MACf,WAAW,CAAC;AAAA,MACZ,iBAAiB,CAAC;AAAA,MAClB;AAAA,MACA;AAAA,MACA,UAAU,CAAC;AAAA,MACX,iBAAiB;AAAA,IACnB,IAAI;AACJ,UAAM;AAAA,MACJ,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,yBAAyB;AAAA,MACzB,0BAA0B;AAAA,MAC1B,2BAA2B;AAAA,MAC3B,mBAAmB,MAAM;AAAA,IAC3B,IAAI;AACJ,SAAK,QAAQ,YAAY;AACzB,SAAK,QAAQ,QAAQ;AACrB,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,SAAK,SAAS,UAAU,iBAAiB,IAAI;AAC7C,SAAK,SAAS,UAAU,iBAAiB,IAAI;AAE7C,SAAK,0BAA0B;AAC/B,SAAK,0BAA0B;AAC/B,SAAK,2BAA2B;AAEhC,SAAK,MAAM,iBAAiB,UAAU,UAAU,EAAC,KAAI,CAAC;AACtD,SAAK,IAAI,QAAQ,2BAA2B;AAAA,MAC1C;AAAA,MACA,sBAAsB;AAAA,IACxB,CAAC;AAED,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,sBAAsB;AAAA,IAC7B;AAEA,UAAM,kBAAkB,mBAAmB,KAAK,KAAK,QAAQ,OAAO;AACpE,SAAK,mBAAmB;AAExB,UAAM,aAAa,gBAAgB,OAAO,KAAK,OAAO;AAEtD,SAAK,gBAAgB,IAAI,kBAAkB,gBAAgB,MAAM;AACjE,SAAK,SAAS,IAAI,UAAU,YAAY,eAAe,UAAU;AACjE,SAAK,SAAS,IAAI;AAAA,MAChB,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAIA,UAAM,gBAAgBC,UAAe;AACrC,SAAK,SAAS,cAAc;AAE5B,UAAM,EAAC,aAAa,cAAc,aAAa,aAAY,IACzD;AACF,SAAK,kBAAkB,EAAC,YAAY,WAAU;AAE9C,UAAM,oBAAoB;AAAA,MACxB,iBAAiB,UAAU;AAAA,MAC3B;AAAA,MACA,KAAK,sBAAsB;AAAA,IAC7B;AAEA,SAAK,sBAAsB,IAAI;AAAA,MAC7B,KAAK,IAAI,YAAY,MAAM;AAAA,MAC3B,IAAI,aAAa,MAAM,MAAM,KAAK,YAAY,CAAC;AAAA,MAC/C;AAAA,IACF;AAEA,SAAK,sBAAsB,IAAI;AAAA,MAC7B,KAAK,IAAI,YAAY,MAAM;AAAA,MAC3B,IAAI,aAAa,MAAM,MAAM,KAAK,YAAY,CAAC;AAAA,IACjD;AAEA,SAAK,SAAS,KAAK,kBAAkB,QAAQ;AAE7C,UAAM,oBAAoBA,UAAiB;AAC3C,SAAK,oBAAoB,kBAAkB;AAC3C,UAAM,wBAAwBA,UAAiB;AAC/C,SAAK,wBAAwB,sBAAsB;AAEnD,QAAI,OAAwC;AAC1C,WAAK,oBAAoB,IAAI,iBAAiB;AAAA,QAC5C,UAAU;AAAA,QACV,IAAI,KAAK;AAAA,QACT;AAAA,QACA,mBAAmB,KAAK,mBAAmB,KAAK,IAAI;AAAA,QACpD,qBAAqB,KAAK,qBAAqB,KAAK,IAAI;AAAA,QACxD,gBAAgB,KAAK,gBAAgB,KAAK,IAAI;AAAA,QAC9C,gBAAgB,KAAK,gBAAgB,KAAK,IAAI;AAAA,QAC9C,sBAAsB,KAAK;AAAA,MAC7B,CAAC;AAAA,IACH;AAEA,SAAK,aAAa;AAAA,MAChB,KAAK;AAAA,MACL,KAAK,sBAAsB;AAAA,MAC3B,iBAAe;AACb,aAAK,KAAK,eAAe,WAAW;AAAA,MACtC;AAAA,IACF;AAEA,SAAK,KAAK;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB;AAAA,MAClB,sBAAsB;AAAA,MACtB,cAAc;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,MACJ,SACA,0BACA,wBACA,gBACA,mBACA,sBACA,cACA,kBACe;AACf,UAAM,EAAC,SAAQ,IAAI;AAGnB,UAAM,iBAAiB,IAAI,KAAK,IAAI;AACpC,UAAM,KAAK,cAAc,aAAa,EAAE,KAAK,iBAAiB;AAC9D,UAAM,KAAK,cAAc,YAAY,KAAK,YAAY;AACtD,UAAM,CAAC,QAAQ,UAAU,EAAE,gBAAgB,IAAI,MAAM;AAAA,MACnD;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO,KAAK,KAAK,gBAAgB;AAAA,MACjC;AAAA,MACc;AAAA,MACd;AAAA,IACF;AAEA,yBAAqB,OAAO,aAAa;AACzC,UAAM;AAAA,MAAU,KAAK;AAAA,MAAQ,WAC3B,MAAM,QAAQ,mBAAmB,QAAQ;AAAA,IAC3C;AAGA,UAAM,KAAK,OAAO,KAAK,UAAU,KAAK,MAAM;AAC5C,iBAAa;AAEb,QAAI,KAAK,0BAA0B;AACjC,WAAK,KAAK,EAAE,MAAMF,KAAI;AACtB,WAAK,KAAK,EAAE,MAAMA,KAAI;AAAA,IACxB;AAEA,UAAM,EAAC,OAAM,IAAI,KAAK;AAEtB;AAAA,MACE;AAAA,MACA,KAAK;AAAA,MACL,MAAM;AACJ,aAAK,6BAA6B,QAAQ;AAAA,MAC5C;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AACA;AAAA,MACE;AAAA,MACA,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AACA;AAAA,MACE,KAAK;AAAA,MACL,KAAK,iBAAiB;AAAA,MACtB;AAAA,MACA;AAAA,MACA,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AACA,sBAAkB,KAAK,QAAQ,wBAAwB,KAAK,KAAK,MAAM;AACvE;AAAA,MACE,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP;AAAA,MACA,MAAM;AACJ,aAAK,oBAAoB,gCAAgC;AAAA,MAC3D;AAAA,MACA,KAAK;AAAA,IACP;AAEA;AAAA,MACE,MAAM,KAAK,iBAAiB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AACA,SAAK,KAAK,iBAAiB;AAE3B,qBAAiB,UAAU,GAAG;AAAA,MAC5B;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,sBAAsB,YAAY;AAChC,QAAI,KAAK,SAAS;AAChB;AAAA,IACF;AAGA,QAAI,iBAAiB,UAAU,GAAG,oBAAoB,WAAW;AAC/D;AAAA,IACF;AAEA,UAAM,KAAK,2CAA2C;AAAA,EACxD;AAAA,EAEA,MAAM,6CAA+D;AACnE,UAAM,EAAC,SAAQ,IAAI;AACnB,UAAMG,kBAAiB,MAAM;AAAA,MAAS,KAAK;AAAA,MAAQ,UACjD,eAAsB,UAAU,IAAI;AAAA,IACtC;AACA,QAAI,CAACA,iBAAgB;AACnB,WAAK,6BAA6B,QAAQ;AAAA,IAC5C;AACA,WAAO,CAACA;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,gBAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAqD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQrD,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAuB;AAC3B,SAAK,UAAU;AACf,UAAM,EAAC,SAAS,QAAO,IAAID,UAAS;AACpC,qBAAiB,IAAI,KAAK,MAAM,OAAO;AAEvC,SAAK,sBAAsB,MAAM;AAEjC,qBAAiB,UAAU,GAAG;AAAA,MAC5B;AAAA,MACA,KAAK;AAAA,IACP;AAEA,UAAM,KAAK;AACX,UAAM,kBAAkB;AAAA,MACtB,KAAK,OAAO,MAAM;AAAA,MAClB,KAAK,OAAO,MAAM;AAAA,MAClB,KAAK,cAAc,MAAM;AAAA,IAC3B;AAEA,SAAK,oBAAoB,MAAM;AAC/B,SAAK,oBAAoB,MAAM;AAE/B,SAAK,eAAe,MAAM;AAE1B,UAAM,QAAQ,IAAI,eAAe;AACjC,qBAAiB,OAAO,KAAK,IAAI;AACjC,YAAQ;AAAA,EACV;AAAA,EAEA,MAAM,aAAa,UAAgB,WAAkC;AACnE,eAAS;AACP,UAAI,KAAK,SAAS;AAChB;AAAA,MACF;AAEA,YAAM,KAAK;AACX,YAAM,EAAC,SAAQ,IAAI;AACnB,YAAM,KAAK,KAAK,IACb,YAAY,cAAc,EAC1B,YAAY,aAAa,SAAS;AACrC,YAAM,EAAC,iBAAiB,OAAO,aAAa,SAAQ,IAClD,MAAM;AAAA,QACJ,KAAK;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACS;AAAA,MAChB;AAEF,UAAI,CAAC,mBAAmB,gBAAgB,WAAW,GAAG;AAEpD,aAAK,OAAO,QAAQ,aAAa,UAAU,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC;AAC9D,cAAM,KAAK,eAAe,KAAK,KAAK;AACpC,aAAK,KAAK,iBAAiB;AAC3B;AAAA,MACF;AAGA,YAAME,YAAW,MAAM,KAAK,OAAO,YAAY,QAAQ;AACvD,iBAAW,YAAY,iBAAiB;AAItC,YAAI,KAAK,eAAe,4BAA4B;AAClD,gBAAM,QAAQ,QAAQ;AAAA,QACxB;AACA,cAAM,EAAC,KAAI,IAAI;AACf,mBAAW,MAAM;AAAA,UAA0B,KAAK;AAAA,UAAQ,cACtD;AAAA,YACE;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,KAAK;AAAA,YACL;AAAA,YACA,gBAAgB,IAAI,IAAI,KAAK,WAAW;AAAA,YAC1B;AAAA,YACdA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,cAAgC;AAC9B,QAAI,KAAK,gBAAgB,GAAG;AAC1B,aAAO,QAAQ,QAAQ,IAAI;AAAA,IAC7B;AAEA,WAAO,KAAK,mBAAmB,YAAY;AACzC,UAAI;AACF,aAAK,oBAAoB,GAAG,CAAC;AAC7B,cAAM,EAAC,UAAU,WAAW,GAAE,IAAI,MAAM,KAAK,UAAU;AACvD,YAAI,CAAC,IAAI;AACP,iBAAO;AAAA,QACT;AACA,YAAI,aAAa,WAAW;AAC1B,gBAAM,KAAK,aAAa,UAAU,SAAS;AAAA,QAC7C;AAAA,MACF,SAAS,GAAG;AACV,cAAM,MAAM,KAAK,mCAAmC,CAAC;AAAA,MACvD,UAAE;AACA,aAAK,oBAAoB,GAAG,EAAE;AAAA,MAChC;AACA,aAAO;AAAA,IACT,GAAG,MAAM;AAAA,EACX;AAAA,EAEA,kBAAkB;AAChB,WACE,KAAK,yBACJ,KAAK,YAAY,MAAM,gBAAgB,KAAK,MAAM;AAAA,EAEvD;AAAA,EAEA,MAAM,mBACJ,GACA,MACkB;AAClB,QAAI,SAAS;AAEb,QAAI;AACF,aAAO,MAAM,EAAE;AAAA,IACjB,SAAS,GAAG;AAYV,UAAI,aAAa,aAAa,aAAa,WAAW;AACpD,iBAAS;AACT,aAAK,IAAI,QAAQ,GAAG,IAAI;AAAA,GAAa,GAAG,mBAAmB,EAAE,QAAQ;AAAA,MACvE,WAAW,aAAa,aAAa;AACnC,aAAK,IAAI,QAAQ,CAAC;AAAA,MACpB,OAAO;AACL,aAAK,IAAI,OAAO,GAAG,IAAI;AAAA,GAAa,CAAC;AAAA,MACvC;AACA,aAAO;AAAA,IACT,UAAE;AACA,UAAI,KAAK,YAAY,QAAQ;AAC3B,aAAK,UAAU;AACf,aAAK,iBAAiB,MAAM;AAC5B,YAAI,QAAQ;AACV,eAAK,KAAK,iBAAiB;AAAA,QAC7B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,qBACJ,GAOA,MACA,IACA,UAAoCJ,OACpC,WAAqCA,OAIpC;AACD,UAAM,EAAC,SAAQ,IAAI;AACnB,QAAI,iBAAiB;AACrB,QAAI;AACJ,SAAK,GAAG,YAAY,IAAI;AACxB,OAAG;AACD,YAAM,YAAY,aAAa,QAAQ;AACvC,YAAM,YAAY,GAAG,YAAY,aAAa,SAAS;AACvD,YAAM,EAAC,iBAAiB,OAAM,IAAI,MAAM,EAAE,WAAW,SAAS;AAC9D,mBAAa;AACb,UAAI,CAAC,iBAAiB;AACpB,eAAO;AAAA,UACL;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AACA,YAAM,EAAC,cAAc,eAAc,IAAI;AAEvC,UAAI,gBAAgB,mBAAmB,KAAK;AAG1C,kBAAU;AAAA,UACR,gCAAgC,IAAI,KAAK,cAAc,MACpD,eAAe,KAAK,YAAY,KAAK;AAAA,QAC1C;AAAA,MACF;AACA,UAAI,mBAAmB,wBAAwB;AAC7C,eAAO;AAAA,UACL;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AACA,UAAI,CAAC,KAAK,SAAS;AACjB,eAAO;AAAA,UACL;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AACA,UAAI;AACJ,UAAI;AACF,cAAM,QAAQ;AACd,eAAO,MAAM,KAAK,QAAQ;AAAA,MAC5B,UAAE;AACA,cAAM,SAAS;AAAA,MACjB;AACA,UAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,eAAO;AAAA,UACL;AAAA,UACA,aAAa;AAAA,QACf;AAAA,MACF;AACA,WAAK,OAAO;AACZ;AAAA,IACF,SAAS,iBAAiB;AAC1B,OAAG,OAAO,wCAAwC;AAClD,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EAEA,kBAAkB;AAChB,WACE,KAAK,yBACJ,KAAK,YAAY,MAAM,gBAAgB,KAAK,MAAM;AAAA,EAEvD;AAAA,EAEA,MAAM,cAAgC;AACpC,QAAI,OAAS;AACX,WAAK,cAAc;AAAA,IACrB;AACA,QAAI,KAAK,gBAAgB,GAAG;AAC1B,aAAO;AAAA,IACT;AAEA,UAAM,KAAK;AACX,UAAM,YAAY,MAAM,KAAK;AAC7B,UAAM,EAAC,SAAQ,IAAI;AACnB,UAAM,gBAAgB,MAAM,KAAK;AACjC,WAAO,KAAK,mBAAmB,YAAY;AACzC,YAAM,EAAC,QAAQ,aAAY,IAAI,MAAM,KAAK;AAAA,QACxC,OAAO,WAAmB,cAA0B;AAClD,cAAI;AACF,iBAAK,oBAAoB,GAAG,CAAC;AAC7B,kBAAMK,gBAAe,MAAM;AAAA,cACzB;AAAA,cACA,KAAK;AAAA,cACL;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK;AAAA,cACL,KAAK;AAAA,cACL;AAAA,YACF;AACA,mBAAO;AAAA,cACL,QAAQA;AAAA,cACR,iBAAiBA,eAAc;AAAA,YACjC;AAAA,UACF,UAAE;AACA,iBAAK,oBAAoB,IAAI,CAAC;AAAA,UAChC;AAAA,QACF;AAAA,QACA;AAAA,QACA,KAAK;AAAA,MACP;AAEA,UAAI,iBAAiB,QAAW;AAE9B,eAAO;AAAA,MACT;AAEA,YAAM,EAAC,UAAU,gBAAe,IAAI;AAEpC,UAAI,8BAA8B,QAAQ,GAAG;AAC3C,aAAK,mCAAmC,QAAQ;AAAA,MAClD,WAAW,8BAA8B,QAAQ,GAAG;AAClD,cAAM,KAAK,6BAA6B;AAAA,MAC1C;AAIA,aAAO,gBAAgB,mBAAmB;AAAA,IAC5C,GAAG,MAAM;AAAA,EACX;AAAA,EAEA,mCAAmC,UAAuC;AACxE,UAAM,SAA6B;AAAA,MACjC,MAAM,SAAS;AAAA,IACjB;AACA,QAAI,SAAS,aAAa;AACxB,aAAO,cAAc,SAAS;AAAA,IAChC;AACA,SAAK,oBAAoB,MAAM;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,KAAK,EAAC,MAAM,MAAK,IAAI,CAAC,GAAkB;AACtC,WAAO,aAAa,KAAK,oBAAoB,KAAK,GAAG,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,KAAK,EAAC,MAAM,MAAK,IAAI,CAAC,GAAkB;AACtC,WAAO,aAAa,KAAK,oBAAoB,KAAK,GAAG,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,KAAK,MAAmC;AAC5C,UAAM,KAAK;AAOX,UAAM,EAAC,SAAQ,IAAI;AACnB,UAAM,YAAY,aAAa,QAAQ;AACvC,UAAM,KAAK,KAAK,IACb,YAAY,oBAAoB,EAChC,YAAY,aAAa,SAAS;AAErC,UAAM,EAAC,aAAY,IAAI;AAEvB,QAAI,8BAA8B,YAAY,GAAG;AAC/C,WAAK,mCAAmC,YAAY;AACpD;AAAA,IACF;AAEA,QAAI,8BAA8B,YAAY,GAAG;AAC/C,YAAM,KAAK,6BAA6B;AACxC;AAAA,IACF;AAEA,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,KAAK;AAAA,MACL,WAAW,KAAK,UAAU;AAAA,MAC1B;AAAA,MACA;AAAA,MACc;AAAA,IAChB;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAkC;AAChC,cAAM,KAAK,aAAa,OAAO,UAAU,SAAS;AAClD;AAAA,MACF,KAAkC;AAChC,cAAM,IAAI;AAAA,UACR,sCAAsC,KAAK,UAAU,IAAI;AAAA,QAC3D;AAAA,MACF,KAAkC;AAChC;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAM,YAAsC;AAC1C,QAAI,OAAS;AACX,WAAK,YAAY;AAAA,IACnB;AACA,UAAM,KAAK;AACX,UAAM,YAAY,MAAM,KAAK;AAC7B,UAAM,EAAC,SAAQ,IAAI;AACnB,UAAM,gBAAgB,MAAM,KAAK;AACjC,UAAM;AAAA,MACJ,QAAQ,EAAC,mBAAmB,UAAS;AAAA,IACvC,IAAI,MAAM,KAAK;AAAA,MACb,OAAOC,YAAmB,cAA0B;AAClD,cAAMC,qBAAoB,MAAM;AAAA,UAC9B;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACLD;AAAA,UACA,KAAK;AAAA,UACS;AAAA,UACd;AAAA,QACF;AACA,eAAO;AAAA,UACL,QAAQ,EAAC,mBAAAC,oBAAmB,WAAAD,WAAS;AAAA,UACrC,iBAAiBC,mBAAkB;AAAA,QACrC;AAAA,MACF;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL,MAAM,KAAK,oBAAoB,GAAG,EAAE;AAAA,MACpC,MAAM,KAAK,oBAAoB,GAAG,CAAC;AAAA,IACrC;AAEA,UAAM,EAAC,aAAY,IAAI;AACvB,QAAI,8BAA8B,YAAY,GAAG;AAC/C,WAAK,mCAAmC,YAAY;AAAA,IACtD,WAAW,8BAA8B,kBAAkB,YAAY,GAAG;AACxE,YAAM,KAAK,6BAA6B;AAAA,IAC1C;AAEA,UAAM,EAAC,UAAU,gBAAe,IAAI;AACpC,WAAO,EAAC,WAAW,UAAU,IAAI,gBAAgB,mBAAmB,IAAG;AAAA,EACzE;AAAA,EAEA,UAAyB;AAEvB,WAAO,KAAK,aAAa,SAAS,YAAY;AAC5C,YAAM,EAAC,SAAQ,IAAI;AACnB,YAAM,KAAK;AACX,UAAI,KAAK,SAAS;AAChB;AAAA,MACF;AACA,UAAI;AACF,cAAM;AAAA,UACJ,KAAK;AAAA,UACL;AAAA,UACA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM,KAAK;AAAA,UACG;AAAA,UACd,KAAK,OAAO;AAAA,QACd;AAAA,MACF,SAAS,GAAG;AACV,YAAI,aAAa,0BAA0B;AACzC,eAAK,6BAA6B,QAAQ;AAAA,QAC5C,WAAW,KAAK,SAAS;AACvB,eAAK,IAAI,QAAQ,qCAAqC,CAAC;AAAA,QACzD,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,gBAAgB,MAAM,KAAK;AACjC,aAAO,aAAa;AACpB,WAAK,WAAW,EAAC,UAAU,cAAa,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,UAAyB;AAC7B,UAAM,KAAK;AACX,UAAM,EAAC,SAAQ,IAAI;AACnB,QAAI,KAAK,SAAS;AAChB;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM;AAAA,QACpB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,MAAM,KAAK;AAAA,QACG;AAAA,QACd,KAAK;AAAA,MACP;AAAA,IACF,SAAS,GAAG;AACV,UAAI,aAAa,0BAA0B;AACzC,aAAK,6BAA6B,QAAQ;AAAA,MAC5C,WAAW,KAAK,SAAS;AACvB,aAAK,IAAI,QAAQ,qCAAqC,CAAC;AAAA,MACzD,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AACA,QAAI,kBAAkB,QAAW;AAC/B,YAAM,KAAK,eAAe,KAAK,cAAc,KAAK;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,6BAA6B;AAC3B,SAAK,wBAAwB;AAAA,EAC/B;AAAA,EAEA,6BAA6B,UAAoB;AAC/C,SAAK,IAAI,QAAQ,+CAA+C,QAAQ,EAAE;AAC1E,SAAK,2BAA2B;AAAA,EAClC;AAAA,EAEA,MAAM,+BAA+B;AACnC,UAAM,gBAAgB,MAAM,KAAK;AACjC,SAAK,IAAI;AAAA,MACP,oDAAoD,aAAa;AAAA,IACnE;AACA,UAAM,KAAK,mBAAmB;AAC9B,SAAK,2BAA2B;AAAA,EAClC;AAAA,EAEA,MAAM,qBAAoC;AACxC,UAAM,gBAAgB,MAAM,KAAK;AACjC,WAAO,aAAa;AACpB,SAAK,wBAAwB;AAC7B,UAAM;AAAA,MAAU,KAAK;AAAA,MAAQ,cAC3B,mBAAmB,eAAe,QAAQ;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,oBAAoB,QAA4B;AAC9C,SAAK,IAAI,QAAQ,0BAA0B,MAAM,EAAE;AACnD,SAAK,iBAAiB,MAAM;AAAA,EAC9B;AAAA,EAEA,MAAM,mBAAkC;AACtC,QAAI,CAAC,KAAK,yBAAyB;AACjC;AAAA,IACF;AACA,UAAM,KAAK,UAAU,WAAW,KAAK,iBAAiB;AAAA,EACxD;AAAA,EAEA,MAAM,eAAe,aAAyC;AAC5D,SAAK,IAAI,QAAQ,oBAAoB,WAAW;AAChD,UAAM,gBAAgB,MAAM,KAAK;AACjC,QAAI,YAAY,kBAAkB,eAAe;AAC/C,WAAK,KAAK,iBAAiB;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,MAAM,mBAAkC;AACtC,QAAI,CAAC,KAAK,yBAAyB;AACjC;AAAA,IACF;AACA,UAAM,KAAK,UAAU,wBAAwB,KAAK,iBAAiB;AAAA,EACrE;AAAA,EAEA,MAAM,UAAU,MAAc,WAA4C;AACxE,QAAI;AACF,YAAM,UAAU,SAAS;AAAA,IAC3B,SAAS,GAAG;AACV,UAAI,aAAa,YAAY;AAC3B,aAAK,IAAI,QAAQ,aAAa,IAAI,iCAAiC;AAAA,MACrE,OAAO;AACL,aAAK,IAAI,QAAQ,gBAAgB,IAAI,IAAI,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA,EAIA,oBAAoB,WAAmB,WAAyB;AAC9D,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,UAAM,QAAQ,YAAY;AAC1B,UAAM,UAAU,KAAK,eAAe,KAAK;AACzC,QAAK,UAAU,KAAK,YAAY,KAAM,YAAY,GAAG;AACnD,YAAM,UAAU,UAAU;AAE1B,WAAK,QAAQ,QAAQ,EAAE,KAAK,MAAM,KAAK,SAAS,OAAO,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCA,UACE,MACA,SACY;AACZ,QAAI,OAAO,YAAY,YAAY;AACjC,gBAAU,EAAC,QAAQ,QAAO;AAAA,IAC5B;AAEA,UAAM,EAAC,QAAQ,SAAS,QAAQ,QAAO,IAAI;AAC3C,WAAO,KAAK,eAAe;AAAA,MACzB,IAAI,iBAAiB,MAAM,QAAQ,SAAS,QAAQ,OAAO;AAAA,IAC7D;AAAA,EACF;AAAA,EAsBA,kBACE,UACA,SACY;AACZ,WAAO,KAAK,eAAe;AAAA,MACzB,IAAI,kBAAkB,UAA2B,OAAO;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAS,MAA2D;AAClE,WAAO,KAAK,eAAe,IAAI;AAAA,EACjC;AAAA,EAEA,IAAI,SAA0B;AAC5B,WAAO,KAAK,OAAO;AAAA,MAAK,MACtB,SAAS,KAAK,QAAQ,OAAM,YAAW;AACrC,cAAM,eAAe,MAAM,QAAQ,QAAQ,iBAAiB;AAC5D,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI,MAAM,6BAA6B;AAAA,QAC/C;AACA,cAAM,eAAe,MAAM,qBAAqB,cAAc,OAAO;AACrE,cAAM,mBAAmB,aAAa;AACtC,cAAM,SAAS,iBAAiB;AAChC,qBAAa,MAAM;AACnB,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,iBAAgC,OAAM,SAAQ;AAC5C,UAAM,KAAK;AACX,UAAM,EAAC,SAAQ,IAAI;AACnB,WAAO,SAAS,KAAK,QAAQ,OAAM,YAAW;AAC5C,UAAI;AACF,cAAM,SAAS,MAAM,oBAAoB,SAAuB,MAAM;AACtE,cAAM,KAAK,IAAI,oBAAoB,UAAU,QAAQ,KAAK,GAAG;AAC7D,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB,SAAS,IAAI;AACX,cAAM,MAAM,KAAK,mCAAmC,EAAE;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,UACE,MACA,aAGyE;AACzE,SAAK,iBAAiB,IAAI,IAAI;AAK9B,WAAO,CACL,SAGyD;AAGzD,YAAM,eACJ,SAAS,eAAe,SAAY,KAAK,OAAO,cAAc;AAEhE,YAAM,SAAS,KAAK;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY,IAAI;AAAA,MAClB;AAEA,UAAI,cAAc;AAChB,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,QAAQ,aAAa;AAAA;AAAA,UAErB,MAAM,CAAC,aAAa,eAAe;AACjC,iBAAK,IAAI;AAAA,cACP;AAAA,YAEF;AACA,mBAAO,OAAO,KAAK,aAAa,UAAU;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,kBAOE,MAA0B;AAE1B,UAAM,KAAmB,uBAAO,OAAO,IAAI;AAC3C,eAAW,KAAK,MAAM;AACpB,SAAG,CAAC,IAAI,KAAK,UAAU,GAAG,KAAK,CAAC,CAAC;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAIJ,cACA,MACA,aACA,MACA,WACY;AACZ,UAAM,aAAa,WAAW,QAAQ,IAAI;AAI1C,QAAI,KAAK,eAAe,4BAA4B;AAClD,YAAM,QAAQ,QAAQ;AAAA,IACxB;AAEA,UAAM,KAAK;AACX,UAAM,EAAC,SAAQ,IAAI;AACnB,WAAO,0BAA0B,KAAK,QAAQ,OAAM,aAAY;AAC9D,UAAI;AACF,YAAI;AACJ,YAAI;AACJ,YAAI;AACJ,YAAI;AACJ,YAAI;AACF,qBAAW,MAAM,gBAAgB,mBAAmB,QAAQ;AAC5D,gBAAM,eAAe;AAErB,gBAAM,UAAU,MAAM;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACc;AAAA,UAChB;AAEA,gBAAM,aAAa,MAAM,QAAQ,cAAc;AAC/C,gBAAM,KAAK,IAAI;AAAA,YACb;AAAA,YACA;AAAA,YACA;AAAA,YACA,MAAM,KAAK,OAAO,UAAU,UAAU;AAAA,cACpC,cAAc;AAAA,YAChB,CAAC;AAAA,YACD;AAAA,YACA,KAAK;AAAA,UACP;AAEA,cAAI,cAAc;AAChB,iBAAK,OAAO;AAAA,cACV,aAAa;AAAA,cACb;AAAA,YACF;AAAA,UACF;AAEA,mBAAS,MAAM,YAAY,IAAI,IAAI;AAEnC,wBAAc,OAAO;AACrB,gBAAM,iBAAiB,MAAM,QAAQ,cAAc;AACnD,WAAC,SAAS,KAAK,IAAI,MAAM,QAAQ;AAAA,YAC/B;AAAA,YACA,KAAK;AAAA,UACP;AAGA,eAAK,iBAAiB;AAAA,QACxB,SAAS,GAAG;AAGV,cAAI,cAAc;AAChB,iBAAK,OAAO,eAAe,aAAa,aAAa,CAAC;AAAA,UACxD;AACA,gBAAM;AAAA,QACR;AAEA,aAAK,OAAO,QAAQ,UAAU,SAAS,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC;AAG1D,aAAK,oBAAoB,KAAK,KAAK,EAAE,MAAM,MAAM,MAAM;AACvD,cAAM,KAAK,eAAe,KAAK,KAAK;AACpC,aAAK,KAAK,iBAAiB;AAC3B,eAAO;AAAA,MACT,SAAS,IAAI;AACX,cAAM,MAAM,KAAK,mCAAmC,EAAE;AAAA,MACxD;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mCAAmC,IAA+B;AACtE,QACE,cAAc,sBACb,MAAM,KAAK,2CAA2C,GACvD;AACA,aAAO,IAAI,yBAAyB,KAAK,QAAQ;AAAA,IACnD;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,mBAA4C;AAC1C,QAAI,OAAwC;AAE1C,YAAM,SAAS,KAAK,kBAAmB;AAAA,QACrC,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK,iBAAiB;AAAA,MACxB;AACA,UAAI,OAAS;AACX,aAAK,KAAK,mBAAmB,MAAM;AAAA,MACrC;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,+BAAoE;AAClE,WAAO,SAAS,KAAK,QAAQ,sBAAsB;AAAA,EACrD;AACF;AAIA,IAAM,mBAAkD,oBAAI,IAAI;AAEhE,eAAe,aAAa,GAA0C;AACpE,QAAM,MAAM,MAAM;AAClB,MAAI,KAAK;AACP,UAAM,IAAI;AAAA,EACZ;AACF;AAEA,SAAS,SAAe;AACtB,MAAI,OAAO,aAAa,aAAa;AACnC,aAAS,OAAO;AAAA,EAClB;AACF;AAEA,SAAS,gBACP,SACM;AACN,QAAM,EAAC,MAAM,eAAc,IAAI;AAC/B,MAAI,OAAO,SAAS,YAAY,CAAC,MAAM;AACrC,UAAM,IAAI,UAAU,wCAAwC;AAAA,EAC9D;AAEA,MAAI,mBAAmB,QAAW;AAChC,UAAM,MAAM,KAAK,IAAI,aAAa,kBAAkB;AACpD,QAAI,OAAO,mBAAmB,YAAY,kBAAkB,KAAK;AAC/D,YAAM,IAAI;AAAA,QACR,+CAA+C,GAAG;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACF;;;AwCloDA,IAAM,sBAAsB;AAE5B,IAAM,cAAc,CAClB,KACA,YAEA,QAAQ,QAAQ,OAAO,EAAE,KAAK,aAAW;AAAA,EACvC;AAAA,EACA,QAAQ;AAAA,EACR;AACF,EAAE;AASJ,eAAsB,YAEpB,UAAiD;AACjD,QAAM,OAAO,OAAO,KAAK,QAAQ;AAEjC,MAAI,KAAK,WAAW,GAAG;AACrB,UAAM,IAAI,MAAM,mBAAmB;AAAA,EACrC;AAEA,QAAM,UAAU,KAAK;AAAA,IAAI,SACvB,YAAY,KAAK,SAAS,GAAG,CAAwC;AAAA,EACvE;AAEA,SAAO,MAAM,QAAQ,KAAK,OAAO;AACnC;;;ACzCO,SAAS,gBAAgB;AAAC;AAC1B,IAAM,cAAc,OAAO,OAAO,CAAC,CAAC;AACpC,IAAM,aAAa,OAAO,OAAO,CAAC,CAAC;AACnC,SAAS,SAAY,GAAS;AACnC,SAAO;AACT;;;ACHO,IAAM,0BAA4B;AAAA,EACrC,eAAe;AAAA,IACf,WAAa,cAAgB,sBAAO,CAAC,EAAE,SAAS;AAAA,IAChD,gBAAkB,cAAgB,sBAAO,CAAC,EAAE,SAAS;AAAA,EACvD,CAAC;AACH;AAEO,IAAM,6BAA+B,qBAAM;AAAA,EAC9C,uBAAQ,eAAe;AAAA,EACzB;AACF,CAAC;;;ACRM,IAAM,cAAgB,sBAAO;AAAA,EAClC,IAAM,uBAAQ,KAAK;AAAA,EACnB,MAAQ,sBAAO;AAAA,EACf,KAAO,sBAAO,EAAE,SAAS;AAC3B,CAAC;AAEM,IAAM,gBAAgB,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA,EAI9C,KAAK,UAAU,SAAS;AAAA,EACxB,MAAQ,sBAAO,EAAE,SAAS;AAAA,EAC1B,MAAQ,SAAW,qBAAM,UAAU,CAAC,EAAE,SAAS;AACjD,CAAC;AAED,IAAM,cAAgB,sBAAO;AAAA,EAC3B,IAAM,uBAAQ,KAAK;AAAA,EACnB,MAAQ,sBAAO;AACjB,CAAC;AAED,IAAM,gBAAkB,sBAAO;AAAA,EAC7B,IAAM,uBAAQ,OAAO;AACvB,CAAC;AAED,IAAM,gBAAkB,qBAAM,aAAa,aAAa,aAAa;AACrE,IAAM,kBAAoB,qBAAM,eAAe,aAAa,aAAa;AAElE,IAAM,qBAAuB,qBAAM,aAAa;AAChD,IAAM,uBAAyB,qBAAM,eAAe;;;ACnBpD,IAAM,sBAAwB,sBAAO;AAAA,EAC1C,MAAQ,sBAAO;AAAA,EACf,WAAa,sBAAO,EAAE,SAAS;AACjC,CAAC;AAEM,IAAM,yBAA2B,qBAAM;AAAA,EAC1C,uBAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AAED,IAAM,2BAA6B,sBAAO;AAAA,EACxC,qBAAqB;AAAA,EACrB,cAAc,mBAAmB,SAAS;AAAA,EAC1C,SAAS,wBAAwB,SAAS;AAAA;AAAA,EAE1C,aAAe,sBAAO,EAAE,SAAS;AAAA;AAAA,EAEjC,cAAgB,sBAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQlC,eAAiB,qBAAQ,sBAAO,CAAC,EAAE,SAAS;AAC9C,CAAC;AAEM,IAAM,8BAAgC,qBAAM;AAAA,EAC/C,uBAAQ,gBAAgB;AAAA,EAC1B;AACF,CAAC;AAOM,SAAS,mBACd,uBACA,WACQ;AACR,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AAKA,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,KAAK,UAAU,SAAS,CAAC;AAIhE,QAAM,IAAI,MAAM,KAAK,OAAO,UAAQ,OAAO,aAAa,IAAI,CAAC,EAAE,KAAK,EAAE;AAEtE,SAAO,mBAAmB,KAAK,CAAC,CAAC;AACnC;;;ACtEO,IAAM,OAAO;AACb,IAAM,SAAS;;;ACWf,IAAM,qBAAqB;AAKlC,IAAM,iBAAmB,sBAAO;AAAA,EAC9B,IAAM,uBAAQ,QAAQ;AAAA,EACtB,WAAa,sBAAO;AAAA,EACpB,YAAY;AAAA,EACZ,OAAO;AACT,CAAC;AAMD,IAAM,iBAAmB,sBAAO;AAAA,EAC9B,IAAM,uBAAQ,QAAQ;AAAA,EACtB,WAAa,sBAAO;AAAA,EACpB,YAAY;AAAA,EACZ,OAAO;AACT,CAAC;AAKD,IAAM,iBAAmB,sBAAO;AAAA,EAC9B,IAAM,uBAAQ,QAAQ;AAAA,EACtB,WAAa,sBAAO;AAAA,EACpB,YAAY;AAAA;AAAA,EAEZ,OAAO;AACT,CAAC;AAKD,IAAM,iBAAmB,sBAAO;AAAA,EAC9B,IAAM,uBAAQ,QAAQ;AAAA,EACtB,WAAa,sBAAO;AAAA,EACpB,YAAY;AAAA;AAAA,EAEZ,OAAO;AACT,CAAC;AAED,IAAM,eAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,gBAAkB,sBAAO;AAAA,EAC7B,KAAO,qBAAM,YAAY;AAC3B,CAAC;AAED,IAAM,iBAAmB,qBAAM,CAAC,aAAa,CAAC;AAEvC,IAAM,qBAAuB,sBAAO;AAAA,EACzC,MAAQ,uBAAqB,IAAI;AAAA,EACjC,IAAM,sBAAO;AAAA,EACb,UAAY,sBAAO;AAAA,EACnB,MAAQ,uBAAQ,kBAAkB;AAAA,EAClC,MAAM;AAAA,EACN,WAAa,sBAAO;AACtB,CAAC;AAEM,IAAM,uBAAyB,sBAAO;AAAA,EAC3C,MAAQ,uBAAqB,MAAM;AAAA,EACnC,IAAM,sBAAO;AAAA,EACb,UAAY,sBAAO;AAAA,EACnB,MAAQ,sBAAO;AAAA,EACf,MAAQ,qBAAM,UAAU;AAAA,EACxB,WAAa,sBAAO;AACtB,CAAC;AAEM,IAAM,iBAAmB,qBAAM,oBAAoB,oBAAoB;AAEvE,IAAM,iBAAmB,sBAAO;AAAA,EACrC,eAAiB,sBAAO;AAAA,EACxB,WAAa,qBAAM,cAAc;AAAA,EACjC,aAAe,sBAAO;AAAA;AAAA;AAAA;AAAA,EAItB,eAAiB,sBAAO,EAAE,SAAS;AAAA,EACnC,WAAa,sBAAO;AAAA,EACpB,WAAa,sBAAO;AACtB,CAAC;AAEM,IAAM,oBAAsB,qBAAM,CAAG,uBAAQ,MAAM,GAAG,cAAc,CAAC;AAE5E,IAAM,iBAAmB,sBAAO;AAAA,EAC9B,OAAS,uBAAQ,KAAK;AAAA;AAAA,EAEtB,SAAW,sBAAO,EAAE,SAAS;AAAA,EAC7B,SAAS,WAAW,SAAS;AAC/B,CAAC;AACD,IAAM,kBAAoB,sBAAO;AAAA,EAC/B,OAAS;AAAA;AAAA,IAEL,uBAAQ,aAAa;AAAA,IACrB,uBAAQ,kBAAkB;AAAA,EAC9B;AAAA,EACA,SAAS,WAAW,SAAS;AAC/B,CAAC;AAED,IAAM,mBAAqB,sBAAO;AAAA;AAAA,EAEhC,MAAM,WAAW,SAAS;AAC5B,CAAC;AACD,IAAM,sBAAwB,qBAAM,gBAAgB,eAAe;AAE5D,IAAM,uBAAyB;AAAA,EACpC;AAAA,EACA;AACF;AAEO,IAAM,yBAA2B,sBAAO;AAAA,EAC7C,IAAI;AAAA,EACJ,QAAQ;AACV,CAAC;AAED,IAAM,eAAiB,sBAAO;AAAA,EAC5B,WAAa,qBAAM,sBAAsB;AAC3C,CAAC;AAKD,IAAM,+BAAiC,sBAAO;AAAA;AAAA,EAE5C,OAAS,uBAAQ,wBAAwB;AAAA;AAAA,EAEzC,aAAe,qBAAM,gBAAgB,EAAE,SAAS;AAClD,CAAC;AAID,IAAM,iCAAmC,sBAAO;AAAA;AAAA,EAE9C,OAAS,uBAAQ,0BAA0B;AAAA;AAAA,EAE3C,aAAe,qBAAM,gBAAgB,EAAE,SAAS;AAClD,CAAC;AAID,IAAM,kBAAoB,sBAAO;AAAA;AAAA,EAE/B,OAAS,uBAAQ,MAAM;AAAA;AAAA,EAEvB,QAAU,sBAAO;AAAA;AAAA,EAEjB,SAAW,sBAAO;AAAA;AAAA,EAElB,aAAe,qBAAM,gBAAgB,EAAE,SAAS;AAClD,CAAC;AAID,IAAM,wBAA0B,sBAAO;AAAA;AAAA,EAErC,OAAS,uBAAQ,YAAY;AAAA;AAAA,EAE7B,SAAW,sBAAO;AAAA;AAAA,EAElB,aAAe,qBAAM,gBAAgB,EAAE,SAAS;AAClD,CAAC;AAID,IAAM,kBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,yBAA2B,qBAAM,cAAc,eAAe;AAEpE,IAAM,qBAAuB;AAAA,EAClC;AAAA,EACA;AACF;AACO,IAAM,4BAA8B,qBAAM;AAAA,EAC7C,uBAAQ,cAAc;AAAA,EACxB;AACF,CAAC;AAEM,IAAM,oCAAsC,qBAAM;AAAA,EACrD,uBAAQ,sBAAsB;AAAA,EAChC;AACF,CAAC;AAKM,IAAM,mBAAqB,sBAAO;AAAA,EACvC,QAAU,sBAAO;AAAA,EACjB,OAAS,sBAAO;AAClB,CAAC;AA+BM,SAAS,QACd,KACA,KACiB;AACjB,SAAO;AAAA,IACL,KAAK,IAAI,IAAI;AAAA,MACX,CAAC,EAAC,IAAI,WAAW,YAAY,MAAK,OAC/B;AAAA,QACC;AAAA,QACA,WAAW,IAAI,UAAU,SAAS;AAAA,QAClC,YAAY,IAAI,QAAQ,WAAW,UAAU;AAAA,QAC7C,OAAO,IAAI,IAAI,WAAW,KAAK;AAAA;AAAA;AAAA,MAGjC;AAAA,IACJ;AAAA,EACF;AACF;;;AC1PO,IAAMC,eAAgB,sBAAO;AAAA,EAClC,IAAM,uBAAQ,KAAK;AAAA,EACnB,UAAU;AACZ,CAAC;AACM,IAAMC,eAAgB,sBAAO;AAAA,EAClC,IAAM,uBAAQ,KAAK;AAAA,EACnB,IAAI;AACN,CAAC;AAED,IAAMC,iBAAkB,qBAAMF,cAAaC,YAAW;AAC/C,IAAM,uBAAyB,qBAAMC,cAAa;;;AChBzD,IAAMC,eAAgB,sBAAO;AAAA,EAC3B,IAAM,uBAAQ,KAAK;AAAA,EACnB,WAAa,sBAAO;AAAA,EACpB,OAAO;AACT,CAAC;AAED,IAAMC,kBAAmB,sBAAO;AAAA,EAC9B,IAAM,uBAAQ,QAAQ;AAAA,EACtB,WAAa,sBAAO;AAAA,EACpB,IAAI;AAAA,EACJ,OAAO,iBAAiB,SAAS;AAAA,EACjC,WAAa,qBAAQ,sBAAO,CAAC,EAAE,SAAS;AAC1C,CAAC;AAED,IAAMC,eAAgB,sBAAO;AAAA,EAC3B,IAAM,uBAAQ,KAAK;AAAA,EACnB,WAAa,sBAAO;AAAA,EACpB,IAAI;AACN,CAAC;AAED,IAAMC,iBAAkB,sBAAO;AAAA,EAC7B,IAAM,uBAAQ,OAAO;AACvB,CAAC;AAED,IAAM,mBAAqB;AAAA,EACzBH;AAAA,EACAC;AAAA,EACAC;AAAA,EACAC;AACF;AAEO,IAAM,kBAAoB,qBAAM,gBAAgB;;;AClChD,IAAM,gBAAkB,sBAAO;AAC/B,IAAM,wBAA0B,qBAAM,eAAiB,oBAAK,CAAC;;;AC4B7D,IAAM,sBAAwB,sBAAO;AAAA,EAC1C,QAAU,sBAAO;AAAA;AAAA;AAAA;AAAA,EAIjB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA,EAKZ,gBACG,sBAAO;AAAA,IACN,qBAAuB,sBAAO;AAAA,IAC9B,qBAAuB,sBAAO;AAAA,EAChC,CAAC,EACA,SAAS;AAAA,EACZ,WAAa,sBAAO,EAAE,SAAS;AACjC,CAAC;AAEM,IAAM,qBAAuB,sBAAO;AAAA,EACzC,QAAU,sBAAO;AAAA;AAAA,EAEjB,uBAAyB,sBAAS,sBAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EAErD,uBAAyB,sBAAO,kBAAkB,EAAE,SAAS;AAAA;AAAA;AAAA,EAG7D,iBAAiB,mBAAmB,SAAS;AAAA;AAAA,EAE7C,WAAW,gBAAgB,SAAS;AAAA;AAAA,EAEpC,gBAAgB,qBAAqB,SAAS;AAChD,CAAC;AAEM,IAAM,oBAAsB,sBAAO;AAAA,EACxC,QAAU,sBAAO;AAAA;AAAA,EAEjB,QAAQ;AAAA;AAAA;AAAA,EAGR,QAAU,uBAAQ,EAAE,SAAS;AAC/B,CAAC;AAEM,IAAM,yBAA2B,qBAAM;AAAA,EAC1C,uBAAQ,WAAW;AAAA,EACrB;AACF,CAAC;AACM,IAAM,wBAA0B,qBAAM;AAAA,EACzC,uBAAQ,UAAU;AAAA,EACpB;AACF,CAAC;AACM,IAAM,uBAAyB,qBAAM;AAAA,EACxC,uBAAQ,SAAS;AAAA,EACnB;AACF,CAAC;;;ACnFM,IAAM,iBAAmB,sBAAO,CAAC,CAAC;AAClC,IAAM,oBAAsB,qBAAM,CAAG,uBAAQ,MAAM,GAAG,cAAc,CAAC;;;ACArE,IAAM,wBAA0B,sBAAO;AAAA,EAC5C,eAAiB,sBAAO;AAAA,EACxB,QAAQ;AAAA,EACR,WAAa,sBAAO;AACtB,CAAC;AAEM,IAAM,yBAA2B,sBAAO;AAAA,EAC7C,QAAQ;AAAA;AAAA,EAER,WAAa,sBAAO;AAAA,EACpB,uBAAyB,sBAAS,sBAAO,CAAC;AAAA;AAAA;AAG5C,CAAC;AAEM,IAAM,2BAA6B,qBAAM;AAAA,EAC5C,uBAAQ,MAAM;AAAA,EAChB;AACF,CAAC;AAEM,IAAM,4BAA8B,qBAAM;AAAA,EAC7C,uBAAQ,MAAM;AAAA,EAChB;AACF,CAAC;;;ACXM,IAAM,mBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;ACoBO,IAAM,mBAAmB;AAYzB,IAAM,qCAAqC;AAElD,OAAO,qCAAqC,gBAAgB;;;AC/CrD,IAAM,aAAN,MAAiB;AAAA,EACb,UAAU,oBAAI,IAAuB;AAAA,EAE9C,YAAY,QAAgC;AAC1C,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAU,KAAa,KAA4B;AACjD,UAAMC,SAAQ,KAAK,QAAQ,IAAI,GAAG;AAClC,QAAI,CAACA,QAAO;AACV,YAAM,IAAI;AAAA,QACR,kBAAkB,GAAG,KAAK,CAAC,MAAM,KAAK,MAAM,KAAK,UAAU,GAAG,CAAC,EAAE;AAAA,MACnE;AAAA,IACF;AACA,WAAOA;AAAA,EACT;AAAA,EAEA,UAAU,KAAa,SAA6B;AAClD,WAAO,KAAK,UAAU,KAAK,OAAO,EAAE;AAAA,EACtC;AAAA,EAEA,WAAWA,QAAe,KAAa,KAAyB;AAC9D,UAAM,MAAM,KAAK,UAAUA,QAAO,GAAG,EAAE,QAAQ,GAAG;AAClD,QAAI,CAAC,KAAK;AACR,YAAM,IAAI;AAAA,QACR,mBAAmB,GAAG,SAASA,MAAK,WAClC,CAAC,MAAM,KAAK,MAAM,KAAK,UAAU,GAAG,CAAC,EACvC;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IACEA,QACA,KAC6B;AAC7B,UAAM,OAAO,KAAK,UAAUA,MAAK;AACjC,UAAM,EAAC,gBAAgB,QAAO,IAAI;AAClC,QAAI,gBAAgB;AAClB,aAAO;AAAA,IACT;AACA,UAAM,YAA+B,CAAC;AACtC,eAAW,OAAO,KAAK;AAErB,gBAAU,QAAQ,GAAG,KAAK,GAAG,IAAI,IAAI,GAAG;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QACEA,QACA,MACS;AACT,UAAM,OAAO,KAAK,UAAUA,MAAK;AACjC,UAAM,EAAC,gBAAgB,QAAO,IAAI;AAGlC,WAAO,SAAS,UAAa,iBACzB,OACC,KAAK,IAAI,SAAO,QAAQ,GAAG,KAAK,GAAG;AAAA,EAC1C;AACF;;;ACvEO,SAAS,eACd,QACY;AACZ,SAAO,iBAAiB,UAAU,MAAM;AAC1C;AAEO,SAAS,eACd,QACY;AACZ,SAAO,iBAAiB,UAAU,MAAM;AAC1C;AAEA,SAAS,iBACP,KACA,QACY;AACZ,QAAM,UAAU,IAAI;AAAA,IAClB,OAAO,QAAQ,MAAM,EAAE;AAAA,MACrB,CAAC,CAAC,WAAW,EAAC,YAAY,iBAAiB,QAAO,CAAC,MAAM;AACvD,YAAI,iBAAiB;AACrB,cAAM,QAAgC,CAAC;AACvC,mBAAW,CAAC,MAAM,EAAC,WAAU,CAAC,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC1D,cAAI,cAAc,eAAe,MAAM;AACrC,6BAAiB;AAAA,UACnB;AACA,cAAI,QAAQ,UAAU;AACpB,kBAAM,IAAI,IAAI,cAAc;AAAA,UAC9B,OAAO;AACL,kBAAM,cAAc,IAAI,IAAI;AAAA,UAC9B;AAAA,QACF;AACA,eAAO;AAAA,UACL,QAAQ,WAAW,YAAa,mBAAmB;AAAA,UACnD;AAAA,YACE,WACE,QAAQ,WAAY,mBAAmB,YAAa;AAAA,YACtD,SAAS;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO,IAAI,WAAW,OAAO;AAC/B;;;ACyFO,SAAS,iBAAiB,WAAmB,MAAc;AAChE,SAAO,CAAC,UAAU,SAAS,GAAG,GAAG,yCAAyC;AAC1E,SAAO,CAAC,KAAK,SAAS,GAAG,GAAG,oCAAoC;AAChE,SAAO,GAAG,SAAS,IAAI,IAAI;AAC7B;;;ACvHO,SAAS,eACd,QACiC;AACjC,SAAO,OAAO,SAAS,SAAS,KAAK,OAAO,SAAS,aAAa;AACpE;;;AC1BA,SAAQ,YAAAC,iBAAe;;;ACEvB,IAAM,YAAY,oBAAI,QAAqB;AAEpC,SAAS,UAAU,KAAkB;AAC1C,QAAM,aAAa,aAAa,GAAG;AACnC,QAAM,SAAS,UAAU,IAAI,UAAU;AACvC,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AACA,QAAM,OAAO,IAAI,KAAK,UAAU,UAAU,CAAC,EAAE,SAAS,EAAE;AACxD,YAAU,IAAI,YAAY,IAAI;AAC9B,SAAO;AACT;AAEO,SAAS,kBACd,MACA,MACQ;AACR,QAAM,aAAa,KAAK,UAAU,IAAI;AACtC,SAAO,IAAI,GAAG,IAAI,IAAI,UAAU,EAAE,EAAE,SAAS,EAAE;AACjD;;;ACoBO,IAAM,oBAAkC;AAAA,EAC7C,KAAK,SAAuB;AAC1B,UAAM,IAAI,MAAM,gBAAgB;AAAA,EAClC;AAAA,EAEA,OAAO,OAAa,UAAmB;AACrC,UAAM,IAAI,MAAM,gBAAgB;AAAA,EAClC;AACF;AAEO,IAAM,cAAN,MAAiD;AAAA,EAC7C;AAAA,EACT,UAAwB;AAAA,EAExB,YAAY,OAAc;AACxB,SAAK,SAAS;AACd,UAAM,UAAU,IAAI;AAAA,EACtB;AAAA,EAEA,gBAAgB,QAAsB;AACpC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,KAAK,QAAgB;AACnB,SAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,EAChC;AAAA,EAEA,CAAC,MAAM,KAAiC;AACtC,eAAW,QAAQ,KAAK,OAAO,MAAM,GAAG,GAAG;AACzC,UAAI,KAAK,QAAQ,OAAO,MAAM,KAAK,GAAG;AACpC,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,KAAiC;AACxC,eAAW,QAAQ,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC3C,UAAI,KAAK,QAAQ,OAAO,MAAM,IAAI,GAAG;AACnC,cAAM;AAAA,MACR,OAAO;AACL,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,YAAN,MAA+C;AAAA,EAC3C;AAAA,EACA;AAAA,EAET,UAAkB;AAAA,EAElB,YAAY,OAAoB,OAAoB;AAClD,SAAK,SAAS;AACd,SAAK,SAAS;AACd,UAAM,gBAAgB,IAAI;AAAA,EAC5B;AAAA,EAEA,CAAC,MAAM,KAAiC;AACtC,eAAW,QAAQ,KAAK,OAAO,MAAM,GAAG,GAAG;AACzC,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,KAAiC;AACxC,eAAW,QAAQ,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC3C,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,OAAO,OAAa,UAAmB;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,QAAgB;AACxB,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,KAAK,QAAgB;AACnB,SAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,EAChC;AACF;AAEO,SAAS,oBACd,OACA,UACA,UACO;AACP,QAAM,cAAc,IAAI,YAAY,KAAK;AACzC,WAAS,QAAQ,OAAO,WAAW;AACnC,QAAM,SAAS,SAAS,WAAW;AACnC,WAAS,QAAQ,aAAa,MAAM;AACpC,QAAM,YAAY,IAAI,UAAU,aAAa,MAAM;AACnD,WAAS,QAAQ,QAAQ,SAAS;AAClC,SAAO;AACT;;;ACxEO,IAAM,cAAsB;AAAA,EACjC,KAAK,SAAuB;AAC1B,UAAM,IAAI,MAAM,gBAAgB;AAAA,EAClC;AACF;;;AC5EO,UAAU,KAAQ,QAAmB,OAA0B;AACpE,MAAI,QAAQ,GAAG;AACb;AAAA,EACF;AACA,MAAI,QAAQ;AACZ,aAAW,KAAK,QAAQ;AACtB,UAAM;AACN,QAAI,EAAE,UAAU,OAAO;AACrB;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,MAAS,QAAkC;AACzD,QAAM,KAAK,OAAO,OAAO,QAAQ,EAAE;AACnC,QAAM,EAAC,MAAK,IAAI,GAAG,KAAK;AACxB,KAAG,SAAS;AACZ,SAAO;AACT;;;ACcO,IAAM,SAAN,MAAuC;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUxB,UAAU;AAAA,EAEV,YACE,OACA,SACA,kBACA,eACA,MACA;AACA,SAAK,SAAS;AACd,SAAK,oBAAoB;AACzB,SAAK,OAAO,gBAAgB,IAAI;AAChC,SAAK,WAAW;AAChB;AAAA,MACE,KAAK,OAAO,UAAU,EAAE,cAAc,gBAAgB;AAAA,MACtD,wBAAwB,gBAAgB;AAAA,IAC1C;AACA,SAAK,OAAO,SAAS;AACrB,SAAK,iBAAiB;AAGtB,SAAK,eAAe;AAAA,MAClB;AAAA,MACA,KAAK,OAAO,UAAU,EAAE;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,gBAAgB,QAA4B;AAC1C,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,OAAO,MAAY,SAA2B;AAC5C,UAAM,SAAS,KAAK,QAAQ,IAAI,KAAK,KAAK,QAAQ,OAAO,MAAM,OAAO;AACtE,QAAI,SAAS;AACX,WAAK,SAAS,IAAI;AAAA,IACpB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,KAAK,QAAgB;AACnB,WAAO,CAAC,KAAK,SAAS,wBAAwB;AAC9C,SAAK,UAAU;AACf,QAAI;AACF,cAAQ,OAAO,MAAM;AAAA;AAAA;AAAA,QAGnB,KAAK;AAAA,QACL,KAAK,QAAQ;AACX,eAAK,gBAAgB,MAAM;AAC3B;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,gBAAM,OAAO,KAAK,SAAS,OAAO,IAAI;AAItC,cAAI,SAAS,QAAW;AACtB;AAAA,UACF;AACA,eAAK,gBAAgB,QAAQ,IAAI;AACjC,eAAK,SAAS,OAAO,IAAI;AACzB;AAAA,QACF;AAAA,QACA,KAAK;AAKH,cACE,OAAO,MAAM,qBAAqB,KAAK,qBACvC,OAAO,MAAM,OAAO,SAAS,UAC7B,OAAO,MAAM,OAAO,SAAS,SAC7B;AACA,iBAAK,gBAAgB,MAAM;AAC3B;AAAA,UACF;AACA,kBAAQ,OAAO,MAAM,OAAO,MAAM;AAAA,YAChC,KAAK,OAAO;AACV,kBAAI,OAAO,KAAK,SAAS,OAAO,IAAI;AACpC,kBAAI,SAAS,QAAW;AACtB;AACA,qBAAK,SAAS,OAAO,MAAM,IAAI;AAAA,cACjC,OAAO;AACL,uBAAO,KAAK,WAAW,OAAO,IAAI;AAAA,cACpC;AACA,kBAAI,SAAS,GAAG;AACd,oBAAI,KAAK,MAAM;AAKb,uBAAK,QAAQ;AAAA,oBACX;AAAA,sBACE,MAAM;AAAA,sBACN,MAAM;AAAA,wBACJ,KAAK,OAAO,KAAK;AAAA,wBACjB,eAAe;AAAA,0BACb,GAAG,OAAO,KAAK;AAAA,0BACf,CAAC,KAAK,iBAAiB,GAAG,MAAM,CAAC;AAAA,wBACnC;AAAA,sBACF;AAAA,oBACF;AAAA,oBACA;AAAA,kBACF;AAAA,gBACF,OAAO;AACL,uBAAK,QAAQ;AAAA,oBACX;AAAA,sBACE,MAAM;AAAA,sBACN,MAAM,OAAO;AAAA,oBACf;AAAA,oBACA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF,OAAO;AACL,qBAAK,gBAAgB,QAAQ,IAAI;AAAA,cACnC;AACA;AAAA,YACF;AAAA,YACA,KAAK,UAAU;AACb,kBAAI,OAAO,KAAK,SAAS,OAAO,IAAI;AACpC,kBAAI,SAAS,QAAW;AACtB,uBAAO,OAAO,CAAC;AACf;AACA,qBAAK,SAAS,OAAO,MAAM,IAAI;AAAA,cACjC,OAAO;AACL,uBAAO,KAAK,WAAW,OAAO,IAAI;AAAA,cACpC;AACA,kBAAI,SAAS,GAAG;AACd,oBAAI,KAAK,MAAM;AACb,uBAAK,QAAQ;AAAA,oBACX;AAAA,sBACE,MAAM;AAAA,sBACN,MAAM,OAAO;AAAA,oBACf;AAAA,oBACA;AAAA,kBACF;AAAA,gBACF,OAAO;AAIL,uBAAK,QAAQ;AAAA,oBACX;AAAA,sBACE,MAAM;AAAA,sBACN,MAAM;AAAA,wBACJ,KAAK,OAAO,KAAK;AAAA,wBACjB,eAAe;AAAA,0BACb,GAAG,OAAO,KAAK;AAAA,0BACf,CAAC,KAAK,iBAAiB,GAAG,MAAM;AAAA,4BAC9B,OAAO,MAAM,OAAO;AAAA,0BACtB;AAAA,wBACF;AAAA,sBACF;AAAA,oBACF;AAAA,oBACA;AAAA,kBACF;AAAA,gBACF;AAAA,cACF,OAAO;AACL,qBAAK,gBAAgB,QAAQ,IAAI;AAAA,cACnC;AACA;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AACE,sBAAY,MAAM;AAAA,MACtB;AAAA,IACF,UAAE;AACA,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,QAAQ,MAAY,MAAwB;AAC1C,UAAM,UAAU,QAAQ,KAAK,gBAAgB,IAAI,KAAK;AACtD,WAAO,KAAK,OAAO,CAAC,SAAS;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,QAAgB,MAAqB;AACnD,QAAI,KAAK,QAAQ,OAAO,MAAM,IAAI,GAAG;AACnC,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,SAAS,MAAgC;AACvC,WAAO,KAAK,SAAS,IAAI,KAAK,oBAAoB,IAAI,CAAC;AAAA,EACzD;AAAA,EAEA,SAAS,MAAY,MAAc;AACjC,SAAK,SAAS,IAAI,KAAK,oBAAoB,IAAI,GAAG,IAAI;AAAA,EACxD;AAAA,EAEA,SAAS,MAAY;AACnB,SAAK,SAAS,IAAI,KAAK,oBAAoB,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,gBAAgB,MAAoB;AAClC,UAAM,OAAO,KAAK,SAAS,IAAI;AAC/B,QAAI,SAAS,QAAW;AACtB,aAAO;AAAA,IACT;AACA,WAAO,KAAK,WAAW,IAAI;AAAA,EAC7B;AAAA,EAEA,WAAW,MAAoB;AAC7B,QAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,SAAS;AACvC,YAAM,kBAAkB;AAAA,QACtB,KAAK,SAAS,KAAK;AAAA,UACjB,QAAQ,KAAK,0BAA0B,IAAI;AAAA,QAC7C,CAAC;AAAA,MACH;AACA,UAAI,oBAAoB,QAAW;AACjC,aAAK,SAAS,MAAM,gBAAgB,CAAC,CAAC;AACtC,eAAO,gBAAgB,CAAC;AAAA,MAC1B;AAAA,IACF;AAEA,UAAM,eAAe,KAAK,cAAc,KAAK,iBAAiB;AAC9D,WAAO,YAAY;AACnB,QAAI,OAAO;AACX,eAAW,gBAAgB,aAAa,GAAG;AACzC;AAAA,IACF;AAEA,SAAK,SAAS,MAAM,IAAI;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,0BAA0B,MAAkC;AAC1D,WAAO,OACL,KAAK,eACD,KACA,KAAK,UAAU,KAAK,cAAc,MAAM,KAAK,cAAc,CAAC,CAClE;AAAA,EACF;AAAA,EAEA,oBAAoB,MAA4B;AAC9C,WAAO,GAAG,KAAK,0BAA0B,IAAI,CAAC,GAAG,KAAK;AAAA,MACpD,KAAK,cAAc,MAAM,KAAK,OAAO,UAAU,EAAE,UAAU;AAAA,IAC7D,CAAC;AAAA,EACH;AAAA,EAEA,cAAc,MAAY,KAAqC;AAC7D,UAAM,SAA4B,CAAC;AACnC,eAAW,OAAO,KAAK;AACrB,aAAO,KAAK,mBAAmB,KAAK,IAAI,GAAG,CAAC,CAAC;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AACF;;;ACxPO,SAAS,uBACd,mBACA,QACA,QACA,kBACAC,qBACA,uBACA;AACA,MAAI,kBAAkB,WAAW,GAAG;AAGlC;AAAA,EACF;AAGA,QAAM,mBAAmB,oBAAI,IAA4B;AACzD,aAAW,UAAU,mBAAmB;AACtC,QAAI,qBAAqB,WAAW,OAAO,SAAS,SAAS;AAC3D;AAAA,QACE,iBAAiB,IAAI,OAAO,IAAI,MAAM;AAAA,QACtC,MACE,qCAAqC,OAAO,IAAI;AAAA,MACpD;AAAA,IACF;AAEA,UAAM,WAAW,iBAAiB,IAAI,OAAO,IAAI;AACjD,QAAI,eAAe;AACnB,QAAI,UAAU;AAEZ,qBAAeA,oBAAmB,UAAU,MAAM;AAAA,IACpD;AACA,qBAAiB,IAAI,OAAO,MAAM,YAAY;AAAA,EAChD;AAEA,oBAAkB,SAAS;AAE3B,QAAM,QAAQ,CAAC,GAAG,iBAAiB,KAAK,CAAC;AAWzC,UAAQ,kBAAkB;AAAA,IACxB,KAAK;AACH;AAAA,QACE,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM;AAAA,QACnC;AAAA,MACF;AACA,aAAO;AAAA,QACL,sBAAsB,KAAK,iBAAiB,IAAI,QAAQ,CAAC,CAAC;AAAA,QAC1D;AAAA,MACF;AACA;AAAA,IACF,KAAK;AACH;AAAA,QACE,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM;AAAA,QACnC;AAAA,MACF;AACA,aAAO;AAAA,QACL,sBAAsB,KAAK,iBAAiB,IAAI,KAAK,CAAC,CAAC;AAAA,QACvD;AAAA,MACF;AACA;AAAA,IACF,KAAK,QAAQ;AACX;AAAA,QACE,MAAM;AAAA,UACJ,UAAQ,SAAS,SAAS,SAAS,YAAY,SAAS;AAAA,QAC1D;AAAA,QACA;AAAA,MACF;AACA,YAAM,YAAY,iBAAiB,IAAI,KAAK;AAC5C,YAAM,eAAe,iBAAiB,IAAI,QAAQ;AAClD,UAAI,aAAa,iBAAiB,IAAI,MAAM;AAI5C,UAAI,YAAY;AACd,YAAI,WAAW;AACb,uBAAaA,oBAAmB,YAAY,SAAS;AAAA,QACvD;AACA,YAAI,cAAc;AAChB,uBAAaA,oBAAmB,YAAY,YAAY;AAAA,QAC1D;AACA,eAAO,KAAK,sBAAsB,UAAU,GAAG,MAAM;AACrD;AAAA,MACF;AAmBA,UAAI,aAAa,cAAc;AAC7B,eAAO;AAAA,UACL,sBAAsB;AAAA,YACpB,MAAM;AAAA,YACN,MAAM,UAAU;AAAA,YAChB,SAAS,aAAa;AAAA,UACxB,CAAU;AAAA,UACV;AAAA,QACF;AACA;AAAA,MACF;AAEA,aAAO;AAAA,QACL,sBAAsB,KAAK,aAAa,YAAY,CAAC;AAAA,QACrD;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ;AAAA,QACE,MAAM;AAAA,UACJ,UACE,SAAS;AAAA,UACT,SAAS;AAAA,UACT,SAAS;AAAA;AAAA,QACb;AAAA,QACA;AAAA,MACF;AACA;AAAA,QACE,MAAM,UAAU;AAAA,QAChB;AAAA,MACF;AAGA,YAAM,cAAc,iBAAiB,IAAI,OAAO;AAChD,UAAI,aAAa;AACf,eAAO,KAAK,aAAa,MAAM;AAC/B;AAAA,MACF;AAEA,YAAM,YAAY,iBAAiB,IAAI,KAAK;AAC5C,YAAM,eAAe,iBAAiB,IAAI,QAAQ;AAElD;AAAA,QACE,cAAc,UAAa,iBAAiB;AAAA,QAC5C;AAAA,MACF;AAEA,aAAO;AAAA,QACL,sBAAsB,KAAK,aAAa,YAAY,CAAC;AAAA,QACrD;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA;AACE;AAAA,EACJ;AACF;AAKO,SAAS,mBAAmB,MAAc,OAAuB;AAItE,MAAI,KAAK,SAAS,MAAM,MAAM;AAC5B,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK,OAAO;AACV,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,KAAK,KAAK,KAAK;AAAA,YACf,eAAe;AAAA,cACb,GAAG,MAAM,KAAK;AAAA,cACd,GAAG,KAAK,KAAK;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,KAAK,KAAK,KAAK;AAAA,YACf,eAAe;AAAA,cACb,GAAG,MAAM,KAAK;AAAA,cACd,GAAG,KAAK,KAAK;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX,eAAO,MAAM,SAAS,MAAM;AAE5B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,YACJ,KAAK,KAAK,KAAK;AAAA,YACf,eAAe;AAAA,cACb,GAAG,MAAM,KAAK;AAAA,cACd,GAAG,KAAK,KAAK;AAAA,YACf;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,KAAK,KAAK,QAAQ;AAAA,YAClB,eAAe;AAAA,cACb,GAAG,MAAM,QAAQ;AAAA,cACjB,GAAG,KAAK,QAAQ;AAAA,YAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,SAAO,KAAK,SAAS,MAAM;AAC3B,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,OAAO;AACV,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,YACb,GAAG,MAAM,KAAK;AAAA,YACd,GAAG,KAAK,KAAK;AAAA,UACf;AAAA,QACF;AAAA,QACA,SAAS,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,QACX,SAAS;AAAA,UACP,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,YACb,GAAG,MAAM,KAAK;AAAA,YACd,GAAG,KAAK,QAAQ;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,cAAY;AACd;AAEO,SAAS,0BACd,QAC4B;AAC5B,SAAO,CAAC,WAA2B;AACjC,QAAI,OAAO,KAAK,OAAO,aAAa,EAAE,WAAW,GAAG;AAClD,aAAO;AAAA,IACT;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK,UAAU;AACb,cAAM,MAAM;AAAA,UACV,GAAG;AAAA,UACH,MAAM;AAAA,YACJ,GAAG,OAAO;AAAA,YACV,eAAe;AAAA,cACb,GAAG,OAAO,KAAK;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAEA,mBAAW,IAAI,KAAK,eAAe,OAAO,KAAK,OAAO,aAAa,CAAC;AAEpE,eAAO;AAAA,MACT;AAAA,MACA,KAAK,QAAQ;AACX,cAAM,MAAM;AAAA,UACV,GAAG;AAAA,UACH,MAAM;AAAA,YACJ,GAAG,OAAO;AAAA,YACV,eAAe;AAAA,cACb,GAAG,OAAO,KAAK;AAAA,YACjB;AAAA,UACF;AAAA,UACA,SAAS;AAAA,YACP,GAAG,OAAO;AAAA,YACV,eAAe;AAAA,cACb,GAAG,OAAO,QAAQ;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAEA,mBAAW,IAAI,KAAK,eAAe,OAAO,KAAK,OAAO,aAAa,CAAC;AACpE;AAAA,UACE,IAAI,QAAQ;AAAA,UACZ,OAAO,KAAK,OAAO,aAAa;AAAA,QAClC;AAEA,eAAO;AAAA,MACT;AAAA,MACA,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AACF;AAQO,SAAS,WACd,eACA,mBACA;AACA,aAAW,WAAW,mBAAmB;AACvC,QAAI,cAAc,OAAO,MAAM,QAAW;AACxC,oBAAc,OAAO,IAAI,MAAM;AAAA,IACjC;AAAA,EACF;AACF;;;AC5XO,IAAM,QAAN,MAAsC;AAAA,EAClC;AAAA,EACA;AAAA,EACT,UAAwB;AAAA,EACxB,qBAA+B,CAAC;AAAA,EAEhC,YAAY,QAAgB,QAAuB;AACjD,SAAK,UAAU;AACf,SAAK,UAAU,OAAO,UAAU;AAChC,eAAW,SAAS,QAAQ;AAC1B,YAAM,gBAAgB,IAAI;AAC1B,aAAO,KAAK,YAAY,MAAM,UAAU,GAAG,2BAA2B;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,gBAAgB,QAA4B;AAC1C,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,eAAW,SAAS,KAAK,SAAS;AAChC,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,MAAY,SAA2B;AAC5C,WAAO,KAAK,QAAQ,OAAO,MAAM,OAAO;AAAA,EAC1C;AAAA,EAEA,KAAK,QAAgB;AACnB,SAAK,mBAAmB,KAAK,MAAM;AAAA,EACrC;AAAA,EAEA,+BAA+B,kBAAkC;AAC/D,QAAI,KAAK,QAAQ,WAAW,GAAG;AAC7B;AAAA,QACE,KAAK,mBAAmB,WAAW;AAAA,QACnC;AAAA,MACF;AACA;AAAA,IACF;AAEA;AAAA,MACE,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACpEO,IAAM,SAAN,MAAuC;AAAA,EACnC;AAAA,EACA,WAA2B,CAAC;AAAA,EACrC;AAAA,EACA,gBAAwB;AAAA,EAExB,YAAY,OAAoB;AAC9B,SAAK,SAAS;AACd,UAAM,gBAAgB,IAAI;AAAA,EAC5B;AAAA,EAEA,SAAS,OAAc;AACrB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,gBAAgB,QAA4B;AAC1C,SAAK,SAAS,KAAK,MAAM;AAAA,EAC3B;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,gBAAgB,KAAK,SAAS,QAAQ;AAC7C,QAAE,KAAK;AACP,UAAI,KAAK,kBAAkB,KAAK,SAAS,QAAQ;AAC/C,aAAK,OAAO,QAAQ;AAAA,MACtB;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAAA,EACF;AAAA,EAEA,YAAY;AACV,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,OAAO,MAAY,SAA2B;AAC5C,QAAI,SAAS;AACb,eAAW,UAAU,KAAK,UAAU;AAClC,eAAS,OAAO,OAAO,MAAM,OAAO,KAAK;AAGzC,UAAI,CAAC,WAAW,QAAQ;AACtB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,QAAgB;AACnB,eAAW,OAAO,KAAK,UAAU;AAC/B,UAAI,KAAK,QAAQ,IAAI;AAAA,IACvB;AACA;AAAA,MACE,KAAK;AAAA,MACL;AAAA,IACF,EAAE,+BAA+B,OAAO,IAAI;AAAA,EAC9C;AACF;;;AC9DO,SAAS,4BACd,QACA,WACA,QACA,QACA;AACA,QAAM,gBAAgB,UAAU,OAAO,QAAQ,GAAG;AAClD,QAAM,eAAe,UAAU,OAAO,KAAK,GAAG;AAE9C,MAAI,iBAAiB,cAAc;AACjC,WAAO,KAAK,QAAQ,MAAM;AAAA,EAC5B,WAAW,iBAAiB,CAAC,cAAc;AACzC,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF,WAAW,CAAC,iBAAiB,cAAc;AACzC,WAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO;AAAA,MACf;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC/BO,SAAS,WACd,QACA,QACA,QACA,WACA;AACA,MAAI,CAAC,WAAW;AACd,WAAO,KAAK,QAAQ,MAAM;AAC1B;AAAA,EACF;AACA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACH,UAAI,UAAU,OAAO,KAAK,GAAG,GAAG;AAC9B,eAAO,KAAK,QAAQ,MAAM;AAAA,MAC5B;AACA;AAAA,IACF,KAAK;AACH,UAAI,UAAU,OAAO,KAAK,GAAG,GAAG;AAC9B,eAAO,KAAK,QAAQ,MAAM;AAAA,MAC5B;AACA;AAAA,IACF,KAAK;AACH,kCAA4B,QAAQ,WAAW,QAAQ,MAAM;AAC7D;AAAA,IACF;AACE,kBAAY,MAAM;AAAA,EACtB;AACF;;;ACjBO,IAAM,SAAN,MAAuC;AAAA,EACnC;AAAA,EACA;AAAA,EAET,UAAwB;AAAA,EAExB,YAAY,OAAoB,WAAkC;AAChE,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,UAAM,gBAAgB,IAAI;AAAA,EAC5B;AAAA,EAEA,OAAO,MAAY,SAA2B;AAC5C,WAAO,KAAK,WAAW,KAAK,GAAG,KAAK,KAAK,QAAQ,OAAO,MAAM,OAAO;AAAA,EACvE;AAAA,EAEA,gBAAgB,QAAsB;AACpC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,KAAK,QAAgB;AACnB,eAAW,QAAQ,KAAK,SAAS,MAAM,KAAK,UAAU;AAAA,EACxD;AACF;;;ACjCO,SAAS,qBACd,YACA,KACS;AACT,aAAW,OAAO,YAAY;AAC5B,QAAI,CAAC,YAAY,IAAI,GAAG,GAAG,WAAW,GAAG,CAAC,GAAG;AAC3C,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,yBACd,MACA,OACS;AACT,aAAW,OAAO,MAAM;AACtB,QAAI,OAAO,SAAS,CAAC,YAAY,KAAK,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG;AACvD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,4BACd,YACA,SACS;AACT,SAAO,qBAAqB,OAAO,KAAK,UAAU,GAAG,OAAO;AAC9D;AAEO,SAAS,qBACd,KACA,SACS;AACT,QAAM,iBAAiB,CAAC,GAAG,GAAG;AAE9B,MAAI,eAAe,WAAW,QAAQ,QAAQ;AAC5C,WAAO;AAAA,EACT;AAIA,iBAAe,KAAK,aAAa;AAEjC,WAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,QAAI,eAAe,CAAC,MAAM,QAAQ,CAAC,GAAG;AACpC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAkBO,SAAS,wBACd,WACmB;AACnB,MAAI,UAAU,SAAS,OAAO;AAC5B,WAAO,UAAU,WAAW,QAAQ,uBAAuB;AAAA,EAC7D;AAEA,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO,CAAC,SAAS;AAAA,EACnB;AAEA,MAAI,UAAU,SAAS,QAAQ,UAAU,WAAW,WAAW,GAAG;AAChE,WAAO,wBAAwB,UAAU,WAAW,CAAC,CAAC;AAAA,EACxD;AAEA,SAAO,CAAC;AACV;AAOO,SAAS,gCACd,WACA,SACwB;AACxB,MAAI,cAAc,QAAW;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,wBAAwB,SAAS;AACpD,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,QAAM,MAA4B,CAAC;AACnC,aAAW,gBAAgB,YAAY;AACrC,QAAI,aAAa,OAAO,KAAK;AAC3B,YAAM,SAAS,cAAc,YAAY;AACzC,UAAI,WAAW,QAAW;AACxB,YAAI,CAAC,QAAQ,SAAS,OAAO,IAAI,GAAG;AAClC;AAAA,QACF;AACA,YAAI,OAAO,IAAI,IAAI,OAAO;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,GAAG,EAAE,WAAW,QAAQ,QAAQ;AAC9C,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,SAAS,cACP,WAC0C;AAC1C,MAAI,UAAU,KAAK,SAAS,UAAU;AACpC,WAAO,UAAU,MAAM,SAAS,SAAS;AACzC,WAAO,EAAC,MAAM,UAAU,KAAK,MAAM,OAAO,UAAU,MAAM,MAAK;AAAA,EACjE;AAEA,SAAO;AACT;;;AC7IO,UAAU,oBACf,QACA,SACA,QACc;AACd,MAAI,UAAU;AACd,MAAI,iBAAiB;AACrB,MAAI,iBAAiB;AACrB,aAAW,QAAQ,QAAQ;AACzB,QAAI,YAAY;AAChB,QAAI,CAAC,SAAS;AACZ,cAAQ,QAAQ,MAAM;AAAA,QACpB,KAAK,OAAO;AACV,cAAI,OAAO,YAAY,QAAQ,KAAK,KAAK,KAAK,GAAG,MAAM,GAAG;AACxD,sBAAU;AACV,wBAAY;AAAA,UACd;AACA;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,cAAI,OAAO,YAAY,QAAQ,KAAK,KAAK,KAAK,GAAG,IAAI,GAAG;AACtD,sBAAU;AACV,kBAAM,QAAQ;AAAA,UAChB;AACA;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AACX,cACE,CAAC,kBACD,OAAO,YAAY,QAAQ,QAAQ,KAAK,KAAK,GAAG,IAAI,GACpD;AACA,6BAAiB;AACjB,gBAAI,gBAAgB;AAClB,wBAAU;AAAA,YACZ;AACA,kBAAM,QAAQ;AAAA,UAChB;AACA,cACE,CAAC,kBACD,OAAO,YAAY,QAAQ,KAAK,KAAK,KAAK,GAAG,MAAM,GACnD;AACA,6BAAiB;AACjB,gBAAI,gBAAgB;AAClB,wBAAU;AAAA,YACZ;AACA,wBAAY;AAAA,UACd;AACA;AAAA,QACF;AAAA,QACA,KAAK,SAAS;AACZ,cAAI,OAAO,YAAY,QAAQ,KAAK,KAAK,KAAK,GAAG,MAAM,GAAG;AACxD,sBAAU;AACV,kBAAM;AAAA,cACJ,KAAK,KAAK;AAAA,cACV,eAAe;AAAA,gBACb,GAAG,KAAK;AAAA,gBACR,CAAC,QAAQ,MAAM,gBAAgB,GAAG,MAChC;AAAA,kBACE,KAAK,cAAc,QAAQ,MAAM,gBAAgB,EAAE;AAAA,kBACnD,QAAQ,MAAM;AAAA,kBACd,OAAO,cAAc,QAAQ,MAAM,gBAAgB;AAAA,gBACrD;AAAA,cACJ;AAAA,YACF;AACA,wBAAY;AAAA,UACd;AACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,WAAW;AACb,YAAM;AAAA,IACR;AAAA,EACF;AACA,MAAI,CAAC,SAAS;AACZ,QAAI,QAAQ,SAAS,UAAU;AAC7B,gBAAU;AACV,YAAM,QAAQ;AAAA,IAChB,WAAW,QAAQ,SAAS,QAAQ;AAClC,aAAO,cAAc;AACrB,uBAAiB;AACjB,gBAAU;AACV,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAEA,SAAO,OAAO;AAChB;AAEO,SAAS,wBACd,GACA,GACA,KACS;AACT,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,QAAI,cAAc,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG;AAC7C,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,YACd,QACA,WACA,OACA,UACA;AACA,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,QAAI,CAAC,YAAY,OAAO,UAAU,CAAC,CAAC,GAAG,MAAM,SAAS,CAAC,CAAC,CAAC,GAAG;AAC1D,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;;;ACnFO,IAAM,cAAN,MAAmC;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAkB;AAAA,EAElB;AAAA,EAEA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAS;AACP,WAAO,WAAW,OAAO,8CAA8C;AACvE;AAAA,MACE,UAAU,WAAW,SAAS;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,oBAAoB;AAEzB,UAAM,eAAe,OAAO,UAAU;AACtC,UAAM,cAAc,MAAM,UAAU;AACpC,SAAK,UAAU;AAAA,MACb,GAAG;AAAA,MACH,eAAe;AAAA,QACb,GAAG,aAAa;AAAA,QAChB,CAAC,gBAAgB,GAAG;AAAA,UAClB,GAAG;AAAA,UACH,UAAU;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,MACf,MAAM,CAAC,WAAmB,KAAK,YAAY,MAAM;AAAA,IACnD,CAAC;AACD,UAAM,UAAU;AAAA,MACd,MAAM,CAAC,WAAmB,KAAK,WAAW,MAAM;AAAA,IAClD,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AACpB,SAAK,QAAQ,QAAQ;AAAA,EACvB;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,CAAC,MAAM,KAAiC;AAGtC,UAAM,kBAAyC,CAAC;AAChD,QAAI,qBAAqB;AACzB,QAAI,IAAI,YAAY;AAClB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,UAAU,GAAG;AACzD,cAAM,QAAQ,KAAK,WAAW,QAAQ,GAAG;AACzC,YAAI,UAAU,IAAI;AAChB,+BAAqB;AACrB,0BAAgB,KAAK,UAAU,KAAK,CAAC,IAAI;AAAA,QAC3C;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa;AAAA,MACjB,GAAG,KAAK,OAAO;AAAA,QACb,qBAAqB,EAAC,YAAY,gBAAe,IAAI,CAAC;AAAA,MACxD;AAAA,IACF;AASA,QAAI,KAAK,wBAAwB,OAAO,SAAS,UAAU;AACzD,YAAM,cAAc,KAAK,uBAAuB,OAAO;AACvD,YAAMC,WAAU,KAAK,OAAO,UAAU,EAAE;AACxC,YAAM,YAAY;AAAA,QAAa,WAAW;AAAA,QAAQ,OAChDA,SAAQ,YAAY,KAAK,WAAW,CAAC,EAAE,GAAG;AAAA,MAC5C;AACA,iBAAW,OAAO,WAAW,GAAG,WAAW;AAAA,IAC7C;AACA,UAAM,kBAAoC,CAAC;AAC3C,QAAI,QAAQ;AACZ,QAAI;AACF,iBAAW,aAAa,YAAY;AAGlC,cAAM,sBAA4C,CAAC;AACnD,iBAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,8BAAoB,KAAK,WAAW,CAAC,CAAC,IACpC,UAAU,IAAI,KAAK,UAAU,CAAC,CAAC;AAAA,QACnC;AACA,YACE,IAAI,cACJ,CAAC,yBAAyB,qBAAqB,IAAI,UAAU,GAC7D;AACA,0BAAgB,KAAK,WAAW,OAAO,QAAQ,EAAE,CAAC;AAAA,QACpD,OAAO;AACL,gBAAM,SAAS,KAAK,QAAQ,MAAM;AAAA,YAChC,GAAG;AAAA,YACH,YAAY;AAAA,cACV,GAAG,IAAI;AAAA,cACP,GAAG;AAAA,YACL;AAAA,UACF,CAAC;AACD,gBAAMC,YAAW,OAAO,OAAO,QAAQ,EAAE;AACzC,0BAAgB,KAAKA,SAAQ;AAAA,QAC/B;AAAA,MACF;AACA,YAAM,kBAAmC,CAAC;AAC1C,eAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,cAAM,OAAO,gBAAgB,CAAC;AAC9B,cAAM,SAAS,KAAK,KAAK;AACzB,wBAAgB,CAAC,IAAI,OAAO,OAAO,OAAO,OAAO;AAAA,MACnD;AAEA,aAAO,MAAM;AACX,YAAI,gBAAgB;AACpB,YAAI,4BAAsC,CAAC;AAC3C,iBAAS,IAAI,GAAG,IAAI,gBAAgB,QAAQ,KAAK;AAC/C,gBAAM,aAAa,gBAAgB,CAAC;AACpC,cAAI,eAAe,MAAM;AACvB;AAAA,UACF;AACA,cAAI,kBAAkB,MAAM;AAC1B,4BAAgB;AAChB,sCAA0B,KAAK,CAAC;AAAA,UAClC,OAAO;AACL,kBAAM,gBACJ,KAAK,QAAQ,YAAY,WAAW,KAAK,cAAc,GAAG,KACzD,IAAI,UAAU,KAAK;AACtB,gBAAI,kBAAkB,GAAG;AACvB,wCAA0B,KAAK,CAAC;AAAA,YAClC,WAAW,gBAAgB,GAAG;AAC5B,8BAAgB;AAChB,0CAA4B,CAAC,CAAC;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AACA,YAAI,kBAAkB,MAAM;AAC1B;AAAA,QACF;AACA,cAAM,oBAA4B,CAAC;AACnC,mBAAW,2BAA2B,2BAA2B;AAC/D,4BAAkB,KAAK,WAAW,uBAAuB,CAAC;AAC1D,gBAAM,OAAO,gBAAgB,uBAAuB;AACpD,gBAAM,SAAS,KAAK,KAAK;AACzB,0BAAgB,uBAAuB,IAAI,OAAO,OAC9C,OACA,OAAO;AAAA,QACb;AACA,YAAI,4BAA4B;AAChC,YACE,KAAK,0BACL,KAAK,uBAAuB,YAC5B;AAAA,UACE,KAAK,uBAAuB,OAAO,KAAK;AAAA,UACxC,KAAK;AAAA,UACL,cAAc;AAAA,UACd,KAAK;AAAA,QACP,GACA;AACA,gBAAM,qDACJ,KAAK,QACF,UAAU,EACV;AAAA,YACC,cAAc;AAAA,YACd,KAAK,uBAAuB;AAAA,UAC9B,KAAK;AACT,cAAI,KAAK,uBAAuB,OAAO,SAAS,UAAU;AACxD,gBAAI,oDAAoD;AAGtD,0CAA4B,kBAAkB;AAAA,gBAC5C,OAAK,MAAM,KAAK,wBAAwB,OAAO;AAAA,cACjD;AAAA,YACF;AAAA,UACF,WAAW,CAAC,oDAAoD;AAC9D,wCAA4B;AAAA,cAC1B,GAAG;AAAA,gBACD;AAAA,gBACA,KAAK,uBAAuB;AAAA,gBAC5B,KAAK,OAAO,UAAU;AAAA,cACxB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAGA,YAAI,0BAA0B,SAAS,GAAG;AACxC,gBAAM;AAAA,YACJ,GAAG;AAAA,YACH,eAAe;AAAA,cACb,GAAG,cAAc;AAAA,cACjB,CAAC,KAAK,iBAAiB,GAAG,MAAM;AAAA,YAClC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,GAAG;AACV,cAAQ;AACR,iBAAW,QAAQ,iBAAiB;AAClC,YAAI;AACF,eAAK,QAAQ,CAAC;AAAA,QAChB,SAAS,eAAe;AAAA,QAGxB;AAAA,MACF;AACA,YAAM;AAAA,IACR,UAAE;AACA,UAAI,CAAC,OAAO;AACV,mBAAW,QAAQ,iBAAiB;AAClC,cAAI;AACF,iBAAK,SAAS;AAAA,UAChB,SAAS,eAAe;AAAA,UAGxB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,MAAkC;AAAA,EAAC;AAAA,EAE5C,WAAW,QAAsB;AAC/B,UAAM,kBAAkB,CAAC,WAAqB;AAC5C,WAAK,yBAAyB;AAAA,QAC5B;AAAA,QACA,UAAU;AAAA,MACZ;AACA,UAAI;AACF,cAAM,mBAAmB,KAAK,QAAQ,MAAM;AAAA,UAC1C,YAAY,OAAO;AAAA,YACjB,KAAK,WAAW,IAAI,CAAC,KAAK,MAAM;AAAA,cAC9B;AAAA,cACA,OAAO,KAAK,IAAI,KAAK,UAAU,CAAC,CAAC;AAAA,YACnC,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AACD,mBAAW,cAAc,kBAAkB;AACzC,eAAK,yBAAyB;AAAA,YAC5B;AAAA,YACA,UAAU,WAAW;AAAA,UACvB;AACA,gBAAM,kBAAkB,MACtB,KAAK,OAAO,MAAM;AAAA,YAChB,YAAY,OAAO;AAAA,cACjB,KAAK,UAAU,IAAI,CAAC,KAAK,MAAM;AAAA,gBAC7B;AAAA,gBACA,WAAW,IAAI,KAAK,WAAW,CAAC,CAAC;AAAA,cACnC,CAAC;AAAA,YACH;AAAA,UACF,CAAC;AACH,cAAI,CAAC,QAAQ;AACX,uBAAW,aAAa,gBAAgB,GAAG;AACzC,kBACE,KAAK,OACF,UAAU,EACV,YAAY,UAAU,KAAK,OAAO,KAAK,GAAG,MAAM,GACnD;AACA,yBAAS;AACT;AAAA,cACF;AAAA,YACF;AAAA,UACF;AACA,cAAI,QAAQ;AACV,iBAAK,QAAQ;AAAA,cACX;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,kBACJ,GAAG;AAAA,kBACH,eAAe;AAAA,oBACb,GAAG,WAAW;AAAA,oBACd,CAAC,KAAK,iBAAiB,GAAG;AAAA,kBAC5B;AAAA,gBACF;AAAA,gBACA,OAAO;AAAA,kBACL,kBAAkB,KAAK;AAAA,kBACvB;AAAA,gBACF;AAAA,cACF;AAAA,cACA;AAAA,YACF;AAAA,UACF,OAAO;AACL,iBAAK,QAAQ;AAAA,cACX;AAAA,gBACE,GAAG;AAAA,gBACH,MAAM;AAAA,kBACJ,GAAG;AAAA,kBACH,eAAe;AAAA,oBACb,GAAG,WAAW;AAAA,oBACd,CAAC,KAAK,iBAAiB,GAAG,MAAM,CAAC,OAAO,IAAI;AAAA,kBAC9C;AAAA,gBACF;AAAA,cACF;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,UAAE;AACA,aAAK,yBAAyB;AAAA,MAChC;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AACH,wBAAgB;AAChB;AAAA,MACF,KAAK,QAAQ;AACX;AAAA,UACE;AAAA,YACE,OAAO,QAAQ;AAAA,YACf,OAAO,KAAK;AAAA,YACZ,KAAK;AAAA,UACP;AAAA,UACA;AAAA,QACF;AACA,wBAAgB,IAAI;AACpB;AAAA,MACF;AAAA,MACA,KAAK;AACH,wBAAgB,IAAI;AACpB;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,YAAY,QAAsB;AAChC,UAAM,kBAAkB,CAAC,SAAe,MACtC,KAAK,OAAO,MAAM;AAAA,MAChB,YAAY,OAAO;AAAA,QACjB,KAAK,UAAU,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,KAAK,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC;AAAA,MACpE;AAAA,IACF,CAAC;AAEH,UAAM,OAAO,CAAC,UAAgB;AAAA,MAC5B,GAAG;AAAA,MACH,eAAe;AAAA,QACb,GAAG,KAAK;AAAA,QACR,CAAC,KAAK,iBAAiB,GAAG,gBAAgB,IAAI;AAAA,MAChD;AAAA,IACF;AAGA,QAAI,MAAM,gBAAgB,OAAO,IAAI,EAAE,CAAC,MAAM,QAAW;AACvD;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK,SAAS;AACZ,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,GAAG;AAAA,YACH,MAAM,KAAK,OAAO,IAAI;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA,KAAK,QAAQ;AACX;AAAA,UACE;AAAA,YACE,OAAO,QAAQ;AAAA,YACf,OAAO,KAAK;AAAA,YACZ,KAAK;AAAA,UACP;AAAA,UACA;AAAA,QACF;AACA,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,SAAS,KAAK,OAAO,OAAO;AAAA,YAC5B,MAAM,KAAK,OAAO,IAAI;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA;AACE,oBAAY,MAAM;AAAA,IACtB;AAAA,EACF;AACF;;;AC3ZO,IAAM,OAAN,MAA4B;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAkB;AAAA,EAElB;AAAA,EAEA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAAS;AACP,WAAO,WAAW,OAAO,8CAA8C;AACvE;AAAA,MACE,UAAU,WAAW,SAAS;AAAA,MAC9B;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,oBAAoB;AAEzB,UAAM,eAAe,OAAO,UAAU;AACtC,UAAM,cAAc,MAAM,UAAU;AACpC,SAAK,UAAU;AAAA,MACb,GAAG;AAAA,MACH,eAAe;AAAA,QACb,GAAG,aAAa;AAAA,QAChB,CAAC,gBAAgB,GAAG;AAAA,UAClB,GAAG;AAAA,UACH,UAAU;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,UAAU;AAAA,MACf,MAAM,CAAC,WAAmB,KAAK,YAAY,MAAM;AAAA,IACnD,CAAC;AACD,UAAM,UAAU;AAAA,MACd,MAAM,CAAC,WAAmB,KAAK,WAAW,MAAM;AAAA,IAClD,CAAC;AAAA,EACH;AAAA,EAEA,UAAgB;AACd,SAAK,QAAQ,QAAQ;AACrB,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,CAAC,MAAM,KAAiC;AACtC,eAAW,cAAc,KAAK,QAAQ,MAAM,GAAG,GAAG;AAChD,YAAM,KAAK;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,KAAiC;AACxC,eAAW,cAAc,KAAK,QAAQ,QAAQ,GAAG,GAAG;AAClD,YAAM,KAAK;AAAA,QACT,WAAW;AAAA,QACX,WAAW;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAAY,QAAsB;AAChC,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AACH,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,OAAO,KAAK;AAAA,cACZ,OAAO,KAAK;AAAA,cACZ;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF,KAAK;AACH,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,OAAO,KAAK;AAAA,cACZ,OAAO,KAAK;AAAA,cACZ;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF,KAAK;AACH,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,OAAO,KAAK;AAAA,cACZ,OAAO,KAAK;AAAA,cACZ;AAAA,YACF;AAAA,YACA,OAAO,OAAO;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF,KAAK,QAAQ;AAEX;AAAA,UACE;AAAA,YACE,OAAO,QAAQ;AAAA,YACf,OAAO,KAAK;AAAA,YACZ,KAAK;AAAA,UACP;AAAA,UACA;AAAA,QACF;AACA,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,SAAS,KAAK;AAAA,cACZ,OAAO,QAAQ;AAAA,cACf,OAAO,QAAQ;AAAA,cACf;AAAA,YACF;AAAA,YACA,MAAM,KAAK;AAAA,cACT,OAAO,KAAK;AAAA,cACZ,OAAO,KAAK;AAAA,cACZ;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AAAA,MACA;AACE,oBAAY,MAAM;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,WAAW,QAAsB;AAC/B,UAAM,kBAAkB,CAAC,UAAeC,YAAmB;AACzD,WAAK,yBAAyB;AAAA,QAC5B,QAAAA;AAAA,QACA,UAAU;AAAA,MACZ;AACA,UAAI;AACF,cAAM,cAAc,KAAK,QAAQ,MAAM;AAAA,UACrC,YAAY,OAAO;AAAA,YACjB,KAAK,WAAW,IAAI,CAAC,KAAK,MAAM,CAAC,KAAK,SAAS,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC;AAAA,UACpE;AAAA,QACF,CAAC;AAED,mBAAW,cAAc,aAAa;AACpC,eAAK,uBAAuB,WAAW,WAAW;AAClD,gBAAM,cAA2B;AAAA,YAC/B,MAAM;AAAA,YACN,MAAM,KAAK;AAAA,cACT,WAAW;AAAA,cACX,WAAW;AAAA,cACX;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,kBAAkB,KAAK;AAAA,cACvB,QAAAA;AAAA,YACF;AAAA,UACF;AACA,eAAK,QAAQ,KAAK,aAAa,IAAI;AAAA,QACrC;AAAA,MACF,UAAE;AACA,aAAK,yBAAyB;AAAA,MAChC;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AAAA,MACL,KAAK;AACH,wBAAgB,OAAO,KAAK,KAAK,MAAM;AACvC;AAAA,MACF,KAAK;AACH,wBAAgB,OAAO,KAAK,KAAK,MAAM;AACvC;AAAA,MACF,KAAK,QAAQ;AACX,cAAM,WAAW,OAAO,KAAK;AAC7B,cAAM,cAAc,OAAO,QAAQ;AAEnC;AAAA,UACE,wBAAwB,aAAa,UAAU,KAAK,SAAS;AAAA,UAC7D;AAAA,QACF;AACA,wBAAgB,UAAU,MAAM;AAChC;AAAA,MACF;AAAA,MAEA;AACE,oBAAY,MAAM;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,mBACE,eACA,qBACA,MACM;AACN,QAAI,SAA4B;AAChC,QAAI,iBAAiB;AACrB,UAAM,cAAc,MAAM;AACxB,UAAI,CAAC,gBAAgB;AACnB,YAAI,SAAS,WAAW;AACtB,eAAK,SAAS;AAAA,YACZ;AAAA,cACE,KAAK;AAAA,cACL,KAAK,QAAQ,UAAU,EAAE;AAAA,cACzB;AAAA,YACF;AAAA,UACF;AACA,gBAAM,QACJ;AAAA,YACE,GAAG;AAAA,cACD,KAAK,SAAS,KAAK;AAAA,gBACjB,QAAQ,qBAAqB,eAAe,KAAK,UAAU;AAAA,cAC7D,CAAC;AAAA,cACD;AAAA,YACF;AAAA,UACF,EAAE,WAAW;AACf,mBAAS,QAAQ,YAAY;AAAA,QAC/B;AAEA,yBAAiB;AAGjB,YAAI,SAAS,SAAS;AACpB,eAAK,SAAS;AAAA,YACZ;AAAA,cACE,KAAK;AAAA,cACL,KAAK,QAAQ,UAAU,EAAE;AAAA,cACzB;AAAA,YACF;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,OAAO,MAAM,EAAE;AAAA,QACjC,YAAY,OAAO;AAAA,UACjB,KAAK,UAAU,IAAI,CAAC,KAAK,MAAM;AAAA,YAC7B;AAAA,YACA,cAAc,KAAK,WAAW,CAAC,CAAC;AAAA,UAClC,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAED,UACE,KAAK,0BACL;AAAA,QACE;AAAA,QACA,KAAK;AAAA,QACL,KAAK,uBAAuB,OAAO,KAAK;AAAA,QACxC,KAAK;AAAA,MACP,KACA,KAAK,uBAAuB,YAC5B,KAAK,QAAQ;AAAA,QACX;AAAA,QACA,KAAK,uBAAuB;AAAA,MAC9B,IAAI,GACJ;AACA,eAAO;AAAA,UACL;AAAA,UACA,KAAK,uBAAuB;AAAA,UAC5B,KAAK,OAAO,UAAU;AAAA,QACxB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,KAAK;AAAA,MACL,eAAe;AAAA,QACb,GAAG;AAAA,QACH,CAAC,KAAK,iBAAiB,GAAG;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,wBAAwB,QAAkC;AACxE,QAAMC,QAAO,KAAK,UAAU,CAAC,WAAW,GAAG,MAAM,CAAC;AAClD,SAAOA,MAAK,UAAU,GAAGA,MAAK,SAAS,CAAC,IAAI;AAC9C;AAGO,SAAS,qBAAqB,KAAU,KAA0B;AACvE,SAAO,wBAAwB,IAAI,IAAI,OAAK,IAAI,CAAC,CAAC,CAAC;AACrD;AAMO,SAAS,eACd,KACA,YACA,KACQ;AACR,QAAM,SAAkB,IAAI,IAAI,OAAK,IAAI,CAAC,CAAC;AAC3C,aAAWC,QAAO,YAAY;AAC5B,WAAO,KAAK,IAAIA,IAAG,CAAC;AAAA,EACtB;AACA,SAAO,wBAAwB,MAAM;AACvC;;;ACrWO,IAAM,OAAN,MAA+B;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAkB;AAAA,EAElB,YAAY,OAAc,OAAc;AACtC,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,cAAc,MAAM,UAAU,EAAE;AACrC,UAAM,UAAU,IAAI;AAAA,EACtB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAiC;AACrC,WAAO,KAAK,gBAAgB,SAAS,GAAG;AAAA,EAC1C;AAAA,EAEA,QAAQ,KAAiC;AACvC,WAAO,KAAK,gBAAgB,SAAS,GAAG;AAAA,EAC1C;AAAA,EAEA,CAAC,gBAAgB,QAA6B,KAAmB;AAC/D,UAAM,QAAQ,KAAK,UAAU,GAAG;AAChC,QAAI,UAAU,SAAS;AACrB;AAAA,IACF;AACA,UAAM,QAAQ,KAAK,OAAO,MAAM,EAAE,EAAC,GAAG,KAAK,MAAK,CAAC;AACjD,QAAI,CAAC,IAAI,SAAS;AAChB,aAAO;AACP;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI,CAAC,KAAK,iBAAiB,KAAK,GAAG,GAAG;AACpC;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,iBAAiB,KAAmB;AAClC,UAAMC,OAAM,KAAK,YAAY,KAAK,OAAO,KAAK,GAAG;AACjD,WAAOA,OAAM,KAAMA,SAAQ,KAAK,CAAC,KAAK,OAAO;AAAA,EAC/C;AAAA,EAEA,KAAK,QAAsB;AACzB,UAAM,kBAAkB,CAAC,QAAa,KAAK,iBAAiB,GAAG;AAC/D,QAAI,OAAO,SAAS,QAAQ;AAC1B,kCAA4B,QAAQ,iBAAiB,KAAK,SAAS,IAAI;AACvE;AAAA,IACF;AAEA;AAEA,QAAI,gBAAgB,OAAO,KAAK,GAAG,GAAG;AACpC,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAChC;AAAA,EACF;AAAA,EAEA,UAAU,KAAgD;AACxD,UAAM,aAAa;AAAA,MACjB,KAAK,KAAK,OAAO;AAAA,MACjB,OAAO,KAAK,OAAO,YAAY,UAAU;AAAA,IAC3C;AAEA,QAAI,CAAC,IAAI,OAAO;AACd,UAAI,IAAI,SAAS;AACf,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AAEA,UAAMA,OAAM,KAAK,YAAY,KAAK,OAAO,KAAK,IAAI,MAAM,GAAG;AAE3D,QAAI,CAAC,IAAI,SAAS;AAIhB,UAAIA,OAAM,GAAG;AACX,eAAO;AAAA,MACT;AAIA,UAAIA,SAAQ,GAAG;AACb,YAAI,KAAK,OAAO,aAAa,IAAI,MAAM,UAAU,SAAS;AACxD,iBAAO;AAAA,YACL,KAAK,KAAK,OAAO;AAAA,YACjB,OAAO;AAAA,UACT;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAEA,aAAO,IAAI;AAAA,IACb;AAEA,QAAI;AAIJ,QAAIA,OAAM,GAAG;AACX,aAAO;AAAA,IACT;AAEA,QAAIA,SAAQ,GAAG;AAGb,UAAI,CAAC,KAAK,OAAO,aAAa,IAAI,MAAM,UAAU,MAAM;AACtD,eAAO;AAAA,MACT;AAGA,aAAO;AAAA,IACT;AAGA,WAAO,IAAI;AAAA,EACb;AACF;;;ACvIA,IAAM,gBAAgB;AA4Bf,IAAM,OAAN,MAA+B;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAET;AAAA,EAEA,UAAkB;AAAA,EAElB,YACE,OACA,SACA,OACA,cACA;AACA,WAAO,SAAS,GAAG,4BAA4B;AAC/C;AAAA,MACE,MAAM,UAAU,EAAE;AAAA,MAClB,MAAM,UAAU,EAAE;AAAA,IACpB;AACA,UAAM,UAAU,IAAI;AACpB,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,gBAAgB;AACrB,SAAK,0BACH,gBAAgB,2BAA2B,YAAY;AAAA,EAC3D;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,CAAC,MAAM,KAAiC;AACtC,QACE,CAAC,KAAK,iBACL,IAAI,cACH,8BAA8B,IAAI,YAAY,KAAK,aAAa,GAClE;AACA,YAAM,eAAe,gBAAgB,KAAK,eAAe,IAAI,UAAU;AACvE,YAAM,YAAY,KAAK,SAAS,IAAI,YAAY;AAChD,UAAI,CAAC,WAAW;AACd,eAAO,KAAK,cAAc,GAAG;AAC7B;AAAA,MACF;AACA,UAAI,UAAU,UAAU,QAAW;AACjC;AAAA,MACF;AACA,iBAAW,aAAa,KAAK,OAAO,MAAM,GAAG,GAAG;AAC9C,YAAI,KAAK,UAAU,EAAE,YAAY,UAAU,OAAO,UAAU,GAAG,IAAI,GAAG;AACpE;AAAA,QACF;AACA,YACE,KAAK,uBACL,KAAK,UAAU,EAAE;AAAA,UACf,KAAK;AAAA,UACL,UAAU;AAAA,QACZ,MAAM,GACN;AACA;AAAA,QACF;AACA,cAAM;AAAA,MACR;AACA;AAAA,IACF;AAOA,UAAM,WAAW,KAAK,SAAS,IAAI,aAAa;AAChD,QAAI,aAAa,QAAW;AAC1B;AAAA,IACF;AACA,eAAW,aAAa,KAAK,OAAO,MAAM,GAAG,GAAG;AAC9C,UAAI,KAAK,UAAU,EAAE,YAAY,UAAU,KAAK,QAAQ,IAAI,GAAG;AAC7D;AAAA,MACF;AACA,YAAM,eAAe,gBAAgB,KAAK,eAAe,UAAU,GAAG;AACtE,YAAM,YAAY,KAAK,SAAS,IAAI,YAAY;AAChD,UACE,WAAW,UAAU,UACrB,KAAK,UAAU,EAAE,YAAY,UAAU,OAAO,UAAU,GAAG,KAAK,GAChE;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EAEA,CAAC,cAAc,KAAiC;AAC9C,WAAO,IAAI,UAAU,QAAW,2BAA2B;AAC3D,WAAO,CAAC,IAAI,SAAS,yBAAyB;AAC9C;AAAA,MACE,8BAA8B,IAAI,YAAY,KAAK,aAAa;AAAA,MAChE;AAAA,IACF;AAEA,QAAI,KAAK,WAAW,GAAG;AACrB;AAAA,IACF;AAEA,UAAM,eAAe,gBAAgB,KAAK,eAAe,IAAI,UAAU;AACvE;AAAA,MACE,KAAK,SAAS,IAAI,YAAY,MAAM;AAAA,MACpC;AAAA,IACF;AAEA,QAAI,OAAO;AACX,QAAI;AACJ,QAAI,wBAAwB;AAC5B,QAAI,kBAAkB;AACtB,QAAI;AACF,iBAAW,aAAa,KAAK,OAAO,MAAM,GAAG,GAAG;AAC9C,cAAM;AACN,gBAAQ,UAAU;AAClB;AACA,YAAI,SAAS,KAAK,QAAQ;AACxB;AAAA,QACF;AAAA,MACF;AACA,8BAAwB;AAAA,IAC1B,SAAS,GAAG;AACV,wBAAkB;AAClB,YAAM;AAAA,IACR,UAAE;AACA,UAAI,CAAC,iBAAiB;AACpB,aAAK;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA,KAAK,SAAS,IAAI,aAAa;AAAA,QACjC;AAKA;AAAA,UACE,CAAC;AAAA,UACD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,KAAiC;AACxC,WAAO,IAAI,UAAU,QAAW,2BAA2B;AAC3D;AAAA,MACE,8BAA8B,IAAI,YAAY,KAAK,aAAa;AAAA,MAChE;AAAA,IACF;AACA,UAAM,eAAe,gBAAgB,KAAK,eAAe,IAAI,UAAU;AACvE,SAAK,SAAS,IAAI,YAAY;AAC9B,QAAI,OAAO;AACX,eAAW,aAAa,KAAK,OAAO,QAAQ,GAAG,GAAG;AAChD,UAAI,SAAS,KAAK,QAAQ;AACxB;AAAA,MACF;AACA;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,uBAAuB,KAAU;AAC/B,UAAM,eAAe,gBAAgB,KAAK,eAAe,GAAG;AAC5D,UAAM,YAAY,KAAK,SAAS,IAAI,YAAY;AAChD,QAAI;AACJ,QAAI;AACJ,QAAI,WAAW;AACb,iBAAW,KAAK,SAAS,IAAI,aAAa;AAC1C,mBACE,KAAK,iBACL,OAAO;AAAA,QACL,KAAK,cAAc,IAAI,SAAO,CAAC,KAAK,IAAI,GAAG,CAAC,CAAU;AAAA,MACxD;AAAA,IACJ;AAEA,WAAO,EAAC,WAAW,cAAc,UAAU,WAAU;AAAA,EAavD;AAAA,EAEA,KAAK,QAAsB;AACzB,QAAI,OAAO,SAAS,QAAQ;AAC1B,WAAK,gBAAgB,MAAM;AAC3B;AAAA,IACF;AAEA,UAAM,EAAC,WAAW,cAAc,UAAU,WAAU,IAClD,KAAK,uBAAuB,OAAO,KAAK,GAAG;AAC7C,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,UAAM,EAAC,YAAW,IAAI,KAAK,UAAU;AAErC,QAAI,OAAO,SAAS,OAAO;AACzB,UAAI,UAAU,OAAO,KAAK,QAAQ;AAChC,aAAK;AAAA,UACH;AAAA,UACA,UAAU,OAAO;AAAA,UACjB,UAAU,UAAU,UAClB,YAAY,UAAU,OAAO,OAAO,KAAK,GAAG,IAAI,IAC9C,OAAO,KAAK,MACZ,UAAU;AAAA,UACd;AAAA,QACF;AACA,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B;AAAA,MACF;AAEA,UACE,UAAU,UAAU,UACpB,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,KAAK,GACjD;AACA;AAAA,MACF;AAEA,UAAI;AACJ,UAAI;AACJ,UAAI,KAAK,WAAW,GAAG;AACrB,oBAAY;AAAA,UACV;AAAA,YACE,KAAK,OAAO,MAAM;AAAA,cAChB,OAAO;AAAA,gBACL,KAAK,UAAU;AAAA,gBACf,OAAO;AAAA,cACT;AAAA,cACA;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,OAAO;AACL,SAAC,WAAW,eAAe,IAAI;AAAA,UAC7B,KAAK,OAAO,MAAM;AAAA,YAChB,OAAO;AAAA,cACL,KAAK,UAAU;AAAA,cACf,OAAO;AAAA,YACT;AAAA,YACA;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,UACD;AAAA,QACF;AAAA,MACF;AACA,YAAM,eAA6B;AAAA,QACjC,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAGA,WAAK;AAAA,QACH;AAAA,QACA,UAAU;AAAA,QACV,oBAAoB,UAClB,YAAY,OAAO,KAAK,KAAK,gBAAgB,GAAG,IAAI,IAClD,OAAO,KAAK,MACZ,gBAAgB;AAAA,QACpB;AAAA,MACF;AACA,WAAK,wBAAwB,OAAO,KAAK,KAAK,MAAM;AAClD,aAAK,QAAQ,KAAK,cAAc,IAAI;AAAA,MACtC,CAAC;AACD,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAChC,WAAW,OAAO,SAAS,UAAU;AACnC,UAAI,UAAU,UAAU,QAAW;AAEjC;AAAA,MACF;AACA,YAAM,cAAc,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK;AAChE,UAAI,cAAc,GAAG;AAEnB;AAAA,MACF;AACA,YAAM,CAAC,eAAe,IAAI;AAAA,QACxB,KAAK,OAAO,MAAM;AAAA,UAChB,OAAO;AAAA,YACL,KAAK,UAAU;AAAA,YACf,OAAO;AAAA,UACT;AAAA,UACA;AAAA,UACA,SAAS;AAAA,QACX,CAAC;AAAA,QACD;AAAA,MACF;AAEA,UAAI;AACJ,UAAI,iBAAiB;AACnB,cAAMC,QAAO,YAAY,gBAAgB,KAAK,UAAU,KAAK,IAAI;AACjE,mBAAW;AAAA,UACT,MAAM;AAAA,UACN,MAAAA;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,UAAU,MAAM;AACnB,mBAAW,QAAQ,KAAK,OAAO,MAAM;AAAA,UACnC,OAAO;AAAA,YACL,KAAK,UAAU;AAAA,YACf,OAAO;AAAA,UACT;AAAA,UACA;AAAA,QACF,CAAC,GAAG;AACF,gBAAMA,QAAO,YAAY,KAAK,KAAK,UAAU,KAAK,IAAI;AACtD,qBAAW;AAAA,YACT;AAAA,YACA,MAAAA;AAAA,UACF;AACA,cAAIA,OAAM;AACR;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,UAAU,MAAM;AAClB,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B,aAAK;AAAA,UACH;AAAA,UACA,UAAU;AAAA,UACV,SAAS,KAAK;AAAA,UACd;AAAA,QACF;AACA,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM,SAAS;AAAA,UACjB;AAAA,UACA;AAAA,QACF;AACA;AAAA,MACF;AACA,WAAK;AAAA,QACH;AAAA,QACA,UAAU,OAAO;AAAA,QACjB,UAAU,KAAK;AAAA,QACf;AAAA,MACF;AACA,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAChC,WAAW,OAAO,SAAS,SAAS;AAGlC,UACE,UAAU,SACV,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK,KAAK,GACjD;AACA,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAgB,QAA0B;AACxC;AAAA,MACE,CAAC,KAAK,2BACJ,KAAK,wBAAwB,OAAO,QAAQ,KAAK,OAAO,KAAK,GAAG,MAAM;AAAA,MACxE;AAAA,IACF;AAEA,UAAM,EAAC,WAAW,cAAc,UAAU,WAAU,IAClD,KAAK,uBAAuB,OAAO,QAAQ,GAAG;AAChD,QAAI,CAAC,WAAW;AACd;AAAA,IACF;AAEA,WAAO,UAAU,OAAO,qBAAqB;AAC7C,UAAM,EAAC,YAAW,IAAI,KAAK,UAAU;AACrC,UAAM,SAAS,YAAY,OAAO,QAAQ,KAAK,UAAU,KAAK;AAC9D,UAAM,SAAS,YAAY,OAAO,KAAK,KAAK,UAAU,KAAK;AAE3D,UAAM,+BAA+B,MAAM;AACzC,WAAK;AAAA,QACH;AAAA,QACA,UAAU;AAAA,QACV,OAAO,KAAK;AAAA,QACZ;AAAA,MACF;AACA,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,IAChC;AAGA,QAAI,WAAW,GAAG;AAEhB,UAAI,WAAW,GAAG;AAEhB,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B;AAAA,MACF;AAEA,UAAI,SAAS,GAAG;AACd,YAAI,KAAK,WAAW,GAAG;AACrB,uCAA6B;AAC7B;AAAA,QACF;AAMA,cAAM,kBAAkB;AAAA,UACtB;AAAA,YACE,KAAK,OAAO,MAAM;AAAA,cAChB,OAAO;AAAA,gBACL,KAAK,UAAU;AAAA,gBACf,OAAO;AAAA,cACT;AAAA,cACA;AAAA,cACA,SAAS;AAAA,YACX,CAAC;AAAA,UACH;AAAA,QACF;AAEA,aAAK;AAAA,UACH;AAAA,UACA,UAAU;AAAA,UACV,gBAAgB;AAAA,UAChB;AAAA,QACF;AACA,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B;AAAA,MACF;AAEA,aAAO,SAAS,GAAG,uCAAuC;AAE1D,YAAM,eAAe;AAAA,QACnB;AAAA,UACE,KAAK,OAAO,MAAM;AAAA,YAChB,OAAO;AAAA,cACL,KAAK,UAAU;AAAA,cACf,OAAO;AAAA,YACT;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAIA,UAAI,YAAY,aAAa,KAAK,OAAO,KAAK,GAAG,MAAM,GAAG;AACxD,qCAA6B;AAC7B;AAAA,MACF;AAIA,WAAK;AAAA,QACH;AAAA,QACA,UAAU;AAAA,QACV,aAAa;AAAA,QACb;AAAA,MACF;AACA,WAAK,wBAAwB,aAAa,KAAK,MAAM;AACnD,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM,OAAO;AAAA,UACf;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AACD,WAAK,QAAQ;AAAA,QACX;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,SAAS,GAAG;AACd,aAAO,WAAW,GAAG,8CAA8C;AAGnE,UAAI,SAAS,GAAG;AACd;AAAA,MACF;AAGA,aAAO,SAAS,GAAG,oCAAoC;AAEvD,YAAM,CAAC,cAAc,YAAY,IAAI;AAAA,QACnC,KAAK,OAAO,MAAM;AAAA,UAChB,OAAO;AAAA,YACL,KAAK,UAAU;AAAA,YACf,OAAO;AAAA,UACT;AAAA,UACA;AAAA,UACA,SAAS;AAAA,QACX,CAAC;AAAA,QACD;AAAA,MACF;AAGA,WAAK;AAAA,QACH;AAAA,QACA,UAAU;AAAA,QACV,aAAa;AAAA,QACb;AAAA,MACF;AACA,WAAK,wBAAwB,OAAO,KAAK,KAAK,MAAM;AAClD,aAAK,QAAQ;AAAA,UACX;AAAA,YACE,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AACD,WAAK,QAAQ;AAAA,QACX;AAAA,UACE,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAEA;AAAA,IACF;AAEA,QAAI,SAAS,GAAG;AACd,aAAO,WAAW,GAAG,8CAA8C;AAGnE,UAAI,SAAS,GAAG;AACd,aAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B;AAAA,MACF;AAIA,aAAO,SAAS,GAAG,uCAAuC;AAI1D,YAAM,iBAAiB;AAAA,QACrB;AAAA,UACE,KAAK,OAAO,MAAM;AAAA,YAChB,OAAO;AAAA,cACL,KAAK,UAAU;AAAA,cACf,OAAO;AAAA,YACT;AAAA,YACA;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,YAAY,eAAe,KAAK,OAAO,KAAK,GAAG,MAAM,GAAG;AAC1D,qCAA6B;AAC7B;AAAA,MACF;AAEA,WAAK,QAAQ;AAAA,QACX;AAAA,UACE,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACf;AAAA,QACA;AAAA,MACF;AACA,WAAK;AAAA,QACH;AAAA,QACA,UAAU;AAAA,QACV,eAAe;AAAA,QACf;AAAA,MACF;AACA,WAAK,QAAQ;AAAA,QACX;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAEA,gBAAY;AAAA,EACd;AAAA,EAEA,wBAAwB,KAAU,IAAgB;AAChD,SAAK,sBAAsB;AAC3B,QAAI;AACF,SAAG;AAAA,IACL,UAAE;AACA,WAAK,sBAAsB;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cACE,cACA,MACA,OACA,UACA;AACA,SAAK,SAAS,IAAI,cAAc;AAAA,MAC9B;AAAA,MACA;AAAA,IACF,CAAC;AACD,QACE,UAAU,WACT,aAAa,UACZ,KAAK,UAAU,EAAE,YAAY,OAAO,QAAQ,IAAI,IAClD;AACA,WAAK,SAAS,IAAI,eAAe,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AACF;AAEA,SAAS,gBACP,cACA,iBACQ;AAGR,QAAM,kBAA2B,CAAC;AAElC,MAAI,gBAAgB,iBAAiB;AACnC,eAAW,OAAO,cAAc;AAC9B,sBAAgB,KAAK,gBAAgB,GAAG,CAAC;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO,KAAK,UAAU,CAAC,QAAQ,GAAG,eAAe,CAAC;AACpD;AAEA,SAAS,8BACP,YACA,cACS;AACT,MAAI,eAAe,UAAa,iBAAiB,QAAW;AAC1D,WAAO,eAAe;AAAA,EACxB;AACA,MAAI,aAAa,WAAW,OAAO,KAAK,UAAU,EAAE,QAAQ;AAC1D,WAAO;AAAA,EACT;AACA,aAAW,OAAO,cAAc;AAC9B,QAAI,CAAC,OAAO,YAAY,GAAG,GAAG;AAC5B,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,2BAA2B,cAAwC;AAC1E,SAAO,CAAC,GAAG,MAAM;AACf,eAAW,OAAO,cAAc;AAC9B,YAAMC,OAAM,cAAc,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC;AACxC,UAAIA,SAAQ,GAAG;AACb,eAAOA;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;ACvrBO,IAAM,aAAN,MAAqC;AAAA,EACjC;AAAA,EACA;AAAA,EACT,qBAA8B;AAAA,EAC9B,UAAkB;AAAA,EAClB,qBAA+B,CAAC;AAAA,EAEhC,YAAY,QAAqB,QAAiB;AAChD,SAAK,UAAU;AACf,UAAM,eAAe,OAAO,UAAU;AACtC,WAAO,SAAS,IAAI;AAEpB,UAAM,SAAiC;AAAA,MACrC,WAAW,aAAa;AAAA,MACxB,SAAS,aAAa;AAAA,MACtB,YAAY,aAAa;AAAA,MACzB,eAAe;AAAA,QACb,GAAG,aAAa;AAAA,MAClB;AAAA,MACA,UAAU,aAAa;AAAA,MACvB,QAAQ,aAAa;AAAA,MACrB,aAAa,aAAa;AAAA,MAC1B,MAAM,aAAa;AAAA,IACrB;AAGA,UAAM,4BAAyC,oBAAI,IAAI;AACvD,eAAW,SAAS,QAAQ;AAC1B,YAAM,cAAc,MAAM,UAAU;AACpC;AAAA,QACE,OAAO,cAAc,YAAY;AAAA,QACjC,wCAAwC,OAAO,SAAS,QAAQ,YAAY,SAAS;AAAA,MACvF;AACA;AAAA,QACE,OAAO,eAAe,YAAY;AAAA,QAClC;AAAA,MACF;AACA;AAAA,QACE,OAAO,WAAW,YAAY;AAAA,QAC9B,oCAAoC,OAAO,MAAM,QAAQ,YAAY,MAAM;AAAA,MAC7E;AACA;AAAA,QACE,OAAO,gBAAgB,YAAY;AAAA,QACnC;AAAA,MACF;AACA,aAAO,OAAO,SAAS,YAAY,MAAM,+BAA+B;AAExE,iBAAW,CAAC,SAAS,SAAS,KAAK,OAAO;AAAA,QACxC,YAAY;AAAA,MACd,GAAG;AACD,YAAI,WAAW,aAAa,eAAe;AACzC;AAAA,QACF;AAIA;AAAA,UACE,CAAC,0BAA0B,IAAI,OAAO;AAAA,UACtC,gBAAgB,OAAO;AAAA,QACzB;AACA,eAAO,cAAc,OAAO,IAAI;AAChC,kCAA0B,IAAI,OAAO;AAAA,MACvC;AAEA,YAAM,UAAU,IAAI;AAAA,IACtB;AAEA,SAAK,UAAU;AACf,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QAAQ,MAAkC;AAExC,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,UAAgB;AACd,eAAW,SAAS,KAAK,SAAS;AAChC,YAAM,QAAQ;AAAA,IAChB;AAAA,EACF;AAAA,EAEA,MAAM,KAAiC;AACrC,UAAM,YAAY,KAAK,QAAQ,IAAI,WAAS,MAAM,MAAM,GAAG,CAAC;AAC5D,WAAO;AAAA,MACL;AAAA,MACA,CAAC,GAAG,MAAM,KAAK,QAAQ,YAAY,EAAE,KAAK,EAAE,GAAG;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,KAAK,QAAgB,QAAyB;AAC5C,QAAI,CAAC,KAAK,oBAAoB;AAC5B,WAAK,oBAAoB,QAAQ,MAAM;AAAA,IACzC,OAAO;AACL,WAAK,mBAAmB,KAAK,MAAM;AAAA,IACrC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,oBAAoB,QAAgB,QAAyB;AAC3D,QAAI,OAAO,SAAS,SAAS;AAC3B,WAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B;AAAA,IACF;AAEA,WAAO,OAAO,SAAS,SAAS,OAAO,SAAS,QAAQ;AAExD,QAAI,WAAW;AACf,eAAW,SAAS,KAAK,SAAS;AAChC,UAAI,UAAU,QAAQ;AACpB,mBAAW;AACX;AAAA,MACF;AAEA,YAAM,aAAmC,CAAC;AAC1C,iBAAW,OAAO,KAAK,QAAQ,YAAY;AACzC,mBAAW,GAAG,IAAI,OAAO,KAAK,IAAI,GAAG;AAAA,MACvC;AACA,YAAM,cAAc,MAAM,MAAM;AAAA,QAC9B;AAAA,MACF,CAAC;AAED,UAAI,MAAM,WAAW,MAAM,QAAW;AAEpC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,UAAU,mDAAmD;AAGpE,SAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,EAChC;AAAA,EAEA,uBAAuB;AACrB,WAAO,KAAK,uBAAuB,KAAK;AACxC,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,kBAAkB,kBAAkC;AAClD,WAAO,KAAK,kBAAkB;AAC9B,SAAK,qBAAqB;AAC1B,QAAI,KAAK,QAAQ,WAAW,GAAG;AAC7B;AAAA,IACF;AAEA,QAAI,KAAK,mBAAmB,WAAW,GAAG;AAGxC;AAAA,IACF;AAEA;AAAA,MACE,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,0BAA0B,KAAK,OAAO;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AACF;;;AC5MO,IAAM,cAAN,MAAsC;AAAA,EAC3C,gBAAwB;AAAA,EACxB;AAAA,EACS;AAAA,EACA,WAAqB,CAAC;AAAA,EAE/B,YAAY,OAAc;AACxB,SAAK,SAAS;AACd,UAAM,UAAU,IAAI;AAAA,EACtB;AAAA,EAEA,SAAS,OAAmB;AAC1B,WAAO,CAAC,KAAK,aAAa,mCAAmC;AAC7D,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,KAAK,QAAsB;AACzB,SAAK,KAAK,WAAW,EAAE,qBAAqB;AAC5C,eAAW,UAAU,KAAK,UAAU;AAClC,aAAO,KAAK,QAAQ,IAAI;AAAA,IAC1B;AACA,SAAK,KAAK,WAAW,EAAE,kBAAkB,OAAO,IAAI;AAAA,EACtD;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,SAAS,KAAK,MAAM;AAAA,EAC3B;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,MAAM,KAAiC;AACrC,WAAO,KAAK,OAAO,MAAM,GAAG;AAAA,EAC9B;AAAA,EAEA,QAAQ,MAAkC;AAExC,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,gBAAgB,KAAK,SAAS,QAAQ;AAC7C,QAAE,KAAK;AACP,UAAI,KAAK,kBAAkB,KAAK,SAAS,QAAQ;AAC/C,aAAK,OAAO,QAAQ;AAAA,MACtB;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AAAA,EACF;AACF;;;AClCO,IAAM,eAAN,MAAmB;AAAA,EACf,OAAO;AAAA,EAChB;AAAA,EACA;AAAA,EACS;AAAA,EAET,YAAY,QAAiD;AAC3D,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,sBAAwC;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,MAAyB;AACjC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK,YAAY,QAAW,gBAAgB;AACnD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ;AACN,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,eAAqB;AACnB,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kCAAwC;AACtC,eAAW,SAAS,KAAK,SAAS;AAChC,UACE,qCAAqC,SACrC,OAAO,MAAM,oCAAoC,YACjD;AACA,QACE,MACA,gCAAgC;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aACE,4BACA,eACA,cACc;AAGd,QAAI,YAA0B;AAAA,MAC5B,cAAc;AAAA,MACd,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,MACb,aAAa;AAAA,MACb,OAAO;AAAA,IACT;AAEA,QAAI,KAAK,UAAU,MAAM;AAEvB,YAAM,iBAAiB,CAAC,GAAG,GAAG,aAAa;AAC3C,UAAI,UAAU;AACd,UAAI,iBAAiB;AACrB,UAAI,iBAAiB;AACrB,UAAI,aAAa;AAEjB,UAAI,cAAc;AAClB,iBAAW,SAAS,KAAK,SAAS;AAChC,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,YAAI,KAAK,eAAe,SAAS;AAC/B,oBAAU,KAAK;AAAA,QACjB;AACA,YAAI,KAAK,OAAO,gBAAgB;AAC9B,2BAAiB,KAAK;AAAA,QACxB;AACA,YAAI,KAAK,cAAc,gBAAgB;AACrC,2BAAiB,KAAK;AAAA,QACxB;AACA,YAAI,KAAK,UAAU,YAAY;AAC7B,uBAAa,KAAK;AAAA,QACpB;AAKA,uBAAe,IAAI,KAAK;AAGxB;AAAA,UACE,UAAU,UAAU,UAAa,KAAK,UAAU,UAAU;AAAA,UAC1D;AAAA,QACF;AACA,kBAAU,QAAQ,KAAK;AAAA,MACzB;AAEA,gBAAU,eAAe;AACzB,gBAAU,OAAO;AACjB,gBAAU,cAAc,IAAI;AAC5B,gBAAU,cAAc;AACxB,gBAAU,UAAU;AAAA,IACtB,OAAO;AAEL,UAAI,IAAI;AAER,UAAI,cAAc;AAClB,iBAAW,SAAS,KAAK,SAAS;AAChC,cAAM,iBAAiB,CAAC,GAAG,GAAG,aAAa;AAC3C,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,kBAAU,gBAAgB,KAAK;AAC/B,kBAAU,QAAQ,KAAK;AACvB,kBAAU,WAAW,KAAK;AAC1B,kBAAU,cAAc,UAAU,cAAc,KAAK;AAKrD,uBAAe,IAAI,KAAK;AAGxB;AAAA,UACE,UAAU,UAAU,UAAa,KAAK,UAAU,UAAU;AAAA,UAC1D;AAAA,QACF;AACA,kBAAU,QAAQ,KAAK;AACvB;AAAA,MACF;AACA,gBAAU,cAAc,IAAI;AAAA,IAC9B;AAEA,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEA,qBACE,eACA,YACA,MACA,cACM;AACN,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,MAAM,MAAM,QAAQ;AAAA,IACtB,CAAC;AAED,QAAI,KAAK,UAAU,MAAM;AACvB,YAAM,iBAAiB,CAAC,GAAG,GAAG,aAAa;AAQ3C,iBAAW,SAAS,KAAK,SAAS;AAChC,cAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,IAAI;AACR,eAAW,SAAS,KAAK,SAAS;AAChC,YAAM;AAAA,QACJ,CAAC,GAAG,GAAG,aAAa;AAAA,QACpB;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF;AACF;;;AC/NO,IAAM,gBAAN,MAAoB;AAAA,EAChB,OAAO;AAAA,EAChB;AAAA,EACS,WAA0B,CAAC;AAAA,EAC3B;AAAA,EAET,YAAY,OAA8C;AACxD,SAAK,QAAQ;AACb,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UAAU,MAAyB;AACjC,SAAK,SAAS,KAAK,IAAI;AAAA,EACzB;AAAA,EAEA,IAAI,UAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,sBAAwC;AACtC,WAAO,KAAK,OAAO,oBAAoB;AAAA,EACzC;AAAA,EAEA,qBACE,eACA,YACA,MACA,cACM;AACN,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,MAAM,MAAM,QAAQ;AAAA,IACtB,CAAC;AAED,SAAK,OAAO;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aACE,4BACA,eACA,cACc;AACd,UAAM,MAAM,KAAK,OAAO;AAAA,MACtB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,cAAc;AAAA,IAChB,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEA,eAAqB;AACnB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kCAAwC;AACtC,QACE,qCAAqC,KAAK,UAC1C,OAAO,KAAK,OAAO,oCAAoC,YACvD;AACA,MACE,KAAK,OACL,gCAAgC;AAAA,IACpC;AAAA,EACF;AACF;;;AC3FO,SAAS,iBACd,GACA,GAC+B;AAC/B,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,EAAC,GAAG,GAAG,GAAG,EAAC;AACpB;;;ACqCO,IAAM,oBAAN,MAAwB;AAAA,EACpB,OAAO;AAAA;AAAA;AAAA;AAAA,EAKP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASS;AAAA,EAEA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOT,yBAAoD,oBAAI,IAAI;AAAA,EAE5D,YACEC,QACA,OACA,MACA,SACA,QACA,iBACA,OACA,MACA;AACA,SAAK,QAAQA;AACb,SAAK,OAAO,QAAQA;AACpB,SAAK,QAAQ;AACb,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,mBAAmB;AACxB,SAAK,aAAa;AAClB,SAAK,QAAQ;AACb,SAAK,eAAe,oBAAI,IAAI;AAC5B,SAAK,UAAU;AAIf,QAAI,UAAU,UAAa,SAAS;AAClC,YAAM,kBAAkB,MAAMA,QAAO,MAAM,SAAS,MAAS;AAC7D,YAAM,qBAAqB,MAAMA,QAAO,MAAM,QAAW,MAAS;AAClE,WAAK,cACH,mBAAmB,OAAO,IACtB,gBAAgB,OAAO,mBAAmB,OAC1C;AAAA,IACR,OAAO;AAEL,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,UAAU,MAAyB;AACjC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK,YAAY,QAAW,gBAAgB;AACnD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,sBAAwC;AACtC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,qBACE,MACA,GACA,MACA,cACM;AACN,UAAM,MAAM,KAAK,KAAK,GAAG;AACzB,SAAK,aAAa,IAAI,KAAK,CAAC;AAE5B,SAAK,uBAAuB,MAAM;AAElC,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,MAAM,MAAM,QAAQ;AAAA,IACtB,CAAC;AAAA,EACH;AAAA,EAEA,aACE,4BACA,eACA,cACc;AAEd,UAAM,MAAM,cAAc,KAAK,GAAG;AAGlC,QAAI,OAAO,KAAK,uBAAuB,IAAI,GAAG;AAC9C,QAAI,SAAS,QAAW;AACtB,aAAO;AAAA,IACT;AAGA,UAAM,aAAa,KAAK,aAAa,IAAI,GAAG;AAE5C,UAAM,mBAAmB;AAAA,MACvB,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,EAAC,aAAa,KAAI,IAAI,KAAK;AAAA,MAC/B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA,SACE,KAAK,UAAU,SACX,OACA,KAAK,IAAI,MAAM,KAAK,QAAQ,0BAA0B;AAAA,MAC5D,MAAM;AAAA,MACN,cAAc;AAAA,MACd,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,IACd;AACA,SAAK,uBAAuB,IAAI,KAAK,IAAI;AAEzC,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK;AAAA,MACX;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,SAAS,KAAK;AAAA,IAChB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAgB;AACd,QAAI,KAAK,SAAS;AAEhB;AAAA,IACF;AACA,QAAI,KAAK,UAAU,QAAW;AAC5B,WAAK,QAAQ;AAAA,IAIf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kCAAwC;AACtC,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,QAAQ;AACN,SAAK,aAAa,MAAM;AACxB,SAAK,QAAQ,KAAK;AAElB,SAAK,uBAAuB,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAiE;AAC/D,WAAO,IAAI,IAAI,KAAK,YAAY;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBACE,aACM;AACN,SAAK,aAAa,MAAM;AACxB,eAAW,CAAC,KAAK,KAAK,KAAK,aAAa;AACtC,WAAK,aAAa,IAAI,KAAK,KAAK;AAAA,IAClC;AAEA,SAAK,uBAAuB,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAqE;AACnE,WAAO,IAAI,IAAI,KAAK,YAAY;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAA4C;AAC1C,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,6BAAwD;AAEtD,WAAO,IAAI,IAAI,KAAK,sBAAsB;AAAA,EAC5C;AACF;;;ACtTO,IAAM,gBAAN,MAAoB;AAAA,EAChB;AAAA,EACA;AAAA,EAET,YAAY,MAAc,OAA4B;AACpD,SAAK,OAAO;AACZ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,QACE,MACA,SACA,QACA,iBACA,OACmB;AACnB,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACPA,IAAM,sBAAsB;AAWrB,IAAM,eAAN,MAAmB;AAAA;AAAA,EAEf,WAAW,oBAAI,IAA2B;AAAA;AAAA,EAGnD,YAAyC;AAAA;AAAA,EAGzC,QAAuB,CAAC;AAAA,EACxB,UAA2B,CAAC;AAAA,EAC5B,SAAyB,CAAC;AAAA,EAC1B,cAAmC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQpC,qBAAqB;AACnB,eAAW,KAAK,KAAK,MAAO,GAAE,MAAM;AACpC,eAAW,MAAM,KAAK,QAAS,IAAG,MAAM;AACxC,eAAW,MAAM,KAAK,OAAQ,IAAG,MAAM;AACvC,eAAW,KAAK,KAAK,YAAa,GAAE,MAAM;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAAc,OAA2C;AACjE;AAAA,MACE,CAAC,KAAK,SAAS,IAAI,IAAI;AAAA,MACvB,UAAU,IAAI;AAAA,IAChB;AACA,UAAM,SAAS,IAAI,cAAc,MAAM,KAAK;AAC5C,SAAK,SAAS,IAAI,MAAM,MAAM;AAC9B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAA6B;AACrC,UAAM,SAAS,KAAK,SAAS,IAAI,IAAI;AACrC,WAAO,WAAW,QAAW,UAAU,IAAI,yBAAyB;AACpE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,MAAuB;AAC/B,WAAO,KAAK,SAAS,IAAI,IAAI;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,UAAiC;AAC3C,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,qBAAqB,cAAmC;AACtD;AAAA,MACE,KAAK,cAAc;AAAA,MACnB;AAAA,IACF;AACA,SAAK,UAAU,qBAAqB,YAAY;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,cAAqC;AAChD,UAAM,WAAW,KAAK,KAAK,SAAS,EAAE,aAAa,YAAY;AAC/D,WAAO,SAAS,OAAO,SAAS;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,0BAAqC;AACnC,WAAO;AAAA,MACL,aAAa,KAAK,YAAY,IAAI,QAAM;AAAA,QACtC,OAAO,EAAE;AAAA,MACX,EAAE;AAAA,MACF,OAAO,KAAK,MAAM,IAAI,QAAM,EAAC,MAAM,EAAE,KAAI,EAAE;AAAA,MAC3C,SAAS,KAAK,QAAQ,IAAI,SAAO,EAAC,MAAM,GAAG,KAAI,EAAE;AAAA,MACjD,QAAQ,KAAK,OAAO,IAAI,SAAO,EAAC,MAAM,GAAG,KAAI,EAAE;AAAA,MAC/C,uBAAuB,KAAK,YAAY,IAAI,OAAK,EAAE,mBAAmB,CAAC;AAAA,IACzE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,wBAAwB,OAAwB;AAC9C,SAAK,uBAAuB,KAAK;AACjC,SAAK,oBAAoB,KAAK;AAC9B,SAAK,cAAc,KAAK;AACxB,SAAK,iBAAiB,KAAK;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAuB,OAAwB;AAC7C;AAAA,MACE,KAAK,YAAY,WAAW,MAAM,YAAY;AAAA,MAC9C;AAAA,IACF;AACA;AAAA,MACE,KAAK,MAAM,WAAW,MAAM,MAAM;AAAA,MAClC;AAAA,IACF;AACA;AAAA,MACE,KAAK,QAAQ,WAAW,MAAM,QAAQ;AAAA,MACtC;AAAA,IACF;AACA;AAAA,MACE,KAAK,OAAO,WAAW,MAAM,OAAO;AAAA,MACpC;AAAA,IACF;AACA;AAAA,MACE,KAAK,YAAY,WAAW,MAAM,sBAAsB;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,OAAwB;AAC1C,aAAS,IAAI,GAAG,IAAI,KAAK,YAAY,QAAQ,KAAK;AAChD,WAAK,YAAY,CAAC,EAAE,QAAQ,MAAM,YAAY,CAAC,EAAE;AACjD,WAAK,YAAY,CAAC,EAAE,mBAAmB,MAAM,sBAAsB,CAAC,CAAC;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,OAAwB;AACpC,aAAS,IAAI,GAAG,IAAI,KAAK,MAAM,QAAQ,KAAK;AAC1C,YAAM,OAAO,KAAK,MAAM,CAAC;AACzB,YAAM,cAAc,MAAM,MAAM,CAAC;AAGjC,WAAK,MAAM;AAGX,UAAI,YAAY,SAAS,WAAW;AAClC,aAAK,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAiB,OAAwB;AACvC,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,QAAQ,KAAK;AAC5C,YAAM,KAAK,KAAK,QAAQ,CAAC;AACzB,YAAM,aAAa,MAAM,QAAQ,CAAC,EAAE;AACpC,UAAI,eAAe,SAAS,GAAG,SAAS,MAAM;AAC5C,WAAG,aAAa;AAAA,MAClB;AAAA,IACF;AAEA,aAAS,IAAI,GAAG,IAAI,KAAK,OAAO,QAAQ,KAAK;AAC3C,YAAM,KAAK,KAAK,OAAO,CAAC;AACxB,YAAM,aAAa,MAAM,OAAO,CAAC,EAAE;AACnC,UAAI,eAAe,SAAS,GAAG,SAAS,MAAM;AAC5C,WAAG,aAAa;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,KAAK,cAAmC;AAEtC,UAAM,iBAAiB,KAAK,MAAM,OAAO,OAAK,EAAE,YAAY,CAAC;AAG7D,QAAI,eAAe,SAAS,qBAAqB;AAC/C,YAAM,IAAI;AAAA,QACR,aAAa,eAAe,MAAM,4FAC7B,KAAK,eAAe,MAAM,gIACyD,mBAAmB;AAAA,MAC7G;AAAA,IACF;AAGA,UAAM,YAAY,eAAe,IAAI;AAErC,UAAM,cAAc,KAAK,eAAe;AACxC,QAAI,WAAW;AACf,QAAI,WAAkC;AACtC,QAAI,oBAAoB;AAIxB,UAAM,eAAe;AACrB,aAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,UAAI,iBAAiB,UAAa,YAAY,cAAc;AAC1D;AAAA,MACF;AAEA,WAAK,mBAAmB;AAExB,UAAI,cAAc;AAChB,qBAAa,IAAI;AAAA,UACf,MAAM;AAAA,UACN,eAAe;AAAA,UACf,eAAe;AAAA,QACjB,CAAC;AAAA,MACH;AAEA,UAAI;AAGF,iBAAS,IAAI,GAAG,IAAI,eAAe,QAAQ,KAAK;AAC9C,cAAI,UAAW,KAAK,GAAI;AACtB,2BAAe,CAAC,EAAE,KAAK;AAAA,UACzB;AAAA,QACF;AAGA,4BAAoB,SAAS;AAG7B,wCAAgC,IAAI;AAGpC,aAAK,qBAAqB,YAAY;AAEtC,YAAI,cAAc;AAChB,uBAAa,IAAI;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,uBAAuB,KAAK,YAAY,IAAI,QAAM;AAAA,cAChD,YAAY,EAAE;AAAA,cACd,aAAa,EAAE,uBAAuB;AAAA,cACtC,iBAAiB,EAAE,2BAA2B;AAAA,YAChD,EAAE;AAAA,UACJ,CAAC;AAAA,QACH;AAGA,cAAM,YAAY,KAAK,aAAa,YAAY;AAEhD,YAAI,cAAc;AAChB,uBAAa,IAAI;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf;AAAA,YACA,aAAa;AAAA;AAAA;AAAA;AAAA,YAGb,YAAY,KAAK,MAAM,IAAI,OAAK;AAC9B,oBAAM,OAAO,EAAE,aAAa;AAC5B,qBAAO;AAAA,gBACL,MAAM,KAAK;AAAA,gBACX,MAAM,KAAK;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH,CAAC;AAAA,QACH;AAGA,YAAI,YAAY,UAAU;AACxB,qBAAW;AACX,qBAAW,KAAK,wBAAwB;AACxC,8BAAoB;AAAA,QACtB;AAAA,MACF,SAAS,GAAG;AAEV,YAAI,cAAc;AAChB,uBAAa,IAAI;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,QAAQ,gBAAgB,QAAQ,SAAS,CAAC,CAAC,YAAY,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,UACnG,CAAC;AAAA,QACH;AACA;AAAA,MACF;AAAA,IACF;AAGA,QAAI,UAAU;AACZ,WAAK,wBAAwB,QAAQ;AAErC,WAAK,qBAAqB,YAAY;AAEtC,UAAI,cAAc;AAChB,qBAAa,IAAI;AAAA,UACf,MAAM;AAAA,UACN;AAAA,UACA,WAAW;AAAA,UACX,aAAa;AAAA;AAAA,UACb,YAAY,KAAK,MAAM,IAAI,QAAM;AAAA,YAC/B,MAAM,EAAE,QAAQ;AAAA,YAChB,MAAM,EAAE;AAAA,UACV,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AAEL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,eAAe,OAAmD;AACzE,QAAM,QAAQ,oBAAI,IAA6B;AAE/C,aAAW,MAAM,MAAM,SAAS;AAC9B,UAAM,OAAO,eAAe,EAAE;AAC9B,UAAM,IAAI,IAAI,IAAI;AAAA,EACpB;AAEA,SAAO;AACT;AAQA,SAAS,oBAAoB,WAA+C;AAC1E,aAAW,CAAC,IAAI,IAAI,KAAK,WAAW;AAClC,UAAM,iBAAiB,KAAK,aAAa,KAAK,OAAK,EAAE,SAAS,SAAS;AACvE,QAAI,KAAK,MAAM,gBAAgB;AAC7B,SAAG,aAAa;AAChB,WAAK,GAAG,aAAa;AAAA,IACvB;AAAA,EACF;AACF;AAMA,SAAS,eAAe,IAA6B;AACnD,QAAM,eAA8B,CAAC;AACrC,MAAI,KAA+B;AAGnC,QAAM,QAAuB,CAAC,GAAG,GAAG,OAAO;AAC3C,QAAM,UAAU,oBAAI,IAAiB;AAErC,SAAO,MAAM,SAAS,GAAG;AACvB,UAAM,OAAO,KAAK,MAAM,MAAM,CAAC;AAC/B,QAAI,QAAQ,IAAI,IAAI,EAAG;AACvB,YAAQ,IAAI,IAAI;AAEhB,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK;AACH,qBAAa,KAAK,IAAI;AACtB,cAAM,KAAK,KAAK,MAAM;AACtB;AAAA,MACF,KAAK;AAEH,cAAM,KAAK,GAAG,KAAK,OAAO;AAC1B;AAAA,MACF,KAAK;AAEH,aAAK;AACL;AAAA,MACF,KAAK;AAEH;AAAA,MACF,KAAK;AAEH;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,EAAC,IAAI,aAAY;AAC1B;AASA,SAAS,gCAAgC,OAA2B;AAClE,aAAW,QAAQ,MAAM,OAAO;AAC9B,QAAI,KAAK,SAAS,WAAW;AAC3B,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AACF;;;AC9bA,SAAS,mCACP,oBACA,kBACA,iBAC+B;AAC/B,MAAI,CAAC,mBAAoB,QAAO;AAEhC,QAAM,aAAa,OAAO,KAAK,gBAAgB;AAC/C,QAAM,YAAY,OAAO,KAAK,eAAe;AAC7C,QAAM,aAAgC,CAAC;AAEvC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,kBAAkB,GAAG;AAC7D,UAAM,QAAQ,WAAW,QAAQ,GAAG;AACpC,QAAI,UAAU,IAAI;AAGhB,iBAAW,UAAU,KAAK,CAAC,IAAI;AAAA,IACjC;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,UAAU,EAAE,SAAS,IAAI,aAAa;AAC3D;AAgDO,IAAM,cAAN,MAAkB;AAAA,EACd,OAAO;AAAA,EAEP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA;AAAA;AAAA,EAGA;AAAA,EAEA,YACE,QACA,OACA,kBACA,iBACA,WACA,QACA;AACA,SAAK,QAAQ;AACb,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,mBAAmB;AACxB,SAAK,oBAAoB;AACzB,SAAK,aAAa;AAClB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,UAAU,MAAyB;AACjC,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,IAAI,SAAsB;AACxB,WAAO,KAAK,YAAY,QAAW,gBAAgB;AACnD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,sBAAwC;AACtC,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,OAA0B;AACrC,QAAI,UAAU,KAAK,QAAQ;AACzB,WAAK,KAAK;AAAA,IACZ,OAAO;AACL;AAAA,QACE,UAAU,KAAK;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAa;AACX,WAAO,KAAK,UAAU,QAAQ,2BAA2B;AACzD,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,OAA2B;AAC7B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,cAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,mBAAyB;AACvB,WAAO,KAAK,UAAU,WAAW,iCAAiC;AAClE,SAAK,QAAQ,gCAAgC;AAC7C,SAAK,OAAO,gCAAgC;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kCAAwC;AACtC,QAAI,KAAK,UAAU,QAAQ;AACzB,WAAK,QAAQ,gCAAgC;AAAA,IAC/C;AAAA,EAEF;AAAA,EAEA,qBACE,eACA,YACA,MACA,cACM;AACN,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK,QAAQ;AAAA,MACnB;AAAA,MACA;AAAA,MACA,MAAM,OAAO,YAAY,IAAI,IAAI;AAAA,IACnC,CAAC;AAED,QAAI,KAAK,UAAU,QAAQ;AAGzB,WAAK,OAAO;AAAA,QACV;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAEA,WAAK,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF,WAAW,KAAK,UAAU,WAAW;AAMnC,YAAM,uBAAuB;AAAA,QAC3B;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AACA,WAAK,OAAO;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAIA,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,iBAAiB,YAAY,KAAK,iBAAiB;AAAA,QACnD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,QAAc;AACZ,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,aAOE,4BA0BA,eACA,cACc;AAQd,UAAM,QAAQ,KAAK,OAAO,aAAa,GAAG,eAAe,YAAY;AAcrE,UAAM,SAAS,KAAK,QAAQ;AAAA;AAAA;AAAA,MAG1B,MAAM,cAAc;AAAA,MACpB;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AAEJ,QAAI,KAAK,SAAS,QAAQ;AACxB,qBAAe;AAAA,QACb,aAAa,OAAO;AAAA,QACpB,SACE,OAAO,UAAU,SACb,OAAO,eACP,KAAK;AAAA,UACH,OAAO;AAAA,UACP,OAAO,QAAQ;AAAA,QACjB;AAAA,QACN,MACE,OAAO,OAAO,OAAO,WAAW,MAAM,cAAc,MAAM;AAAA,QAC5D,cAAc,OAAO,eAAe,MAAM;AAAA,QAC1C,aAAa,MAAM,cAAc,OAAO;AAAA,QACxC,OAAO,OAAO;AAAA,MAChB;AAAA,IACF,OAAO;AACL,qBAAe;AAAA,QACb,aAAa,MAAM;AAAA,QACnB,SACE,OAAO,UAAU,SACb,OAAO,eACP,KAAK;AAAA,UACH,OAAO,eAAe,MAAM;AAAA,UAC5B,OAAO,QAAQ;AAAA,QACjB;AAAA,QACN,MACE,MAAM,OAAO,MAAM,WAAW,OAAO,cAAc,OAAO;AAAA,QAC5D,cACE,OAAO,eAAe,MAAM,eAAe,MAAM;AAAA,QACnD,aAAa,OAAO,cAAc,MAAM;AAAA,QACxC,OAAO,OAAO;AAAA,MAChB;AAAA,IACF;AAEA,kBAAc,IAAI;AAAA,MAChB,MAAM;AAAA,MACN,UAAU;AAAA,MACV,MAAM,KAAK,QAAQ;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,IACjB,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAkB;AAChB,UAAM,aAAa,YAAY,KAAK,OAAO;AAC3C,UAAM,YAAY,YAAY,KAAK,MAAM;AACzC,WAAO,GAAG,UAAU,WAAM,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,eAIE;AACA,WAAO;AAAA,MACL,MAAM,KAAK,QAAQ;AAAA,MACnB,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,IACf;AAAA,EACF;AACF;AAEO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAMA,SAAS,YAAY,MAA2B;AAC9C,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,KAAK;AAAA,IACd,KAAK;AACH,aAAO,KAAK,QAAQ;AAAA,IACtB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,EACX;AACF;;;ACpaO,IAAM,kBAAN,MAAsB;AAAA,EAClB,OAAO;AAAA,EACP;AAAA,EAET,YAAY,OAA8C;AACxD,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,sBAAwC;AACtC,WAAO,KAAK,OAAO,oBAAoB;AAAA,EACzC;AAAA,EAEA,qBAAqB,cAAmC;AACtD,SAAK,OAAO,qBAAqB,CAAC,GAAG,QAAW,MAAM,YAAY;AAAA,EACpE;AAAA,EAEA,aAAa,cAA2C;AAEtD,WAAO,KAAK,OAAO,aAAa,GAAG,CAAC,GAAG,YAAY;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kCAAwC;AAAA,EAExC;AACF;;;ACnBA,SAAS,WAAW,MAAmB,IAAuB;AAC5D,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,WAAK,UAAU,EAAE;AACjB;AAAA,IACF,KAAK;AACH,WAAK,UAAU,EAAE;AACjB;AAAA,IACF,KAAK;AACH,aAAO,OAAO,oCAAoC;AAAA,EACtD;AACF;AAOO,SAAS,eACd,KACA,OACA,QACA,iBACO;AACP,QAAM,QAAQ,IAAI,aAAa;AAC/B,MAAI,aAAa;AAEjB,QAAM,SAAS,MAAM,UAAU,IAAI,OAAO,KAAK;AAC/C,QAAM,aAAa,OAAO;AAAA,IACxB,IAAI,WAAW,CAAC;AAAA,IAChB,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,IAAI;AAAA,EACN;AACA,QAAM,YAAY,KAAK,UAAU;AAEjC,MAAI,MAAmB;AACvB,MAAI,IAAI,OAAO;AACb,UAAM;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA,IAAI;AAAA,MACJ,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,gBAAgB,GAAG;AACxC,aAAW,KAAK,QAAQ;AACxB,QAAM,YAAY,QAAQ;AAE1B,QAAM,WAAmC,CAAC;AAC1C,MAAI,IAAI,SAAS;AACf,eAAW,OAAO,IAAI,SAAS;AAC7B,YAAM,QAAQ;AAAA,QACZ,IAAI,SAAS;AAAA,QACb;AAAA,MACF;AACA,YAAM,mBAAmB;AAAA,QACvB,IAAI,YAAY;AAAA,QAChB,IAAI,SAAS;AAAA,MACf;AACA,eAAS,KAAK,IAAI;AAAA,QAChB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAC,MAAM,OAAO,SAAQ;AAC/B;AAEA,SAAS,iBACP,WACA,OACA,OACA,OACA,aACA,WACuC;AACvC,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,WAAW,WAAW,OAAO,OAAO,OAAO,aAAa,SAAS;AAAA,IAC1E,KAAK;AACH,aAAO,UAAU,WAAW,OAAO,OAAO,OAAO,aAAa,SAAS;AAAA,IACzE,KAAK;AACH,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,EACJ;AACF;AAEA,SAAS,WACP,WACA,OACA,OACA,OACA,aACA,WACuC;AACvC,MAAI,MAAM;AACV,aAAW,gBAAgB,UAAU,YAAY;AAC/C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,UACP,WACA,OACA,OACA,OACA,aACA,WACuC;AACvC,QAAM,qBAAqB,UAAU,WAAW;AAAA,IAC9C,OAAK,EAAE,SAAS,wBAAwB,sBAAsB,CAAC;AAAA,EACjE;AAEA,MAAI,mBAAmB,WAAW,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,IAAI,cAAc,KAAK;AACtC,QAAM,QAAQ,KAAK,MAAM;AACzB,aAAW,OAAO,MAAM;AAExB,QAAM,WAAoD,CAAC;AAC3D,aAAW,gBAAgB,oBAAoB;AAC7C,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,aAAS,KAAK,MAAM;AACpB,WAAO,UAAU,MAAM;AAAA,EACzB;AAEA,QAAM,QAAQ,IAAI,aAAa,QAAQ;AACvC,QAAM,OAAO,KAAK,KAAK;AACvB,aAAW,UAAU,UAAU;AAC7B,eAAW,QAAQ,KAAK;AAAA,EAC1B;AAEA,SAAO;AACT;AAEA,SAAS,0BACP,WACA,OACA,OACA,OACA,aACA,WACuC;AACvC,QAAM,EAAC,QAAO,IAAI;AAClB,QAAM,aAAa,QAAQ,SAAS;AAEpC,QAAM,cAAc,MAAM,UAAU,UAAU,IAC1C,MAAM,UAAU,UAAU,IAC1B,MAAM,UAAU,YAAY,KAAK;AAErC,QAAM,kBAAkB,YAAY;AAAA,IAClC,QAAQ,SAAS,WAAW,CAAC;AAAA,IAC7B,QAAQ,SAAS;AAAA,IACjB;AAAA,IACA;AAAA;AAAA,IACA,UAAU,OAAO,WAAW,IAAI;AAAA,EAClC;AACA,QAAM,YAAY,KAAK,eAAe;AAEtC,MAAI,WAAwB;AAC5B,MAAI,QAAQ,SAAS,OAAO;AAC1B,eAAW;AAAA,MACT,QAAQ,SAAS;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,mBAAmB;AAAA,IACvB,QAAQ,YAAY;AAAA,IACpB;AAAA,EACF;AACA,QAAM,kBAAkB;AAAA,IACtB,QAAQ,YAAY;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,SAAS,UAAU;AACzB,YAAU,YAAY,IAAI;AAE1B,QAAM,OAAO,IAAI;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,OAAO;AAAA,IACjB;AAAA,EACF;AACA,QAAM,MAAM,KAAK,IAAI;AAErB,aAAW,OAAO,IAAI;AACtB,aAAW,UAAU,IAAI;AAEzB,SAAO;AACT;AAEA,SAAS,sBAAsB,WAA+B;AAC5D,MAAI,UAAU,SAAS,sBAAsB;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,UAAU,SAAS,SAAS,UAAU,SAAS,MAAM;AACvD,WAAO,UAAU,WAAW,KAAK,qBAAqB;AAAA,EACxD;AACA,SAAO;AACT;AAEA,SAAS,kBACP,QACA,YACmB;AACnB,SAAO,OAAO,YAAY,OAAO,IAAI,WAAS,CAAC,OAAO,MAAS,CAAC,CAAC;AACnE;AAEA,SAAS,gBAAgB,OAAc,cAAmC;AACxE,aAAW,WAAW,OAAO,OAAO,MAAM,QAAQ,GAAG;AACnD,oBAAgB,SAAS,YAAY;AAAA,EACvC;AACA,QAAM,KAAK,KAAK,YAAY;AAC9B;AAEO,SAAS,UACd,KACA,OACA,cACK;AACL,QAAM,QAAQ,eAAe,KAAK,OAAO,IAAI;AAC7C,kBAAgB,OAAO,YAAY;AACnC,SAAO,gBAAgB,KAAK,KAAK;AACnC;AAEA,SAAS,iBACP,WACA,YACW;AACX,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,SAAS,sBAAsB;AAC3C,UAAM,SAAU,UACd,YACF;AACA,UAAM,aAAa,WAAW,UAAa,WAAW,IAAI,MAAM;AAEhE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,aAAa,OAAO,UAAU;AAAA,MACpC,SAAS;AAAA,QACP,GAAG,UAAU;AAAA,QACb,UAAU;AAAA,UACR,GAAG,UAAU,QAAQ;AAAA,UACrB,OAAO,UAAU,QAAQ,SAAS,QAC9B,iBAAiB,UAAU,QAAQ,SAAS,OAAO,UAAU,IAC7D;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY,UAAU,WAAW,IAAI,OAAK,iBAAiB,GAAG,UAAU,CAAC;AAAA,EAC3E;AACF;AAEO,SAAS,gBAAgB,KAAU,OAAmB;AAC3D,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,QAAQ,MAAM,KAAK,OAAO;AACnC,QAAI,KAAK,SAAS,aAAa,KAAK,WAAW,QAAW;AACxD,iBAAW,IAAI,KAAK,MAAM;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,IAAI,QAAQ,iBAAiB,IAAI,OAAO,UAAU,IAAI;AAAA,IAC7D,SAAS,IAAI,SAAS,IAAI,SAAO;AAC/B,YAAM,QAAQ;AAAA,QACZ,IAAI,SAAS;AAAA,QACb;AAAA,MACF;AACA,YAAM,UAAU,MAAM,SAAS,KAAK;AACpC,aAAO;AAAA,QACL,GAAG;AAAA,QACH,UAAU,UACN,gBAAgB,IAAI,UAAU,OAAO,IACrC,IAAI;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7SO,IAAM,oBAAN,MAGL;AAAA,EACS;AAAA,EAMT,YACE,QAKA;AACA,SAAK,UAAU;AACf,SAAK,SAAS,KAAK,OAAO,KAAK,IAAI;AAAA,EACrC;AAAA,EAEA,IAAI,KAAK;AACP,WAAO;AAAA,EACT;AAAA,EAoBA,IACE,OACA,WACA,OACW;AACX,WAAO,IAAI,OAAO,WAAW,KAAK;AAAA,EACpC;AAAA,EAEA,OACE,MACA,IACA,OACW;AACX,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,qBAAqB,IAAI,IAC3B,KAAK,aAAa,EAAE,IACpB,EAAC,MAAM,WAAW,OAAO,KAAI;AAAA,MACjC,OAAO,qBAAqB,KAAK,IAC7B,MAAM,aAAa,EAAE,IACrB,EAAC,MAAM,WAAW,OAAO,MAAK;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EAEN,SAAS,CACP,cACA,IAGA,YACc,KAAK,QAAQ,cAAc,IAAI,OAAO;AACxD;AAEO,SAAS,OAAO,YAAkD;AACvE,QAAM,cAAc,WAAW,gBAAgB,UAAU,CAAC;AAE1D,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO,YAAY,CAAC;AAAA,EACtB;AAEA,MAAI,YAAY,KAAK,aAAa,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,SAAO,EAAC,MAAM,OAAO,YAAY,YAAW;AAC9C;AAEO,SAAS,MAAM,YAAkD;AACtE,QAAM,cAAc,YAAY,gBAAgB,UAAU,CAAC;AAE3D,MAAI,YAAY,WAAW,GAAG;AAC5B,WAAO,YAAY,CAAC;AAAA,EACtB;AAEA,MAAI,YAAY,KAAK,YAAY,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,SAAO,EAAC,MAAM,MAAM,YAAY,YAAW;AAC7C;AAEO,SAAS,IAAI,YAAkC;AACpD,UAAQ,WAAW,MAAM;AAAA,IACvB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY,WAAW,WAAW,IAAI,GAAG;AAAA,MAC3C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY,WAAW,WAAW,IAAI,GAAG;AAAA,MAC3C;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,WAAW;AAAA,QACpB,IAAI,eAAe,WAAW,EAAE;AAAA,MAClC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,eAAe,WAAW,EAAE;AAAA,QAChC,MAAM,WAAW;AAAA,QACjB,OAAO,WAAW;AAAA,MACpB;AAAA,EACJ;AACF;AAEO,SAAS,IACd,OACA,WACA,OACW;AACX,MAAI;AACJ,MAAI,UAAU,QAAW;AACvB,YAAQ;AACR,SAAK;AAAA,EACP,OAAO;AACL,SAAK;AAAA,EACP;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM,EAAC,MAAM,UAAU,MAAM,MAAK;AAAA,IAClC,OAAO,qBAAqB,KAAK,IAC7B,MAAM,aAAa,EAAE,IACrB,EAAC,MAAM,WAAW,MAAK;AAAA,IAC3B;AAAA,EACF;AACF;AAEA,SAAS,qBACP,OAC6B;AAC7B,SACE,UAAU,QAAQ,OAAO,UAAU,YAAa,MAAc,aAAa;AAE/E;AAEO,IAAM,OAAkB;AAAA,EAC7B,MAAM;AAAA,EACN,YAAY,CAAC;AACf;AAEA,IAAM,QAAmB;AAAA,EACvB,MAAM;AAAA,EACN,YAAY,CAAC;AACf;AAEA,SAAS,aAAa,WAA+B;AACnD,SAAO,UAAU,SAAS,SAAS,UAAU,WAAW,WAAW;AACrE;AAEA,SAAS,cAAc,WAA+B;AACpD,SAAO,UAAU,SAAS,QAAQ,UAAU,WAAW,WAAW;AACpE;AAEO,SAAS,kBAAkB,GAAyB;AACzD,MAAI,EAAE,SAAS,YAAY,EAAE,SAAS,sBAAsB;AAC1D,WAAO;AAAA,EACT;AACA,MAAI,EAAE,WAAW,WAAW,GAAG;AAC7B,WAAO,kBAAkB,EAAE,WAAW,CAAC,CAAC;AAAA,EAC1C;AACA,QAAM,aAAa,QAAQ,EAAE,MAAM,EAAE,WAAW,IAAI,iBAAiB,CAAC;AACtE,MAAI,EAAE,SAAS,SAAS,WAAW,KAAK,aAAa,GAAG;AACtD,WAAO;AAAA,EACT;AACA,MAAI,EAAE,SAAS,QAAQ,WAAW,KAAK,YAAY,GAAG;AACpD,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,QACd,MACA,YACa;AACb,QAAM,YAAyB,CAAC;AAChC,aAAW,KAAK,YAAY;AAC1B,QAAI,EAAE,SAAS,MAAM;AACnB,gBAAU,KAAK,GAAG,EAAE,UAAU;AAAA,IAChC,OAAO;AACL,gBAAU,KAAK,CAAC;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,IAAM,0BAA0B;AAAA,EAC9B,CAAC,GAAG,GAAG;AAAA,EACP,CAAC,IAAI,GAAG;AAAA,EACR,CAAC,GAAG,GAAG;AAAA,EACP,CAAC,GAAG,GAAG;AAAA,EACP,CAAC,IAAI,GAAG;AAAA,EACR,CAAC,IAAI,GAAG;AAAA,EACR,CAAC,IAAI,GAAG;AAAA,EACR,CAAC,QAAQ,GAAG;AAAA,EACZ,CAAC,MAAM,GAAG;AAAA,EACV,CAAC,UAAU,GAAG;AAAA,EACd,CAAC,OAAO,GAAG;AAAA,EACX,CAAC,WAAW,GAAG;AAAA,EACf,CAAC,IAAI,GAAG;AAAA,EACR,CAAC,QAAQ,GAAG;AACd;AAEA,IAAM,oBAAoB;AAAA,EACxB,GAAG;AAAA,EACH,CAAC,QAAQ,GAAG;AAAA,EACZ,CAAC,YAAY,GAAG;AAClB;AAEO,SAAS,eACd,IACgC;AAChC,SAAO,KAAK,kBAAkB,EAAE,CAAC;AACnC;AAEA,SAAS,gBAAmBC,SAA+B;AACzD,SAAOA,QAAM,OAAO,OAAK,MAAM,MAAS;AAC1C;AAEA,SAAS,WAAW,YAAsC;AACxD,SAAO,WAAW,OAAO,OAAK,CAAC,aAAa,CAAC,CAAC;AAChD;AAEA,SAAS,YAAY,YAAsC;AACzD,SAAO,WAAW,OAAO,OAAK,CAAC,cAAc,CAAC,CAAC;AACjD;;;ACjTO,SAAS,iBACd,SACA,OACuB;AACvB,QAAM,KAAK,UAAU,OAAO,OAAO,GAAG,KAAK;AAC3C,SAAO,CAAC,QAAsB;AAC5B,iBAAa,GAAG;AAChB,WAAO,GAAG,OAAO,GAAG,CAAC;AAAA,EACvB;AACF;AAEA,SAAS,UAAU,SAAiB,OAA2C;AAO7E,MAAI,CAAC,SAAS,KAAK,OAAO,GAAG;AAC3B,QAAI,UAAU,KAAK;AACjB,YAAM,WAAW,QAAQ,YAAY;AACrC,aAAO,CAAC,QAAgB,IAAI,YAAY,MAAM;AAAA,IAChD;AACA,WAAO,CAAC,QAAgB,QAAQ;AAAA,EAClC;AACA,QAAM,KAAK,gBAAgB,SAAS,KAAK;AACzC,SAAO,CAAC,QAAgB,GAAG,KAAK,GAAG;AACrC;AAEA,IAAM,iBAAiB;AAEvB,SAAS,gBAAgB,QAAgB,QAAkB,IAAY;AAMrE,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,QAAI,IAAI,OAAO,CAAC;AAChB,YAAQ,GAAG;AAAA,MACT,KAAK;AACH,mBAAW;AACX;AAAA,MACF,KAAK;AACH,mBAAW;AACX;AAAA;AAAA,MAGF,KAAK;AACH,YAAI,MAAM,OAAO,SAAS,GAAG;AAC3B,gBAAM,IAAI,MAAM,iDAAiD;AAAA,QACnE;AACA;AACA,YAAI,OAAO,CAAC;AAAA;AAAA,MAGd;AACE,YAAI,eAAe,KAAK,CAAC,GAAG;AAC1B,qBAAW;AAAA,QACb;AACA,mBAAW;AAEX;AAAA,IACJ;AAAA,EACF;AACA,SAAO,IAAI,OAAO,UAAU,KAAK,QAAQ,GAAG;AAC9C;;;AC7CO,SAAS,gBACd,WACuB;AACvB,MAAI,UAAU,SAAS,UAAU;AAC/B,UAAM,aAAa,UAAU,WAAW,IAAI,OAAK,gBAAgB,CAAC,CAAC;AACnE,WAAO,UAAU,SAAS,QACtB,CAAC,QAAa;AAEZ,iBAAW,aAAa,YAAY;AAClC,YAAI,CAAC,UAAU,GAAG,GAAG;AACnB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT,IACA,CAAC,QAAa;AAEZ,iBAAW,aAAa,YAAY;AAClC,YAAI,UAAU,GAAG,GAAG;AAClB,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAAA,EACN;AACA,QAAM,EAAC,KAAI,IAAI;AACf,QAAM,EAAC,MAAK,IAAI;AAChB;AAAA,IACE,MAAM,SAAS;AAAA,IACf;AAAA,EACF;AACA;AAAA,IACE,KAAK,SAAS;AAAA,IACd;AAAA,EACF;AAEA,UAAQ,UAAU,IAAI;AAAA,IACpB,KAAK;AAAA,IACL,KAAK,UAAU;AACb,YAAMC,QAAO,kBAAkB,MAAM,OAAO,UAAU,EAAE;AACxD,UAAI,KAAK,SAAS,WAAW;AAC3B,cAAM,SAASA,MAAK,KAAK,KAAK;AAC9B,eAAO,MAAM;AAAA,MACf;AACA,aAAO,CAAC,QAAaA,MAAK,IAAI,KAAK,IAAI,CAAC;AAAA,IAC1C;AAAA,EACF;AAEA,MAAI,MAAM,UAAU,QAAQ,MAAM,UAAU,QAAW;AACrD,WAAO,CAAC,SAAc;AAAA,EACxB;AAEA,QAAM,OAAO,oBAAoB,MAAM,OAAO,UAAU,EAAE;AAC1D,MAAI,KAAK,SAAS,WAAW;AAC3B,QAAI,KAAK,UAAU,QAAQ,KAAK,UAAU,QAAW;AACnD,aAAO,CAAC,SAAc;AAAA,IACxB;AACA,UAAM,SAAS,KAAK,KAAK,KAAK;AAC9B,WAAO,MAAM;AAAA,EACf;AAEA,SAAO,CAAC,QAAa;AACnB,UAAM,MAAM,IAAI,KAAK,IAAI;AACzB,QAAI,QAAQ,QAAQ,QAAQ,QAAW;AACrC,aAAO;AAAA,IACT;AACA,WAAO,KAAK,GAAG;AAAA,EACjB;AACF;AAEA,SAAS,kBACP,KACA,UACiB;AACjB,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,SAAO,QAAQ;AAAA,IACxB,KAAK;AACH,aAAO,SAAO,QAAQ;AAAA,EAC1B;AACF;AAEA,SAAS,oBACP,KACA,UACuB;AACvB,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,aAAO,SAAO,QAAQ;AAAA,IACxB,KAAK;AACH,aAAO,SAAO,QAAQ;AAAA,IACxB,KAAK;AACH,aAAO,SAAO,MAAM;AAAA,IACtB,KAAK;AACH,aAAO,SAAO,OAAO;AAAA,IACvB,KAAK;AACH,aAAO,SAAO,MAAM;AAAA,IACtB,KAAK;AACH,aAAO,SAAO,OAAO;AAAA,IACvB,KAAK;AACH,aAAO,iBAAiB,KAAK,EAAE;AAAA,IACjC,KAAK;AACH,aAAOC,KAAI,iBAAiB,KAAK,EAAE,CAAC;AAAA,IACtC,KAAK;AACH,aAAO,iBAAiB,KAAK,GAAG;AAAA,IAClC,KAAK;AACH,aAAOA,KAAI,iBAAiB,KAAK,GAAG,CAAC;AAAA,IACvC,KAAK,MAAM;AACT,aAAO,MAAM,QAAQ,GAAG,CAAC;AACzB,YAAM,MAAM,IAAI,IAAI,GAAG;AACvB,aAAO,SAAO,IAAI,IAAI,GAAG;AAAA,IAC3B;AAAA,IACA,KAAK,UAAU;AACb,aAAO,MAAM,QAAQ,GAAG,CAAC;AACzB,YAAM,MAAM,IAAI,IAAI,GAAG;AACvB,aAAO,SAAO,CAAC,IAAI,IAAI,GAAG;AAAA,IAC5B;AAAA,IACA;AACE;AACA,YAAM,IAAI,MAAM,wBAAwB,QAAQ,EAAE;AAAA,EACtD;AACF;AAEA,SAASA,KAAO,GAAwB;AACtC,SAAO,CAAC,QAAW,CAAC,EAAE,GAAG;AAC3B;AAWO,SAAS,iBAAiB,SAG/B;AACA,MAAI,CAAC,SAAS;AACZ,WAAO,EAAC,SAAS,QAAW,mBAAmB,MAAK;AAAA,EACtD;AACA,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,EAAC,SAAS,mBAAmB,MAAK;AAAA,IAC3C,KAAK;AACH,aAAO,EAAC,SAAS,QAAW,mBAAmB,KAAI;AAAA,IACrD,KAAK;AAAA,IACL,KAAK,MAAM;AACT,YAAM,wBAA+C,CAAC;AACtD,UAAI,oBAAoB;AACxB,iBAAW,QAAQ,QAAQ,YAAY;AACrC,cAAM,cAAc,iBAAiB,IAAI;AAGzC,YAAI,YAAY,YAAY,UAAa,QAAQ,SAAS,MAAM;AAC9D,iBAAO,EAAC,SAAS,QAAW,mBAAmB,KAAI;AAAA,QACrD;AACA,4BAAoB,qBAAqB,YAAY;AACrD,YAAI,YAAY,SAAS;AACvB,gCAAsB,KAAK,YAAY,OAAO;AAAA,QAChD;AAAA,MACF;AACA,aAAO;AAAA,QACL,SAAS,kBAAkB;AAAA,UACzB,MAAM,QAAQ;AAAA,UACd,YAAY;AAAA,QACd,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAAA,IACA;AACE,kBAAY,OAAO;AAAA,EACvB;AACF;;;AC/EO,SAAS,cACd,KACA,UACA,SACA,WACO;AACP,QAAM,SAAS,SAAS,SAAS,OAAO,GAAG,IAAI;AAC/C,MAAI,WAAW;AACb,UAAM,UAAU,KAAK,SAAS;AAAA,EAChC;AACA,SAAO,sBAAsB,KAAK,UAAU,SAAS,EAAE;AACzD;AA+EA,IAAM,eAAe;AACrB,IAAM,2BAA2B;AAOjC,SAAS,kBAAkB,WAA4B;AACrD,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK;AACH;AAAA,IAEF,KAAK;AACH,UAAI,UAAU,OAAO,cAAc;AACjC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH,iBAAW,KAAK,UAAU,YAAY;AACpC,0BAAkB,CAAC;AAAA,MACrB;AACA;AAAA,IACF;AACE,kBAAY,SAAS;AAAA,EACzB;AACF;AAEA,SAAS,sBACP,KACA,UACA,SACA,MACA,cACO;AACP,QAAM,SAAS,SAAS,UAAU,IAAI,KAAK;AAC3C,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,qBAAqB,IAAI,KAAK,EAAE;AAAA,EAClD;AACA,QAAM,2CAA2C,GAAG;AAEpD,MAAI,CAAC,SAAS,mBAAmB,IAAI,OAAO;AAC1C,sBAAkB,IAAI,KAAK;AAAA,EAC7B;AAEA,QAAM,gBAAgB,wCAAwC,IAAI,KAAK;AACvE,QAAM,gBAA6B,eAC/B,IAAI,IAAI,YAAY,IACpB,oBAAI,IAAI;AACZ,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,OAAO,eAAe;AAC/B,YAAQ,IAAI,IAAI,QAAQ,SAAS,SAAS,EAAE;AAC5C,eAAW,OAAO,IAAI,QAAQ,YAAY,aAAa;AACrD,oBAAc,IAAI,GAAG;AAAA,IACvB;AAAA,EACF;AACA,MAAI,IAAI,SAAS;AACf,eAAW,OAAO,IAAI,SAAS;AAC7B,iBAAW,OAAO,IAAI,YAAY,aAAa;AAC7C,sBAAc,IAAI,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,OAAO;AAAA,IAClB,KAAK,IAAI,OAAO;AAAA,IAChB,IAAI;AAAA,IACJ;AAAA,IACA,SAAS;AAAA,EACX;AAEA,MAAI,MAAa,SAAS,oBAAoB,MAAM,OAAO;AAC3D,QAAM,SAAS,cAAc,KAAK,GAAG,IAAI,WAAW,IAAI,KAAK,GAAG;AAChE,QAAM,EAAC,oBAAmB,IAAI;AAE9B,MAAI,IAAI,OAAO;AACb,UAAM,OAAO,IAAI,KAAK,KAAK,IAAI,KAAK;AACpC,aAAS,QAAQ,KAAK,IAAI;AAC1B,UAAM,SAAS,cAAc,MAAM,GAAG,IAAI,QAAQ;AAAA,EACpD;AAEA,aAAW,gBAAgB,eAAe;AAExC,QAAI,CAAC,aAAa,MAAM;AACtB,YAAM;AAAA,QACJ;AAAA,UACE,GAAG,aAAa;AAAA,UAChB,UAAU;AAAA,YACR,GAAG,aAAa,QAAQ;AAAA,YACxB,OACE,aAAa,QAAQ,WAAW,gBAC5B,2BACA;AAAA,UACR;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,UAAU,CAAC,uBAAuB,SAAS,qBAAqB;AACtE,UAAM,WAAW,KAAK,IAAI,OAAO,UAAU,IAAI;AAAA,EACjD;AAEA,MAAI,IAAI,UAAU,QAAW;AAC3B,UAAM,WAAW,GAAG,IAAI;AACxB,UAAMC,QAAO,IAAI;AAAA,MACf;AAAA,MACA,SAAS,cAAc,QAAQ;AAAA,MAC/B,IAAI;AAAA,MACJ;AAAA,IACF;AACA,aAAS,QAAQ,KAAKA,KAAI;AAC1B,UAAM,SAAS,cAAcA,OAAM,QAAQ;AAAA,EAC7C;AAEA,MAAI,IAAI,SAAS;AACf,eAAW,OAAO,IAAI,SAAS;AAC7B,YAAM,wBAAwB,KAAK,UAAU,SAAS,KAAK,MAAM,KAAK;AAAA,IACxE;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,WACP,OACA,WACA,UACA,MACO;AACP,MAAI,CAAC,2CAA2C,SAAS,GAAG;AAC1D,WAAO;AAAA,MAAoB;AAAA,MAAO;AAAA,MAAU,iBAC1C,YAAY,aAAa,WAAW,UAAU,IAAI;AAAA,IACpD;AAAA,EACF;AAEA,SAAO,qBAAqB,OAAO,WAAW,UAAU,IAAI;AAC9D;AAEA,SAAS,qBACP,OACA,WACA,UACA,MACO;AACP,MAAI,MAAM;AACV,SAAO,UAAU,SAAS,UAAU,qCAAqC;AAEzE,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK,OAAO;AACV,YAAM,CAAC,aAAa,cAAc,IAAI;AAAA,QACpC,UAAU;AAAA,QACV;AAAA,MACF;AACA,UAAI,eAAe,SAAS,GAAG;AAC7B,cAAM;AAAA,UAAoB;AAAA,UAAO;AAAA,UAAU,iBACzC;AAAA,YACE;AAAA,YACA;AAAA,cACE,MAAM;AAAA,cACN,YAAY;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,aAAO,YAAY,SAAS,GAAG,kCAAkC;AACjE,iBAAW,QAAQ,aAAa;AAC9B,cAAM,qBAAqB,KAAK,MAAM,UAAU,IAAI;AAAA,MACtD;AACA;AAAA,IACF;AAAA,IACA,KAAK,MAAM;AACT,YAAM,CAAC,aAAa,cAAc,IAAI;AAAA,QACpC,UAAU;AAAA,QACV;AAAA,MACF;AACA,aAAO,YAAY,SAAS,GAAG,kCAAkC;AAEjE,YAAM,MAAM,IAAI,YAAY,GAAG;AAC/B,eAAS,QAAQ,KAAK,GAAG;AACzB,YAAM,SAAS,cAAc,KAAK,GAAG,IAAI,MAAM;AAE/C,YAAM,WAAoB,CAAC;AAC3B,UAAI,eAAe,SAAS,GAAG;AAC7B,iBAAS;AAAA,UACP;AAAA,YAAoB;AAAA,YAAK;AAAA,YAAU,iBACjC;AAAA,cACE;AAAA,cACA;AAAA,gBACE,MAAM;AAAA,gBACN,YAAY;AAAA,cACd;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,iBAAW,QAAQ,aAAa;AAC9B,iBAAS,KAAK,qBAAqB,KAAK,MAAM,UAAU,IAAI,CAAC;AAAA,MAC/D;AAEA,YAAM,MAAM,IAAI,WAAW,KAAK,QAAQ;AACxC,iBAAW,UAAU,UAAU;AAC7B,iBAAS,QAAQ,QAAQ,GAAG;AAAA,MAC9B;AACA,YAAM,SAAS,cAAc,KAAK,GAAG,IAAI,MAAM;AAE/C;AAAA,IACF;AAAA,IACA,KAAK,sBAAsB;AACzB,YAAM,KAAK,UAAU;AACrB,YAAM,QAAQ;AAAA,QACZ,GAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA,GAAG,IAAI,IAAI,GAAG,SAAS,KAAK;AAAA,QAC5B,GAAG,YAAY;AAAA,MACjB;AACA,YAAM,cAAc,IAAI,YAAY;AAAA,QAClC,QAAQ;AAAA,QACR;AAAA,QACA,WAAW,GAAG,YAAY;AAAA,QAC1B,UAAU,GAAG,YAAY;AAAA,QACzB,kBAAkB;AAAA,UAChB,GAAG,SAAS;AAAA,UACZ;AAAA,QACF;AAAA,QACA,QAAQ,GAAG,UAAU;AAAA,QACrB,QAAQ,GAAG,UAAU;AAAA,MACvB,CAAC;AACD,eAAS,QAAQ,KAAK,WAAW;AACjC,eAAS,QAAQ,OAAO,WAAW;AACnC,YAAM,SAAS;AAAA,QACb;AAAA,QACA,GAAG,IAAI,iBAAiB,GAAG,SAAS,KAAK;AAAA,MAC3C;AACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,YACP,OACA,WACA,UACA,MACA;AACA,UAAQ,UAAU,MAAM;AAAA,IACtB,KAAK;AACH,aAAO,SAAS,OAAO,WAAW,UAAU,IAAI;AAAA,IAClD,KAAK;AACH,aAAO,QAAQ,OAAO,WAAW,UAAU,IAAI;AAAA,IACjD,KAAK;AACH,aAAO,iCAAiC,OAAO,WAAW,UAAU,IAAI;AAAA,IAC1E,KAAK;AACH,aAAO,qBAAqB,OAAO,UAAU,SAAS;AAAA,EAC1D;AACF;AAEA,SAAS,SACP,OACA,WACA,UACA,MACa;AACb,aAAW,gBAAgB,UAAU,YAAY;AAC/C,YAAQ,YAAY,OAAO,cAAc,UAAU,IAAI;AAAA,EACzD;AACA,SAAO;AACT;AAEO,SAAS,QACd,OACA,WACA,UACA,MACa;AACb,QAAM,CAAC,oBAAoB,eAAe,IACxC,wBAAwB,SAAS;AAEnC,MAAI,mBAAmB,WAAW,GAAG;AACnC,UAAM,SAAS,IAAI;AAAA,MACjB;AAAA,MACA,gBAAgB;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AACA,aAAS,QAAQ,OAAO,MAAM;AAC9B,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,IAAI,OAAO,KAAK;AAC/B,WAAS,QAAQ,OAAO,MAAM;AAC9B,QAAM,WAAW,mBAAmB;AAAA,IAAI,kBACtC,YAAY,QAAQ,cAAc,UAAU,IAAI;AAAA,EAClD;AACA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,UAAM,SAAS,IAAI;AAAA,MACjB;AAAA,MACA,gBAAgB;AAAA,QACd,MAAM;AAAA,QACN,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AACA,aAAS,QAAQ,QAAQ,MAAM;AAC/B,aAAS,KAAK,MAAM;AAAA,EACtB;AACA,QAAM,MAAM,IAAI,MAAM,QAAQ,QAAQ;AACtC,aAAW,UAAU,UAAU;AAC7B,aAAS,QAAQ,QAAQ,GAAG;AAAA,EAC9B;AACA,SAAO,SAAS,GAAG;AACnB,SAAO;AACT;AAEO,SAAS,wBAAwB,WAAwB;AAC9D,QAAM,cAGF,CAAC,CAAC,GAAG,CAAC,CAAC;AACX,aAAW,gBAAgB,UAAU,YAAY;AAC/C,QAAI,+BAA+B,YAAY,GAAG;AAChD,kBAAY,CAAC,EAAE,KAAK,YAAY;AAAA,IAClC,OAAO;AACL,kBAAY,CAAC,EAAE,KAAK,YAAY;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,+BACd,WACkC;AAClC,MAAI,UAAU,SAAS,sBAAsB;AAC3C,WAAO;AAAA,EACT;AACA,MAAI,UAAU,SAAS,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,UAAU,WAAW,MAAM,8BAA8B;AAClE;AAEA,SAAS,qBACP,OACA,UACA,WACa;AACb,QAAM,SAAS,IAAI,OAAO,OAAO,gBAAgB,SAAS,CAAC;AAC3D,WAAS;AAAA,IACP;AAAA,IACA,GAAG,aAAa,UAAU,IAAI,CAAC,IAAI,UAAU,EAAE,IAAI,aAAa,UAAU,KAAK,CAAC;AAAA,EAClF;AACA,WAAS,QAAQ,OAAO,MAAM;AAC9B,SAAO;AACT;AAEA,SAAS,aAAa,MAAqB;AACzC,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,KAAK;AAAA,IACd,KAAK;AACH,aAAO,KAAK;AAAA,IACd,KAAK;AACH,aAAO,KAAK;AAAA,EAChB;AACF;AAEA,SAAS,wBACP,IACA,UACA,SACA,KACA,MACA,eACA;AAGA,MAAI,GAAG,SAAS,UAAU,KAAK,eAAe;AAC5C,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,SAAS,OAAO,6BAA6B;AACvD,QAAM,QAAQ;AAAA,IACZ,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA,GAAG,IAAI,IAAI,GAAG,SAAS,KAAK;AAAA,IAC5B,GAAG,YAAY;AAAA,EACjB;AAEA,QAAM,WAAW,GAAG,IAAI,SAAS,GAAG,SAAS,KAAK;AAClD,QAAM,OAAO,IAAI,KAAK;AAAA,IACpB,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,SAAS,cAAc,QAAQ;AAAA,IACxC,WAAW,GAAG,YAAY;AAAA,IAC1B,UAAU,GAAG,YAAY;AAAA,IACzB,kBAAkB,GAAG,SAAS;AAAA,IAC9B,QAAQ,GAAG,UAAU;AAAA,IACrB,QAAQ,GAAG,UAAU;AAAA,EACvB,CAAC;AACD,WAAS,QAAQ,KAAK,IAAI;AAC1B,WAAS,QAAQ,OAAO,IAAI;AAC5B,SAAO,SAAS,cAAc,MAAM,QAAQ;AAC9C;AAEA,SAAS,iCACP,OACA,WACA,UACA,MACa;AACb,SAAO,UAAU,OAAO,YAAY,UAAU,OAAO,YAAY;AACjE,MAAI,UAAU,QAAQ,SAAS,UAAU,GAAG;AAC1C,QAAI,UAAU,OAAO,UAAU;AAC7B,YAAMC,UAAS,IAAI,OAAO,OAAO,MAAM,KAAK;AAC5C,eAAS,QAAQ,OAAOA,OAAM;AAC9B,aAAOA;AAAA,IACT;AACA,UAAM,SAAS,IAAI,OAAO,OAAO,MAAM,IAAI;AAC3C,aAAS,QAAQ,OAAO,MAAM;AAC9B,WAAO;AAAA,EACT;AACA,QAAM,aAAa,GAAG,IAAI,WAAW,UAAU,QAAQ,SAAS,KAAK;AACrE,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,IACA,SAAS,cAAc,UAAU;AAAA,IACjC,KAAK,UAAU,QAAQ,SAAS,KAAK;AAAA,IACrC,UAAU,QAAQ,YAAY;AAAA,IAC9B,UAAU;AAAA,EACZ;AACA,WAAS,QAAQ,OAAO,MAAM;AAC9B,SAAO,SAAS,oBAAoB,QAAQ,UAAU;AACxD;AAEA,SAAS,wCACP,WACA;AACA,QAAM,OAAsC,CAAC;AAC7C,QAAM,SAAS,CAACC,eAAyB;AACvC,QAAIA,WAAU,SAAS,sBAAsB;AAC3C,WAAK,KAAKA,UAAS;AACnB;AAAA,IACF;AACA,QAAIA,WAAU,SAAS,SAASA,WAAU,SAAS,MAAM;AACvD,iBAAW,KAAKA,WAAU,YAAY;AACpC,eAAO,CAAC;AAAA,MACV;AACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,WAAW;AACb,WAAO,SAAS;AAAA,EAClB;AACA,SAAO;AACT;AAEO,SAAS,yBACd,UACA,IACM;AAEN,QAAM,iBAAiB,SAAS,IAAI,CAAC,CAAC,KAAK,MAAM,KAAK;AACtD,QAAM,gBAAgB,GAAG,OAAO,aAAW,CAAC,eAAe,SAAS,OAAO,CAAC;AAE5E,MAAI,cAAc,SAAS,GAAG;AAC5B,UAAM,IAAI;AAAA,MACR,0DAA0D,cAAc;AAAA,QACtE;AAAA,MACF,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,IAKH;AAAA,EACF;AACF;AAEA,SAAS,2CAA2C,KAAe;AACjE,MAAI,CAAC,IAAI,OAAO;AACd,WAAO;AAAA,EACT;AACA,QAAM,EAAC,MAAK,IAAI;AAChB,MAAI,MAAM,SAAS,SAAS,MAAM,SAAS,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AACZ,QAAM,6BAA6B,CAAC,UAAuC;AAAA,IACzE,GAAG;AAAA,IACH,SAAS;AAAA,MACP,GAAG,KAAK;AAAA,MACR,UAAU;AAAA,QACR,GAAG,KAAK,QAAQ;AAAA,QAChB,QAAQ,KAAK,QAAQ,SAAS,SAAS,MAAM,MAAM;AAAA,MACrD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,SAA+B;AAC/C,QAAI,KAAK,SAAS,UAAU;AAC1B,aAAO;AAAA,IACT,WAAW,KAAK,SAAS,sBAAsB;AAC7C,aAAO,2BAA2B,IAAI;AAAA,IACxC;AACA,UAAM,aAAa,CAAC;AACpB,eAAW,KAAK,KAAK,YAAY;AAC/B,iBAAW,KAAK,SAAS,CAAC,CAAC;AAAA,IAC7B;AACA,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,OAAO,SAAS,KAAK;AAAA,EACvB;AACA,SAAO;AACT;AAEO,SAAS,2CACd,MACS;AACT,MAAI,KAAK,SAAS,sBAAsB;AACtC,WAAO,CAAC,CAAC,KAAK;AAAA,EAChB;AACA,MAAI,KAAK,SAAS,SAAS,KAAK,SAAS,MAAM;AAC7C,WAAO,KAAK,WAAW;AAAA,MAAK,OAC1B,2CAA2C,CAAC;AAAA,IAC9C;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,kBACd,YACA,WACA;AACA,QAAM,UAAuB,CAAC;AAC9B,QAAM,aAA0B,CAAC;AACjC,aAAW,KAAK,YAAY;AAC1B,QAAI,UAAU,CAAC,GAAG;AAChB,cAAQ,KAAK,CAAC;AAAA,IAChB,OAAO;AACL,iBAAW,KAAK,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO,CAAC,SAAS,UAAU;AAC7B;;;ACxwBO,IAAM,sBAAN,cAAkC,MAAM;AAAA,EAC7C,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACiBO,IAAM,YAAN,MAAgE;AAAA,EAC5D;AAAA,EACA,aAAa,oBAAI,IAAiB;AAAA,EAClC;AAAA,EACA;AAAA;AAAA;AAAA,EAIA;AAAA,EAET;AAAA,EAEA,SAAS;AAAA,EACT,cAA0B;AAAA,EAC1B;AAAA,EACS;AAAA,EAET,YACE,OACA,QACA,eACA,WACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU,MAAM,UAAU;AAC/B,SAAK,UAAU;AACf,SAAK,aAAa;AAClB,SAAK,QAAQ,EAAC,IAAI,OAAO,WAAW,SAAY,CAAC,EAAC;AAClD,UAAM,UAAU,IAAI;AAEpB,QAAI,kBAAkB,MAAM;AAC1B,WAAK,cAAc;AAAA,IACrB,WAAW,WAAW,eAAe;AACnC,WAAK,cAAc;AACnB,WAAK,SAAS;AAAA,IAChB,OAAO;AACL,WAAK,cACF,KAAK,MAAM;AACV,aAAK,cAAc;AACnB,aAAK,eAAe;AAAA,MACtB,CAAC,EACA,MAAM,OAAK;AACV,aAAK,cAAc;AACnB,aAAK,SAAS;AACd,aAAK,eAAe;AAAA,MACtB,CAAC;AAAA,IACL;AACA,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,MAAM,EAAE;AAAA,EACtB;AAAA,EAEA,YAAY,UAAuB;AACjC,WAAO,CAAC,KAAK,WAAW,IAAI,QAAQ,GAAG,6BAA6B;AACpE,SAAK,WAAW,IAAI,QAAQ;AAE5B,SAAK,cAAc,QAAQ;AAE3B,WAAO,MAAM;AACX,WAAK,WAAW,OAAO,QAAQ;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,iBAAiB;AACf,eAAW,YAAY,KAAK,YAAY;AACtC,WAAK,cAAc,QAAQ;AAAA,IAC7B;AAAA,EACF;AAAA,EAEA,cAAc,UAAuB;AACnC,aAAS,KAAK,MAAsB,KAAK,aAAa,KAAK,MAAM;AAAA,EACnE;AAAA,EAEA,UAAU;AACR,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,WAAW;AACT,SAAK,SAAS;AACd,eAAW,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,GAAG;AACxC;AAAA,QACE,KAAK;AAAA,QACL,EAAC,MAAM,OAAO,KAAI;AAAA,QAClB,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,MACP;AAAA,IACF;AACA,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,KAAK,QAAsB;AACzB,SAAK,SAAS;AACd,gBAAY,KAAK,OAAO,QAAQ,KAAK,SAAS,IAAI,KAAK,OAAO;AAAA,EAChE;AAAA,EAEA,QAAQ;AACN,QAAI,CAAC,KAAK,QAAQ;AAChB;AAAA,IACF;AACA,SAAK,SAAS;AACd,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,UAAU,KAAU;AAClB,SAAK,WAAW,GAAG;AAAA,EACrB;AACF;;;ACzHO,IAAM,gBAAwB;AAAA,EACnC,UAAU;AAAA,EACV,eAAe,CAAC;AAClB;;;AC0BO,IAAM,iBAAiB,OAAO,UAAU;;;ApCiBxC,SAAS,YACd,OACA,UACA,kBAGA,cACA;AACA,MAAI,OAAO,qBAAqB,YAAY;AAC1C,WAAQ,MACL,cAAc,EAAE,QAAQ,EACxB,YAAY,kBAAkB,cAAc,GAAG;AAAA,EACpD;AACA,SAAQ,MACL,cAAc,EAAE,QAAQ,EACxB,YAAY,kBAAkB,GAAG;AACtC;AAEA,IAAM,YAAY,OAAO;AAMlB,SAAS,SAId,UACA,QACAC,QACwB;AACxB,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACAA;AAAA,IACA,EAAC,OAAAA,OAAK;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,IAAM,iBAAiB,OAAO;AAE9B,IAAe,gBAAf,MAKP;AAAA,EACW;AAAA,EACU;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACT,QAAgB;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,UACA,QACA,WACA,KACA,QACA,QACA,eACA,iBACA;AACA,SAAK,UAAU;AACf,SAAK,YAAY;AACjB,SAAK,aAAa;AAClB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,mBAAmB;AACxB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,CAAC,cAAc,EAAE,UAA0D;AACzE,WAAO,KAAK,cAAc;AAAA,MACxB;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,YACE,MACA,MACiC;AACjC,WAAO,KAAK,cAAc;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE;AAAA,QACA;AAAA,MACF;AAAA,MACA,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,KAAK,SAAS,IAAS;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,MAAM;AACR,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,OAAe;AACb,QAAI,CAAC,KAAK,OAAO;AACf,WAAK,QAAQ,UAAU,KAAK,aAAa,CAAC;AAAA,IAC5C;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAiBA,MAAM,MACJ,KAAK,cAAc;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,MACE,GAAG,KAAK;AAAA,MACR,OAAO;AAAA,IACT;AAAA,IACA;AAAA,MACE,GAAG,KAAK;AAAA,MACR,UAAU;AAAA,IACZ;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAAA,EAEF,cAAc,CACZ,cACA,aACA,YACoC;AACpC,UAAM,KAAK,OAAO,gBAAgB,aAAa,cAAc;AAC7D,UAAM,OAAO,OAAO,gBAAgB,aAAa,UAAU;AAC3D,UAAM,UAAU,MAAM,QAAQ;AAC9B,WAAO,KAAK,MAAM,CAAC,EAAC,OAAM,MAAM,OAAO,cAAc,IAAI,EAAC,MAAM,QAAO,CAAC,CAAC;AAAA,EAC3E;AAAA,EAEA,UAAU,CACR,cACA,OACa;AACb,QAAI,aAAa,WAAW,WAAW,GAAG;AACxC,YAAM,IAAI;AAAA,QACR,0CAA0C,WAAW;AAAA,MACvD;AAAA,IACF;AACA,SAAK,OAAO,OAAK;AAEjB,UAAM,UAAU,KAAK,QAAQ,cAAc,KAAK,UAAU,EAAE,YAAY;AACxE,WAAO,SAAS,sBAAsB;AACtC,QAAI,SAAS,OAAO,GAAG;AACrB,YAAM,EAAC,YAAY,WAAW,aAAa,YAAW,IAAI,QAAQ,CAAC;AACnE,YAAM,IAAc,KAAK,cAAc;AAAA,QACrC,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,QACA;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,eAAe,CAAC;AAAA,UAChB,UAAU,gBAAgB;AAAA,QAC5B;AAAA,QACA,KAAK;AAAA,QACL;AAAA,MACF;AAOA,YAAM,KAAK,GAAG,CAAC;AACf;AAAA,QACE,cAAc,WAAW;AAAA,QACzB;AAAA,MACF;AACA;AAAA,QACE,cAAc,SAAS;AAAA,QACvB;AAAA,MACF;AACA;AAAA,QACE,YAAY,WAAW,UAAU;AAAA,QACjC;AAAA,MACF;AAEA,aAAO,KAAK,cAAc;AAAA,QACxB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,UACE,GAAG,KAAK;AAAA,UACR,SAAS;AAAA,YACP,GAAI,KAAK,KAAK,WAAW,CAAC;AAAA,YAC1B;AAAA,cACE,QAAQ,KAAK;AAAA,cACb,aAAa;AAAA,gBACX,aAAa;AAAA,gBACb,YAAY;AAAA,cACd;AAAA,cACA,UAAU;AAAA,gBACR,KAAK,QAAQ,OAAO,UAAU;AAAA,gBAC9B,GAAG;AAAA,cACL;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,YACb,GAAG,KAAK,OAAO;AAAA,YACf,CAAC,YAAY,GAAG,GAAG;AAAA,UACrB;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,GAAG;AACrB,YAAM,CAAC,eAAe,cAAc,IAAI;AACxC,YAAM,EAAC,WAAU,IAAI;AACrB,YAAM,iBAAiB,cAAc;AACrC,YAAM,KAAK;AAAA,QACT,KAAK,cAAc;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,UACT;AAAA,UACA;AAAA,YACE,eAAe,CAAC;AAAA,YAChB,UAAU,eAAe,gBAAgB;AAAA,UAC3C;AAAA,UACA,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAEA,aAAO,cAAc,cAAc,WAAW,GAAG,sBAAsB;AACvE,aAAO,cAAc,cAAc,SAAS,GAAG,sBAAsB;AACrE,aAAO,cAAc,eAAe,WAAW,GAAG,sBAAsB;AACxE,aAAO,cAAc,eAAe,SAAS,GAAG,sBAAsB;AAEtE,aAAO,KAAK,cAAc;AAAA,QACxB,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,UACE,GAAG,KAAK;AAAA,UACR,SAAS;AAAA,YACP,GAAI,KAAK,KAAK,WAAW,CAAC;AAAA,YAC1B;AAAA,cACE,QAAQ,KAAK;AAAA,cACb,aAAa;AAAA,gBACX,aAAa,cAAc;AAAA,gBAC3B,YAAY,cAAc;AAAA,cAC5B;AAAA,cACA,QAAQ;AAAA,cACR,UAAU;AAAA,gBACR,OAAO;AAAA,gBACP,OAAO;AAAA,gBACP,SAAS;AAAA,kBACP,KAAK,QAAQ,OAAO,cAAc;AAAA,kBAClC;AAAA,gBACF;AAAA,gBACA,SAAS;AAAA,kBACP;AAAA,oBACE,QAAQ,KAAK;AAAA,oBACb,aAAa;AAAA,sBACX,aAAa,eAAe;AAAA,sBAC5B,YAAY,eAAe;AAAA,oBAC7B;AAAA,oBACA,UAAU;AAAA,sBACR,KAAK,QAAQ,OAAO,UAAU;AAAA,sBAC9B,GAAG;AAAA,oBACL;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA;AAAA,UACE,GAAG,KAAK;AAAA,UACR,eAAe;AAAA,YACb,GAAG,KAAK,OAAO;AAAA,YACf,CAAC,YAAY,GAAG,GAAG;AAAA,UACrB;AAAA,QACF;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,wBAAwB,YAAY,EAAE;AAAA,EACxD;AAAA,EAEA,QAAQ,CACN,0BACA,WACA,UACoC;AACpC,QAAI;AAEJ,QAAI,OAAO,6BAA6B,YAAY;AAClD,aAAO;AAAA,QACL,IAAI,kBAAkB,KAAK,OAAO;AAAA,MAIpC;AAAA,IACF,OAAO;AACL,aAAO,cAAc,QAAW,mBAAmB;AACnD,aAAO,IAAI,0BAA0B,WAAW,KAAK;AAAA,IACvD;AAEA,UAAM,gBAAgB,KAAK,KAAK;AAChC,QAAI,eAAe;AACjB,aAAO,IAAI,eAAe,IAAI;AAAA,IAChC;AAEA,UAAM,QAAQ,kBAAkB,IAAI;AAEpC,WAAO,KAAK,cAAc;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE,GAAG,KAAK;AAAA,QACR;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,QAAQ,CACN,KACA,SAEA,KAAK,cAAc;AAAA,IACjB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL;AAAA,MACE,GAAG,KAAK;AAAA,MACR,OAAO;AAAA,QACL;AAAA,QACA,WAAW,CAAC,MAAM;AAAA,MACpB;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAAA,EAEF,QAAQ,CAAC,UAAmD;AAC1D,QAAI,QAAQ,GAAG;AACb,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AACA,SAAK,QAAQ,OAAO,OAAO;AACzB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AACA,QAAI,KAAK,kBAAkB;AACzB,YAAM,IAAI;AAAA,QACR,gGACE,KAAK;AAAA,MACT;AAAA,IACF;AAEA,WAAO,KAAK,cAAc;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE,GAAG,KAAK;AAAA,QACR;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,UAAU,CACR,OACA,cACoC;AACpC,QAAI,KAAK,kBAAkB;AACzB,YAAM,IAAI;AAAA,QACR,mGACE,KAAK;AAAA,MACT;AAAA,IACF;AACA,WAAO,KAAK,cAAc;AAAA,MACxB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,QACE,GAAG,KAAK;AAAA,QACR,SAAS,CAAC,GAAI,KAAK,KAAK,WAAW,CAAC,GAAI,CAAC,OAAiB,SAAS,CAAC;AAAA,MACtE;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEU,UAAU,CAClB,cACA,IACA,YACc;AACd,SAAK,OAAO,OAAK;AACjB,UAAM,OAAO,SAAS,QAAQ;AAC9B,UAAM,UAAU,KAAK,QAAQ,cAAc,KAAK,UAAU,EAAE,YAAY;AACxE,WAAO,SAAS,sBAAsB;AAEtC,QAAI,SAAS,OAAO,GAAG;AACrB,YAAM,EAAC,YAAY,aAAa,UAAS,IAAI,QAAQ,CAAC;AACtD,aAAO,cAAc,WAAW,GAAG,sBAAsB;AACzD,aAAO,cAAc,SAAS,GAAG,sBAAsB;AAEvD,YAAM,KAAK;AAAA,QACT,KAAK,cAAc;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO,GAAG,WAAW,GAAG,YAAY;AAAA,UACtC;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ,KAAK;AAAA,UACb,aAAa;AAAA,YACX,aAAa;AAAA,YACb,YAAY;AAAA,UACd;AAAA,UACA,UAAU;AAAA,YACR,KAAK,QAAQ,OAAO,UAAU;AAAA,YAC9B,GAAG;AAAA,UACL;AAAA,QACF;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,GAAG;AACrB,YAAM,CAAC,eAAe,cAAc,IAAI;AACxC,aAAO,cAAc,cAAc,WAAW,GAAG,sBAAsB;AACvE,aAAO,cAAc,cAAc,SAAS,GAAG,sBAAsB;AACrE,aAAO,cAAc,eAAe,WAAW,GAAG,sBAAsB;AACxE,aAAO,cAAc,eAAe,SAAS,GAAG,sBAAsB;AACtE,YAAM,EAAC,WAAU,IAAI;AACrB,YAAM,iBAAiB,cAAc;AACrC,YAAM,cAAc;AAAA,QAClB,KAAK,cAAc;AAAA,UACjB,KAAK;AAAA,UACL,KAAK;AAAA,UACL;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO,GAAG,WAAW,WAAW,YAAY;AAAA,UAC9C;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS;AAAA,UACP,QAAQ,KAAK;AAAA,UACb,aAAa;AAAA,YACX,aAAa,cAAc;AAAA,YAC3B,YAAY,cAAc;AAAA,UAC5B;AAAA,UACA,UAAU;AAAA,YACR,OAAO;AAAA,YACP,OAAO,GAAG,WAAW,GAAG,YAAY;AAAA,YACpC,SAAS;AAAA,cACP,KAAK,QAAQ,OAAO,cAAc;AAAA,cAClC;AAAA,YACF;AAAA,YACA,OAAO;AAAA,cACL,MAAM;AAAA,cACN,SAAS;AAAA,gBACP,QAAQ,KAAK;AAAA,gBACb,aAAa;AAAA,kBACX,aAAa,eAAe;AAAA,kBAC5B,YAAY,eAAe;AAAA,gBAC7B;AAAA,gBAEA,UAAU;AAAA,kBACR,KAAK,QAAQ,OAAO,UAAU;AAAA,kBAC7B,YAAoC;AAAA,gBACvC;AAAA,cACF;AAAA,cACA,IAAI;AAAA,cACJ;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI,MAAM,wBAAwB,YAAY,EAAE;AAAA,EACxD;AAAA,EAEA;AAAA,EAEU,eAAoB;AAC5B,QAAI,CAAC,KAAK,eAAe;AACvB,YAAM,eAAe;AAAA,QACnB,KAAK,QAAQ,OAAO,KAAK,UAAU;AAAA,QACnC,KAAK,KAAK;AAAA,MACZ;AACA,UAAI,KAAK,KAAK,OAAO;AACnB,cAAM,EAAC,IAAG,IAAI,KAAK,KAAK;AACxB,cAAM,cAAgC,CAAC;AACvC,mBAAW,CAAC,KAAK,KAAK,cAAc;AAClC,sBAAY,KAAK,IAAI,IAAI,KAAK;AAAA,QAChC;AACA,aAAK,gBAAgB;AAAA,UACnB,GAAG,KAAK;AAAA,UACR,OAAO;AAAA,YACL,GAAG,KAAK,KAAK;AAAA,YACb,KAAK;AAAA,UACP;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF,OAAO;AACL,aAAK,gBAAgB;AAAA,UACnB,GAAG,KAAK;AAAA,UACR,SAAS;AAAA,YACP,KAAK,QAAQ,OAAO,KAAK,UAAU;AAAA,YACnC,KAAK,KAAK;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,EACd;AAcF;AAEA,IAAM,qBAAqB,OAAO;AAM3B,IAAM,YAAN,MAAM,mBAIH,cAAwC;AAAA,EACvC;AAAA,EAET,YACE,UACA,QACA,WACA,MAAW,EAAC,OAAO,UAAS,GAC5B,SAAiB,eACjB,SAAiB,UACjB,eACA,iBACA;AACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,KAAK,kBAAkB,IAAS;AAC9B,WAAO,KAAK,aAAa;AAAA,EAC3B;AAAA,EAEA,CAAW,cAAc,EAKvB,UACA,QACA,WACA,KACA,QACA,eACA,iBACqC;AACrC,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YACE,cACA,MAAW,gBACR;AACH,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,IACF;AACA,QAAI;AACJ,QAAI,OAAO,iBAAiB,YAAY;AACtC,gBAAU;AAAA,IACZ,OAAO;AACL,YAAM,gBAAgB;AAAA,IACxB;AACA,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,UAAU,KAAK,gBACjB,kBAAkB,KAAK,cAAc,MAAM,KAAK,cAAc,IAAI,IAClE,KAAK,KAAK;AACd,UAAM,wBAAwBC,UAAe;AAC7C,QAAI,gBAAwC,SAAS;AACrD,UAAM,YAAY,CAAC,WAAgB;AACjC,WAAK,gBACD,SAAS,kBAAkB,KAAK,eAAe,MAAM,IACrD,SAAS,kBAAkB,KAAK,MAAM;AAAA,IAC5C;AAEA,UAAM,cAA2B,CAAC,KAAK,UAAU;AAC/C,UAAI,OAAO;AACT,8BAAsB,OAAO,KAAK;AAClC,wBAAgB;AAChB;AAAA,MACF;AAEA,UAAI,KAAK;AACP,iBAAS;AAAA,UACP;AAAA,UACA,YAAY,IAAI,IAAI;AAAA,UACpB;AAAA,UACA;AAAA,QACF;AACA,wBAAgB;AAChB,8BAAsB,QAAQ,IAAI;AAAA,MACpC;AAAA,IACF;AAEA,QAAI;AACJ,UAAM,YAAY,MAAM;AACtB,YAAM,QAAQ;AACd,6BAAuB;AACvB,uBAAiB;AAAA,IACnB;AAEA,UAAM,KAAK,YAAY,IAAI;AAE3B,UAAM,mBAAmB,KAAK,gBAC1B,SAAS,eAAe,KAAK,KAAK,eAAe,KAAK,WAAW,IACjE,SAAS,eAAe,KAAK,KAAK,WAAW;AAEjD,UAAM,QAAQ,cAAc,KAAK,UAAU,OAAO;AAElD,UAAM,OAAO,SAAS;AAAA,MAAiB,OACpC,WAAW;AAAA,QACV;AAAA,QACA;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,QAAM;AACJ,iCAAuB,SAAS,oBAAoB,EAAE;AAAA,QACxD;AAAA,QACA,iBAAiB,sBAAsB;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,aAAS;AAAA,MACP;AAAA,MACA,YAAY,IAAI,IAAI;AAAA,MACpB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,SAAuD;AACzD,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,IACF;AACA,aAAS,sBAAsB,OAAO;AACtC,UAAM,IAAuC,KAAK,YAAY,SAAS,GAAG;AAC1E,QAAI,SAAS,SAAS,YAAY;AAChC,aAAO,IAAI,QAAQ,aAAW;AAC5B,UAAE,YAAY,CAAC,MAAM,SAAS;AAC5B,cAAI,SAAS,YAAY;AACvB,cAAE,QAAQ;AACV,oBAAQ,IAA8B;AAAA,UACxC,WAAW,SAAS,SAAS;AAC3B,cAAE,QAAQ;AACV,oBAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,UAC9B;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAEA,aAAS;AAET,UAAM,MAAM,EAAE;AACd,MAAE,QAAQ;AACV,WAAO,QAAQ,QAAQ,GAAG;AAAA,EAC5B;AAAA,EAEA,QAAQ,SAGN;AACA,UAAM,WAAW;AAAA,MACf,KAAK;AAAA,MACL;AAAA,IACF;AACA,UAAM,MAAM,SAAS,OAAO;AAC5B,UAAM,MAAM,KAAK,aAAa;AAC9B,UAAM,EAAC,SAAS,SAAS,SAAQ,IAAIA,UAAe;AACpD,QAAI,KAAK,eAAe;AACtB,YAAMC,WAAU,SAAS;AAAA,QACvB;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,SAAO;AACL,cAAI,KAAK;AACP,oBAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AACA,aAAO;AAAA,QACL,SAAAA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,SAAS,eAAe,KAAK,KAAK,SAAO;AACvD,UAAI,KAAK;AACP,gBAAQ;AAAA,MACV;AAAA,IACF,CAAC;AACD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,eACP,QACA,SACU;AACV,YAAU,WAAW,CAAC;AACtB,QAAM,EAAC,WAAU,IAAI;AACrB,QAAM,mBAAmB,IAAI,IAAI,UAAU;AAE3C,aAAW,CAAC,KAAK,KAAK,SAAS;AAC7B,qBAAiB,OAAO,KAAK;AAAA,EAC/B;AAEA,MAAI,iBAAiB,SAAS,GAAG;AAC/B,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG,CAAC,GAAG,gBAAgB,EAAE,IAAI,SAAO,CAAC,KAAK,KAAK,CAAoB;AAAA,EACrE;AACF;AAEA,SAAS,oBAAoB,QAAqB,KAAe;AAC/D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,eAAe,QAAQ,IAAI,OAAO;AAAA,EAC7C;AACF;AAEA,SAAS,iBAKP,QACA,OACA,QACA,WACA,qBACA,eACA,WACmC;AACnC,QAAM,IAAI,IAAI;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,IAAE,YAAY;AACd,sBAAoB,MAAM;AACxB,MAAE,MAAM;AAAA,EACV,CAAC;AACD,SAAO;AACT;AAEA,SAAS,cAAc,OAAgD;AACrE,SAAO,MAAM,QAAQ,KAAK,KAAK,MAAM,UAAU;AACjD;AAEA,SAAS,SAAY,GAAoC;AACvD,SAAO,EAAE,WAAW;AACtB;AAEA,SAAS,SAAY,GAAuC;AAC1D,SAAO,EAAE,WAAW;AACtB;;;AqC56BO,SAAS,KAAK,IAAe,MAAgB;AAClD,KAAG,KAAK,KAAK,UAAU,IAAI,CAAC;AAC9B;;;ACJA,SAAQ,YAAAC,iBAAe;AAYvB,IAAM,YAAY;AAElB,SAAS,WAAW,eAAuB,UAA0B;AACnE,SAAO,GAAG,SAAS,IAAI,aAAa,IAAI,QAAQ;AAClD;AAEA,SAAS,uBAAuB,eAA+B;AAC7D,SAAO,GAAG,SAAS,IAAI,aAAa;AACtC;AAEA,SAAS,aACP,SACuD;AACvD,MAAI,CAAC,WAAW,CAAC,QAAQ,WAAW,SAAS,GAAG;AAC9C,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,QAAQ,MAAM,UAAU,MAAM,EAAE,MAAM,GAAG;AACvD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,eAAe,MAAM,CAAC;AAAA,IACtB,UAAU,MAAM,CAAC;AAAA,EACnB;AACF;AAEA,SAAS,iBAAiB,GAAY;AACpC,MAAI,aAAa,SAAS,EAAE,SAAS,cAAc;AAEjD;AAAA,EACF;AACA,QAAM;AACR;AA0BO,IAAM,uBAAN,MAAM,sBAAqB;AAAA,EACvB;AAAA,EACA;AAAA,EACA,YAAYC,UAAe;AAAA,EAC3B;AAAA,EACA,iBAA8B,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAM/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,OACX,eACA,UACA,QAC+B;AAC/B,UAAM,WAAW,IAAI,sBAAqB,eAAe,UAAU,MAAM;AACzE,UAAM,SAAS,MAAM,MAAM;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,YACN,eACA,UACA,QACA;AACA,SAAK,gBAAgB;AACrB,SAAK,WAAW;AAChB,SAAK,eAAe,qBAAqB,MAAM;AAC/C,SAAK,eAAe,IAAI,QAAQ;AAAA,EAClC;AAAA,EAEA,MAAM,MAAM,QAAoC;AAC9C,UAAM,EAAC,eAAe,SAAQ,IAAI;AAClC,UAAM,OAAO,WAAW,eAAe,QAAQ;AAS/C,UAAM,UAAU,IAAI,GAAiB,uBAAuB,aAAa,CAAC;AAC1E,YAAQ;AAAA,MACN;AAAA,MACA,OAAK;AACH,cAAM,SAAS,aAAa,EAAE,IAAI;AAClC,YAAI,QAAQ,kBAAkB,KAAK,eAAe;AAChD,eAAK,WAAW,OAAO,QAAQ;AAAA,QACjC;AAAA,MACF;AAAA,MACA,EAAC,OAAM;AAAA,IACT;AAEA,SAAK,aACF,QAAQ,MAAM,aAAa,MAAM,KAAK,UAAU,OAAO,EACvD,MAAM,gBAAgB;AAEzB,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AACJ,aAAK,aAAa,QAAQ,MAAM,MAAM,KAAK,UAAU,QAAQ,CAAC;AAC9D,gBAAQ,MAAM;AAAA,MAChB;AAAA,MACA,EAAC,MAAM,KAAI;AAAA,IACb;AAEA,eAAWC,aAAY,MAAM,KAAK,kBAAkB,GAAG;AACrD,UAAIA,cAAa,KAAK,UAAU;AAC9B,aAAK,WAAWA,SAAQ;AAAA,MAC1B;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,SAAS;AACnB,cAAQ,YAAY,IAAI;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,IAAI,gBAAqC;AACvC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,oBAA0C;AAC9C,UAAM,gBAA6B,oBAAI,IAAI;AAE3C,qBAAiB,YAAY,KAAK,aAAa,eAAe,GAAG;AAC/D,YAAM,SAAS,aAAa,QAAQ;AACpC,UAAI,QAAQ,kBAAkB,KAAK,eAAe;AAChD,sBAAc,IAAI,OAAO,QAAQ;AAAA,MACnC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,6BAA6B,UAAwB;AACnD,UAAM,OAAO,WAAW,KAAK,eAAe,QAAQ;AACpD,SAAK,aACF,QAAQ,MAAM,UAAU,MAAM,KAAK,cAAc,QAAQ,CAAC,EAC1D,MAAM,gBAAgB;AAAA,EAC3B;AAAA,EAEA,WAAW,UAAwB;AACjC,QAAI,CAAC,KAAK,eAAe,IAAI,QAAQ,GAAG;AACtC,WAAK,eAAe,IAAI,QAAQ;AAChC,WAAK,6BAA6B,QAAQ;AAC1C,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,cAAc,UAAwB;AACpC,QAAI,KAAK,eAAe,OAAO,QAAQ,GAAG;AACxC,WAAK,WAAW,UAAU,KAAK,aAAa;AAAA,IAC9C;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,QAAwC;AACpE,QAAM,QAAQ,iBAAiB,WAAW,GAAG;AAC7C,MAAI,OAAO;AACT,WAAO,IAAI,wBAAwB,OAAO,MAAM;AAAA,EAClD;AACA,SAAO,IAAI,sBAAsB;AACnC;AAYA,IAAM,0BAAN,MAA2D;AAAA,EAChD;AAAA,EACA;AAAA,EAET,YAAY,OAAoB,QAAqB;AACnD,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,QACE,MACA,MACA,IACe;AACf,WAAO,KAAK,OAAO,QAAQ,MAAM,EAAC,MAAM,QAAQ,KAAK,QAAO,GAAG,EAAE;AAAA,EACnE;AAAA,EAEA,QAAQ,OAAe,IAAsB;AAC3C,OAAG;AAAA,EACL;AAAA,EAEA,OAAO,iBAAwC;AAC7C,UAAM,WAAW,MAAM,KAAK,OAAO,MAAM;AACzC,eAAW,QAAQ;AAAA,MACjB,GAAI,SAAS,QAAQ,CAAC;AAAA,MACtB,GAAI,SAAS,WAAW,CAAC;AAAA,IAC3B,GAAG;AACD,UAAI,KAAK,SAAS,eAAe,KAAK,MAAM;AAC1C,cAAM,KAAK;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,gBAAgB,oBAAI,IAAY;AAEtC,IAAM,gBAA6C,oBAAI,IAAI;AAE3D,IAAM,wBAAN,MAAyD;AAAA,EAC9C,aAA0C,oBAAI,IAAI;AAAA,EAE3D,QACE,MACA,MACA,IACe;AACf,QAAI,SAAS,aAAa;AACxB,oBAAc,IAAI,IAAI;AAAA,IACxB,OAAO;AACL;AAIA,YAAM,WAAW,CAAC,YAAoB;AACpC,YAAI,YAAY,MAAM;AACpB,wBAAc,OAAO,QAAQ;AAC7B,iBAAO,GAAG;AAAA,QACZ;AAAA,MACF;AACA,oBAAc,IAAI,QAAQ;AAC1B,WAAK,WAAW,IAAI,QAAQ;AAAA,IAC9B;AACA,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,QAAQ,MAAc,IAAsB;AAC1C,kBAAc,OAAO,IAAI;AACzB,eAAW,YAAY,eAAe;AACpC,eAAS,IAAI;AAAA,IACf;AACA,eAAW,YAAY,KAAK,YAAY;AACtC,oBAAc,OAAO,QAAQ;AAAA,IAC/B;AACA,OAAG;AAAA,EACL;AAAA,EAEA,OAAO,iBAAwC;AAC7C,WAAO;AAAA,EACT;AACF;;;ACnTA,SAAuB,YAAAC,iBAAe;;;ACA/B,IAAM,eAAN,MAGL;AAAA,EACU,aAAa,oBAAI,IAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1C,YAAY,CAAC,aAAsC;AACjD,SAAK,WAAW,IAAI,QAAQ;AAE5B,WAAO,MAAM;AACX,WAAK,WAAW,OAAO,QAAQ;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,CAAC,WAAwB;AAChC,SAAK,WAAW,QAAQ,cAAY,SAAS,MAAM,CAAC;AAAA,EACtD;AAAA,EAEA,eAAe,MAAe,KAAK,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA,EAKrD,UAAU,MAAY;AACpB,SAAK,WAAW,MAAM;AAAA,EACxB;AACF;;;AD1BA,IAAM,oCAAoC;AA6D1C,IAAM,kBAAkB;AAAA,EACtB,+BAAiB;AAAA,EACjB,+BAAiB;AACnB;AAQO,IAAM,oBAAN,MAAM,2BAA0B,aAA8B;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA,uBAAkDC,UAAS;AAAA,EAE3D,YAAY,SAAmC;AAC7C,UAAM;AAEN,UAAM,MAAM,KAAK,IAAI;AAErB,SAAK,uBAAuB,QAAQ;AACpC,SAAK,0BACH,QAAQ,0BAA0B;AACpC,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB,SAAS;AAAA,MACT,cAAc,MAAM,KAAK;AAAA,IAC3B;AACA,SAAK,uBAAuB;AAC5B,SAAK,2BAA2B;AAAA,EAClC;AAAA,EAEA,IAAI,QAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,GAAG,QAAmC;AACpC,WAAO,KAAK,OAAO,SAAS;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAA6B;AAC3B,WAAO,mBAAkB,gBAAgB,KAAK,MAAM;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,gBACL,OACkC;AAClC,WAAQ,gBAAgD;AAAA,MACtD,MAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,wBAAiC;AAC/B,WAAO,KAAK,OAAO,SAAS,+BAAiB;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAA+C;AAC7C,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,WAAW,QAET;AAEA,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAKA,QAAI,KAAK,OAAO,SAAS,+BAAiB,cAAc;AACtD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAEA,UAAM,MAAM,KAAK,IAAI;AAGrB,QAAI,KAAK,OAAO,SAAS,+BAAiB,YAAY;AACpD,WAAK,SAAS;AAAA,QACZ,GAAG,KAAK;AAAA,QACR,SAAS,KAAK,OAAO,UAAU;AAAA,QAC/B;AAAA,MACF;AACA,YAAMC,oBAAmB,KAAK,2BAA2B;AACzD,WAAK,2BAA2B;AAChC,aAAO,EAAC,kBAAAA,kBAAgB;AAAA,IAC1B;AAKA,QAAI,KAAK,yBAAyB,QAAW;AAC3C,WAAK,uBAAuB;AAAA,IAC9B;AAEA,UAAM,eAAe,KAAK,uBAAuB,KAAK;AAEtD,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB,SAAS;AAAA,MACT;AAAA,MACA;AAAA,IACF;AACA,UAAM,mBAAmB,KAAK,2BAA2B;AACzD,SAAK,2BAA2B;AAChC,WAAO,EAAC,iBAAgB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAA0D;AAExD,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,QAAI,KAAK,OAAO,SAAS,+BAAiB,WAAW;AACnD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,SAAK,uBAAuB;AAC5B,SAAK,0BAA0B;AAE/B,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,IACzB;AACA,UAAM,mBAAmB,KAAK,2BAA2B;AACzD,WAAO,EAAC,iBAAgB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,QAEX;AAEA,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,QAAI,KAAK,OAAO,SAAS,+BAAiB,cAAc;AACtD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAIA,QAAI,KAAK,OAAO,SAAS,+BAAiB,WAAW;AACnD,WAAK,uBAAuB;AAAA,IAC9B;AAIA,SAAK,0BAA0B;AAE/B,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB;AAAA,IACF;AACA,UAAM,mBAAmB,KAAK,2BAA2B;AACzD,WAAO,EAAC,iBAAgB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,UAAU,QAER;AAEA,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,QAAI,KAAK,OAAO,SAAS,+BAAiB,WAAW;AACnD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,SAAK,uBAAuB;AAC5B,SAAK,0BAA0B;AAE/B,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB;AAAA,IACF;AACA,UAAM,mBAAmB,KAAK,2BAA2B;AACzD,WAAO,EAAC,iBAAgB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAiE;AAErE,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,QAAI,KAAK,OAAO,SAAS,+BAAiB,OAAO;AAC/C,aAAO,EAAC,kBAAkB,KAAK,kBAAkB,EAAC;AAAA,IACpD;AAGA,SAAK,uBAAuB;AAC5B,SAAK,0BAA0B;AAE/B,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB;AAAA,IACF;AACA,UAAM,mBAAmB,KAAK,2BAA2B;AACzD,WAAO,EAAC,iBAAgB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,SAAS;AAEP,QAAI,KAAK,OAAO,SAAS,+BAAiB,QAAQ;AAChD;AAAA,IACF;AAEA,SAAK,uBAAuB;AAC5B,SAAK,0BAA0B;AAE/B,SAAK,SAAS;AAAA,MACZ,MAAM,+BAAiB;AAAA,MACvB,QAAQ,IAAI,YAAY;AAAA,QACtB,MAAM,+BAAgB;AAAA,QACtB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,SAAK,cAAc;AACnB,SAAK,QAAQ;AACb;AAAA,EACF;AAAA,EAES,UAAU,MAAY;AAC7B,SAAK,WAAW,MAAM;AACtB,SAAK,yBAAyB;AAAA,EAChC;AAAA,EAEA,2BAAiC;AAC/B,SAAK,qBAAqB,QAAQ,KAAK,MAAM;AAC7C,SAAK,uBAAuBD,UAAS;AAAA,EACvC;AAAA,EAEA,gBAAsB;AACpB,SAAK,OAAO,KAAK,MAAM;AACvB,SAAK,yBAAyB;AAAA,EAChC;AAAA,EAEA,oBAA8C;AAC5C,WAAO,KAAK,qBAAqB;AAAA,EACnC;AAAA,EAEA,6BAAuD;AACrD,SAAK,cAAc;AACnB,WAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAyB;AACvB,QAAI,KAAK,OAAO,SAAS,+BAAiB,YAAY;AACpD,aAAO;AAAA,IACT;AAEA,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,OAAO,KAAK,OAAO,cAAc;AACnC,WAAK;AAAA,QACH,IAAI,YAAY;AAAA,UACd,MAAM,+BAAgB;AAAA,UACtB,SAAS,kCAAkC,KAAK,MAAM,KAAK,uBAAuB,GAAI,CAAC;AAAA,QACzF,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,6BAAmC;AACjC,QAAI,KAAK,qBAAqB,QAAW;AACvC;AAAA,IACF;AACA,SAAK,mBAAmB,YAAY,MAAM;AACxC,WAAK,cAAc;AAAA,IACrB,GAAG,KAAK,uBAAuB;AAAA,EACjC;AAAA,EAEA,4BAAkC;AAChC,QAAI,KAAK,qBAAqB,QAAW;AACvC;AAAA,IACF;AACA,kBAAc,KAAK,gBAAgB;AACnC,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAOO,IAAM,yBAAyB,CAAC,UAA2B;AAChE,MACE,kBAAkB,gBAAgB,KAAK,KACvC,MAAM,SAAS,+BAAiB,WAC9B,MAAM,SAAS,+BAAiB,cAChC,MAAM,SAAS,+BAAiB,iBAChC,MAAM,QACR;AACA,QACE,cAAc,MAAM,MAAM,MACzB,MAAM,OAAO,SAAS,+BAAgB,kBACrC,MAAM,OAAO,SAAS,+BAAgB,eACtC,MAAM,OAAO,SAAS,+BAAgB,aACxC;AACA;AAAA,IACF;AACA,UAAM,MAAM;AAAA,EACd;AACF;;;AEtbO,IAAM,iBAAN,MAA2C;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACE,mBACA,IACA,SACA;AACA,SAAK,qBAAqB;AAC1B,SAAK,MAAM;AACX,SAAK,UAAU,IAAI,iBAAiB,iBAAiB;AACrD,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,QAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAQ,MAAyD;AACrE,UAAM,KAAK,KAAK,IAAI,YAAY,SAAS;AAEzC,QAAI,QAAQ,UAAU,MAAM;AAC1B,SAAG,QAAQ,yCAAyC;AACpD,WAAK,SAAS,KAAK,IAAI;AAAA,IACzB;AAGA,QAAI,CAAC,KAAK,mBAAmB,kBAAkB,GAAG;AAChD,SAAG;AAAA,QACD;AAAA,QACA,KAAK,mBAAmB,MAAM;AAAA,MAChC;AACA;AAAA,IACF;AAEA,OAAG;AAAA,MACD,mCAAmC,KAAK,mBAAmB,MAAM,IAAI;AAAA,IACvE;AAIA,UAAM,EAAC,iBAAgB,IAAI,KAAK,mBAAmB,WAAW;AAC9D,UAAM;AAAA,EACR;AACF;AAEO,IAAM,mBAAN,MAA0D;AAAA,EACtD;AAAA,EAET,YAAY,mBAAsC;AAChD,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEA,IAAI,UAA2B;AAC7B,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA,EAEA,IAAI,YAAY;AACd,WAAO,KAAK,mBAAmB;AAAA,EACjC;AACF;;;ACxGA,SAAQ,eAAAE,oBAAkB;;;ACE1B,IAAM,gBAAgB;AAGf,IAAM,WAAN,MAAM,UAAY;AAAA,EACvB,QAAkB;AAAA,EAClB,OAAe;AAAA,EAEN;AAAA,EAET,YAAYC,aAA2B,SAA+B;AACpE,SAAK,aAAaA;AAClB,QAAI,SAAS;AACX,iBAAW,OAAO,SAAS;AACzB,aAAK,IAAI,GAAG;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ;AACN,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,QAAQ;AACN,SAAK,MAAM,WAAW;AACtB,UAAM,MAAM,IAAI,UAAY,KAAK,UAAU;AAC3C,QAAI,QAAQ,KAAK;AACjB,QAAI,OAAO,KAAK;AAChB,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAuB;AACzB,WAAO,KAAK,MAAM,IAAI,KAAK,IAAI;AAAA,EACjC;AAAA,EAEA,IAAI,KAAc;AAChB,QAAI,KAAK,MAAM,SAAU,MAAK,QAAQ,KAAK,MAAM,MAAM;AACvD,UAAM,SAAS,KAAK,MAAM,IAAI,KAAK,IAAI;AACvC,QAAI,WAAW,KAAM,QAAO;AAE5B,SAAK,QAAQ,IAAI,cAAiB,CAAC,KAAK,OAAO,MAAM,CAAC;AACtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,IAAI,KAAiB;AACnB,WAAO,KAAK,MAAM,IAAI,KAAK,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,KAAiB;AACtB,WAAO,KAAK,QAAQ,GAAG;AAAA,EACzB;AAAA,EAEA,QAAQ,KAAiB;AACvB,QAAI,OAAO,KAAK;AAChB,QAAI,KAAK,UAAU;AACjB,WAAK,QAAQ,OAAO,KAAK,MAAM;AAAA,IACjC;AACA,QAAI;AACF,aAAO,KAAK,OAAO,KAAK,IAAI;AAAA,IAC9B,UAAE;AACA,UAAI;AACJ,aAAO,KAAK,KAAK,UAAU,KAAK,KAAK,WAAW,GAAG;AACjD,qBAAa,KAAK;AAClB,aAAK,QAAQ,OACX,KAAK,KAAK,WAAW,IAAI,YAAY,KAAK,SAAS,CAAC;AAAA,MACxD;AAEA,UAAI,UAAU;AACZ,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAA4B;AAC1B,WAAO,WAAW,KAAK,OAAO,KAAK,YAAY,QAAW,IAAI;AAAA,EAChE;AAAA,EAEA,SAA8B;AAC5B,WAAO,WAAW,KAAK,OAAO,KAAK,YAAY,QAAW,IAAI;AAAA,EAChE;AAAA,EAEA,WAAW,WAAe,YAAqB,MAA2B;AACxE,WAAO,WAAW,KAAK,OAAO,KAAK,YAAY,WAAW,SAAS;AAAA,EACrE;AAAA,EAEA,iBAAsC;AACpC,WAAO;AAAA,MACL,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBACE,YACA,YAAqB,MACA;AACrB,WAAO;AAAA,MACL,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,UAAyB;AACvB,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,CAAC,OAAO,QAAQ,IAAyB;AACvC,WAAO,KAAK,KAAK;AAAA,EACnB;AACF;AAEA,SAAS,WACP,MACAA,aACA,WACA,WACqB;AACrB,QAAM,OAAO,SAAS,WAAW,MAAMA,WAAU;AACjD,MAAI,SAAS,QAAW;AACtB,WAAO,SAAY,OAAO,EAAC,MAAM,MAAM,OAAO,OAAS,EAAE;AAAA,EAC3D;AAEA,MAAI,CAAC,WAAW,WAAW,IAAI,IAAI;AACnC,MAAI,IACF,cAAc,SACV,KACA,QAAQ,WAAW,KAAK,MAAM,GAAGA,WAAU,IAAI;AAErD,MACE,CAAC,aACD,IAAI,KAAK,KAAK;AAAA,EAEdA,YAAW,KAAK,KAAK,IAAI,CAAC,GAAG,SAAU,MAAM,GAC7C;AACA;AAAA,EACF;AAEA,SAAO,SAAY,MAAM;AACvB,eAAS;AACP,UAAI,EAAE,IAAI,KAAK,KAAK,QAAQ;AAC1B,eAAO,EAAC,MAAM,OAAO,OAAO,KAAK,KAAK,CAAC,EAAC;AAAA,MAC1C;AAEA,UAAI,QAAQ;AACZ,iBAAS;AACP,YAAI,EAAE,SAAS,UAAU,QAAQ;AAC/B,iBAAO,EAAC,MAAM,MAAM,OAAO,OAAS;AAAA,QACtC;AACA,YAAI,EAAE,UAAU,KAAK,IAAI,UAAU,KAAK,EAAE,QAAQ;AAChD;AAAA,QACF;AAAA,MACF;AACA,aAAO,QAAQ,GAAG,SAAS;AACzB,kBAAU,QAAQ,CAAC,IACjB,UAAU,KAAK,EAAE,UAAU,KAAK,CAAC,EACjC;AACF,kBAAU,QAAQ,CAAC,IAAI;AAAA,MACzB;AACA,aAAO,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AAChC,UAAI;AAAA,IACN;AAAA,EACF,CAAC;AACH;AAEA,SAAS,mBACP,QACA,MACAA,aACA,YACA,WACqB;AACrB,MAAI,eAAe,QAAW;AAC5B,iBAAa;AACb,QAAI,eAAe;AACjB,aAAO,SAAY,OAAO,EAAC,MAAM,MAAM,OAAO,OAAS,EAAE;AAAA,EAC7D;AACA,MAAI,CAAC,WAAW,WAAW,IAAI,IAC7B,SAAS,YAAY,MAAMA,WAAU,KACrC,SAAS,QAAQ,MAAMA,WAAU;AACnC,SAAO,CAAC,UAAU,CAAC,KAAK,SAAS,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AAC3D,MAAI,IAAI,QAAQ,YAAY,KAAK,MAAM,GAAGA,WAAU;AACpD,MACE,aACA,IAAI,KAAK,KAAK,UACdA,YAAW,KAAK,KAAK,CAAC,GAAG,UAAU,KAAK,GACxC;AACA;AAAA,EACF;AAEA,SAAO,SAAY,MAAM;AACvB,eAAS;AACP,UAAI,EAAE,KAAK,GAAG;AACZ,eAAO,EAAC,MAAM,OAAO,OAAO,KAAK,KAAK,CAAC,EAAC;AAAA,MAC1C;AAEA,UAAI;AAEJ,WAAK,QAAQ,QAAQ;AACnB,YAAI,EAAE,SAAS,UAAU,QAAQ;AAC/B,iBAAO,EAAC,MAAM,MAAM,OAAO,OAAS;AAAA,QACtC;AACA,YAAI,EAAE,UAAU,KAAK,KAAK,GAAG;AAC3B;AAAA,QACF;AAAA,MACF;AACA,aAAO,QAAQ,GAAG,SAAS;AACzB,kBAAU,QAAQ,CAAC,IACjB,UAAU,KAAK,EAAE,UAAU,KAAK,CAAC,EACjC;AACF,kBAAU,QAAQ,CAAC,IAAI,UAAU,QAAQ,CAAC,EAAE,SAAS;AAAA,MACvD;AACA,aAAO,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AAChC,UAAI,KAAK,KAAK;AAAA,IAChB;AAAA,EACF,CAAC;AACH;AAEA,SAAS,SACP,KACA,MACAA,aAC4E;AAC5E,MAAI,WAAW;AACf,QAAM,YAA0B,CAAC;AACjC,QAAM,YAAsB,CAAC;AAE7B,MAAI,SAAS,WAAW,GAAG;AACzB,aAAS,IAAI,GAAG,SAAS,WAAW,GAAG,KAAK;AAC1C,gBAAU,CAAC,IAAI,SAAS;AACxB,gBAAU,CAAC,IACT,QAAQ,SAAY,IAAI,QAAQ,KAAK,SAAS,MAAM,GAAGA,WAAU;AACnE,UAAI,UAAU,CAAC,KAAK,UAAU,CAAC,EAAE,OAAQ;AACzC,iBAAW,UAAU,CAAC,EAAE,UAAU,CAAC,CAAC;AAAA,IACtC;AACA,cAAU,QAAQ;AAClB,cAAU,QAAQ;AAAA,EACpB;AACA,SAAO,CAAC,WAAW,WAAW,QAAQ;AACxC;AAEA,SAAS,SAAY,MAAoD;AACvE,SAAO;AAAA,IACL;AAAA,IACA,CAAC,OAAO,QAAQ,IAAI;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,IAAM,QAAN,MAAM,OAAS;AAAA;AAAA,EAEb;AAAA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAEA,YAAY,MAAW;AACrB,SAAK,OAAO;AACZ,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,aAAuC;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,SAAS;AACP,WAAO,KAAK,KAAK,KAAK,KAAK,SAAS,CAAC;AAAA,EACvC;AAAA,EAEA,SAAwB;AACtB,WAAO,KAAK,KAAK,CAAC;AAAA,EACpB;AAAA,EAEA,QAAkB;AAChB,WAAO,IAAI,OAAS,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,EACxC;AAAA,EAEA,IAAI,KAAQ,MAAkC;AAC5C,UAAM,IAAI,QAAQ,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU;AACrD,WAAO,IAAI,IAAI,SAAY,KAAK,KAAK,CAAC;AAAA,EACxC;AAAA,EAEA,IAAI,KAAQ,MAA4B;AACtC,UAAM,IAAI,QAAQ,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU;AACrD,WAAO,KAAK,KAAK,IAAI,KAAK,KAAK;AAAA,EACjC;AAAA,EAEA,IAAI,KAAQ,MAAoC;AAC9C,QAAI,IAAI,QAAQ,KAAK,KAAK,MAAM,IAAI,KAAK,UAAU;AACnD,QAAI,IAAI,GAAG;AAET,UAAI,CAAC;AACL,WAAK;AAEL,UAAI,KAAK,KAAK,SAAS,eAAe;AACpC,aAAK,KAAK,OAAO,GAAG,GAAG,GAAG;AAC1B,eAAO;AAAA,MACT;AAEA,YAAM,kBAAkB,KAAK,kBAAkB;AAE/C,UAAI,SAAmB;AACvB,UAAI,IAAI,KAAK,KAAK,QAAQ;AACxB,aAAK,KAAK,KAAK;AACf,iBAAS;AAAA,MACX;AAEA,aAAO,KAAK,OAAO,GAAG,GAAG,GAAG;AAE5B,aAAO;AAAA,IACT;AAGA,SAAK,KAAK,CAAC,IAAI;AACf,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,KAAe;AAC3B,SAAK,KAAK,KAAK,IAAI,KAAK,MAAM,CAAE;AAAA,EAClC;AAAA,EAEA,aAAa,KAAe;AAC1B,SAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,CAAE;AAAA,EACnC;AAAA,EAEA,oBAA8B;AAC5B,UAAM,OAAO,KAAK,KAAK,UAAU;AACjC,UAAM,OAAO,KAAK,KAAK,OAAO,IAAI;AAClC,WAAO,IAAI,OAAS,IAAI;AAAA,EAC1B;AAAA,EAEA,OAAO,KAAQ,MAA4B;AACzC,UAAMC,OAAM,KAAK;AACjB,UAAM,OAAO,QAAQ,KAAK,KAAK,MAAM,IAAIA,IAAG;AAC5C,UAAM,QAAQ,OAAO;AAErB,QAAI,OAAO,GAAG;AACZ,aAAO;AAAA,IACT;AAEA,UAAM,EAAC,KAAI,IAAI;AACf,aAAS,IAAI,MAAM,IAAI,OAAO,KAAK;AACjC,YAAMC,OAAM,KAAK,CAAC;AAElB,UAAIA,SAAQ,KAAK,CAAC,KAAK,KAAK,aAAa,MAAM;AAC7C,cAAM,IAAI,MAAM,6CAA6C;AAAA,MAC/D;AAEA,WAAK,KAAK,OAAO,GAAG,CAAC;AACrB,WAAK;AACL,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,KAAe,GAAW;AACrC,SAAK,KAAK,KAAK,GAAG,IAAI,IAAI;AAAA,EAC5B;AACF;AAGA,IAAM,gBAAN,MAAM,uBAAyB,MAAS;AAAA;AAAA;AAAA;AAAA,EAItC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,UAAsB,MAAY;AAC5C,QAAI,CAAC,MAAM;AACT,aAAO,CAAC;AACR,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,aAAK,CAAC,IAAI,SAAS,CAAC,EAAE,OAAO;AAAA,MAC/B;AAAA,IACF;AACA,UAAM,IAAI;AACV,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,aAAuC;AACrC,WAAO;AAAA,EACT;AAAA,EAEA,QAAkB;AAChB,UAAM,WAAW,KAAK,SAAS,MAAM,CAAC;AACtC,aAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,eAAS,CAAC,EAAE,WAAW;AAAA,IACzB;AACA,WAAO,IAAI,eAAiB,UAAU,KAAK,KAAK,MAAM,CAAC,CAAC;AAAA,EAC1D;AAAA,EAEA,SAAS;AACP,WAAO,KAAK,SAAS,CAAC,EAAE,OAAO;AAAA,EACjC;AAAA,EAEA,IAAI,KAAQ,MAAkC;AAC5C,UAAM,IAAI,QAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,UAAU;AACpD,UAAM,EAAC,SAAQ,IAAI;AACnB,WAAO,IAAI,SAAS,SAAS,SAAS,CAAC,EAAE,IAAI,KAAK,IAAI,IAAI;AAAA,EAC5D;AAAA,EAEA,IAAI,KAAQ,MAA4B;AACtC,UAAM,IAAI,QAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,UAAU;AACpD,UAAM,EAAC,SAAQ,IAAI;AACnB,WAAO,IAAI,SAAS,SAAS,SAAS,CAAC,EAAE,IAAI,KAAK,IAAI,IAAI;AAAA,EAC5D;AAAA,EAEA,IAAI,KAAQ,MAAoC;AAC9C,UAAM,IAAI,KAAK;AACf,UAAMD,OAAM,KAAK;AACjB,QAAI,IAAI,KAAK,IAAI,QAAQ,KAAK,KAAK,MAAM,GAAGA,IAAG,GAAG,EAAE,SAAS,CAAC;AAC9D,QAAI,QAAQ,EAAE,CAAC;AAEf,QAAI,MAAM,UAAU;AAClB,QAAE,CAAC,IAAI,QAAQ,MAAM,MAAM;AAAA,IAC7B;AACA,QAAI,MAAM,KAAK,UAAU,eAAe;AAKtC,UAAI;AACJ,UACE,IAAI,MACH,QAAQ,EAAE,IAAI,CAAC,GAAG,KAAK,SAAS,iBACjCA,KAAI,MAAM,KAAK,CAAC,GAAG,GAAG,IAAI,GAC1B;AACA,YAAI,MAAM,UAAU;AAClB,YAAE,IAAI,CAAC,IAAI,QAAQ,MAAM,MAAM;AAAA,QACjC;AACA,cAAM,cAAc,KAAK;AACzB,aAAK,KAAK,IAAI,CAAC,IAAI,MAAM,OAAO;AAAA,MAClC,YACG,QAAQ,EAAE,IAAI,CAAC,OAAO,UACvB,MAAM,KAAK,SAAS,iBACpBA,KAAI,MAAM,OAAO,GAAG,GAAG,IAAI,GAC3B;AACA,YAAI,MAAM,SAAU,GAAE,IAAI,CAAC,IAAI,QAAQ,MAAM,MAAM;AACnD,cAAM,aAAa,KAAK;AACxB,aAAK,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,OAAO;AAAA,MAC7B;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,IAAI,KAAK,IAAI;AAClC,SAAK,KAAK,CAAC,IAAI,MAAM,OAAO;AAC5B,QAAI,WAAW,KAAM,QAAO;AAG5B,QAAI,KAAK,KAAK,SAAS,eAAe;AAEpC,WAAK,OAAO,IAAI,GAAG,MAAM;AACzB,aAAO;AAAA,IACT;AAEA,UAAM,kBAAkB,KAAK,kBAAkB;AAE/C,QAAI,SAA2B;AAC/B,QAAIA,KAAI,OAAO,OAAO,GAAG,KAAK,OAAO,CAAC,IAAI,GAAG;AAC3C,eAAS;AACT,WAAK,KAAK,KAAK;AAAA,IACjB;AACA,WAAO,OAAO,IAAI,GAAG,MAAM;AAC3B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,GAAW,OAAiB;AACjC,SAAK,SAAS,OAAO,GAAG,GAAG,KAAK;AAChC,SAAK,KAAK,OAAO,GAAG,GAAG,MAAM,OAAO,CAAC;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB;AAClB,UAAM,OAAO,KAAK,SAAS,UAAU;AACrC,WAAO,IAAI;AAAA,MACT,KAAK,SAAS,OAAO,IAAI;AAAA,MACzB,KAAK,KAAK,OAAO,IAAI;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,cAAc,KAAe;AAC3B,SAAK,KAAK,KAAK,IAAI,KAAK,MAAM,CAAE;AAChC,SAAK,SAAS,KAAM,IAAyB,SAAS,MAAM,CAAE;AAAA,EAChE;AAAA,EAEA,aAAa,KAAe;AAC1B,SAAK,KAAK,QAAQ,IAAI,KAAK,IAAI,CAAE;AACjC,SAAK,SAAS,QAAS,IAAyB,SAAS,IAAI,CAAE;AAAA,EACjE;AAAA,EAEA,OAAO,KAAQ,MAA4B;AACzC,UAAMA,OAAM,KAAK;AACjB,UAAM,EAAC,KAAI,IAAI;AACf,UAAM,EAAC,SAAQ,IAAI;AACnB,QAAI,OAAO,QAAQ,KAAK,KAAK,MAAM,GAAGA,IAAG;AACzC,QAAI,IAAI;AACR,UAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,SAAS,CAAC;AAC5C,QAAI,KAAK,OAAO;AACd,UAAI;AACF,YAAI,SAAS,CAAC,EAAE,UAAU;AACxB,mBAAS,CAAC,IAAI,SAAS,CAAC,EAAE,MAAM;AAAA,QAClC;AACA,cAAM,SAAS,SAAS,CAAC,EAAE,OAAO,KAAK,IAAI;AAG3C,aAAK,CAAC,IAAI,SAAS,CAAC,EAAE,OAAO;AAC7B,eAAO;AAAA,MACT,UAAE;AAEA,cAAM,OAAO,iBAAiB;AAC9B,YAAI,OAAO,EAAG;AACd,aAAK,IAAI,OAAO,KAAK,MAAM,KAAK;AAC9B,cAAI,SAAS,CAAC,EAAE,KAAK,UAAU,MAAM;AACnC,gBAAI,SAAS,CAAC,EAAE,KAAK,WAAW,GAAG;AACjC,mBAAK,SAAS,GAAG,aAAa;AAAA,YAChC,OAAO;AAEL,mBAAK,OAAO,GAAG,CAAC;AAChB,uBAAS,OAAO,GAAG,CAAC;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,SAAS,GAAW,SAA0B;AAC5C,UAAM,EAAC,SAAQ,IAAI;AACnB,QAAI,KAAK,KAAK,IAAI,IAAI,SAAS,QAAQ;AACrC,UAAI,SAAS,CAAC,EAAE,KAAK,SAAS,SAAS,IAAI,CAAC,EAAE,KAAK,UAAU,SAAS;AACpE,YAAI,SAAS,CAAC,EAAE;AAEd,mBAAS,CAAC,IAAI,SAAS,CAAC,EAAE,MAAM;AAClC,iBAAS,CAAC,EAAE,aAAa,SAAS,IAAI,CAAC,GAAG,OAAO;AACjD,iBAAS,OAAO,IAAI,GAAG,CAAC;AACxB,aAAK,KAAK,OAAO,IAAI,GAAG,CAAC;AACzB,aAAK,KAAK,CAAC,IAAI,SAAS,CAAC,EAAE,OAAO;AAClC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,KAAe,aAAqB;AAE/C,UAAM,YAAY,KAAK,KAAK;AAC5B,SAAK,KAAK,KAAK,GAAG,IAAI,IAAI;AAC1B,UAAM,cAAe,IAAoC;AACzD,SAAK,SAAS,KAAK,GAAG,WAAW;AAEjC,QAAI,IAAI,YAAY,CAAC,KAAK,UAAU;AAGlC,eAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,oBAAY,CAAC,EAAE,WAAW;AAAA,MAC5B;AAAA,IACF;AAKA,SAAK,SAAS,YAAY,GAAG,WAAW;AAAA,EAC1C;AACF;AAIA,SAAS,QACP,KACA,MACA,SACAD,aACQ;AACR,MAAI,KAAK;AACT,MAAI,KAAK,KAAK;AACd,MAAI,MAAM,MAAM;AAChB,SAAO,KAAK,IAAI;AACd,UAAM,IAAIA,YAAW,KAAK,GAAG,GAAG,GAAG;AACnC,QAAI,IAAI,GAAG;AACT,WAAK,MAAM;AAAA,IACb,WAAW,IAAI,GAAG;AAEhB,WAAK;AAAA,IACP,WAAW,MAAM,GAAG;AAClB,aAAO;AAAA,IACT,OAAO;AAEL,UAAI,QAAQ,KAAK;AAEf,eAAO,KAAK;AAAA,MACd;AACA,YAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AACA,UAAO,KAAK,MAAO;AAAA,EACrB;AACA,SAAO,MAAM;AACf;AAGA,IAAM,YAAY,IAAI,MAAW,CAAC,CAAC;AACnC,UAAU,WAAW;;;AD5nBrB,SAAS,WAAW,GAAU,GAAkB;AAC9C,SAAOG,aAAY,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;AAC/B;AAMO,IAAM,gBAAN,MAAuC;AAAA,EAC5C,QAAyB,IAAI,SAAS,UAAU;AAAA,EAEhD,IAAI,KAAa,OAAkB;AACjC,SAAK,MAAM,IAAI,CAAC,KAAK,KAAK,CAAC;AAAA,EAC7B;AAAA,EAEA,IAAI,KAAa,KAAwC;AACvD,UAAM,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,IAAI,CAAC;AACpC,QAAI,MAAM,QAAW;AACnB,aAAO,EAAE,CAAC;AAAA,IACZ;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAa;AACf,SAAK,MAAM,OAAO,CAAC,KAAK,IAAI,CAAC;AAAA,EAC/B;AAAA,EAEA,CAAC,KAAK,SAAyD;AAC7D,eAAW,SAAS,KAAK,MAAM;AAAA,MAC7B,WAAW,CAAC,QAAQ,QAAQ,IAAI;AAAA,IAClC,GAAG;AACD,UAAI,WAAW,CAAC,MAAM,CAAC,EAAE,WAAW,QAAQ,MAAM,GAAG;AACnD;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,YAAuC;AACrC,WAAO,gBAAgB,OAAO,YAAY,KAAK,MAAM,OAAO,CAAC,CAAC;AAAA,EAChE;AACF;;;AElCO,IAAM,sBAAN,MAA8C;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EAET,UAAkB;AAAA,EACT;AAAA,EAET,YACE,OACA,SACA,iBACA,YACA;AACA,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,mBAAmB;AACxB,SAAK,cAAc;AACnB,UAAM,UAAU,IAAI;AAAA,EACtB;AAAA,EAEA,UAAU,QAAsB;AAC9B,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,KAAiC;AACrC,WAAO,KAAK,OAAO,MAAM,GAAG;AAAA,EAC9B;AAAA,EAEA,QAAQ,KAAiC;AACvC,WAAO,KAAK,OAAO,QAAQ,GAAG;AAAA,EAChC;AAAA,EAEA,YAA0B;AACxB,WAAO,KAAK,OAAO,UAAU;AAAA,EAC/B;AAAA,EAEA,UAAgB;AACd,SAAK,OAAO,QAAQ;AAAA,EACtB;AAAA,EAEA,KAAK,QAAsB;AACzB,UAAM,YAAY,YAAY,IAAI;AAClC,SAAK,QAAQ,KAAK,QAAQ,IAAI;AAC9B,SAAK,iBAAiB;AAAA,MACpB,KAAK;AAAA,MACL,YAAY,IAAI,IAAI;AAAA,MACpB,KAAK;AAAA,IACP;AAAA,EACF;AACF;;;ACwBO,IAAM,eAAN,MAAM,cAA+B;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAA+B,oBAAI,IAAI;AAAA,EACvC,eAA6B,CAAC;AAAA,EAEvC;AAAA,EAEA,YACE,WACA,SACA,YACA,kBACA;AACA,SAAK,aAAa;AAClB,SAAK,WAAW;AAChB,SAAK,cAAc;AACnB,SAAK,oBAAoB,WAAW,IAAI,OAAK,CAAC,GAAG,KAAK,CAAC;AACvD,UAAMC,cAAa,oBAAoB,KAAK,iBAAiB;AAC7D,SAAK,SAAS,IAAI,KAAK,UAAU,KAAK,iBAAiB,GAAG;AAAA,MACxD,YAAAA;AAAA,MACA,MAAM,oBAAoB,IAAI,SAAcA,WAAU;AAAA,MACtD,QAAQ,oBAAI,IAAI;AAAA,IAClB,CAAC;AACD,6BAAyB,KAAK,mBAAmB,KAAK,WAAW;AAAA,EACnE;AAAA;AAAA,EAGA,gBAAgB;AACd,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,OAAO;AACL,UAAM,eAAe,KAAK,iBAAiB;AAC3C,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,aAAa,KAAK,MAAM;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,IAAI,OAAsB;AACxB,WAAO,KAAK,iBAAiB,EAAE;AAAA,EACjC;AAAA,EAEA,WAAW,YAAsC;AAC/C,WAAO;AAAA,MACL,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,MAAM,WAAW;AAAA,MACjB,QAAQ;AAAA,MACR,eAAe,CAAC;AAAA,MAChB,UAAU;AAAA,MACV,aAAa,WAAW;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,QACE,MACA,SACA,eACa;AACb,UAAM,qBAAqB,iBAAiB,OAAO;AAEnD,UAAM,QAAqB;AAAA,MACzB,WAAW,MAAM;AAAA,MACjB,OAAO,SAAO,KAAK,OAAO,KAAK,UAAU;AAAA,MACzC,SAAS,SAAO,KAAK,SAAS,KAAK,UAAU;AAAA,MAC7C,WAAW,YAAU;AACnB,mBAAW,SAAS;AAAA,MACtB;AAAA,MACA,SAAS,MAAM;AACb,aAAK,YAAY,KAAK;AAAA,MACxB;AAAA,MACA,qBAAqB,CAAC,mBAAmB;AAAA,IAC3C;AAEA,UAAM,aAAyB;AAAA,MAC7B;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA,aAAa,eAAe,IAAI;AAAA,MAChC,SAAS,mBAAmB,UACxB;AAAA,QACE,WAAW,mBAAmB;AAAA,QAC9B,WAAW,gBAAgB,mBAAmB,OAAO;AAAA,MACvD,IACA;AAAA,IACN;AACA,UAAM,SAAS,KAAK,WAAW,UAAU;AACzC,6BAAyB,MAAM,KAAK,WAAW;AAC/C,SAAK,aAAa,KAAK,UAAU;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,OAAoB;AAC9B,UAAM,MAAM,KAAK,aAAa,UAAU,OAAK,EAAE,UAAU,KAAK;AAC9D,WAAO,QAAQ,IAAI,sBAAsB;AACzC,SAAK,aAAa,OAAO,KAAK,CAAC;AAAA,EASjC;AAAA,EAEA,mBAA0B;AACxB,UAAM,QAAQ,KAAK,SAAS,IAAI,KAAK,UAAU,KAAK,iBAAiB,CAAC;AACtE,WAAO,OAAO,yBAAyB;AACvC,WAAO;AAAA,EACT;AAAA,EAEA,kBAAkB,MAAgB,QAA2B;AAC3D,UAAM,MAAM,KAAK,UAAU,IAAI;AAC/B,UAAM,QAAQ,KAAK,SAAS,IAAI,GAAG;AAGnC,QAAI,OAAO;AACT,YAAM,OAAO,IAAI,MAAM;AACvB,aAAO;AAAA,IACT;AAEA,UAAMA,cAAa,oBAAoB,IAAI;AAS3C,UAAM,OAAO,IAAI,SAAcA,WAAU;AAIzC,eAAW,OAAO,KAAK,iBAAiB,EAAE,MAAM;AAC9C,WAAK,IAAI,GAAG;AAAA,IACd;AAEA,UAAM,WAAW,EAAC,YAAAA,aAAY,MAAM,QAAQ,oBAAI,IAAI,CAAC,MAAM,CAAC,EAAC;AAC7D,SAAK,SAAS,IAAI,KAAK,QAAQ;AAC/B,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,eAAyB;AACvB,WAAO,CAAC,GAAG,KAAK,SAAS,KAAK,CAAC;AAAA,EACjC;AAAA,EAEA,CAAC,OAAO,KAAmB,MAAgC;AACzD,UAAM,yBAAyB,KAAK,aAAa,QAAQ,IAAI;AAC7D,WAAO,2BAA2B,IAAI,kBAAkB;AACxD,UAAM,OAAO,KAAK,aAAa,sBAAsB;AACrD,UAAM,EAAC,MAAM,eAAe,YAAW,IAAI;AAC3C,UAAM,uBAAuB,CAAC,IAAS,OACrC,YAAY,IAAI,EAAE,KAAK,IAAI,UAAU,KAAK;AAE5C,UAAM,eAAe;AAAA,MACnB,KAAK,SAAS;AAAA,MACd,KAAK;AAAA,IACP;AAGA,UAAM,sBAAsB,gBAAgB,IAAI;AAGhD,UAAM,YAAyB,CAAC;AAChC,QAAI,qBAAqB;AACvB,iBAAW,OAAO,OAAO,KAAK,mBAAmB,GAAG;AAClD,kBAAU,KAAK,CAAC,KAAK,KAAK,CAAC;AAAA,MAC7B;AAAA,IACF;AAKA,QACE,KAAK,YAAY,SAAS,KAC1B,CAAC,uBACD,CAAC,4BAA4B,qBAAqB,KAAK,WAAW,GAClE;AACA,gBAAU,KAAK,GAAG,aAAa;AAAA,IACjC;AAEA,UAAM,QAAQ,KAAK,kBAAkB,WAAW,IAAI;AACpD,UAAM,EAAC,MAAM,YAAYC,SAAO,IAAI;AACpC,UAAM,kBAAkB,CAAC,IAAS,OAChCA,SAAQ,IAAI,EAAE,KAAK,IAAI,UAAU,KAAK;AAExC,UAAM,UAAU,IAAI,OAAO;AAY3B,QAAI;AAEJ,QAAI,qBAAqB;AACvB,kBAAY,CAAC;AACb,iBAAW,CAAC,KAAK,GAAG,KAAK,WAAW;AAClC,YAAI,OAAO,qBAAqB,GAAG,GAAG;AACpC,oBAAU,GAAG,IAAI,oBAAoB,GAAG;AAAA,QAC1C,OAAO;AACL,cAAI,IAAI,SAAS;AACf,sBAAU,GAAG,IAAI,QAAQ,QAAQ,WAAW;AAAA,UAC9C,OAAO;AACL,sBAAU,GAAG,IAAI,QAAQ,QAAQ,WAAW;AAAA,UAC9C;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,kBAAY;AAAA,IACd;AAEA,UAAM,eAAe,aAAa,MAAM,WAAW,IAAI,OAAO;AAC9D,UAAM,cAAcC;AAAA,MAClB;AAAA,MACA,eAAe,KAAK,YAAY,IAAI;AAAA;AAAA;AAAA;AAAA,MAIpC,IAAI;AAAA,MACJ,KAAK;AAAA,MACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA;AAAA,MACA,KAAK,SAAS;AAAA,IAChB;AAEA,UAAM,iBAAiB;AAAA,MACrB,kBAAkB,aAAa,IAAI,OAAO,oBAAoB;AAAA;AAAA;AAAA,MAG9D,IAAI;AAAA,IACN;AAEA,WAAO,KAAK,UACR,mBAAmB,gBAAgB,KAAK,QAAQ,SAAS,IACzD;AAAA,EACN;AAAA,EAEA,SAAS,KAAmB,YAAsC;AAChE,WAAO,KAAK,OAAO,KAAK,UAAU;AAAA,EACpC;AAAA,EAEA,KAAK,QAA4B;AAC/B,eAAW,KAAK,KAAK,QAAQ,MAAM,GAAG;AAAA,IAEtC;AAAA,EACF;AAAA,EAEA,CAAC,QAAQ,QAAsB;AAC7B,UAAM,eAAe,KAAK,iBAAiB;AAC3C,UAAM,EAAC,KAAI,IAAI;AACf,UAAM,SAAS,CAAC,QAAa,KAAK,IAAI,GAAG;AACzC,UAAM,aAAa,CAAC,MAA4B,KAAK,WAAW;AAChE,UAAM,cAAc,CAAC,MAAoB,KAAK,aAAa,CAAC;AAC5D,WAAO;AAAA,MACL,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa,QAAsB;AACjC,eAAW,EAAC,KAAI,KAAK,KAAK,SAAS,OAAO,GAAG;AAC3C,cAAQ,OAAO,MAAM;AAAA,QACnB,KAAK,OAAO;AACV,gBAAM,QAAQ,KAAK,IAAI,OAAO,GAAG;AAEjC,iBAAO,KAAK;AACZ;AAAA,QACF;AAAA,QACA,KAAK,UAAU;AACb,gBAAM,UAAU,KAAK,OAAO,OAAO,GAAG;AAEtC,iBAAO,OAAO;AACd;AAAA,QACF;AAAA,QACA,KAAK,QAAQ;AAKX,gBAAM,UAAU,KAAK,OAAO,OAAO,MAAM;AAEzC,iBAAO,OAAO;AACd,eAAK,IAAI,OAAO,GAAG;AACnB;AAAA,QACF;AAAA,QACA;AACE,sBAAY,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACF;AAEA,UAAU,uBACR,IACA,YACA;AACA,aAAW,QAAQ,IAAI;AACrB,QAAI,cAAc,CAAC,qBAAqB,YAAY,KAAK,GAAG,GAAG;AAC7D;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAEA,UAAU,mBAAmB,IAAkB,QAA+B;AAC5E,aAAW,QAAQ,IAAI;AACrB,QAAI,OAAO,KAAK,GAAG,GAAG;AACpB,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAEO,UAAU,6BACf,aACA,QACA,QACA,YACA,aACA;AACA,MAAI,kBAAkB;AACtB,MAAI,OAAO,SAAS,QAAQ;AAC1B,eAAW,EAAC,cAAa,KAAK,aAAa;AACzC,UAAI,eAAe;AACjB,mBAAW,OAAO,eAAe;AAC/B,cAAI,CAAC,YAAY,OAAO,IAAI,GAAG,GAAG,OAAO,OAAO,GAAG,CAAC,GAAG;AACrD,8BAAkB;AAClB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,UAAU,iBAAiB;AAC7C,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,KAAK,OAAO;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QACN,KAAK,OAAO;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,OAAO;AACL,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEA,UAAU,gBACR,aACA,QACA,QACA,YACA,aACA;AACA,aAAW,KAAK,QAAQ,aAAa,QAAQ,QAAQ,UAAU,GAAG;AAChE,UAAM;AAAA,EACR;AACA,cAAY,MAAM;AACpB;AAEA,UAAU,QACR,aACA,QACA,QACA,YACA;AACA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AACH;AAAA,QACE,CAAC,OAAO,OAAO,GAAG;AAAA,QAClB,MAAM,sBAAsB,UAAU,MAAM,CAAC;AAAA,MAC/C;AACA;AAAA,IACF,KAAK;AACH,aAAO,OAAO,OAAO,GAAG,GAAG,MAAM,iBAAiB,UAAU,MAAM,CAAC,EAAE;AACrE;AAAA,IACF,KAAK;AACH,aAAO,OAAO,OAAO,MAAM,GAAG,MAAM,iBAAiB,UAAU,MAAM,CAAC,EAAE;AACxE;AAAA,IACF;AACE,kBAAY,MAAM;AAAA,EACtB;AAEA,aAAW,CAAC,aAAa,EAAC,QAAQ,SAAS,MAAK,CAAC,KAAK,YAAY,QAAQ,GAAG;AAC3E,QAAI,QAAQ;AACV,iBAAW,EAAC,aAAa,OAAM,CAAC;AAChC,YAAM,eACJ,OAAO,SAAS,SACZ;AAAA,QACE,MAAM,OAAO;AAAA,QACb,SAAS;AAAA,UACP,KAAK,OAAO;AAAA,UACZ,eAAe,CAAC;AAAA,QAClB;AAAA,QACA,MAAM;AAAA,UACJ,KAAK,OAAO;AAAA,UACZ,eAAe,CAAC;AAAA,QAClB;AAAA,MACF,IACA;AAAA,QACE,MAAM,OAAO;AAAA,QACb,MAAM;AAAA,UACJ,KAAK,OAAO;AAAA,UACZ,eAAe,CAAC;AAAA,QAClB;AAAA,MACF;AACN,iBAAW,cAAc,QAAQ,OAAO,SAAS,SAAS;AAC1D;AAAA,IACF;AAAA,EACF;AAEA,aAAW,MAAS;AACtB;AAEO,UAAU,kBACf,OACA,OACAD,UACc;AACd,MAAI,CAAC,OAAO;AACV,WAAO;AACP;AAAA,EACF;AACA,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,SAAS;AACZ,UAAI,MAAM,UAAU,MAAM;AACxB,YAAIA,SAAQ,KAAK,KAAK,MAAM,GAAG,KAAK,GAAG;AACrC,oBAAU;AAAA,QACZ;AAAA,MACF,WAAW,MAAM,UAAU,SAAS;AAClC,YAAIA,SAAQ,KAAK,KAAK,MAAM,GAAG,IAAI,GAAG;AACpC,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AACA,QAAI,SAAS;AACX,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAcO,UAAUC,qBACf,SACA,MACA,YACA,SACA,iBACAD,UACA,iBACA;AACA,MAAI,iBAAsC;AAC1C,MAAI,WAAW,mBAAmB,QAAQ,aAAa;AACrD,qBAAiB;AAAA,EACnB;AACA,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACAA;AAAA,IACA;AAAA,EACF;AACA,SAAO,yBAAyB,MAAM,UAAUA,QAAO;AACzD;AAEA,SAAS,gBACP,SACA,YACA,SACAA,UACA,iBACU;AACV,MAAI,WAAqB;AAAA,IACvB,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACA,UAAQ,SAAS,OAAO,MAAM;AAAA,IAC5B,KAAK;AACH,iBAAW;AAAA,QACT,KAAK,QAAQ,OAAO;AAAA,QACpB,QAAQ;AAAA,MACV;AACA;AAAA,IACF,KAAK;AACH,iBAAW;AAAA,QACT,KAAK;AAAA,QACL,QAAQ,QAAQ,OAAO;AAAA,MACzB;AACA;AAAA,IACF,KAAK;AACH,iBAAW;AAAA,QACT,KAAK,QAAQ,OAAO;AAAA,QACpB,QAAQ,QAAQ,OAAO;AAAA,MACzB;AACA;AAAA,EACJ;AAEA,MAAI,SAAS;AACX,eAAW,mBAAmB,UAAU,SAASA,QAAO;AAAA,EAC1D;AAEA,MAAI,YAAY;AACd,eAAW,sBAAsB,UAAU,UAAU;AAAA,EACvD;AAEA,MAAI,iBAAiB;AACnB,eAAW,2BAA2B,UAAU,eAAe;AAAA,EACjE;AAEA,SAAO;AACT;AAIA,SAAS,mBACP,EAAC,KAAAE,MAAK,OAAM,GACZ,SACAC,UACU;AACV,QAAM,2BAA2B,CAAC,QAChC,QAAQ,UAAaA,SAAQ,KAAK,OAAO,IAAI,IAAI,SAAY;AAC/D,SAAO;AAAA,IACL,KAAK,yBAAyBD,IAAG;AAAA,IACjC,QAAQ,yBAAyB,MAAM;AAAA,EACzC;AACF;AAIA,SAAS,sBACP,EAAC,KAAAE,MAAK,OAAM,GACZ,YACU;AACV,QAAM,mCAAmC,CAAC,QACxC,QAAQ,UAAa,CAAC,qBAAqB,YAAY,GAAG,IACtD,SACA;AAEN,SAAO;AAAA,IACL,KAAK,iCAAiCA,IAAG;AAAA,IACzC,QAAQ,iCAAiC,MAAM;AAAA,EACjD;AACF;AAEA,SAAS,2BACP,EAAC,KAAAA,MAAK,OAAM,GACZ,iBACU;AACV,QAAM,+BAA+B,CAAC,QACpC,QAAQ,UAAa,CAAC,gBAAgB,GAAG,IAAI,SAAY;AAE3D,SAAO;AAAA,IACL,KAAK,6BAA6BA,IAAG;AAAA,IACrC,QAAQ,6BAA6B,MAAM;AAAA,EAC7C;AACF;AAEO,UAAU,yBACf,aACA,UACAC,UACA;AACA,MAAI,oBAAoB;AACxB,MAAI,uBAAuB;AAC3B,aAAW,OAAO,aAAa;AAC7B,QAAI,CAAC,qBAAqB,SAAS,KAAK;AACtC,YAAMC,OAAMD,SAAQ,SAAS,KAAK,GAAG;AACrC,UAAIC,OAAM,GAAG;AACX,4BAAoB;AACpB,cAAM,EAAC,KAAK,SAAS,KAAK,eAAe,CAAC,EAAC;AAAA,MAC7C;AAAA,IACF;AAEA,QAAI,CAAC,wBAAwB,SAAS,QAAQ;AAC5C,YAAMA,OAAMD,SAAQ,SAAS,QAAQ,GAAG;AACxC,UAAIC,SAAQ,GAAG;AACb,+BAAuB;AACvB;AAAA,MACF;AAAA,IACF;AACA,UAAM,EAAC,KAAK,eAAe,CAAC,EAAC;AAAA,EAC/B;AAEA,MAAI,CAAC,qBAAqB,SAAS,KAAK;AACtC,UAAM,EAAC,KAAK,SAAS,KAAK,eAAe,CAAC,EAAC;AAAA,EAC7C;AACF;AASA,IAAM,WAAW,OAAO,WAAW;AAEnC,IAAM,WAAW,OAAO,WAAW;AAGnC,SAAS,oBAAoB,MAAgB;AAC3C,SAAO,CAAC,GAAa,MAAgB;AAEnC,eAAW,SAAS,MAAM;AACxB,YAAM,MAAM,MAAM,CAAC;AACnB,YAAMA,OAAM,cAAc,EAAE,GAAG,GAAG,EAAE,GAAG,CAAC;AACxC,UAAIA,SAAQ,GAAG;AACb,eAAO,MAAM,CAAC,MAAM,QAAQA,OAAM,CAACA;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,cAAc,GAAU,GAAkB;AACjD,MAAI,MAAM,GAAG;AACX,WAAO;AAAA,EACT;AACA,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,MAAI,MAAM,UAAU;AAClB,WAAO;AAAA,EACT;AACA,SAAO,cAAc,GAAG,CAAC;AAC3B;AAEA,UAAU,aACR,MACA,WACA,SACA;AACA,SAAO,KAAK,UAAU,uBAAuB,YAAY;AAAA,IACvD;AAAA,EACF;AACF;AAEO,SAAS,UAAU,QAAsB;AAC9C,SAAO,KAAK;AAAA,IAAU;AAAA,IAAQ,CAAC,GAAG,MAChC,OAAO,MAAM,WAAW,EAAE,SAAS,IAAI;AAAA,EACzC;AACF;;;ACzvBO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EACT;AAAA,EAEA,YACE,QACA,MACA,UAAiD,oBAAI,IAAI,GACzD;AACA,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,UAAU,MAAwC;AAChD,QAAI,KAAK,SAAS,IAAI,IAAI,GAAG;AAC3B,aAAO,KAAK,SAAS,IAAI,IAAI;AAAA,IAC/B;AAEA,UAAM,SAAS,KAAK,QAAQ,IAAI;AAChC,UAAM,SAAS,SACX,IAAI,aAAa,MAAM,OAAO,SAAS,OAAO,UAAU,IACxD;AACJ,SAAK,SAAS,IAAI,MAAM,MAAM;AAC9B,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ;AACN,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,cAAgC,SAAe,OAAoB;AACzE;AAAA,MACE,KAAK,SAAS;AAAA,MACd,MACE,gDAAgD,KAAK,IAAI,eAAe,YAAY;AAAA,IACxF;AAEA,eAAW,OAAO,IAAI;AACtB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WACJ,OACA,aACA,aAC0B;AAC1B,UAAM,OAAO,KAAK,KAAK;AAEvB,QAAI,KAAK,SAAS,aAAa;AAC7B,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,aAAa,OAAO,MAAM,WAAW;AACvD,SAAK,OAAO;AACZ,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAO;AACL,WAAO,IAAI;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,MACL,IAAI;AAAA,QACF,aAAa,KAAK,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM;AAAA,UAC5D;AAAA,UACA,QAAQ,KAAK;AAAA,QACf,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAyBA,eAAe,YACb,aACA,OACA,MACA,aACA;AACA,QAAM,QAAQ,MAAM;AAAA,IAClB,KAAK,KAAK,IAAI;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,CAAC,OAAO;AACV;AAAA,EACF;AACA,aAAW,OAAO,IAAI;AACxB;AAEA,eAAe,aACb,WACA,SACA,OACA,aACmC;AACnC,QAAM,SAAS,CAAC,YACdC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,oBAAoB,MAAM;AAAA,MAC1B,2BAA2B,OAAO;AAChC,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACc;AAAA,EAChB;AAEF,MAAI;AACJ,MAAI,aAAa,oBAAoB;AACnC,YAAQ,MAAM,MAAM,MAAM,KAAK,YAAY,kBAAkB,GAAG,MAAM;AAAA,EACxE,WAAW,aAAa,cAAc;AACpC,YAAQ,MAAM,OAAO,YAAY,YAAY;AAAA,EAC/C,OAAO;AACL,YAAQ,MAAM,SAAS,OAAO,MAAM;AAAA,EACtC;AAEA,SAAO,MAAM,IAAI,EAAE;AACrB;AAEA,SAAS,WAAW,OAAoB,QAAyB;AAC/D,WACM,IAAI,iBAAiB,OAAO,qBAAqB,CAAAA,UAAQA,MAAK,GAAG,GACrE,IAAI,MAAM,QACV,KACA;AACA,UAAMA,QAAO,MAAM,CAAC;AACpB,UAAM,EAAC,IAAG,IAAIA;AACd,QAAI,CAAC,IAAI,WAAW,mBAAmB,GAAG;AACxC;AAAA,IACF;AACA,UAAM,OAAO,kBAAkB,GAAG;AAClC,UAAM,SAAS,KAAK,OAAO,UAAU,IAAI,CAAC;AAC1C,YAAQA,MAAK,IAAI;AAAA,MACf,KAAK;AACH,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,KAAKA,MAAK;AAAA,QACZ,CAAC;AACD;AAAA,MACF,KAAK;AACH,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,KAAKA,MAAK;AAAA,QACZ,CAAC;AACD;AAAA,MACF,KAAK;AACH,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,KAAKA,MAAK;AAAA,UACV,QAAQA,MAAK;AAAA,QACf,CAAC;AACD;AAAA,IACJ;AAAA,EACF;AACF;;;AC1MO,IAAM,cAAN,MAA2C;AAAA;AAAA;AAAA;AAAA;AAAA,EAKvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,mBAAwC,oBAAI,IAAI;AAAA,EAEhD;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB;AAAA,EAEvB;AAAA,EAET,YACE,IACA,aACA,UACA,gBACA,aACA,mBACA,mBACA,kBACA,WACAC,wBACA;AACA,SAAK,eAAe;AACpB,SAAK,iBAAiB;AACtB,SAAK,oBAAoB;AACzB,SAAK,oBAAoB;AACzB,SAAK,oBAAoB;AACzB,SAAK,MAAM;AACX,SAAK,wBAAwBA;AAC7B,SAAK,iBAAiB;AACtB,SAAK,oBAAoB;AACzB,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,UAAU,MAAkC;AAC1C,WAAO,KAAK,aAAa,UAAU,IAAI;AAAA,EACzC;AAAA,EAEA,OAAO,KAAe;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,gBAAyB;AACvB,WAAO,IAAI,cAAc;AAAA,EAC3B;AAAA,EAEA,cAAc,OAAqB;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,oBAAoB,OAAiC;AACnD,WAAO;AAAA,EACT;AAAA,EAEA,oBAAoB,OAAoB,SAAwB;AAC9D,WAAO,IAAI,oBAAoB,OAAO,SAAS,MAAM,qBAAqB;AAAA,EAC5E;AAAA,EAEA,UAAU;AAAA,EAAC;AAAA,EAEX,oBAAoB,IAAgC;AAClD,SAAK,iBAAiB,IAAI,EAAE;AAC5B,WAAO,MAAM;AACX,WAAK,iBAAiB,OAAO,EAAE;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,iBAAoB,kBAA2B;AAC7C,QAAI;AACJ,QAAI,uBAAuB;AAC3B,SAAK,kBAAkB,MAAM;AAC3B,eAAS,iBAAiB;AAC1B,6BAAuB;AAAA,IACzB,CAAC;AACD;AAAA,MACE;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,eACE,cACA,SACA,SACA;AACA,SAAK,iBAAiB,MAAM;AAC1B,UAAI;AACF,aAAK,aAAa,QAAQ,cAAc,SAAS,OAAO;AAAA,MAC1D,UAAE;AACA,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,kBAAkB;AAChB,eAAW,YAAY,KAAK,kBAAkB;AAC5C,UAAI;AACF,iBAAS;AAAA,MACX,SAAS,GAAG;AAIV,aAAK,IAAI;AAAA,UACP,wBAAU;AAAA,UACV;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC9EO,SAAS,eACd,QACA,WACsD;AACtD,QAAM,EAAC,CAAC,kBAAkB,GAAG,SAAQ,IAAI;AAEzC,QAAM,cAAc,OAAU,SAA6C;AACzE,UAAM,MAAgB,CAAC;AACvB,UAAM,IAAI,CAAC;AACX,eAAW,QAAQ,OAAO,KAAK,OAAO,MAAM,GAAG;AAC7C,QAAE,IAAI,IAAI,oBAAoB,MAAM,QAAQ,GAAG;AAAA,IACjD;AAEA,UAAM,KAAK,MAAM,KAAK,CAAiB;AACvC,UAAM,SAAS,EAAC,IAAG,CAAC;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,SAAoD,CAAC;AAC3D,aAAW,CAAC,MAAM,WAAW,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAC/D,WAAO,IAAI,IAAI,qBAAqB,MAAM,YAAY,YAAY,QAAQ;AAAA,EAC5E;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,qBACP,WACA,YACA,UACiB;AACjB,SAAO;AAAA,IACL,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,SAAS,EAAC,KAAK,CAAC,EAAE,EAAC,CAAC;AAAA,IAC7B;AAAA,IACA,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,SAAS,EAAC,KAAK,CAAC,EAAE,EAAC,CAAC;AAAA,IAC7B;AAAA,IACA,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,SAAS,EAAC,KAAK,CAAC,EAAE,EAAC,CAAC;AAAA,IAC7B;AAAA,IACA,QAAQ,CAAC,OAAoB;AAC3B,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT;AACA,aAAO,SAAS,EAAC,KAAK,CAAC,EAAE,EAAC,CAAC;AAAA,IAC7B;AAAA,EACF;AACF;AAMO,SAAS,oBACd,WACA,QACA,KACiB;AACjB,QAAM,EAAC,WAAU,IAAI,OAAO,OAAO,SAAS;AAC5C,SAAO;AAAA,IACL,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,KAAK,EAAE;AACX,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,KAAK,EAAE;AACX,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,CAAC,UAA0B;AACjC,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAI,KAAK,EAAE;AACX,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,CAAC,OAAoB;AAC3B,YAAM,KAAe;AAAA,QACnB,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,QACA,OAAO;AAAA,MACT;AACA,UAAI,KAAK,EAAE;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAiBO,SAAS,gBAAgB,QAA6B;AAC3D,SAAO,eAAe,gBACpB,IACA,SACe;AACf,eAAW,MAAM,QAAQ,KAAK;AAC5B,cAAQ,GAAG,IAAI;AAAA,QACb,KAAK;AACH,gBAAM,WAAW,IAAI,IAAI,QAAQ,MAAS;AAC1C;AAAA,QACF,KAAK;AACH,gBAAM,WAAW,IAAI,IAAI,QAAQ,MAAS;AAC1C;AAAA,QACF,KAAK;AACH,gBAAM,WAAW,IAAI,IAAI,QAAQ,MAAS;AAC1C;AAAA,QACF,KAAK;AACH,gBAAM,WAAW,IAAI,IAAI,QAAQ,MAAS;AAC1C;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,4BACP,QACA,OACoB;AACpB,MAAI,KAAK;AACT,aAAW,QAAQ,OAAO,SAAS;AACjC,QAAI,GAAG,IAAI,MAAM,QAAW;AAC1B,WAAK,EAAC,GAAG,IAAI,CAAC,IAAI,GAAG,KAAI;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,WACpB,IACA,KACA,QACA,WACe;AACf,QAAM,MAAM;AAAA,IACV,IAAI;AAAA,IACJ,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B,IAAI;AAAA,EACN;AACA,MAAI,CAAE,MAAM,GAAG,IAAI,GAAG,GAAI;AACxB,UAAM,MAAM;AAAA,MACV,OAAO,OAAO,IAAI,SAAS;AAAA,MAC3B,IAAI;AAAA,IACN;AACA,UAAM,GAAG,IAAI,KAAK,GAAG;AACrB,QAAI,WAAW;AACb,WAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KAAK;AAAA,QAC5C,MAAM;AAAA,QACN,KAAK,IAAI;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,eAAsB,WACpB,IACA,KACA,QACA,WACe;AACf,QAAM,MAAM;AAAA,IACV,IAAI;AAAA,IACJ,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B,IAAI;AAAA,EACN;AACA,MAAI,MAAM,GAAG,IAAI,GAAG,GAAG;AACrB,UAAM,WAAW,IAAI,EAAC,GAAG,KAAK,IAAI,SAAQ,GAAG,QAAQ,SAAS;AAAA,EAChE,OAAO;AACL,UAAM,WAAW,IAAI,EAAC,GAAG,KAAK,IAAI,SAAQ,GAAG,QAAQ,SAAS;AAAA,EAChE;AACF;AAEA,eAAsB,WACpB,IACA,KACA,QACA,WACe;AACf,QAAM,MAAM;AAAA,IACV,IAAI;AAAA,IACJ,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B,IAAI;AAAA,EACN;AACA,QAAM,OAAO,MAAM,GAAG,IAAI,GAAG;AAC7B,MAAI,SAAS,QAAW;AACtB;AAAA,EACF;AACA,QAAM,SAAS,IAAI;AACnB,QAAM,OAAO,EAAC,GAAI,KAA2B;AAC7C,aAAW,KAAK,QAAQ;AACtB,QAAI,OAAO,CAAC,MAAM,QAAW;AAC3B,WAAK,CAAC,IAAI,OAAO,CAAC;AAAA,IACpB;AAAA,EACF;AACA,QAAM,GAAG,IAAI,KAAK,IAAI;AACtB,MAAI,WAAW;AACb,SAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KAAK;AAAA,MAC5C,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACF;AAEA,eAAsB,WACpB,IACA,KACA,QACA,WACe;AACf,QAAM,MAAM;AAAA,IACV,IAAI;AAAA,IACJ,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,IAC7B,IAAI;AAAA,EACN;AACA,QAAM,OAAO,MAAM,GAAG,IAAI,GAAG;AAC7B,MAAI,SAAS,QAAW;AACtB;AAAA,EACF;AACA,QAAM,GAAG,IAAI,GAAG;AAChB,MAAI,WAAW;AACb,SAAK,UAAU,UAAU,IAAI,SAAS,CAAC,EAAE,KAAK;AAAA,MAC5C,MAAM;AAAA,MACN,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACF;;;AC7QO,IAAM,kBAAN,MAAwE;AAAA,EAC7E,YAAY,IAAoB,OAAyB,QAAW;AAClE,UAAM,cAAc;AACpB,SAAK,MAAM,WAAW,aAAa,MAAM,WAAW,QAAQ;AAC5D,SAAK,WAAW,MAAM;AACtB,SAAK,aAAa,MAAM;AACxB,SAAK,SAAS,MAAM,WAAW,YAAY,eAAe;AAC1D,UAAM,SAAS;AAAA,MACb,YAAY,QAAQ;AAAA,MACpB;AAAA,IACF;AACA,SAAK,SAAS;AAAA,MACZ;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AACA,SAAK,QAAQ;AAAA,MACX;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AACA,SAAK,QAAQ,OAAO;AAAA,EACtB;AAAA,EAES;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AACX;AAEO,SAAS,sBACd,IACA,SACA,QACA;AACA,SAAO,OACL,OACA,SACkB;AAClB,UAAM,KAAK,IAAI,gBAAgB,IAAI,OAAO,MAAM;AAChD,UAAM,QAAQ,IAAI,IAAI;AAAA,EACxB;AACF;AAEA,SAAS,eACP,QACA,IACA,WACA;AAGA,SAAO,IAAI;AAAA,IACT,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAAgD,MAAc;AAChE,YAAI,QAAQ,QAAQ;AAClB,iBAAO,OAAO,IAAI;AAAA,QACpB;AAEA,eAAO,IAAI,IAAI,cAAc,QAAQ,MAAM,IAAI,SAAS;AACxD,eAAO,OAAO,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,SAAuC;AAEpE;AAAA,IACE,SAAS,SAAS;AAAA,IAClB;AAAA,EACF;AACF;AAEA,SAAS,gBACP,IACA,QACA,WACA;AACA,QAAM,UAAU,IAAI;AAAA,IAClB;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,IACA,sBAAoB,iBAAiB;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AAEA,SAAO,IAAI;AAAA,IACT,CAAC;AAAA,IACD;AAAA,MACE,IAAI,QAA0C,MAAc;AAC1D,YAAI,QAAQ,QAAQ;AAClB,iBAAO,OAAO,IAAI;AAAA,QACpB;AAEA,eAAO,IAAI,IAAI,SAAS,SAAS,QAAQ,IAAI;AAC7C,eAAO,OAAO,IAAI;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,cACP,QACA,WACA,IACA,WACA;AACA,QAAMC,SAAQ,KAAK,OAAO,OAAO,SAAS,CAAC;AAC3C,QAAM,EAAC,WAAU,IAAIA;AACrB,SAAO;AAAA,IACL,QAAQ,CAAC,UACP;AAAA,MACE;AAAA,MACA,EAAC,IAAI,UAAU,WAAW,YAAY,MAAK;AAAA,MAC3C;AAAA,MACA;AAAA,IACF;AAAA,IACF,QAAQ,CAAC,UACP;AAAA,MACE;AAAA,MACA,EAAC,IAAI,UAAU,WAAW,YAAY,MAAK;AAAA,MAC3C;AAAA,MACA;AAAA,IACF;AAAA,IACF,QAAQ,CAAC,UACP;AAAA,MACE;AAAA,MACA,EAAC,IAAI,UAAU,WAAW,YAAY,MAAK;AAAA,MAC3C;AAAA,MACA;AAAA,IACF;AAAA,IACF,QAAQ,CAAC,OACP;AAAA,MACE;AAAA,MACA,EAAC,IAAI,UAAU,WAAW,YAAY,OAAO,GAAE;AAAA,MAC/C;AAAA,MACA;AAAA,IACF;AAAA,EACJ;AACF;;;ACrNO,IAAM,uBAAN,MAA2B;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YACEC,OACA,UACA,IACA,eACA;AACA,SAAK,QAAQA;AACb,SAAK,YAAY;AACjB,SAAK,MAAM;AACX,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,iBAAiB,gBAA+C;AACpE,SAAK,IAAI,QAAQ,gCAAgC,cAAc;AAC/D,UAAM,gBAAgB,MAAM,KAAK;AACjC,SAAK,MAAM;AAAA,MACT;AAAA,MACA;AAAA,QACE,WAAW,eACR,OAAO,QAAM,GAAG,kBAAkB,aAAa,EAC/C,IAAI,QAAM,GAAG,QAAQ;AAAA,MAC1B;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,6BAA4C;AAChD,UAAM,gBAAgB,MAAM,KAAK;AACjC,UAAM,UAAU,MAAM;AAAA,MAAS,KAAK;AAAA,MAAW,aAC7C,kBAAkB,OAAO;AAAA,IAC3B;AAGA,UAAM,YAAY,QACf,OAAO,OAAK,EAAE,kBAAkB,aAAa,EAC7C,IAAI,OAAK,EAAE,QAAQ;AAEtB,QAAI,UAAU,SAAS,GAAG;AACxB,WAAK,MAAM,CAAC,iBAAiB,EAAC,UAAS,CAAC,CAAC;AACzC,WAAK,IAAI,QAAQ,gCAAgC,OAAO;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,uBAAuB,gBAAkD;AACvE,UAAM,EAAC,YAAY,CAAC,GAAG,iBAAiB,CAAC,EAAC,IAAI;AAC9C,QAAI,UAAU,SAAS,KAAK,eAAe,SAAS,GAAG;AAGrD,aAAO,UAAU,KAAK,WAAW,OAAM,aAAY;AACjD,aAAK,IAAI,QAAQ,2BAA2B,WAAW,cAAc;AACrE,cAAM,sBAAsB,UAAU,WAAW,cAAc;AAAA,MACjE,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,oBAA6C;AACjD,UAAM,iBAAiB,MAAM;AAAA,MAAS,KAAK;AAAA,MAAW,UACpD,kBAAkB,IAAI;AAAA,IACxB;AACA,UAAM,gBAAgB,MAAM,KAAK;AACjC,WAAO,eAAe,OAAO,OAAK,EAAE,kBAAkB,aAAa;AAAA,EACrE;AACF;;;AC1GA,IAAM,qBACJ;AAGF,IAAM,8BAA8B;AAE7B,IAAM,4BAA4B,IAAI;AAAA,EAC3C,IAAI,mBAAmB,MAAM,IAAI,4BAA4B,MAAM;AACrE;AAEO,SAAS,sBACd,QACA,kBAAkB,MACT;AACT,MAAI,CAAC,iBAAiB;AACpB,WAAO;AAAA,EACT;AACA,QAAM,YAAY,WAAW,OAAO,OAAO,IAAI,IAAI,MAAM;AACzD,QAAM,iBAAiB,WAAW;AAIlC,SACE,WAAW,QACX,mBAAmB,UACnB,mBAAmB,eACnB,CAAC,0BAA0B,KAAK,cAAc;AAElD;;;ACvBO,SAAS,WAAW,KAA2B;AACpD,SAAQ,OAAO,IAAI,MAAM,CAAC;AAC5B;AAcO,SAAS,WACd,KACA,UACG;AACH,SAAQ,OAAO,IAAI,SAAS,GAAG,IAAI,SAAS,UAAU,CAAC,IAAI;AAC7D;;;AC3BA;AAAA,EACE,cAAAC;AAAA,EACA,kBAAAC;AAAA,OAIK;;;ACNP,SAAQ,QAAAC,aAAW;AAanB,IAAM,cAAc,IAAI;AAAA,EACtB;AACF;AAGO,IAAM,4BAA4B;AAClC,IAAM,wBAAwB;AACrC,IAAM,kBAAkB,IAAI,OAAO;AACnC,IAAM,sBAAsB;AAKrB,IAAM,kBAAkB,kBAAkB;AAE1C,IAAM,iBAAN,MAAwC;AAAA,EAC7C,YAAuB,CAAC;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,WAA8C;AAAA,EAC9C,aAAa,IAAIA,MAAK;AAAA,EAEtB,YAAY,SAAgC;AAC1C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAAC;AAAA,MACA,WAAW;AAAA,MACX,SAAS,UAAU;AAAA,IACrB,IAAI;AAEJ,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,QAAQ;AACb,SAAK,WAAWA;AAChB,SAAK,YAAY;AACjB,SAAK,WAAW,QAAQ,SAAS;AAAA,EACnC;AAAA,EAEA,IAAI,OAAiB,YAAiC,MAAuB;AAC3E,SAAK,UAAU,KAAK,YAAY,MAAM,SAAS,KAAK,CAAC;AACrD,QAAI,UAAU,WAAW,KAAK,UAAU,WAAW,uBAAuB;AAExE,WAAK,KAAK,MAAM;AAAA,IAClB,OAAO;AACL,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EACA,cAAc;AACZ,QAAI,KAAK,UAAU;AACjB;AAAA,IACF;AAEA,SAAK,WAAW,WAAW,MAAM;AAC/B,WAAK,WAAW;AAEhB,WAAK,KAAK,MAAM;AAAA,IAClB,GAAG,KAAK,SAAS;AAAA,EACnB;AAAA,EAEA,QAAuB;AACrB,WAAO,KAAK,WAAW,SAAS,YAAY;AAC1C,YAAM,EAAC,OAAM,IAAI,KAAK;AACtB,UAAI,WAAW,GAAG;AAChB;AAAA,MACF;AACA,SAAG;AACD,cAAM,YAAY,KAAK,IAAI;AAC3B,cAAM,cAAc,CAAC;AACrB,YAAI,aAAa;AAEjB,mBAAW,KAAK,KAAK,WAAW;AAK9B,YAAE,eAAe,YAAY,EAAE;AAE/B,cAAI,MAAM,KAAK,UAAU,CAAC;AAC1B,cAAI,IAAI,SAAS,iBAAiB;AAGhC,cAAE,UAAU,8BAA8B,IAAI,MAAM;AACpD,kBAAM,KAAK,UAAU,CAAC;AAAA,UACxB;AAEA,cAAI,IAAI,SAAS,aAAa,YAAY,SAAS,iBAAiB;AAClE;AAAA,UACF;AACA,wBAAc,IAAI;AAClB,sBAAY,KAAK,GAAG;AAEpB,cAAI,YAAY,WAAW,2BAA2B;AACpD;AAAA,UACF;AAAA,QACF;AAEA,cAAM,OAAO,YAAY,KAAK,IAAI;AAClC,cAAM,MAAM,IAAI,IAAI,KAAK,QAAQ;AACjC,YAAI,KAAK,YAAY,QAAW;AAC9B,cAAI,aAAa,IAAI,cAAc,KAAK,OAAO;AAAA,QACjD;AAEA,YAAI,KAAK,SAAS;AAGhB,cAAI,aAAa,IAAI,YAAY,KAAK,OAAO;AAC7C,cAAI,aAAa,IAAI,iBAAiB,KAAK,OAAO;AAAA,QACpD;AAEA,YAAI,KAAK,UAAU;AACjB,cAAI,aAAa,IAAI,WAAW,KAAK,QAAQ;AAAA,QAC/C;AAEA,YAAI,KAAK,OAAO;AACd,cAAI,aAAa,IAAI,QAAQ,KAAK,KAAK;AAAA,QACzC;AAEA,YAAI,KAAK,UAAU;AACjB,cAAI,aAAa,IAAI,UAAU,WAAW,KAAK,QAAQ,EAAE;AAAA,QAC3D;AAEA,YAAI,KAAK;AACT,YAAI;AACF,gBAAM,WAAW,MAAM,MAAM,IAAI,SAAS,GAAG;AAAA,YAC3C,QAAQ;AAAA,YACR;AAAA,YACA,WAAW;AAAA,UACb,CAAgB;AAEhB,eAAK,SAAS;AACd,cAAI,CAAC,IAAI;AAGP,oBAAQ;AAAA,cACN;AAAA,cACA,SAAS;AAAA,cACT,SAAS;AAAA,cACT,MAAM,SAAS;AAAA,YACjB;AAAA,UACF;AAAA,QACF,SAAS,GAAG;AAGV,kBAAQ,MAAM,+BAA+B,CAAC;AAAA,QAChD;AAEA,YAAI,IAAI;AAEN,eAAK,UAAU,OAAO,GAAG,YAAY,MAAM;AAAA,QAC7C,OAAO;AACL,cAAI,wBAAwB;AAC5B,mBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,kBAAM,IAAI,KAAK,UAAU,CAAC;AAC1B,cAAE,mBAAmB,EAAE,mBAAmB,KAAK;AAC/C,gBAAI,EAAE,kBAAkB,qBAAqB;AAC3C;AAAA,YACF;AAAA,UACF;AACA,cAAI,wBAAwB,GAAG;AAE7B,oBAAQ;AAAA,cACN,YAAY,qBAAqB,8CAC/B,sBAAsB,CACxB;AAAA,YACF;AAEA,iBAAK,UAAU,OAAO,GAAG,qBAAqB;AAAA,UAChD;AAAA,QACF;AAAA,MACF,SAAS,KAAK,UAAU,UAAU;AAElC,UAAI,KAAK,UAAU,QAAQ;AACzB,aAAK,YAAY;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAWA,SAAS,eAAe,SAA2B;AACjD,MAAI,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAAG;AAClD,WAAO,eAAe,QAAQ,CAAC,CAAC;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,aAAa,GAIpB;AACA,SAAO;AAAA,IACL,MAAM,EAAE;AAAA,IACR,SAAS,EAAE;AAAA,IACX,OAAO,EAAE;AAAA,EACX;AACF;AAEA,SAAS,cAAc,SAA2B;AAChD,MAAI,mBAAmB,OAAO;AAC5B,WAAO,aAAa,OAAO;AAAA,EAC7B;AACA,MAAI,mBAAmB,OAAO;AAC5B,UAAM,mBAA8B,CAAC;AACrC,eAAW,QAAQ,SAAS;AAC1B,UAAI,gBAAgB,OAAO;AACzB,yBAAiB,KAAK,aAAa,IAAI,CAAC;AAAA,MAC1C,OAAO;AACL,yBAAiB,KAAK,IAAI;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,IAAM,6BAA6B;AACnC,IAAM,iCAAiC;AAGvC,IAAM,sBAAsB;AAO5B,IAAM,gBAAuC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AACF;AAEA,SAAS,YACP,SACA,SACA,UACS;AACT,MAAI,cAAc;AAClB,MAAI,YAAY,QAAW;AACzB,eAAW,eAAe,eAAe;AACvC,UAAI,OAAO,OAAO,SAAS,WAAW,GAAG;AACvC,YAAI,gBAAgB,QAAW;AAC7B,wBAAc,EAAC,GAAG,QAAO;AAAA,QAC3B;AACA,oBAAY,sBAAsB,WAAW,IAC3C,YAAY,WAAW;AACzB,eAAO,YAAY,WAAW;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AACA,QAAM,MAAe;AAAA,IACnB,GAAI,eAAe;AAAA,IACnB,MAAM,KAAK,IAAI;AAAA,IACf,SAAS,cAAc,eAAe,OAAO,CAAC;AAAA,IAC9C,QAAQ;AAAA,EACV;AACA,MAAI,aAAa,SAAS;AACxB,QAAI,QAAQ,EAAC,QAAQ,SAAQ;AAAA,EAC/B;AACA,SAAO;AACT;;;AClSO,IAAMC,WAAU;;;AFGvB,IAAM,qBAAN,MAA4C;AAAA,EACjC;AAAA,EACA;AAAA,EAET,YAAY,gBAAyB,OAAiB;AACpD,SAAK,kBAAkB;AACvB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,OAAiB,YAAiC,MAAuB;AAC3E,QAAI,KAAK,WAAW,WAAW,UAAU,SAAS;AAChD;AAAA,IACF;AACA,QAAI,KAAK,WAAW,UAAU,UAAU,SAAS;AAC/C;AAAA,IACF;AACA,SAAK,gBAAgB,IAAI,OAAO,SAAS,GAAG,IAAI;AAAA,EAClD;AAAA,EAEA,MAAM,QAAQ;AACZ,UAAMC,gBAAe,QAAQ;AAAA,EAC/B;AACF;AAEA,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AAOlB,SAAS,iBACd,SAKA,uBAAoE,CAClEC,aACG,IAAI,eAAeA,QAAO,GACnB;AACZ,QAAM,EAAC,iBAAiB,QAAQ,gBAAe,IAAI;AAEnD,MAAI,CAAC,mBAAmB,WAAW,MAAM;AACvC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,SAASD;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,IAAI,MAAM;AAChC,QAAM,EAAC,SAAQ,IAAI;AACnB,QAAM,sBAAsB,SAAS,SAAS,gBAAgB,IAC1D,SACG,UAAU,GAAG,SAAS,SAAS,iBAAiB,MAAM,EACtD,YAAY,IACf;AACJ,QAAM,UAAU,IAAI,IAAI,WAAW,QAAQ,cAAc,CAAC;AAC1D,QAAM,WAAW,oBAAoB,UAAU,UAAU;AACzD,QAAM,UAAU,IAAIE,YAAW;AAAA,IAC7B,IAAI,mBAAmBF,iBAAgB,eAAe;AAAA,IACtD,IAAI;AAAA,MACF,qBAAqB;AAAA,QACnB,SAAS;AAAA,QACT,MAAM,SAAS;AAAA,QACf,SAAAG;AAAA,QACA;AAAA,MACF,CAAC;AAAA,MACD;AAAA,IACF;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;;;AG1FA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,IAAM,kBAAkB;AACxB,IAAM,mBAAmB;AACzB,IAAM,oBAAoB;AAC1B,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAC7B,IAAM,eAAe;;;ACUrB,IAAM,wBAAwB,MAAM;AAEpC,IAAM,qBAAqB;AAS3B,SAAS,yBAAyB,QAAmB;AAC1D,SAAO,GAAG,cAAc,MAAM,IAAI,YAAY,SAAS,GAAG,aAAa,OAAO,IAAI,CAAC;AACrF;AAKA,SAAS,aAAa,MAA6B;AACjD,SAAO,KACJ,MAAM,cAAc,EACpB,KAAK,GAAG,EACR,YAAY;AACjB;AAUO,SAAS,yBAAyB,QAA4B;AACnE,MAAI,CAAC,cAAc,MAAM,GAAG;AAC1B,WAAO;AAAA,EACT;AACA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,+BAAgB;AAAA,IACrB,KAAK,+BAAgB;AAAA,IACrB,KAAK,+BAAgB;AAAA,IACrB,KAAK,+BAAgB;AAAA,IACrB,KAAK,+BAAgB;AACnB,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAgBO,IAAM,gBAAN,MAAoB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,MAA4B;AACtC,SAAK,oBAAoB,KAAK;AAC9B,SAAK,QAAQ,KAAK;AAClB,SAAK,YAAY,KAAK;AACtB,SAAK,MAAM,KAAK;AAEhB,SAAK,KAAK,KAAK,UAAU,KAAK,MAAM,EAAE;AAEtC,SAAK,gBAAgB,IAAI,qBAAqB;AAC9C,SAAK,uBAAuB,MAAM;AAElC,SAAK,WAAW,YAAY,MAAM;AAChC,WAAK,KAAK,MAAM;AAAA,IAClB,GAAG,KAAK,iBAAiB;AAAA,EAC3B;AAAA,EAEA,WAAwB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBhB,kBAAkB,KAAK;AAAA,IAC9B,IAAI,MAAM,yBAAW,eAAe;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,mBAAmB,KAAK;AAAA,IAC/B,IAAI;AAAA,MACF,yBAAW;AAAA,MACX;AAAA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAIS,gBAAgB,KAAK,UAAU,IAAI,MAAM,yBAAW,YAAY,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOjE,qBAAqB,KAAK;AAAA,IACjC,IAAI,MAAM,yBAAW,iBAAiB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMS,sBAAsB,KAAK;AAAA,IAClC,IAAI,MAAM,yBAAW,kBAAkB;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQS,wBAAwB,KAAK;AAAA,IACpC,IAAI,MAAM,yBAAW,oBAAoB;AAAA,EAC3C;AAAA,EAEA,uBAAuB,QAA4B;AACjD,SAAK,cAAc,IAAI,MAAM;AAAA,EAC/B;AAAA,EAEA,aAAa,iBAAyB,sBAA8B;AAClE,SAAK,cAAc,MAAM;AACzB,SAAK,oBAAoB,MAAM;AAC/B,SAAK,mBAAmB,IAAI,eAAe;AAC3C,SAAK,sBAAsB,IAAI,oBAAoB;AAAA,EACrD;AAAA,EAEA,mCAAmC;AACjC,SAAK,mBAAmB,MAAM;AAC9B,SAAK,sBAAsB,MAAM;AACjC,SAAK,oBAAoB,MAAM;AAC/B,QAAI;AACJ,YAAQ,KAAK,cAAc,IAAI,GAAG;AAAA,MAChC,KAAK;AACH,6BAAqB;AACrB;AAAA,MACF,KAAK;AACH,6BAAqB;AACrB;AAAA,MACF;AACE,6BAAqB;AACrB;AAAA,IACJ;AACA,SAAK,uBAAuB,kBAAkB;AAAA,EAChD;AAAA,EAEA,gBAAgB,QAAmB;AACjC,SAAK,mBAAmB,MAAM;AAC9B,SAAK,sBAAsB,MAAM;AACjC,SAAK,uBAAuB,OAAO;AACnC,SAAK,oBAAoB,IAAI,yBAAyB,MAAM,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKS,OAAiB,CAAC;AAAA;AAAA;AAAA,EAI3B,MAAM,QAAQ;AACZ,UAAM,KAAK,KAAK;AAChB,QAAI,KAAK,aAAa,MAAM;AAC1B,SAAG,QAAQ,kDAAkD;AAC7D;AAAA,IACF;AACA,UAAM,YAAsB,CAAC;AAC7B,eAAW,UAAU,KAAK,UAAU;AAClC,YAAM,SAAS,OAAO,MAAM;AAC5B,UAAI,WAAW,QAAW;AACxB,kBAAU,KAAK;AAAA,UACb,GAAG;AAAA,UACH,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,UAAU,WAAW,GAAG;AAC1B,UAAI,QAAQ,sBAAsB;AAClC;AAAA,IACF;AACA,QAAI;AACF,YAAM,KAAK,UAAU,SAAS;AAAA,IAChC,SAAS,GAAG;AACV,UAAI,QAAQ,2BAA2B,CAAC;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,OAAO;AACL,QAAI,KAAK,aAAa,MAAM;AAC1B,WAAK,IAAI,QAAQ,iDAAiD;AAClE;AAAA,IACF;AACA,kBAAc,KAAK,QAAQ;AAC3B,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,UAA+B,QAAW;AACxC,SAAK,SAAS,KAAK,MAAM;AACzB,WAAO;AAAA,EACT;AACF;AAqBA,SAAS,UAAU,IAAY,OAAsB;AACnD,SAAO,CAAC,IAAI,CAAC,KAAK,CAAC;AACrB;AAoBO,IAAM,QAAN,MAAiC;AAAA,EAC7B;AAAA,EACT,SAA6B;AAAA,EAE7B,YAAY,MAAc;AACxB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,IAAI,OAAe;AACjB,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM;AACJ,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ;AACN,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,WAAW,QAAW;AAC7B,aAAO;AAAA,IACT;AAGA,UAAM,SAAS,CAAC,UAAU,EAAE,GAAG,KAAK,MAAM,CAAC;AAC3C,WAAO,EAAC,QAAQ,KAAK,OAAO,OAAM;AAAA,EACpC;AACF;AAEA,SAAS,IAAI;AACX,SAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACrC;AAeO,IAAM,QAAN,MAAiC;AAAA,EAC7B;AAAA,EACA;AAAA,EACT,WAA+B;AAAA,EAE/B,YAAY,QAAgB,eAAe,OAAO;AAChD,SAAK,UAAU;AACf,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,IAAI,OAAe;AACjB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAM;AACJ,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ;AACN,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,QAAQ;AACN,QAAI,KAAK,aAAa,QAAW;AAC/B,aAAO;AAAA,IACT;AACA,UAAM,QAAQ,IAAI,MAAM,CAAC,KAAK,SAAS,KAAK,QAAQ,EAAE,KAAK,GAAG,CAAC;AAC/D,UAAM,IAAI,CAAC;AACX,UAAM,SAAS,MAAM,MAAM;AAC3B,QAAI,KAAK,eAAe;AACtB,WAAK,MAAM;AAAA,IACb;AACA,WAAO;AAAA,EACT;AACF;;;AC1XA,SAAQ,YAAAC,kBAA8B;AAsCtC,IAAI,qBAAqB;AACzB,SAAS,kBAA+B;AACtC,SAAO,EAAE;AACX;AAKO,IAAM,kBAAN,MAAsB;AAAA,EAClB;AAAA,EAOA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,IACA,cACA,cACA;AACA,SAAK,MAAM,GAAG,YAAY,iBAAiB;AAC3C,SAAK,wBAAwB,oBAAI,IAAI;AACrC,SAAK,4BAA4B,oBAAI,IAAI;AACzC,SAAK,gCAAgC,oBAAI,IAAI;AAC7C,SAAK,gCAAgC;AACrC,SAAK,qBAAqB;AAC1B,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,oBACE,UACA,mBACA;AACA,WAAO,KAAK,cAAc,QAAW,sBAAsB;AAC3D,SAAK,YAAY;AACjB;AAAA,MACE,WAAS;AACP,aAAK,0BAA0B,KAAK;AAAA,MACtC;AAAA,MACA;AAAA,QACE,QAAQ,uBAAuB,WAAW;AAAA,QAC1C,0BAA0B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,gBAAsC;AACpC,UAAM,KAAK,gBAAgB;AAC3B,UAAM,mBAAmBC,WAAgC;AAEzD,SAAK,sBAAsB,IAAI,IAAI;AAAA,MACjC,UAAU;AAAA,IACZ,CAAC;AACD,WAAO,EAAC,aAAa,IAAI,eAAe,iBAAiB,QAAO;AAAA,EAClE;AAAA,EAEA,mBAAmB,IAAiB,YAA0B;AAC5D,UAAM,QAAQ,KAAK,sBAAsB,IAAI,EAAE;AAC/C,QAAI,OAAO;AACT,YAAM,aAAa;AACnB,WAAK,0BAA0B,IAAI,YAAY,EAAE;AACjD,WAAK,gCAAgC,KAAK;AAAA,QACxC,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAe,IAAiB,GAAkB;AAChD,UAAM,QAAQ,KAAK,sBAAsB,IAAI,EAAE;AAC/C,QAAI,OAAO;AACT,WAAK,gBAAgB,IAAI,OAAO,UAAU,yBAAyB,CAAC,CAAC;AAAA,IACvE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,0BAA0B,OAA0B;AAClD,UAAM,WAAW,KAAK,KAAK,SAAS;AACpC,QAAI,cAAc;AAClB,eAAWC,SAAQ,OAAO;AACxB,YAAM,aAAa;AAAA,QACjBA,MAAK,IAAI,MAAM,qBAAqB,SAAS,SAAS,SAAS,CAAC;AAAA,MAClE;AACA;AAAA,QACE,CAAC,MAAM,UAAU;AAAA,QACjB,gEAAgEA,MAAK,GAAG;AAAA,MAC1E;AACA,oBAAc,KAAK,IAAI,aAAa,UAAU;AAC9C,cAAQA,MAAK,IAAI;AAAA,QACf,KAAK,OAAO;AACV,gBAAM,SAAW,MAAMA,MAAK,UAAU,oBAAoB;AAC1D,cAAI,WAAW,QAAQ;AACrB,iBAAK,sBAAsB,UAAU,YAAY,MAAM;AAAA,UACzD,OAAO;AACL,iBAAK,mBAAmB,UAAU,YAAY,MAAM;AAAA,UACtD;AACA;AAAA,QACF;AAAA,QACA,KAAK;AACH;AAAA,QACF,KAAK;AACH,gBAAM,IAAI,MAAM,mDAAmD;AAAA,MACvE;AAAA,IACF;AAEA,QAAI,cAAc,GAAG;AACnB,WAAK,cAAc;AAAA,QACjB,UAAU,KAAK,KAAK,SAAS;AAAA,QAC7B,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,oBAAoB,UAAkC;AACpD,QAAI,WAAW,UAAU;AACvB,WAAK,IAAI;AAAA,QACP;AAAA,QACA;AAAA,MACF;AACA,YAAM,aAAa,KAAK,yBAAyB,QAAQ;AACzD,UAAI,YAAY;AACd,aAAK,cAAc,UAAU;AAAA,MAC/B;AAAA,IACF,OAAO;AACL,WAAK,eAAe,QAAQ;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,yBAAyB,OAAyC;AAChE,YAAQ,MAAM,OAAO;AAAA,MACnB,KAAK;AACH,eAAO,IAAI,cAAc;AAAA,UACvB,MAAM,wBAAU;AAAA,UAChB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,0BAAY;AAAA,UACpB,SAAS;AAAA,UACT,aAAa,CAAC;AAAA,QAChB,CAAC;AAAA,MACH,KAAK;AACH,eAAO,IAAI,cAAc;AAAA,UACvB,MAAM,wBAAU;AAAA,UAChB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,0BAAY;AAAA,UACpB,SAAS;AAAA,UACT,aAAa,CAAC;AAAA,QAChB,CAAC;AAAA,MACH,KAAK;AACH,eAAO,IAAI,cAAc;AAAA,UACvB,MAAM,wBAAU;AAAA,UAChB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,MAAM;AAAA,UACd,SAAS,gDAAgD,MAAM,MAAM,KAAK,MAAM,WAAW,SAAS;AAAA,UACpG,aAAa,CAAC;AAAA,QAChB,CAAC;AAAA,MACH,KAAK;AACH,eAAO,IAAI,cAAc;AAAA,UACvB,MAAM,wBAAU;AAAA,UAChB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,0BAAY;AAAA,UACpB,SAAS,qBAAqB,MAAM,WAAW,SAAS;AAAA,UACxD,aAAa,CAAC;AAAA,QAChB,CAAC;AAAA,MACH;AACE,oBAAY,KAAK;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA,YAAY,gBAAwB;AAClC,SAAK,aAAa,cAAc;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAa,gBAA8B;AACzC;AAAA,MACE,kBAAkB,KAAK;AAAA,MACvB;AAAA,IACF;AACA,QAAI,mBAAmB,KAAK,oBAAoB;AAC9C;AAAA,IACF;AAEA,QAAI;AACF,WAAK,qBAAqB;AAC1B,WAAK,kBAAkB,cAAc;AAAA,IACvC,UAAE;AACA,UAAI,kBAAkB,KAAK,+BAA+B;AAExD,aAAK,oCAAoC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,IAAI,OAAO;AACT,WAAO,KAAK,sBAAsB;AAAA,EACpC;AAAA,EAEA,kBAAkB,MAAoB;AAGpC,eAAW,CAAC,IAAI,KAAK,KAAK,KAAK,uBAAuB;AACpD,UAAI,MAAM,cAAc,MAAM,cAAc,MAAM;AAChD,aAAK,gBAAgB,IAAI,OAAO,WAAW,WAAW;AAAA,MACxD,OAAO;AACL;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,eAAe,IAAkB;AAC/B,eAAW,YAAY,GAAG,WAAW;AACnC,UAAI,WAAW,SAAS,QAAQ;AAC9B,aAAK;AAAA,UACH,SAAS,GAAG;AAAA,UACZ,SAAS,GAAG;AAAA,UACZ,SAAS;AAAA,QACX;AAAA,MACF,OAAO;AACL,aAAK;AAAA,UACH,SAAS,GAAG;AAAA,UACZ,SAAS,GAAG;AAAA,UACZ,SAAS;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,sBACE,UACA,KACA,OACM;AACN;AAAA,MACE,aAAa,KAAK;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,0BAA0B,IAAI,GAAG;AAC1D,QAAI,CAAC,eAAe,MAAM,UAAU,oBAAoB;AACtD;AAAA,IACF;AAUA;AAAA,MACE;AAAA,MACA,+CAA+C,MAAM,KAAK;AAAA,IAC5D;AAEA,UAAM,QAAQ,KAAK,sBAAsB,IAAI,WAAW;AACxD,WAAO,SAAS,MAAM,eAAe,GAAG;AACxC,SAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,UAAU,QACZ,IAAI;AAAA,QACF,MAAM,WAAW,8BAA8B,MAAM,KAAK;AAAA,QAC1D,MAAM,UAAU,EAAC,SAAS,MAAM,QAAO,IAAI;AAAA,MAC7C,IACA,IAAI;AAAA,QACF,MAAM,UAAU,qBACZ,+BACA,MAAM,UAAU,gBACd,6CACA,2CAA2C,GAAG,KAAK,MAAM,KAAK;AAAA,MACtE;AAAA,IACN;AAGA,QAAI,MAAM,UAAU,eAAe;AACjC,WAAK;AAAA,QACH,IAAI,cAAc;AAAA,UAChB,MAAM,wBAAU;AAAA,UAChB,QAAQ,0BAAY;AAAA,UACpB,QAAQ,0BAAY;AAAA,UACpB,SAAS;AAAA,UACT,SAAS,MAAM;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAmB,UAAkB,KAAa,QAA0B;AAC1E;AAAA,MACE,aAAa,KAAK;AAAA,MAClB;AAAA,IACF;AAEA,UAAM,cAAc,KAAK,0BAA0B,IAAI,GAAG;AAC1D;AAAA,MACE;AAAA,MACA;AAAA,IAEF;AACA,UAAM,QAAQ,KAAK,sBAAsB,IAAI,WAAW;AACxD,WAAO,SAAS,MAAM,eAAe,GAAG;AACxC,SAAK,gBAAgB,aAAa,OAAO,WAAW,MAAM;AAAA,EAC5D;AAAA,EAEA,gBACE,aACA,OAIA,MACA,QACM;AACN,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,cAAM,SAAS,QAAQ,MAAoB;AAC3C;AAAA,MACF,KAAK;AACH,cAAM,SAAS,OAAO,MAAM;AAC5B;AAAA,IACJ;AAEA,SAAK,sBAAsB,OAAO,WAAW;AAC7C,QAAI,MAAM,YAAY;AACpB,WAAK,0BAA0B,OAAO,MAAM,UAAU;AAAA,IACxD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,sBAAsB,UAA4B;AAChD,SAAK,8BAA8B,IAAI,QAAQ;AAAA,EACjD;AAAA,EAEA,sCAAsC;AACpC,eAAW,YAAY,KAAK,+BAA+B;AACzD,eAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACpXO,IAAM,eAAN,MAAgD;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAkC,oBAAI,IAAI;AAAA,EAC1C;AAAA,EACA,iBAA8B,oBAAI,IAAI;AAAA,EACtC,cAA2B,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA,uBAA2C,CAAC;AAAA,EAC5C;AAAA,EACT,mBAAsC,CAAC;AAAA,EACvC;AAAA,EACS;AAAA,EACA,WAAyB,WAAW;AAAA,EACpC,gBAA2C,oBAAI,IAAI;AAAA,EACnD;AAAA,EAET,YACE,IACA,iBACA,UACA,QACAC,OACA,mBACA,sBACA,uBACA,0BACA,cACA;AACA,SAAK,MAAM,GAAG,YAAY,cAAc;AACxC,SAAK,YAAY;AACjB,SAAK,kBAAkB,eAAe,MAAM;AAC5C,SAAK,kBAAkB,eAAe,MAAM;AAC5C,SAAK,wBAAwB;AAC7B,SAAK,QAAQA;AACb,SAAK,mBAAmB;AACxB,SAAK,yBAAyB;AAC9B,SAAK,4BAA4B;AACjC,SAAK,gBAAgB;AACrB,SAAK,iBAAiB,sBAAsB,MAAM;AAChD,UAAI,KAAK,iBAAiB,WAAW,GAAG;AACtC;AAAA,MACF;AACA,YAAM,kBAAkB,KAAK;AAC7B,WAAK,mBAAmB,CAAC;AACzB,iBAAW,WAAW,iBAAiB;AACrC,gBAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAED;AAAA,MACE,CAAAC,UAAQ;AACN,mBAAW,UAAUA,OAAM;AACzB,gBAAM,YAAY,OAAO,IAAI,UAAU,uBAAuB,MAAM;AACpE,kBAAQ,OAAO,IAAI;AAAA,YACjB,KAAK;AACH,mBAAK,YAAY,IAAI,SAAS;AAC9B,mBAAK,kBAAkB,WAAW,IAAI;AACtC;AAAA,YACF,KAAK;AACH,mBAAK,YAAY,OAAO,SAAS;AACjC,mBAAK,kBAAkB,WAAW,KAAK;AACvC;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,QACE,QAAQ;AAAA,QACR,0BAA0B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,SAAkC;AACvC,UAAM,MAAM,KAAK,SAAS,IAAI,OAAO,GAAG;AACxC,WAAO,OAAO,OAAO,KAAK,KAAK,eAAe;AAAA,EAChD;AAAA,EAEA,kBAAkB,WAAmB,KAAc;AACjD,UAAM,eAAe,KAAK,SAAS,IAAI,SAAS,GAAG,gBAAgB,CAAC;AACpE,eAAW,eAAe,cAAc;AACtC,kBAAY,GAAG;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,gBACJ,IACA,WACwC;AACxC,UAAM,sBAAsB,oBAAI,IAAY;AAC5C,UAAM,SAAS,8BAA8B,KAAK,SAAS;AAC3D,qBAAiB,OAAO,GAAG,KAAK,EAAC,OAAM,CAAC,EAAE,KAAK,GAAG;AAChD,0BAAoB,IAAI,IAAI,UAAU,OAAO,QAAQ,IAAI,MAAM,CAAC;AAAA,IAClE;AACA,UAAM,QAAuC,oBAAI,IAAI;AACrD,eAAW,QAAQ,qBAAqB;AACtC,UAAI,CAAC,KAAK,SAAS,IAAI,IAAI,GAAG;AAC5B,cAAM,IAAI,MAAM,EAAC,IAAI,OAAO,KAAI,CAAC;AAAA,MACnC;AAAA,IACF;AAEA,eAAW,CAAC,MAAM,EAAC,YAAY,KAAK,MAAM,KAAI,CAAC,KAAK,KAAK,UAAU;AACjE,UAAI,CAAC,oBAAoB,IAAI,IAAI,GAAG;AAClC,cAAM,IAAI,MAAM;AAAA,UACd,IAAI;AAAA,UACJ;AAAA,UACA,KAAK,SAAS,SAAY,aAAa;AAAA,UACvC;AAAA,UACA;AAAA;AAAA;AAAA,UAGA,KAAK,SAAS,GAAG;AAAA;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,WAAW;AAGb,iBAAW,CAAC,MAAM,EAAC,GAAE,CAAC,KAAK,WAAW;AACpC,YAAI,OAAO,SAAS,CAAC,MAAM,IAAI,IAAI,GAAG;AACpC,gBAAM,IAAI,MAAM,EAAC,IAAI,OAAO,KAAI,CAAC;AAAA,QACnC;AAAA,MACF;AAEA,iBAAW,CAAC,MAAM,EAAC,GAAE,CAAC,KAAK,OAAO;AAChC,cAAM,cAAc,UAAU,IAAI,IAAI;AACtC,YAAI,eAAe,YAAY,OAAO,IAAI;AACxC,gBAAM,OAAO,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,sBAAsB,QAAwB;AAC5C,eAAW,SAAS,QAAQ;AAC1B,YAAM,UAAU,MAAM;AACtB,YAAM,QAAQ,KAAK,SAAS,IAAI,OAAO;AAGvC,UAAI,CAAC,OAAO;AACV;AAAA,MACF;AAEA,UAAI,MAAM,UAAU,SAAS,MAAM,UAAU,SAAS;AACpD,cAAM,aAAa,QAAQ,cAAY,SAAS,OAAO,KAAK,CAAC;AAAA,MAC/D,OAGK;AACH,aAAK;AAAA,UACH,IAAI,cAAc;AAAA,YAChB,MAAM,wBAAU;AAAA,YAChB,QAAQ,0BAAY;AAAA,YACpB,QAAQ,0BAAY;AAAA,YACpB,SAAS,uCAAuC,KAAK,UAAU,KAAK,CAAC;AAAA,YACrE,UAAU,CAAC;AAAA,UACb,CAAC;AAAA,QACH;AAAA,MAEF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UACE,KACA,EAAC,MAAM,KAAI,GACX,KACA,aACY;AACZ,UAAM,aAAa,aAAa,GAAG;AACnC,UAAM,UAAU,kBAAkB,MAAM,IAAI;AAC5C,WAAO,KAAK,KAAK,SAAS,YAAY,MAAM,MAAM,KAAK,WAAW;AAAA,EACpE;AAAA,EAEA,UAAU,KAAU,KAAU,aAAuC;AACnE,UAAM,aAAa,aAAa,GAAG;AACnC,UAAM,UAAU,UAAU,UAAU;AACpC,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,KACE,SACA,YACA,MACA,MACA,KACA,aACA;AACA;AAAA,MACG,SAAS,YAAgB,SAAS;AAAA,MACnC;AAAA,IACF;AACA,UAAM,SAAS,KAAK,KAAK,GAAG;AAC5B,QAAI,QAAQ,KAAK,SAAS,IAAI,OAAO;AACrC,SAAK,eAAe,OAAO,OAAO;AAClC,QAAI,CAAC,OAAO;AACV,mBAAa,OAAO,YAAY,KAAK,eAAe;AAEpD,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,QACP,cAAc,cAAc,CAAC,WAAW,IAAI,CAAC;AAAA,QAC7C;AAAA,MACF;AACA,WAAK,SAAS,IAAI,SAAS,KAAK;AAChC,WAAK,kBAAkB;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,KAAK,SAAS,SAAY,aAAa;AAAA,QACvC;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,QAAE,MAAM;AACR,WAAK,aAAa,OAAO,SAAS,GAAG;AAErC,UAAI,aAAa;AACf,cAAM,aAAa,KAAK,WAAW;AAAA,MACrC;AAAA,IACF;AAEA,QAAI,aAAa;AACf,kBAAY,KAAK,YAAY,IAAI,OAAO,CAAC;AAAA,IAC3C;AAEA,QAAI,UAAU;AACd,UAAM,YAAY,MAAM;AACtB,UAAI,SAAS;AACX;AAAA,MACF;AACA,gBAAU;AAIV,UAAI,KAAK,iBAAiB,OAAO,GAAG;AAClC,aAAK,iBAAiB;AAAA,UAAK,MACzB,KAAK,QAAQ,OAAO,SAAS,WAAW;AAAA,QAC1C;AACA;AAAA,MACF;AAEA,WAAK,QAAQ,OAAO,SAAS,WAAW;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,EAAC,MAAM,KAAI,GAAkB,KAAU;AAClD,UAAM,UAAU,kBAAkB,MAAM,IAAI;AAC5C,UAAM,QAAQ,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC;AAC7C,SAAK,aAAa,OAAO,SAAS,GAAG;AAAA,EACvC;AAAA,EAEA,aAAa,KAAU,KAAU;AAC/B,UAAM,aAAa,aAAa,GAAG;AACnC,UAAM,UAAU,UAAU,UAAU;AACpC,UAAM,QAAQ,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC;AAC7C,SAAK,aAAa,OAAO,SAAS,GAAG;AAAA,EACvC;AAAA,EAEA,aAAa,OAAc,SAAiB,KAAgB;AAG1D,UAAM,SAAS,KAAK,KAAK,GAAG;AAC5B,QAAI,WAAW,KAAK,MAAM,GAAG,IAAI,GAAG;AAClC,YAAM,MAAM;AACZ,WAAK,kBAAkB;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,KAAK,MAAM,SAAS,SAAY,MAAM,aAAa;AAAA,QACnD,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,kBAAkB,IAAsB;AACtC,SAAK,qBAAqB,KAAK,EAAE;AACjC,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,iBAAiB;AACf,QAAI,KAAK,gBAAgB,QAAW;AAClC,WAAK,cAAc;AAAA,QACjB,MAAM,KAAK,WAAW;AAAA,QACtB,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAa;AACX,QAAI,KAAK,gBAAgB,QAAW;AAClC,mBAAa,KAAK,WAAW;AAC7B,WAAK,cAAc;AAAA,IACrB;AACA,QAAI,KAAK,qBAAqB,SAAS,GAAG;AACxC,WAAK,MAAM;AAAA,QACT;AAAA,QACA;AAAA,UACE,qBAAqB,CAAC,GAAG,KAAK,oBAAoB;AAAA,QACpD;AAAA,MACF,CAAC;AACD,WAAK,qBAAqB,SAAS;AAAA,IACrC;AAAA,EACF;AAAA,EAEA,QAAQ,OAAc,SAAiB,aAAsC;AAC3E,QAAI,aAAa;AACf,YAAM,QAAQ,MAAM,aAAa,QAAQ,WAAW;AACpD,YAAM,aAAa,OAAO,OAAO,CAAC;AAAA,IACpC;AACA,MAAE,MAAM;AACR,QAAI,MAAM,UAAU,GAAG;AACrB,WAAK,eAAe,IAAI,OAAO;AAC/B,UAAI,KAAK,eAAe,OAAO,KAAK,uBAAuB;AACzD,cAAM,aAAa,KAAK,eAAe,OAAO,EAAE,KAAK,EAAE;AACvD,eAAO,UAAU;AACjB,aAAK,SAAS,OAAO,UAAU;AAC/B,aAAK,eAAe,OAAO,UAAU;AACrC,aAAK,cAAc,OAAO,UAAU;AACpC,aAAK,kBAAkB,EAAC,IAAI,OAAO,MAAM,WAAU,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAwB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,UACE,QACA,UACG,MACG;AAGN;AAIA,SAAK,SAAS,MAAM,EAAE,IAAI,KAAK;AAE/B,UAAM,UAAU,KAAK,CAAC;AAGtB,QAAI,WAAW,oCAAoC;AACjD,YAAM,MAAM,KAAK,CAAC;AAElB,UACE,KAAK,8BAA8B,UACnC,QAAQ,KAAK,2BACb;AACA,aAAK,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AACL,aAAK,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,WAAW,KAAK,cAAc,IAAI,OAAO;AAC7C,QAAI,CAAC,UAAU;AACb,iBAAW,WAAW;AACtB,WAAK,cAAc,IAAI,SAAS,QAAQ;AAAA,IAC1C;AACA,aAAS,MAAM,EAAE,IAAI,KAAK;AAAA,EAC5B;AAAA,EAEA,gBAAgB,SAA2C;AACzD,WAAO,KAAK,cAAc,IAAI,OAAO;AAAA,EACvC;AACF;AAEA,SAAS,aAA2B;AAClC,SAAO;AAAA,IACL,gCAAgC,IAAI,QAAQ;AAAA,IAC5C,oCAAoC,IAAI,QAAQ;AAAA,IAChD,uBAAuB,IAAI,QAAQ;AAAA,EACrC;AACF;;;AC3NO,IAAM,+BACT;AAAA,EACA,uCAAuB;AAAA,EACvB,uCAAuB;AAAA,EACvB,uCAAuB;AACzB;;;ACrQK,IAAM,4BAA4B;AAClC,IAAM,2BAA2B;AAExC,IAAM,qBAAuB,qBAAM;AAAA,EAC/B,qBAAM,8BAA8B,eAAe;AAAA,EACnD,sBAAO;AACX,CAAC;AAED,IAAM,qBAAuB,sBAAO;AAAA,EAClC,gBAAkB,sBAAO,EAAE,QAAQ,CAAC;AAAA,EACpC,gBAAkB,sBAAO,EAAE,QAAQ,CAAC;AACtC,CAAC;AAIM,IAAM,yBAAyB;AAC/B,IAAM,yBAAyB;AAG/B,IAAM,8BAA8B;AAE3C,IAAI,cAAoD;AAIjD,SAAS,iBACd,IACAC,SACA,QACA,SACA;AACA,MAAI,aAAa;AACf,OAAG,OAAO,gCAAgC;AAC1C;AAAA,EACF;AACA,QAAM,MAAM,KAAK,IAAI;AACrB,QAAM,UAAU,YAAY,IAAI,GAAG;AAGnC,MAAI,OAAO,mBAAmB,aAAa;AACzC,mBAAe,QAAQ,0BAA0B,KAAK,UAAU,OAAO,CAAC;AACxE,mBAAe;AAAA,MACb;AAAA,MACA,KAAK,UAAU,CAAC,QAAQ,OAAO,CAAC;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,QAAQ,QAAQ,iBAAiB;AACvC,KAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,IAAI,MAAM,QAAQ,GAAI,aAAa;AAAA,EAC7C;AACA,gBAAc,WAAW,MAAM;AAC7B,kBAAc;AACd,IAAAA,QAAO;AAAA,EACT,GAAG,KAAK;AACV;AAEO,SAAS,mBAAmB,IAAoB;AACrD,MAAI,OAAO,mBAAmB,aAAa;AACzC,UAAM,QAAQ,eAAe,QAAQ,yBAAyB;AAC9D,QAAI,OAAO;AACT,qBAAe,WAAW,yBAAyB;AACnD,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,KAAK;AAC/B,cAAM,CAAC,YAAY,OAAO,IAAM,MAAM,QAAQ,kBAAkB;AAChE,WAAG,QAAQ,YAAY,2BAA2B,OAAO;AAAA,MAC3D,SAAS,GAAG;AACV,WAAG,QAAQ,2BAA2B,CAAC;AAEvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAGO,SAAS,kBAAkB;AAChC,SAAO,gBAAgB;AACzB;AAGO,SAAS,eAAe;AAC7B,MAAI,OAAO,mBAAmB,aAAa;AACzC,mBAAe,WAAW,wBAAwB;AAAA,EACpD;AACF;AAEA,SAAS,YAAY,IAAoB,KAA2B;AAClE,MAAI,OAAO,mBAAmB,aAAa;AACzC,OAAG;AAAA,MACD,gDACE,8BAA8B,GAChC;AAAA,IACF;AACA,WAAO;AAAA,MACL,gBAAgB,MAAM;AAAA,MACtB,gBAAgB;AAAA,IAClB;AAAA,EACF;AACA,QAAM,MAAM,eAAe,QAAQ,wBAAwB;AAC3D,MAAI,CAAC,KAAK;AACR,WAAO,EAAC,gBAAgB,KAAK,gBAAgB,uBAAsB;AAAA,EACrE;AACA,MAAI;AACJ,MAAI;AACF,aAAW,MAAM,KAAK,MAAM,GAAG,GAAG,oBAAoB,aAAa;AAAA,EACrE,SAAS,GAAG;AACV,OAAG,OAAO,qCAAqC,KAAK,CAAC;AACrD,WAAO,EAAC,gBAAgB,KAAK,gBAAgB,uBAAsB;AAAA,EACrE;AACA,QAAM,EAAC,gBAAgB,eAAc,IAAI;AAGzC,MAAI,MAAM,iBAAiB,yBAAyB,GAAG;AACrD,WAAO,EAAC,gBAAgB,KAAK,gBAAgB,uBAAsB;AAAA,EACrE;AACA,MAAI,MAAM,gBAAgB;AAExB,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,KAAK,IAAI,KAAK,iBAAiB,cAAc;AACpE,SAAO;AAAA,IACL,gBAAgB;AAAA,IAChB,gBAAgB,KAAK,IAAI,iBAAiB,GAAG,sBAAsB;AAAA,EACrE;AACF;;;ACpIA,SAAS,oBAAoB,WAAmB,QAA4B;AAC1E,QAAM,mBAAmB;AACzB,QAAM,aAAa,CAAC,OAAe,OACjC,kBAAkB,gBAAgB,4BAA4B,IAAI;AAEpE,MACE,CAAC,OAAO,WAAW,GAAG,gBAAgB,KAAK,KAC3C,CAAC,OAAO,WAAW,GAAG,gBAAgB,MAAM,GAC5C;AACA,UAAM,IAAI;AAAA,MACR,eAAe,SAAS,kBAAkB,gBAAgB,SAAS,gBAAgB;AAAA,IACrF;AAAA,EACF;AACA,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,MAAM;AAAA,EACtB,QAAQ;AACN,UAAM,IAAI;AAAA,MACR,eAAe,SAAS,wBAAwB,WAAW,CAAC;AAAA,IAC9D;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,SAAS;AAE/B,QAAM,iBAAiB,IAAI,SAAS,MAAM,GAAG;AAC7C,MAAI,eAAe,CAAC,MAAM,IAAI;AAC5B,mBAAe,MAAM;AAAA,EACvB;AACA,MAAI,eAAe,eAAe,SAAS,CAAC,MAAM,IAAI;AACpD,mBAAe,IAAI;AAAA,EACrB;AACA,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,IAAI;AAAA,MACR,eAAe,SAAS,wCAAwC;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW,CAAC,UAAU,eAAe,KAAK;AAAA,IACxC,CAAC,UAAU,GAAG;AAAA,IACd,CAAC,QAAQ,GAAG;AAAA,EACd,GAAY;AACV,QAAI,IAAI,QAAQ,KAAK,UAAU,SAAS,eAAe,GAAG;AACxD,YAAM,IAAI;AAAA,QACR,eAAe,SAAS,uBAAuB,QAAQ,cAAc,WAAW,CAAC;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,UACd,QACmB;AACnB,QAAM,KAAK,iBAAiB,WAAW;AACvC,MAAI,CAAC,IAAI;AAEP,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,MAAI,WAAW,UAAa,WAAW,MAAM;AAE3C,YAAQ;AAAA,MACN;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,SAAO,oBAAoB,UAAU,MAAM;AAC7C;;;AC3EA,SAAQ,cAAAC,mBAAiB;AAGlB,IAAM,iBAAiBA;;;ACH9B,SAAQ,QAAAC,aAAW;AA+CZ,IAAM,cAAN,MAAkB;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,iBAA+D;AAAA,EACtD,cAAiC,CAAC;AAAA,EAC3C,2BAA2B;AAAA,EAC3B,wBAAwB;AAAA;AAAA;AAAA,EAGf,YAAY,IAAIC,MAAK;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EAEA,OACP,uBAAuB,uBAAuB,KAAK;AAAA,EAErD,YACE,gBACA,aACA,UACA,QACA,IACA,iBACA;AACA,SAAK,kBAAkB;AACvB,SAAK,eAAe;AACpB,SAAK,YAAY;AACjB,SAAK,UAAU;AACf,SAAK,kBAAkB,eAAe,OAAO,MAAM;AACnD,SAAK,MAAM,GAAG,YAAY,aAAa;AACvC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,gBAAgB,WAA0B;AACxC,QAAI,KAAK,gBAAgB;AACvB,WAAK;AAAA,QACH,aAAa,KAAK;AAAA,UAChB;AAAA,QACF,CAAC,2BAA2B,KAAK;AAAA,UAC/B,KAAK,eAAe;AAAA,QACtB,CAAC;AAAA,MACH;AACA;AAAA,IACF;AACA,SAAK,iBAAiB;AAAA,MACpB;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,eAAe,UAA4C;AACzD,QAAI,SAAS,WAAW,KAAK,gBAAgB,UAAU,QAAQ;AAC7D,WAAK;AAAA,QACH,gBAAgB,SAAS,MAAM,oBAC7B,KAAK,gBAAgB,UAAU,MACjC;AAAA,MACF;AACA;AAAA,IACF;AACA,SAAK,eAAe,MAAM,KAAK,QAAQ;AACvC,WAAO,SAAS,wBAAwB,KAAK,SAAS;AAAA,EACxD;AAAA,EAEA,cAAc,SAA4B;AACxC,QAAI,QAAQ,WAAW,KAAK,gBAAgB,UAAU,QAAQ;AAC5D,WAAK;AAAA,QACH,eAAe,QAAQ,MAAM,oBAC3B,KAAK,gBAAgB,UAAU,MACjC;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,QAAQ,QAAQ;AAClB,WAAK,iBAAiB;AACtB;AAAA,IACF;AACA,SAAK,YAAY,KAAK,EAAC,GAAG,KAAK,gBAAgB,QAAO,CAAC;AACvD,SAAK,iBAAiB;AACtB,QAAI,CAAC,KAAK,0BAA0B;AAClC,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,mBAAyB;AACvB,SAAK,IAAI,QAAQ,4BAA4B;AAC7C,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,qBAAqB;AACnB,SAAK,IAAI,QAAQ,wBAAwB;AACzC,SAAK,2BAA2B;AAChC,SAAK,KAAK,KAAK,YAAY;AAAA,EAC7B;AAAA,EAEA,eAAe,YAAY;AACzB,UAAM,QAAQ,KAAK,IAAI,YAAY,SAAS,KAAK,MAAM,YAAY,IAAI,CAAC,CAAC;AACzE,QAAI,KAAK,YAAY,WAAW,GAAG;AACjC,YAAM,QAAQ,wBAAwB;AACtC,WAAK,2BAA2B;AAChC;AAAA,IACF;AACA,SAAK,KAAK,KAAK,YAAY;AAC3B,UAAM,QAAQ,YAAY,IAAI;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA,QAAQ,KAAK;AAAA,IACf;AACA,SAAK,wBAAwB;AAC7B,UAAM,KAAK,sBAAsB,KAAK;AACtC,UAAM,QAAQ,yBAAyB,YAAY,IAAI,IAAI,KAAK;AAAA,EAClE;AAAA,EAEA,sBAAsB,IAAmC;AACvD,WAAO,KAAK,UAAU,SAAS,YAAY;AACzC,YAAM,MAAM,KAAK,IAAI;AACrB,SAAG,QAAQ,oBAAoB,GAAG;AAClC,SAAG,QAAQ,WAAW,KAAK,YAAY,MAAM;AAC7C,UAAI;AACF,cAAM,SAAS;AAAA,UACb,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,QACP;AACA,aAAK,YAAY,SAAS;AAC1B,YAAI,WAAW,QAAW;AACxB,aAAG,QAAQ,gBAAgB;AAC3B;AAAA,QACF;AACA,cAAM,QAAQ,YAAY,IAAI;AAC9B,WAAG,QAAQ,mBAAmB;AAC9B,cAAM,KAAK,gBAAgB,MAAM;AACjC,WAAG,QAAQ,0BAA0B,YAAY,IAAI,IAAI,KAAK;AAE9D,YAAI,EAAE,WAAW,OAAO,eAAe;AACrC,gBAAM,OACJ,OAAO,aAAa,sBAAsB,KAAK,SAAS;AAC1D,cAAI,SAAS,QAAW;AACtB,iBAAK,iBAAiB,aAAa,IAAI;AAAA,UACzC;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AACV,aAAK,iBAAiB,CAAC;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,iBAAiB,GAAY;AAC3B,QAAI,OAAO,CAAC,EAAE,SAAS,iCAAiC,GAAG;AAIzD,WAAK,IAAI,QAAQ,mBAAmB,CAAC;AAAA,IACvC,OAAO;AACL,WAAK,IAAI,QAAQ,yCAAyC,CAAC;AAAA,IAC7D;AACA,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,SAAS;AACP,SAAK,iBAAiB;AACtB,SAAK,YAAY,SAAS;AAAA,EAC5B;AACF;AAEO,SAAS,WACd,YACA,QACAC,iBAGY;AACZ,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,QAAM,EAAC,WAAU,IAAI,WAAW,CAAC,EAAE;AACnC,QAAM,WAAW,WAAW,WAAW,SAAS,CAAC;AACjD,QAAM,EAAC,OAAM,IAAI,SAAS;AAC1B,QAAM,cAAwC,CAAC;AAC/C,QAAM,8BAAsD,CAAC;AAC7D,QAAM,kBAAmC,CAAC;AAE1C,MAAI,cAAc;AAClB,aAAW,mBAAmB,YAAY;AACxC,QACE,eACA,gBAAgB,UAAU,cAC1B,gBAAgB,UAAU,aAAa,YAAY,QACnD;AACA,YAAM;AAAA,QACJ,yBAAyB,KAAK,UAAU,WAAW,CAAC,IAAI,KAAK;AAAA,UAC3D,gBAAgB;AAAA,QAClB,CAAC;AAAA,MACH;AAAA,IACF;AACA,kBAAc,gBAAgB;AAC9B,eAAW,YAAY,gBAAgB,OAAO;AAC5C,UAAI,SAAS,uBAAuB;AAClC,mBAAW,CAAC,UAAU,cAAc,KAAK,OAAO;AAAA,UAC9C,SAAS;AAAA,QACX,GAAG;AACD,sCAA4B,QAAQ,IAAI;AAAA,QAC1C;AAAA,MACF;AACA,UAAI,SAAS,uBAAuB;AAClC,mBAAW,CAAC,UAAU,YAAY,KAAK,OAAO;AAAA,UAC5C,SAAS;AAAA,QACX,GAAG;AACD,qBAAW,MAAM,cAAc;AAC7B,wBAAY;AAAA,cACV;AAAA,gBAAgC;AAAA,gBAAI,UAClC,oBAAoB,UAAU,IAAI;AAAA,cACpC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS,iBAAiB;AAC5B,mBAAW,MAAM,SAAS,iBAAiB;AACzC,sBAAY;AAAA,YACV,gCAAgC,IAAI,eAAe;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS,WAAW;AACtB,mBAAW,KAAK,SAAS,WAAW;AAClC,sBAAY;AAAA,YACV,+BAA+B,GAAG,QAAQA,eAAc;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS,gBAAgB;AAC3B,mBAAW,MAAM,SAAS,gBAAgB;AACxC,sBAAY,KAAK,mCAAmC,EAAE,CAAC;AAAA,QACzD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,MAAsE;AAAA,IAC1E;AAAA,IACA,cAAc;AAAA,MACZ,uBAAuB;AAAA,MACvB,OAAO;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAKA,MAAI,gBAAgB,SAAS,GAAG;AAC9B,QAAI,kBAAkB;AAAA,EACxB;AACA,SAAO;AACT;AAEA,SAAS,gCACP,IACA,OACgB;AAChB,UAAQ,GAAG,IAAI;AAAA,IACb,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK,MAAM,GAAG,IAAI;AAAA,MACpB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK,MAAM,GAAG,IAAI;AAAA,QAClB,OAAO;AAAA,MACT;AAAA,IACF;AACE,kBAAY,EAAE;AAAA,EAClB;AACF;AAEO,SAAS,mCACd,IACwB;AACxB,UAAQ,GAAG,IAAI;AAAA,IACb,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK,sBAAsB,GAAG,SAAS,EAAE;AAAA,QACzC,OAAO,GAAG,SAAS;AAAA,MACrB;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK,sBAAsB,GAAG,EAAE;AAAA,MAClC;AAAA,EACJ;AACF;AAEA,SAAS,+BACP,IACA,QACAA,iBACwB;AACxB,MAAI,GAAG,OAAO,SAAS;AACrB,WAAO;AAAA,EACT;AACA,QAAM,YAAYA,gBAAe,UAAU,GAAG,WAAW,EAAe;AACxE,UAAQ,GAAG,IAAI;AAAA,IACb,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK;AAAA,UACH;AAAA,UACA,OAAO,OAAO,SAAS,EAAE;AAAA,UACzBA,gBAAe,IAAI,GAAG,WAAW,GAAG,EAAE;AAAA,QACxC;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK;AAAA,UACH;AAAA,UACA,OAAO,OAAO,SAAS,EAAE;AAAA,UACzBA,gBAAe,IAAI,GAAG,WAAW,GAAG,KAAK;AAAA,QAC3C;AAAA,QACA,OAAOA,gBAAe,IAAI,GAAG,WAAW,GAAG,KAAK;AAAA,MAClD;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,KAAK;AAAA,UACH;AAAA,UACA,OAAO,OAAO,SAAS,EAAE;AAAA,UACzBA,gBAAe,IAAI,GAAG,WAAW,GAAG,EAAE;AAAA,QACxC;AAAA,QACA,OAAO,GAAG,QACNA,gBAAe,IAAI,GAAG,WAAW,GAAG,KAAK,IACzC;AAAA,QACJ,WAAWA,gBAAe,QAAQ,GAAG,WAAW,GAAG,SAAS;AAAA,MAC9D;AAAA,IACF;AACE,kBAAY,EAAE;AAAA,EAClB;AACF;AAMA,SAAS,YAAY,UAA4B;AAC/C,aAAW,UAAU,CAAC;AACxB;;;AC1XA,IAAM,2BAA2B;AAE1B,IAAM,wBAAwB,CACnC,SACW,QAAQ;AAEd,IAAM,0BAA0B,CAAC,SACtC,CAAC,OAAO,SAAY;AAOf,IAAM,UAAN,MAAoC;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT;AAAA;AAAA,EAEA,QAAgB;AAAA,EAEhB,YACE,SACA,SACA,uBACA,iBACA;AACA,SAAK,WAAW;AAChB,SAAK,WAAW;AAChB,SAAK,yBAAyB;AAC9B,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,IAAI,KAAK,MAAc;AACrB,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,MAAM,KAAK,MAAY,OAAkB;AACvC,UAAM,QAAiC,CAAC;AACxC,UAAM,SAAS,OAAO,OAAM,YAAW;AACrC,YAAM,OAAO,MAAM,aAAa,MAAM,SAAuB,MAAM;AACnE,uBAAiB,SAAS,KAAK,IAAI,KAAK,mBAAmB,GAAG;AAC5D,YAAI,CAAC,MAAM,CAAC,EAAE,WAAW,mBAAmB,GAAG;AAC7C;AAAA,QACF;AACA,cAAM,KAAK;AAAA,UACT,IAAI;AAAA,UACJ,KAAK,MAAM,CAAC;AAAA,UACZ,UAAU,MAAM,CAAC;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AACD,SAAK,SAAS;AAEd,SAAK,SAAS,eAAe,QAAW,MAAM,KAAK;AAAA,EACrD;AAAA,EAEA,YAAY,CACV,aACA,gBACgC;AAIhC,QAAI,CAAC,KAAK,wBAAwB;AAChC;AAAA,IACF;AAEA,WAAO,KAAK,SACT,WAAW,KAAK,KAAK,MAAM,GAAG,aAAa,WAAW,EACtD,KAAK,aAAW;AAAA,MACf,YAAY;AAAA,MACZ,OAAO,wBAAwB,KAAK,KAAK;AAAA,IAC3C,EAAE;AAAA,EACN;AAAA,EAEA,UAAU,CAAC,cAAoB,SAAe,UAA8B;AAC1E,SAAK,SAAS,eAAe,cAAc,SAAS,KAAK;AAAA,EAC3D;AAAA,EAEA,gBAAsC;AACpC,WAAO,KAAK,iBAAiB,cAAc;AAAA,EAC7C;AAAA,EACA,mBAAmB,aAA0B,YAA0B;AACrE,SAAK,iBAAiB,mBAAmB,aAAa,UAAU;AAAA,EAClE;AAAA,EACA,eAAe,aAA0B,IAAmB;AAC1D,SAAK,iBAAiB,eAAe,aAAa,EAAE;AAAA,EACtD;AACF;;;A7HsFO,IAAM,yBAAyB,OAAO;AACtC,IAAM,yBAAyB,OAAO;AAgBtC,IAAM,uBAAuB;AAK7B,IAAM,mBAAmB;AAKzB,IAAM,kBAAkB;AAMxB,IAAM,kBAAkB;AAExB,IAAM,qCAAqC;AAQ3C,IAAM,gCAAgC,IAAI,KAAK;AAM/C,IAAM,qBAAqB;AAElC,IAAM,wCAAwC;AAE9C,IAAM,6BAA6B,EAAC,UAAU,IAAI,IAAI,GAAE;AAExD,IAAM,mCAAmC;AAEzC,SAAS,4BACP,QACoB;AACpB,SAAO,EAAC,MAAM,OAAO,KAAI;AAC3B;AAEA,SAAS,gCAAgC,QAA4B;AACnE,QAAM,EAAC,KAAI,IAAI;AACf,MAAI,YAAY;AAChB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,kBACE;AACF;AAAA,IACF,KAAK;AACH,kBACE;AACF;AAAA,IACF,KAAK;AACH,kBAAY;AACZ;AAAA,IACF;AACE,kBAAY,IAAI;AAAA,EACpB;AACA,MAAI,OAAO,SAAS;AAClB,iBAAa,MAAM,OAAO;AAAA,EAC5B;AACA,SAAO;AACT;AAEA,IAAM,0BAA0B;AAEhC,SAAS,kCAAkC,cAAsB;AAC/D,SAAO,kEAAkE,YAAY;AACvF;AACA,IAAM,0CACJ;AAgBF,IAAM,oBAAoB;AAInB,IAAM,OAAN,MAAM,MAGX;AAAA,EACS,UAAUC;AAAA,EAEV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA;AAAA,EAEA,sBACE;AAAA,EAEF,UAAsB,MAAM;AAAA,EAEnB;AAAA,EAEA;AAAA,EACA;AAAA;AAAA,EAET,iBAAkC;AAAA;AAAA,EAElC,kBAAkB;AAAA;AAAA;AAAA,EAGlB,gBAAgB;AAAA,EAChB,eAAe;AAAA;AAAA,EAEf,qBAAqB;AAAA,EAErB,oBAAoB,MAAM;AAAA,EAE1B;AAAA,EAES;AAAA,EACA;AAAA,EAET,2BAAoE,oBAAI,IAAI;AAAA,EAC5E,0BAA0B;AAAA,EAE1B,UAAiC;AAAA,EACjC,kBAAkBC,WAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMtC,mBAAmBA,WAAe;AAAA,EAElC,wBAAwB,IAAI,gBAAgB;AAAA,EAEnC;AAAA,EAEA;AAAA,EACA;AAAA,EACT,8BAAwD;AAAA,EAC/C;AAAA,EACT;AAAA,EAEA,gBAAoC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpC,uBAA2C;AAAA,EAElC;AAAA,EAEA;AAAA;AAAA;AAAA,EAIT;AAAA;AAAA;AAAA,EAIA,UAAU,MAAM,iBAAiB,UAAU,GAAG,OAAO;AAAA;AAAA;AAAA;AAAA,EAKrD,YAAY,SAA6B;AACvC,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,2BAA2B;AAAA,MAC3B;AAAA,MACA,mBAAmB,sBAAoB,iBAAiB;AAAA,MACxD,mBAAmB;AAAA,MACnB,2BAA2B;AAAA,IAC7B,IAAI;AACJ,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,YAAY;AAAA,QACpB,MAAM,+BAAgB;AAAA,QACtB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,UAAM,SAAS,UAAU,QAAQ,MAAM;AACvC,SAAK,mBAAmB;AAAA,MACtB;AAAA,MACA;AAAA;AAAA,IACF;AAEA,QAAI,EAAC,UAAU,MAAK,IAAI;AACxB,QAAI,YAAY,OAAO;AACrB,UAAI,CAAC,iBAAiB,WAAW,GAAG;AAElC,gBAAQ;AAAA,UACN;AAAA,QACF;AACA,kBAAU;AAAA,MACZ;AAAA,IACF;AAEA,QAAI,2BAA2B,GAAG;AAChC,YAAM,IAAI,YAAY;AAAA,QACpB,MAAM,+BAAgB;AAAA,QACtB,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,SAAK,iBAAiB,IAAI,cAAc;AAExC,QAAI,gBAAgB;AAClB,WAAK,eAAe,UAAU,cAAc;AAAA,IAC9C;AAEA,SAAK,WAAW;AAEhB,SAAK,cAAc,KAAK,kBAAkB;AAAA,MACxC,iBAAiB,QAAQ,YAAY;AAAA,MACrC,QAAQ;AAAA;AAAA,MACR,iBAAiB,KAAK;AAAA,IACxB,CAAC;AACD,UAAM,aAAa,KAAK;AAExB,SAAK,qBAAqB,IAAI,kBAAkB;AAAA,MAC9C,qBAAqB;AAAA,IACvB,CAAC;AACD,UAAM,kBAAkB,CAAC,UAA2B;AAClD,WAAK,eAAe,UAAU,MAAM,SAAS,+BAAiB,SAAS;AAAA,IACzE;AACA,oBAAgB,KAAK,mBAAmB,KAAK;AAC7C,SAAK,8BACH,KAAK,mBAAmB,UAAU,eAAe;AAEnD,UAAM,EAAC,uBAAuB,MAAM,sBAAsB,KAAI,IAAI;AAElE,UAAM,qBAEF;AAAA,MACF,CAAC,kBAAkB,GAAG,uBAClB,gBAAgB,MAAM,IACtB,MACE,QAAQ;AAAA,QACN,IAAI,YAAY;AAAA,UACd,MAAM,+BAAgB;AAAA,UACtB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACR;AACA,SAAK,WAAW,IAAI,gBAAgB,OAAO,MAAM;AAEjD,aAAS,aAAa,KAAa;AACjC;AAAA,QACE,mBAAmB,GAAG,MAAM;AAAA,QAC5B,iEAAiE,GAAG;AAAA,MACtE;AAAA,IACF;AAIA,UAAM,EAAC,QAAO,IAAI;AAClB,UAAM,OAAO,WAAW;AACxB,UAAM,UAAsC;AAAA,MAC1C,IAAI,OAAO,YAAY,MAAM;AAC3B,YAAI,UAAU,WAAW,SAAS;AAChC,kBAAQ,GAAI,IAA0B;AAAA,QACxC,OAAO;AACL,eAAK,IAAI,OAAO,SAAS,GAAG,IAAI;AAAA,QAClC;AAAA,MACF;AAAA,MACA,MAAM,QAAQ;AACZ,cAAM,KAAK,QAAQ;AAAA,MACrB;AAAA,IACF;AAEA,UAAM,KAAK,IAAI,eAAe,WAAW,UAAU,CAAC,GAAG,OAAO;AAE9D,SAAK,mBAAmB,IAAI;AAAA,MAC1B;AAAA,MACA,CAAC,SAAqB,KAAK,MAAM,CAAC,wBAAwB,IAAI,CAAC;AAAA,MAC/D,WAAS;AACP,aAAK,YAAY,IAAI,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,QAAI,QAAQ,UAAU;AACpB,iBAAW,CAAC,gBAAgB,iBAAiB,KAAK,OAAO;AAAA,QACvD,QAAQ;AAAA,MACV,GAAG;AACD,YAAI,OAAO,sBAAsB,YAAY;AAC3C,gBAAM,MAAM;AACZ,uBAAa,GAAG;AAChB,6BAAmB,GAAG,IAAI;AAAA,YACxB;AAAA,YACA;AAAA,YACA;AAAA;AAAA;AAAA,UAGF;AACA;AAAA,QACF;AACA,YAAI,OAAO,sBAAsB,UAAU;AACzC,qBAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,iBAAiB,GAAG;AAC/D,kBAAM,MAAM;AAAA,cACV;AAAA,cACA;AAAA,YACF;AACA,yBAAa,GAAG;AAChB,+BAAmB,GAAG,IAAI;AAAA,cACxB;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AACA;AAAA,QACF;AACA,oBAAY,iBAAiB;AAAA,MAC/B;AAAA,IACF;AAEA,SAAK,aAAa,cAAc;AAEhC,UAAM,EAAC,cAAc,KAAI,IAAI,iBAAiB,MAAM;AACpD,SAAK,gBAAgB;AAGrB,UAAM,UAAU,KAAK,UAAU;AAAA,MAC7B,YAAY,KAAK;AAAA,MACjB,WAAW,QAAQ,aAAa;AAAA,MAChC,UAAU,QAAQ,iBAAiB;AAAA,IACrC,CAAC;AACD,UAAM,YAAY,IAAI,OAAO,EAAE,SAAS,EAAE;AAE1C,UAAM,oBAA8D;AAAA;AAAA;AAAA,MAGlE,eAAe,GAAG,gBAAgB,IAAI,IAAI;AAAA,MAC1C,UAAU,WAAW;AAAA,MACrB,UAAU,CAAC,WAAW,OAAO;AAAA,MAC7B,UAAU;AAAA,MACV,MAAM,QAAQ,MAAM,IAAI,SAAS;AAAA,MACjC,QAAQ,CAAC,KAAK,UAAU,KAAK,QAAQ,KAAK,KAAK;AAAA,MAC/C,QAAQ,CAAC,KAAK,UAAU,KAAK,QAAQ,KAAK,KAAK;AAAA,MAC/C,WAAW;AAAA,MACX,gBAAgB;AAAA,QACd,YAAY;AAAA,QACZ,YAAY;AAAA,MACd;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,IACF;AAEA,SAAK,eAAe,IAAI;AAAA,MACtB;AAAA,MACA,KAAK;AAAA,MACL,CAAC,KAAK,KAAK,gBAAgB;AACzB,YAAI,qBAAqB;AACvB,iBAAO,KAAK,cAAc,UAAU,KAAK,KAAK,WAAW;AAAA,QAC3D;AAEA,eAAO;AAAA,MACT;AAAA,MACA,CAAC,KAAK,eAAe,KAAK,gBACxB,KAAK,cAAc,UAAU,KAAK,eAAe,KAAK,WAAW;AAAA,MACnE,CAAC,KAAK,QAAQ;AACZ,YAAI,qBAAqB;AACvB,eAAK,cAAc,aAAa,KAAK,GAAG;AAAA,QAC1C;AAAA,MACF;AAAA,MACA,CAAC,eAAe,QACd,KAAK,cAAc,aAAa,eAAe,GAAG;AAAA,MACpD,MAAM,KAAK,cAAc,WAAW;AAAA,MACpC;AAAA,MACA,KAAK;AAAA,MACLC;AAAA,IACF;AACA,SAAK,gBAAgB,KAAK;AAE1B,UAAM,wBAA+C;AAAA,MACnD,0BAA0B;AAAA,MAC1B,wBAAwB;AAAA,MACxB,yBAAyB;AAAA;AAAA,MACzB,kBAAkB,oBAChB,KAAK,sBAAsB,iBAAiB,cAAc;AAAA,MAC5D,MAAM,IAAI;AAAA,QACR,KAAK;AAAA,QACL,KAAK;AAAA,QACL,QAAQ,aAAa;AAAA,QACrB,KAAK;AAAA,MACP;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,eAAe,mBAAmB,qBAAqB;AACvE,SAAK,OAAO;AAEZ,QAAI,OAAS;AACX,gCAA0B,IAAI,MAAM,GAAG;AAAA,IACzC;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,MAAM,GAAG,YAAY,YAAY,IAAI,QAAQ;AAClD,SAAK,cAAc,IAAI;AAAA,MACrB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,UAAQ,KAAK,SAAS,IAAI;AAAA,IAC5B;AACA,SAAK,iBAAiB;AAAA,MACpB,IAAI;AAAA,MACJ,IAAI,kBAAkB,KAAK,GAAG;AAAA,IAChC;AAEA,SAAK,wBAAwB;AAAA,MAC3B,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,KAAK,sBAAsB;AAAA,MAC3B,CAAC,UAAoB,kBACnB,KAAK,sBAAsB,iBAAiB;AAAA,QAC1C,EAAC,eAAe,SAAQ;AAAA,MAC1B,CAAC;AAAA,IACL;AAEA,UAAM,yBAAyB,CAAC,WAA+B;AAC7D,UAAI,gBAAgB;AAClB,uBAAe,MAAM;AAAA,MACvB,OAAO;AACL;AAAA,UACE,KAAK;AAAA,UACL,KAAK;AAAA,UACL,OAAO;AAAA,UACP,gCAAgC,MAAM;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AACA,SAAK,kBAAkB;AACvB,SAAK,KAAK,iBAAiB,YAAU;AACnC,6BAAuB,4BAA4B,MAAM,CAAC;AAAA,IAC5D;AAEA,UAAM,gCACJ,0BACC,CAAC,WAAoB;AACpB;AAAA,QACE,KAAK;AAAA,QACL,KAAK;AAAA,QACL,wBAAU;AAAA,QACV,UAAU;AAAA,MACZ;AAAA,IACF;AACF,SAAK,yBAAyB;AAC9B,SAAK,KAAK,wBAAwB;AAGlC,UAAM,EAAC,QAAQ,YAAW,IAAI,eAAkB,QAAQ,IAAI,MAAM;AAElE,QAAI,QAAQ,UAAU;AACpB,iBAAW,CAAC,gBAAgB,iBAAiB,KAAK,OAAO;AAAA,QACvD,QAAQ;AAAA,MACV,GAAG;AACD,YAAI,OAAO,sBAAsB,YAAY;AAC3C,iBAAO,cAAc,IAAI,KAAK,IAAI,OAAO,cAAwB,CAAC;AAClE;AAAA,QACF;AAEA,YAAI,WAAW,OAAO,cAAc;AACpC,YAAI,aAAa,QAAW;AAC1B,qBAAW,CAAC;AACZ,iBAAO,cAAc,IAAI;AAAA,QAC3B;AAEA,mBAAW,QAAQ,OAAO,KAAK,iBAAiB,GAAG;AACjD,mBAAS,IAAI,IAAI;AAAA,YACf,IAAI,OAAO,iBAAiB,gBAAgB,IAAI,CAAC;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS;AACd,SAAK,cAAc;AAEnB,SAAK,gBAAgB,IAAI;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,SAAO,KAAK,MAAM,GAAG;AAAA,MACrB,IAAI,kBAAkB,KAAK,GAAG;AAAA,MAC9B;AAAA,MACA,QAAQ,yBAAyB;AAAA,MACjC;AAAA,MACA,CAAC,UAAqB;AACpB,aAAK,YAAY,IAAI,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,SAAK,kBAAkB,eAAe,OAAO,MAAM;AAEnD,SAAK,wBAAwB,IAAI;AAAA,MAC/B,SAAO,KAAK,MAAM,GAAG;AAAA,MACrB,IAAI;AAAA,MACJ,KAAK;AAAA,MACL,KAAK,KAAK;AAAA,IACZ;AAEA,SAAK,QAAQ,KAAK,iBAAiB,MAAM;AAEzC,uBAAmB,KAAK,GAAG;AAE3B,SAAK,WAAW,IAAI,cAAc;AAAA,MAChC,kBAAkB;AAAA,MAClB,MAAM,iBAAiB,UAAU,GAAG,QAAQ;AAAA,MAC5C,QAAQ;AAAA,MACR,UAAU,KAAK,mBACX,eAAa,KAAK,eAAe,SAAS,IAC1C,MAAM,QAAQ,QAAQ;AAAA,MAC1B,IAAI,KAAK;AAAA,IACX,CAAC;AACD,SAAK,SAAS,KAAK,KAAK,WAAW,KAAK,OAAO,EAAE;AAEjD,SAAK,eAAe,IAAI;AAAA,MACtB,UAAQ,KAAK,KAAK,KAAK,IAAI;AAAA,MAC3B,MAAM,KAAK,aAAa;AAAA,MACxB,IAAI;AAAA,MACJ;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,SAAK,qBAAqB;AAAA,MACxB,iBAAiB,UAAU;AAAA,MAC3B;AAAA,MACA,KAAK,sBAAsB;AAAA,IAC7B;AAEA,SAAK,KAAK,SAAS;AAEnB,SAAK,QAAQ;AAEb,QAAI,OAAS;AACX,iBAAW,IAAI,EAAE,sBAAsB,IAAI;AAAA,QACzC,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,WAAW,CAAC,MAAkB;AAC5B,eAAK,UAAU;AAAA,QACjB;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,cAAc,MAAM,KAAK;AAAA,QACzB,gBAAgB,MAAM,KAAK;AAAA,QAC3B,mBAAmB,MAAM,KAAK;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU;AAGR,UAAM,IAAI;AACV,QAAI,EAAE,WAAW,QAAW;AAC1B,QAAE,SAAS;AAAA,IACb,WAAW,EAAE,kBAAkB,OAAM;AACnC,YAAM,OAAO,EAAE;AACf,QAAE,SAAS;AAAA,QACT,CAAC,KAAK,QAAQ,GAAG;AAAA,QACjB,CAAC,KAAK,QAAQ,GAAG;AAAA,MACnB;AAAA,IACF,OAAO;AACL,QAAE,OAAO,KAAK,QAAQ,IAAI;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,YAAY;AAEV,UAAM,IAAI;AACV,WAAO,EAAE,WAAW,MAAS;AAC7B,QAAI,EAAE,kBAAkB,OAAM;AAC5B,aAAO,EAAE,WAAW,IAAI;AACxB,aAAO,EAAE;AAAA,IACX,OAAO;AACL,aAAO,EAAE,OAAO,KAAK,QAAQ;AAC7B,UAAI,OAAO,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAG;AACzC,UAAE,SAAS,OAAO,OAAO,EAAE,MAAM,EAAE,CAAC;AAAA,MACtC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,KAAqB;AACzB,QACE,KAAK,WACL,KAAK,mBAAmB,GAAG,+BAAiB,SAAS,GACrD;AACA,WAAK,KAAK,SAAS,GAAG;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,kBAAkB,SAIH;AACb,QAAI,OAAS;AACX,YAAM,WAAW,WAAW,IAAI;AAChC,UAAI,SAAS,sBAAsB,GAAG;AACpC,eAAO,SAAS,sBAAsB,EAAE,OAAO;AAAA,MACjD;AAAA,IACF;AACA,WAAO,iBAAiB,OAAO;AAAA,EACjC;AAAA,EAEA,QAEE,OACA,SACA;AACA,WAAO,MAAM,cAAc,EAAE,KAAK,YAAY,EAAE,QAAQ,OAAO;AAAA,EACjE;AAAA,EAEA,IACE,OACA,YACyC;AACzC,WAAQ,MACL,cAAc,EAAE,KAAK,YAAY,EACjC,IAAI,UAAU;AAAA,EACnB;AAAA,EAWA,YACE,OACA,kBAGA,cACA;AACA,WAAO;AAAA,MACL;AAAA,MACA,KAAK;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAA4B;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,UAAkB;AACpB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,IAAI,SAAY;AACd,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,WAAqB;AACvB,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEA,IAAI,gBAAwC;AAC1C,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBT,IAAI,aAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,SAAkB;AACpB,WAAO,KAAK,mBAAmB,GAAG,+BAAiB,MAAM;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAuB;AAC3B,UAAM,KAAK,KAAK,IAAI,YAAY,OAAO;AAEvC,QAAI;AACF,UAAI,KAAK,QAAQ;AACf,WAAG,QAAQ,2CAA2C;AACtD;AAAA,MACF;AAEA,SAAG,QAAQ,iCAAiC,IAAI,MAAM,EAAE,KAAK;AAE7D,WAAK,8BAA8B;AACnC,WAAK,8BAA8B;AACnC,WAAK,eAAe,QAAQ;AAE5B,UAAI,CAAC,KAAK,mBAAmB,GAAG,+BAAiB,YAAY,GAAG;AAC9D,aAAK;AAAA,UACH;AAAA,UACA,IAAI,YAAY;AAAA,YACd,MAAM,+BAAgB;AAAA,YACtB,SAAS;AAAA,UACX,CAAC;AAAA,UACD;AAAA,QACF;AAAA,MACF;AACA,SAAG,QAAQ,8CAA8C;AACzD,WAAK,sBAAsB,MAAM;AACjC,WAAK,SAAS,KAAK;AACnB,YAAM,MAAM,MAAM,KAAK,KAAK,MAAM;AAClC,WAAK,UAAU;AACf,aAAO;AAAA,IACT,SAAS,GAAG;AACV,SAAG,QAAQ,+BAA+B,CAAC;AAC3C,YAAM;AAAA,IACR,UAAE;AACA,WAAK,mBAAmB,OAAO;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,aAAa,CAAC,MAA4B;AACxC,UAAM,KAAK,KAAK;AAChB,OAAG,QAAQ,oBAAoB,EAAE,IAAI;AACrC,QAAI,KAAK,QAAQ;AACf,SAAG,QAAQ,yCAAyC;AACpD;AAAA,IACF;AAEA,QAAI;AACJ,UAAM,EAAC,KAAI,IAAI;AACf,QAAI;AACF,oBAAqB;AAAA,QACnB,KAAK,MAAM,IAAI;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAASC,IAAG;AACV,YAAM,sBAAsB,IAAI,YAAY;AAAA,QAC1C,MAAM,+BAAgB;AAAA,QACtB,SAAS,yCAAyCA,cAAa,QAAQA,GAAE,UAAU,OAAO,EAAE,GAAG,IAAI;AAAA,MACrG,CAAC;AACD,WAAK,YAAY,IAAI,mBAAmB;AACxC;AAAA,IACF;AACA,SAAK;AACL,UAAM,UAAU,YAAY,CAAC;AAC7B,YAAQ,SAAS;AAAA,MACf,KAAK;AACH,eAAO,KAAK,wBAAwB,IAAI,WAAW;AAAA,MAErD,KAAK;AACH,eAAO,KAAK,oBAAoB,IAAI,WAAW;AAAA,MAEjD,KAAK;AAIH,qBAAa;AACb,eAAO,KAAK,QAAQ;AAAA,MAEtB,KAAK;AACH,eAAO,KAAK,iBAAiB,IAAI,WAAW;AAAA,MAE9C,KAAK;AACH,YAAI,YAAY,CAAC,EAAE,WAAW;AAG5B,uBAAa;AAAA,QACf;AACA,eAAO,KAAK,gBAAgB,IAAI,WAAW;AAAA,MAE7C,KAAK;AACH,eAAO,KAAK,eAAe,IAAI,WAAW;AAAA,MAE5C,KAAK;AACH,eAAO,KAAK,oBAAoB,IAAI,WAAW;AAAA,MAEjD,KAAK;AACH,eAAO,KAAK,sBAAsB;AAAA,UAChC,YAAY,CAAC;AAAA,QACf;AAAA,MAEF,KAAK;AACH,eAAO,KAAK,iBAAiB,oBAAoB,YAAY,CAAC,CAAC;AAAA,MAEjE,KAAK;AACH,aAAK,cAAc,sBAAsB,YAAY,CAAC,CAAC;AACvD;AAAA,MAEF,KAAK;AAEH;AAAA,MAEF,SAAS;AACP,cAAM,sBAAsB,IAAI,YAAY;AAAA,UAC1C,MAAM,+BAAgB;AAAA,UACtB,SAAS,yCAAyC,IAAI;AAAA,QACxD,CAAC;AACD,aAAK,YAAY,IAAI,mBAAmB;AACxC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,MAAM;AACd,UAAM,IAAI,qCAAqC,KAAK,SAAU,KAAK,GAAG;AACtE,QAAI,KAAK,kBAAkB,QAAW;AACpC,QAAE,QAAQ,qDAAqD;AAAA,IACjE,OAAO;AACL,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,eAAe,MAAM,KAAK;AAChC,QAAE,OAAO,yBAAyB;AAAA,QAChC,iBAAiB,gBAAW;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,WAAW,CAAC,MAAkB;AAC5B,UAAM,KAAK,qCAAqC,KAAK,SAAU,KAAK,GAAG;AACvE,UAAM,EAAC,MAAM,QAAQ,SAAQ,IAAI;AACjC,QAAI,QAAQ,MAAM;AAChB,SAAG,OAAO,0BAA0B,EAAC,MAAM,QAAQ,SAAQ,CAAC;AAAA,IAC9D,OAAO;AACL,SAAG,QAAQ,qCAAqC;AAAA,QAC9C;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAMC,cAAa,IAAI;AAAA,MACrB,WACI;AAAA,QACE,MAAM,+BAAgB;AAAA,QACtB,SAAS;AAAA,MACX,IACA;AAAA,QACE,MAAM,+BAAgB;AAAA,QACtB,SAAS;AAAA,MACX;AAAA,IACN;AACA,SAAK,iBAAiB,OAAOA,WAAU;AACvC,SAAK,YAAY,IAAIA,WAAU;AAAA,EACjC;AAAA;AAAA,EAGA,MAAM,oBACJ,IACA,aACe;AACf,UAAM,CAAC,EAAE,EAAC,MAAM,QAAO,CAAC,IAAI;AAK5B,QAAI,SAAS,wBAAU,qBAAqB;AAC1C,WAAK,sBAAsB;AAC3B,SAAG,QAAQ,MAAM,yBAAyB,EAAC,QAAO,CAAC;AACnD;AAAA,IACF;AAEA,OAAG,OAAO,GAAG,IAAI,KAAK,OAAO,GAAG;AAChC,UAAM,QAAQ,IAAI,cAAc,YAAY,CAAC,CAAC;AAC9C,OAAG,QAAQ,GAAG,MAAM,IAAI;AAAA;AAAA,EAAQ,MAAM,UAAU,OAAO,IAAI,KAAK;AAEhE,OAAG,QAAQ,2CAA2C,KAAK;AAC3D,SAAK,iBAAiB,OAAO,KAAK;AAClC,SAAK,YAAY,IAAI,KAAK;AAE1B,QAAI,SAAS,wBAAU,qBAAqB;AAC1C,WAAK,gBAAgB,EAAC,MAAM,MAAM,QAAO,CAAC;AAAA,IAC5C,WAAW,SAAS,wBAAU,2BAA2B;AACvD,YAAM,KAAK,KAAK,mBAAmB;AACnC,WAAK,gBAAgB;AAAA,QACnB,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AAAA,IACH,WAAW,SAAS,wBAAU,gBAAgB;AAC5C,YAAM,KAAK,KAAK,mBAAmB;AACnC,WAAK,yBAAyB,kCAAkC,OAAO,CAAC;AAAA,IAC1E,WACE,SAAS,wBAAU,0CACnB,SAAS,wBAAU,oCACnB;AACA,YAAM,aAAa,KAAK,KAAK,OAAO;AACpC,uBAAiB,IAAI,KAAK,SAAS,MAAM,uBAAuB;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,MAAM,wBACJ,IACA,kBACe;AACf,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,CAAC,EAAE,WAAW,IAAI;AACxB,SAAK,2BAA2B,YAAY,MAAM,EAAE;AAEpD,QAAI,KAAK,oBAAoB,GAAG;AAC9B,WAAK,mBAAmB,cAAc;AAAA,IACxC,WAAW,KAAK,qBAAqB,GAAG;AACtC,WAAK,mBAAmB,mBAAmB;AAAA,IAC7C;AACA,SAAK;AACL,SAAK,eAAe;AACpB,SAAK,SAAS,iBAAiB,MAAM;AACrC,UAAM,8BAA8B,KAAK;AACzC,SAAK,qBAAqB;AAE1B,QAAI;AACJ,QAAI;AACJ,QAAI,KAAK,kBAAkB,QAAW;AACpC,SAAG,QAAQ,4DAA4D;AAAA,IACzE,OAAO;AACL,wBAAkB,MAAM,KAAK;AAC7B,WAAK,SAAS,gBAAgB,IAAI,eAAe;AACjD,4BACE,YAAY,cAAc,SACtB,MAAM,YAAY,YAClB;AACN,WAAK,gBAAgB;AAAA,IACvB;AACA,QAAI;AACJ,QAAI,KAAK,yBAAyB,QAAW;AAC3C,SAAG;AAAA,QACD;AAAA,MACF;AAAA,IACF,OAAO;AACL,6BAAuB,MAAM,KAAK;AAClC,WAAK,uBAAuB;AAAA,IAC9B;AAEA,SAAK,SAAS,aAAa,mBAAmB,GAAG,wBAAwB,CAAC;AAE1E,OAAG,OAAO,aAAa;AAAA,MACrB,iBAAiB,gBAAW;AAAA,MAC5B;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB,KAAK;AAAA,MACrB;AAAA,IACF,CAAC;AACD,SAAK,sBAAsB;AAE3B,OAAG,QAAQ,4BAA4B;AACvC,UAAM,SAAS,KAAK,KAAK,OAAO;AAChC,UAAM,eAAe,MAAM,KAAK,KAAK;AAAA,MAAM,QACzC,KAAK,cAAc,gBAAgB,IAAI,KAAK,sBAAsB;AAAA,IACpE;AAEA,UAAM,oBAAoB,MACxB,eAAe,KAAK,iBAAiB,SAAS,KAC9C,eAAe,KAAK,iBAAiB,cAAc;AAErD,UAAM,0BAA0B,MAAM;AACpC,UAAI,kBAAkB,GAAG;AACvB,aAAK,QAAQ,CAAC,iBAAiB,KAAK,eAAgB,CAAC;AACrD,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAEA,QAAI,aAAa,OAAO,KAAK,KAAK,2BAA2B,QAAW;AACtE,8BAAwB;AACxB,WAAK,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,UACE,qBAAqB,CAAC,GAAG,aAAa,OAAO,CAAC;AAAA,QAChD;AAAA,MACF,CAAC;AAAA,IACH,WAAW,KAAK,2BAA2B,QAAW;AAGpD,YAAM,eAAe,KAAK;AAC1B,WAAK,QAAQ;AAAA,QACX;AAAA,QACA;AAAA,UACE,qBAAqB,CAAC,GAAG,aAAa,OAAO,CAAC;AAAA,UAC9C,SAAS,wBAAwB,KAAK,eAAe;AAAA;AAAA;AAAA,UAGrD,GAAI,KAAK,mBAAmB,OAAO,EAAC,aAAY,IAAI,CAAC;AAAA,UACrD,aAAa,KAAK,SAAS;AAAA,UAC3B,cAAc,KAAK,SAAS;AAAA,QAC9B;AAAA,MACF,CAAC;AACD,WAAK,kBAAkB;AAAA,IACzB;AACA,SAAK,yBAAyB;AAE9B,4BAAwB;AAExB,SAAK,mBAAmB,UAAU;AAClC,SAAK,iBAAiB,QAAQ;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,SACJ,IACA,yBACe;AACf,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,WAAO,KAAK,SAAS,oBAAoB;AAIzC;AAAA,MACE,KAAK,mBAAmB,GAAG,+BAAiB,YAAY,KACtD,KAAK,mBAAmB,GAAG,+BAAiB,UAAU;AAAA,MACxD,0CACE,KAAK,mBAAmB,MAAM;AAAA,IAClC;AAEA,UAAM,OAAO,OAAO;AACpB,SAAK,2BAA2B,MAAM,EAAE;AACxC,OAAG,OAAO,iBAAiB,EAAC,iBAAiB,gBAAW,OAAM,CAAC;AAE/D,SAAK,mBAAmB,WAAW;AAInC,WAAO,KAAK,kBAAkB,QAAW,+BAA+B;AAExE,UAAM,MAAM,KAAK,IAAI;AACrB,SAAK,gBAAgB;AACrB,QAAI,KAAK,yBAAyB,QAAW;AAC3C,WAAK,uBAAuB;AAAA,IAC9B;AAEA,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AACA,SAAK,iBAAwB;AAAA,MAC3B,MAAM,KAAK,KAAK;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AACA,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAGA,UAAM,YAAY,WAAW,MAAM;AACjC,SAAG,QAAQ,2CAA2C;AACtD,YAAM,eAAe,IAAI,YAAY;AAAA,QACnC,MAAM,+BAAgB;AAAA,QACtB,SAAS,sCAAsC,qBAAqB,GAAI;AAAA,MAC1E,CAAC;AACD,WAAK,iBAAiB,OAAO,YAAY;AACzC,WAAK,YAAY,IAAI,YAAY;AAAA,IACnC,GAAG,kBAAkB;AACrB,UAAM,eAAe,MAAM;AACzB,mBAAa,SAAS;AAAA,IACxB;AAEA,SAAK,sBAAsB,OAAO,iBAAiB,SAAS,YAAY;AAExE,UAAM,CAAC,IAAI,uBAAuB,cAAc,IAAI,MAAM;AAAA,MACxD,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,WAAW,KAAK,OAAO;AAAA,MACvB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,MAAM,KAAK;AAAA,MACX,KAAK;AAAA,MACL,KAAK;AAAA,MACL,wBAAwB,KAAK,KAAK,IAAI;AAAA,MACtC,KAAK;AAAA,MACL;AAAA,MACA,KAAK,SAAS,aAAa;AAAA,MAC3B;AAAA,MACA,KAAK,SAAS;AAAA,MACd,KAAK,SAAS;AAAA,MACd;AAAA,MACA,MAAM,KAAK;AAAA,MACX,KAAK,SAAS;AAAA,IAChB;AAEA,QAAI,KAAK,QAAQ;AACf;AAAA,IACF;AAEA,SAAK,yBAAyB;AAC9B,SAAK,kBAAkB;AACvB,OAAG,iBAAiB,WAAW,KAAK,UAAU;AAC9C,OAAG,iBAAiB,QAAQ,KAAK,OAAO;AACxC,OAAG,iBAAiB,SAAS,KAAK,QAAQ;AAC1C,SAAK,UAAU;AACf,SAAK,gBAAgB,QAAQ,EAAE;AAE/B,QAAI;AACF,SAAG,QAAQ,2CAA2C;AACtD,YAAM,KAAK,iBAAiB;AAC5B,WAAK,iBAAiB,YAAY,KAAK,uBAAuB;AAE9D,WAAK,KAAK,KAAK,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IACjC,UAAE;AACA,mBAAa,SAAS;AACtB,WAAK,sBAAsB,OAAO;AAAA,QAChC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,YACE,IACA,QACA,WACM;AACN,QAAI,yBAAyB,MAAM,GAAG;AACpC,WAAK;AACL,WAAK,SAAS,iBAAiB,IAAI,yBAAyB,MAAM,CAAC;AACnE,WAAK,SAAS,gBAAgB,IAAI,qBAAqB;AACvD,WAAK,SAAS,gBAAgB,MAAM;AACpC,UACE,KAAK,qBAAqB,0CAC1B,GACA;AACA,aAAK,mBAAmB,qBAAqB,KAAK,kBAAkB,EAAE;AAAA,MACxE;AAAA,IACF;AAEA,OAAG,OAAO,iBAAiB;AAAA,MACzB,iBAAiB,gBAAW;AAAA,MAC5B,QAAQ,OAAO;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,qBAAqB,KAAK;AAAA,MAC1B,aAAa,KAAK;AAAA,MAClB,oBAAoB,KAAK,eACrB,KAAK,IAAI,IAAI,KAAK,eAClB;AAAA,MACJ,cAAc,KAAK;AAAA,MACnB,iBAAiB,KAAK,mBAAmB;AAAA,MACzC,mBAAmB,KAAK;AAAA,IAC1B,CAAC;AAED,UAAM,mBAAmB,KAAK,mBAAmB,MAAM;AACvD,YAAQ,kBAAkB;AAAA,MACxB,KAAK,+BAAiB,WAAW;AAC/B,YAAI,KAAK,kBAAkB,QAAW;AACpC,aAAG;AAAA,YACD;AAAA,UACF;AAAA,QAEF;AACA;AAAA,MACF;AAAA,MACA,KAAK,+BAAiB;AACpB,WAAG,QAAQ,kCAAkC;AAC7C;AAAA,MAEF,KAAK,+BAAiB;AAAA,MACtB,KAAK,+BAAiB;AAAA,MACtB,KAAK,+BAAiB;AAAA,MACtB,KAAK,+BAAiB;AACpB;AAAA,MAEF;AACE,oBAAY,gBAAgB;AAAA,IAChC;AAEA,SAAK,kBAAkBH,WAAS;AAChC,OAAG,QAAQ,+BAA+B;AAC1C,SAAK,mBAAmBA,WAAS;AACjC,SAAK,gBAAgB;AACrB,SAAK,gBAAgB;AACrB,SAAK,eAAe;AACpB,SAAK,SAAS,oBAAoB,WAAW,KAAK,UAAU;AAC5D,SAAK,SAAS,oBAAoB,QAAQ,KAAK,OAAO;AACtD,SAAK,SAAS,oBAAoB,SAAS,KAAK,QAAQ;AACxD,SAAK,SAAS,MAAM,SAAS;AAC7B,SAAK,UAAU;AACf,SAAK,sBAAsB;AAC3B,SAAK,aAAa,iBAAiB;AAEnC,UAAM,aAAa,6BAA6B,MAAM;AAEtD,YAAQ,WAAW,QAAQ;AAAA,MACzB,KAAK,+BAAiB;AACpB,aAAK,mBAAmB,UAAU,WAAW,MAAM;AACnD;AAAA,MACF,KAAK,+BAAiB;AACpB,aAAK,mBAAmB,MAAM,WAAW,MAAM;AAC/C;AAAA,MACF,KAAK,+BAAiB;AACpB,aAAK,mBAAmB,aAAa,WAAW,MAAM;AACtD;AAAA,MACF,KAAK,+BAAiB;AACpB,aAAK,mBAAmB,OAAO;AAC/B;AAAA,MACF,KAAK;AACH,aAAK,mBAAmB,WAAW,WAAW,MAAM;AACpD;AAAA,MACF;AACE,oBAAY,UAAU;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,iBAAiB,KAAqB,aAAqC;AACzE,SAAK,kBAAkB;AACvB,SAAK,aAAa,gBAAgB,YAAY,CAAC,CAAC;AAAA,EAClD;AAAA,EAEA,gBAAgB,KAAqB,aAAoC;AACvE,SAAK,kBAAkB;AACvB,UAAM,8BAA8B,KAAK,aAAa;AAAA,MACpD,YAAY,CAAC;AAAA,IACf;AACA,QAAI,gCAAgC,QAAW;AAC7C,WAAK,0BAA0B;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,eAAe,KAAqB,aAAmC;AACrE,SAAK,kBAAkB;AACvB,SAAK,aAAa,cAAc,YAAY,CAAC,CAAC;AAAA,EAChD;AAAA,EAEA,eAAqB;AACnB,UAAM,KAAK,KAAK;AAChB,OAAG;AAAA,MACD;AAAA,MACA,CAAC,KAAK,mBAAmB,GAAG,+BAAiB,YAAY;AAAA,IAC3D;AAKA,QAAI,CAAC,KAAK,mBAAmB,GAAG,+BAAiB,YAAY,GAAG;AAC9D,WAAK;AAAA,QACH;AAAA,QACA,IAAI,YAAY;AAAA,UACd,MAAM,+BAAgB;AAAA,UACtB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,oBACE,IACA,qBACM;AACN,SAAK,kBAAkB;AACvB,UAAM,OAAO,oBAAoB,CAAC;AAClC,SAAK,GAAG,YAAY,aAAa,KAAK,SAAS;AAC/C,OAAG,QAAQ,0BAA0B,IAAI;AACzC,UAAMA,aAAW,KAAK,yBAAyB,IAAI,KAAK,SAAS;AACjE,QAAI,CAACA,YAAU;AAGb,SAAG,QAAQ,mBAAmB;AAC9B;AAAA,IACF;AACA,IAAAA,WAAS,QAAQ,oBAAoB,CAAC,CAAC;AAAA,EACzC;AAAA,EAEA,MAAM,QAAQ,KAAkB,WAA0C;AAExE,WAAO,IAAI,gBAAgB,CAAC;AAE5B,UAAM,KAAK,iBAAiB;AAC5B,UAAM,KAAK,KAAK,IAAI,YAAY,aAAa,SAAS;AACtD,OAAG,QAAQ,WAAW,IAAI,UAAU,MAAM,YAAY;AACtD,UAAM,SAAS,KAAK;AACpB,WAAO,MAAM;AAEb,UAAM,yBACJ,IAAI,kBAAmB,MAAM,KAAK;AACpC,UAAM,QAAQ,yBACV,IACA,IAAI,UAAU;AAAA,MACZ,OACE,EAAE,aAAa,KAAK,oBAAoB,YACxC,EAAE,OAAO,KAAK,oBAAoB;AAAA,IACtC,IAAI;AACR,OAAG;AAAA,MACD,yBAAyB,yBAAyB;AAAA,MAClD,IAAI,UAAU,SAAS;AAAA,MACvB;AAAA,MACA,IAAI,UAAU;AAAA,MACd;AAAA,IACF;AACA,UAAM,MAAM,KAAK,IAAI;AACrB,aAAS,IAAI,OAAO,IAAI,IAAI,UAAU,QAAQ,KAAK;AACjD,YAAM,IAAI,IAAI,UAAU,CAAC;AACzB,YAAM,YAAY,MAAM,KAAK,MAAM,YAAY,IAAI,IAAI,EAAE,SAAS;AAClE,YAAM,QACJ,EAAE,SAAS,qBACN;AAAA,QACC,MAAmB;AAAA,QACnB;AAAA,QACA,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE;AAAA,QACR,MAAM,CAAC,QAAQ,EAAE,MAAyB,KAAK,eAAe,CAAC;AAAA,MACjE,IACC;AAAA,QACC,MAAmB;AAAA,QACnB;AAAA,QACA,IAAI,EAAE;AAAA,QACN,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE;AAAA,QACR,MAAM,CAAC,EAAE,IAAI;AAAA,MACf;AACN,YAAM,MAAmB;AAAA,QACvB;AAAA,QACA;AAAA,UACE,WAAW;AAAA,UACX,eAAe,IAAI;AAAA,UACnB,WAAW,CAAC,KAAK;AAAA,UACjB,aAAa,IAAI;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AACA,WAAK,QAAQ,GAAG;AAChB,UAAI,CAAC,wBAAwB;AAC3B,aAAK,sBAAsB,EAAC,UAAU,EAAE,UAAU,IAAI,EAAE,GAAE;AAAA,MAC5D;AAAA,IACF;AACA,WAAO;AAAA,MACL,iBAAiB;AAAA,QACf,cAAc;AAAA,QACd,gBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,WAAW;AACf,SAAK,IAAI,OAAO,0BAA0B,KAAK,OAAO,EAAE;AAExD,QAAI,KAAK,YAAY,MAAM;AACzB,WAAK,IAAI,OAAO,uDAAuD;AACvE,WAAK,mBAAmB;AAAA,QACtB,IAAI,YAAY;AAAA,UACd,MAAM,+BAAgB;AAAA,UACtB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAEA,QAAI,iBAAiB;AACrB,UAAM,iBAAiB,KAAK;AAC5B,UAAM,gBAAgB,MAAM;AAC1B,UAAI,KAAK;AACT,UAAI,KAAK,SAAS;AAChB,aAAK,qCAAqC,KAAK,SAAS,EAAE;AAAA,MAC5D;AACA,aAAO,GAAG,YAAY,kBAAkB,cAAc;AAAA,IACxD;AAGA,UAAM,EAAC,KAAI,IAAI,KAAK;AACpB,SAAK,SAAS,IAAI;AAElB,QAAI;AACJ,QAAI;AAEJ,WAAO,KAAK,mBAAmB,sBAAsB,GAAG;AACtD;AACA,UAAI,KAAK,cAAc;AACvB,kBAAY;AAEZ,UAAI;AACF,cAAM,eAAe,KAAK,mBAAmB;AAE7C,gBAAQ,aAAa,MAAM;AAAA,UACzB,KAAK,+BAAiB;AAAA,UACtB,KAAK,+BAAiB,cAAc;AAClC,gBAAI,KAAK,mBAAmB,oBAAoB,UAAU;AACxD,mBAAK,SAAS,iCAAiC;AAG/C,mBAAK,uBAAuB;AAAA,YAC9B;AAIA,kBAAM,mBAAmB,MAAM,YAAY;AAAA,cACzC,SAAS,KAAK,mBAAmB,eAAe;AAAA,cAChD,aAAa,KAAK,mBAAmB,mBAAmB;AAAA,YAC1D,CAAC;AAED,gBAAI,iBAAiB,QAAQ,eAAe;AAC1C,qCAAuB,iBAAiB,MAAM;AAC9C;AAAA,YACF;AAGA,gBAAI,gBAAgB,GAAG;AACrB;AAAA,YACF;AAEA,kBAAM,KAAK,SAAS,IAAI,uBAAuB;AAC/C,sCAA0B;AAE1B,mCAAuB,KAAK,mBAAmB,KAAK;AAGpD,mBAAO,KAAK,OAAO;AACnB,iBAAK,cAAc;AAEnB,eAAG,QAAQ,wBAAwB;AACnC;AAAA,UACF;AAAA,UAEA,KAAK,+BAAiB,WAAW;AAO/B,kBAAM,aAAa,IAAI,gBAAgB;AACvC,iBAAK,oBAAoB,MAAM,WAAW,MAAM;AAChD,kBAAM,CAAC,oBAAoB,kBAAkB,IAAI;AAAA,cAC/C;AAAA,cACA,WAAW;AAAA,YACb;AAEA,kBAAM,aAAa,MAAM,YAAY;AAAA,cACnC,aAAa;AAAA,cACb,oBAAoB;AAAA,cACpB,WAAW,KAAK,mBAAmB,cAAc;AAAA,cACjD,aAAa,KAAK,mBAAmB,mBAAmB;AAAA,YAC1D,CAAC;AAED,oBAAQ,WAAW,KAAK;AAAA,cACtB,KAAK,eAAe;AAClB,sBAAM,KAAK,MAAM,EAAE;AACnB;AAAA,cACF;AAAA,cAEA,KAAK;AACH;AAAA,cAEF,KAAK,aAAa;AAChB,sBAAM,cAAc,IAAI,YAAY;AAAA,kBAClC,MAAM,+BAAgB;AAAA,kBACtB,SAAS;AAAA,gBACX,CAAC;AACD,qBAAK,YAAY,IAAI,WAAW;AAChC;AAAA,cACF;AAAA,cAEA,KAAK;AACH,uCAAuB,WAAW,MAAM;AACxC;AAAA,cAEF;AACE,4BAAY,UAAU;AAAA,YAC1B;AAEA;AAAA,UACF;AAAA,UAEA,KAAK,+BAAiB,WAAW;AAE/B,eAAG;AAAA,cACD;AAAA,cACA,aAAa;AAAA,YACf;AAEA,kBAAM,KAAK,mBAAmB,mBAAmB;AACjD;AAAA,UACF;AAAA,UAEA,KAAK,+BAAiB,OAAO;AAE3B,eAAG;AAAA,cACD;AAAA,cACA,aAAa;AAAA,YACf;AAEA,kBAAM,KAAK,mBAAmB,mBAAmB;AACjD;AAAA,UACF;AAAA,UAEA,KAAK,+BAAiB;AAEpB;AAAA,UAEF;AACE,wBAAY,YAAY;AAAA,QAC5B;AAAA,MACF,SAAS,IAAI;AACX,cAAM,sBACJ,cAAc,EAAE,KAAK,GAAG,SAAS,+BAAgB;AAEnD,YACE,CAAC,KAAK,mBAAmB,GAAG,+BAAiB,SAAS,KACtD,CAAC,qBACD;AACA,gBAAM,QAAQ,YAAY,EAAE,IAAI,SAAS;AACzC,gBAAM,OAAO,cAAc,EAAE,IAAI,GAAG,OAAO;AAC3C,aAAG,KAAK,IAAI,qBAAqB,IAAI,MAAM;AAAA,YACzC,MAAM,KAAK;AAAA,YACX,YAAY,KAAK;AAAA,UACnB,CAAC;AAAA,QACH;AAEA,WAAG;AAAA,UACD;AAAA,UACA;AAAA,UACA,KAAK,mBAAmB;AAAA,UACxB;AAAA,UACA;AAAA,QACF;AAEA,cAAM,aAAa,6BAA6B,EAAE;AAElD,gBAAQ,WAAW,QAAQ;AAAA,UACzB,KAAK,sBAAsB;AAIzB,kBAAM,gBAAgB,iBAAiB,WAAW,MAAM;AACxD,gBAAI,eAAe;AACjB,kBAAI,cAAc,iBAAiB,QAAW;AAC5C,4BAAY,KAAK,IAAI,WAAW,cAAc,YAAY;AAAA,cAC5D;AACA,kBAAI,cAAc,iBAAiB,QAAW;AAC5C,4BAAY,KAAK,IAAI,WAAW,cAAc,YAAY;AAAA,cAC5D;AACA,wCAA0B,cAAc;AAAA,YAC1C;AAEA,eAAG;AAAA,cACD;AAAA,cACA;AAAA,cACA;AAAA,cACA,KAAK,mBAAmB;AAAA,YAC1B;AACA,kBAAM,MAAM,SAAS;AACrB;AAAA,UACF;AAAA,UACA,KAAK,+BAAiB,WAAW;AAC/B,eAAG;AAAA,cACD;AAAA,YACF;AACA,iBAAK,mBAAmB,UAAU,WAAW,MAAM;AAEnD;AAAA,UACF;AAAA,UACA,KAAK,+BAAiB,OAAO;AAC3B,eAAG,QAAQ,uDAAuD;AAElE,iBAAK,mBAAmB,MAAM,WAAW,MAAM;AAE/C;AAAA,UACF;AAAA,UACA,KAAK,+BAAiB,cAAc;AAClC,iBAAK,mBAAmB,aAAa,WAAW,MAAM;AACtD;AAAA,UACF;AAAA,UACA,KAAK,+BAAiB,QAAQ;AAC5B;AAAA,UACF;AAAA,UACA;AACE,wBAAY,UAAU;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,KAAkB,WAA0C;AAExE,WAAO,IAAI,gBAAgB,CAAC;AAC5B,UAAM,KAAK,KAAK,IAAI,YAAY,aAAa,SAAS;AACtD,OAAG,QAAQ,QAAQ,GAAG;AAItB,QAAI,IAAI,kBAAmB,MAAM,KAAK,eAAgB;AACpD,aAAO;AAAA,QACL,iBAAiB;AAAA,UACf,cAAc;AAAA,UACd,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,iBAAiB;AAC5B,UAAM,SAAS,KAAK;AACpB,WAAO,MAAM;AAEb,OAAG,QAAQ,+BAA+B;AAC1C,UAAM,SAAgB;AAAA,MACpB,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AACA,UAAM,qBAAyC;AAAA,MAC7C;AAAA,MACA;AAAA,QACE,eAAe,IAAI;AAAA,QACnB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,SAAK,QAAQ,kBAAkB;AAC/B,UAAM,uBAAmDA,WAAS;AAClE,SAAK,yBAAyB,IAAI,WAAW,oBAAoB;AACjE,QAAI;AACF,YAAM,aAAa,MAAM,YAAY;AAAA,QACnC,SAAS,MAAM,eAAe;AAAA,QAC9B,SAAS,qBAAqB;AAAA,MAChC,CAAC;AACD,cAAQ,WAAW,KAAK;AAAA,QACtB,KAAK;AACH,aAAG,QAAQ,kCAAkC;AAC7C,gBAAM,IAAI,YAAY;AAAA,YACpB,MAAM,+BAAgB;AAAA,YACtB,SAAS;AAAA,UACX,CAAC;AAAA,QACH,KAAK,WAAW;AACd,aAAG,QAAQ,2CAA2C;AACtD,gBAAM,WAAW,MAAM,qBAAqB;AAC5C,iBAAO;AAAA,YACL,UAAU;AAAA,cACR,QAAQ,SAAS;AAAA,cACjB,uBAAuB,SAAS;AAAA,cAChC,OAAO,CAAC;AAAA,YACV;AAAA,YACA,iBAAiB;AAAA,cACf,cAAc;AAAA,cACd,gBAAgB;AAAA,YAClB;AAAA,UACF;AAAA,QACF;AAAA,QACA;AACE,sBAAY,UAAU;AAAA,MAC1B;AAAA,IACF,UAAE;AACA,2BAAqB;AAAA,QACnB,IAAI,YAAY;AAAA,UACd,MAAM,+BAAgB;AAAA,UACtB,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA,WAAK,yBAAyB,OAAO,SAAS;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,MAAuC;AAC9C,SAAK,KAAK,OAAO,sBAAsB,IAAI;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,SAAkB;AACpB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,CAAC,aACV,KAAK,eAAe,UAAU,QAAQ;AAAA;AAAA;AAAA;AAAA,EAKxC,MAAM,MAAM,IAAmC;AAC7C,OAAG,QAAQ,SAAS;AACpB,UAAM,EAAC,SAAS,QAAO,IAAIA,WAAS;AACpC,SAAK,UAAU;AACf,UAAM,cAA2B,CAAC,QAAQ,CAAC,CAAC;AAC5C,UAAM,KAAK,YAAY,IAAI;AAC3B,WAAO,KAAK,OAAO;AACnB,SAAK,KAAK,SAAS,WAAW;AAE9B,UAAM,aAAa,MAAM,YAAY;AAAA,MACnC,aAAa;AAAA,MACb,aAAa,MAAM,eAAe;AAAA,MAClC,aAAa,KAAK,mBAAmB,mBAAmB;AAAA,IAC1D,CAAC;AAED,UAAM,QAAQ,YAAY,IAAI,IAAI;AAClC,YAAQ,WAAW,KAAK;AAAA,MACtB,KAAK,eAAe;AAClB,WAAG,QAAQ,qBAAqB,OAAO,IAAI;AAC3C;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAClB,WAAG,OAAO,kBAAkB,OAAO,oBAAoB;AACvD,cAAM,mBAAmB,IAAI,YAAY;AAAA,UACvC,MAAM,+BAAgB;AAAA,UACtB,SAAS;AAAA,QACX,CAAC;AACD,aAAK,YAAY,IAAI,gBAAgB;AACrC,cAAM;AAAA,MACR;AAAA,MAEA,KAAK,eAAe;AAClB,WAAG;AAAA,UACD;AAAA,UACA,WAAW;AAAA,QACb;AACA,+BAAuB,WAAW,MAAM;AACxC;AAAA,MACF;AAAA,MAEA;AACE,oBAAY,UAAU;AAAA,IAC1B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,YAAsB;AAAA,EAsB3C;AAAA,EAEA,mBAAmB,QAAgB;AACjC,SAAK,KAAK,wBAAwB,MAAM;AAAA,EAC1C;AAAA,EAEA,wBAAwB,SAAiB;AAAA,EAkBzC;AAAA,EAEA,iBAAiB,QAAgD;AAC/D,UAAM,KAAK,CAAC;AACZ,UAAM,UAAU,KAAK;AAErB,eAAW,QAAQ,OAAO,KAAK,OAAO,MAAM,GAAG;AAC7C,SAAG,IAAI,IAAI,SAAS,SAAS,QAAQ,IAAI;AAAA,IAC3C;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAAuB;AAMzB,iBAAa;AACX,aAAQ,KAAK,eAAe,IAAI;AAAA,QAC9B,KAAK;AAAA,QACL,KAAK;AAAA,QACL,YAAY;AACV,gBAAM,KAAK,iBAAiB;AAC5B,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAIY,CAAC,QAAQ,UAAU,SAAS;AACtC,WAAO,eAAe,MAAM,GAAG,mBAAmB,MAAM,EAAE;AAC1D,SAAK,cAAc;AAAA,MACjB;AAAA,MACA;AAAA,MACA,GAAI;AAAA,IACN;AAAA,EACF;AACF;AAEO,IAAM,gBAAN,cAA4B,aAAsB;AAAA,EACvD,UAAU;AAAA,EAEV,UAAU,QAAuB;AAC/B,QAAI,KAAK,YAAY,QAAQ;AAC3B;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,OAAO,MAAM;AAAA,EACpB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AACF;AAEA,eAAsB,aACpB,KACA,cACA,sBACA,cACA,YACA,UACA,eACA,cACA,QACA,MACA,MACA,MACA,WACA,IACA,aACA,cACA,yBACA,sBACA,kBAAkB,OAAO,GAOzB;AACA,QAAM,MAAM,IAAI;AAAA,IACd,WAAW,cAAc,UAAU,gBAAgB,UAAU;AAAA,EAC/D;AACA,QAAM,EAAC,aAAY,IAAI;AACvB,eAAa,IAAI,YAAY,QAAQ;AACrC,eAAa,IAAI,iBAAiB,aAAa;AAC/C,eAAa,IAAI,UAAU,MAAM;AACjC,eAAa,IAAI,cAAc,eAAe,OAAO,KAAK,OAAO,UAAU,CAAC;AAC5E,eAAa,IAAI,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC;AAChD,eAAa,IAAI,QAAQ,OAAO,IAAI,CAAC;AACrC,eAAa,IAAI,QAAQ,IAAI;AAC7B,MAAI,WAAW;AACb,iBAAa,IAAI,aAAa,KAAK,SAAS,CAAC;AAAA,EAC/C;AACA,MAAI,yBAAyB;AAC3B,eAAW,KAAK,yBAAyB;AACvC,UAAI,aAAa,IAAI,CAAC,GAAG;AACvB,WAAG,OAAO,kCAAkC,CAAC,EAAE;AAAA,MACjD,OAAO;AACL,qBAAa,IAAI,GAAG,wBAAwB,CAAC,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAEA,KAAG,OAAO,iBAAiB,IAAI,SAAS,CAAC;AAOzC,QAAM,KAAK,qBAAqB,WAAW;AAC3C,QAAM,gBAAgB,IAAI,MAAM,QAAM,aAAa,gBAAgB,EAAE,CAAC;AACtE,QAAM,sBAAsB,MAAM,qBAAqB,kBAAkB;AACzE,MAAI,iBACF,4BAA4B,qBAAqB,aAAa;AAChE,MAAI,eACF,MAAM;AACR,QAAM,EAAC,cAAa,IAAI;AAExB,MAAI,cAAc;AAAA,IAChB;AAAA,MACE;AAAA,MACA;AAAA,QACE,qBAAqB,CAAC,GAAG,aAAa,OAAO,CAAC;AAAA,QAC9C,SAAS,wBAAwB,cAAc;AAAA;AAAA;AAAA,QAG/C,GAAI,eAAe,OAAO,EAAC,aAAY,IAAI,CAAC;AAAA,QAC5C;AAAA,QACA;AAAA,QACA,eAAe,CAAC,GAAG,aAAa;AAAA,MAClC;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACA,MAAI,YAAY,SAAS,iBAAiB;AACxC,kBAAc,mBAAmB,QAAW,IAAI;AAChD,QAAI,YAAY,SAAS,iBAAiB;AACxC,SAAG;AAAA,QACD,8BAA8B,YAAY,MAAM,0CACd,eAAe;AAAA,MAEnD;AAAA,IACF;AACA,mBAAe;AAAA,EACjB,OAAO;AACL,qBAAiB;AAAA,EACnB;AACA,SAAO;AAAA,IACL,IAAI;AAAA;AAAA,MAEF,IAAI,SAAS;AAAA,MACb;AAAA,IACF;AAAA,IACA;AAAA,IACA,wBAAwB,cAAc;AAAA,EACxC;AACF;AAEA,SAAS,eACP,KAC0B;AAC1B,SAAO,OAAO,IAAI,SAAS,IAAI,MAAM;AACvC;AAEA,SAAS,wBACP,gBAC+B;AAC/B,MAAI,CAAC,gBAAgB;AACnB,WAAO;AAAA,EACT;AACA,QAAM,EAAC,WAAW,eAAc,IAAI;AACpC,OACG,CAAC,aAAa,UAAU,WAAW,OACnC,CAAC,kBAAkB,eAAe,WAAW,IAC9C;AACA,WAAO;AAAA,EACT;AACA,QAAM,OAAoC,CAAC;AAC3C,OAAK,YAAY,eAAe,SAAS;AACzC,OAAK,iBAAiB,eAAe,cAAc;AACnD,SAAO;AACT;AAEA,SAAS,4BACP,gBACA,eAC+B;AAC/B,MAAI,eAAe,WAAW,GAAG;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,eACf,OAAO,UAAQ,KAAK,YAAY,KAAK,kBAAkB,aAAa,EACpE,IAAI,UAAQ,KAAK,QAAQ;AAC5B,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO;AAAA,EACT;AAGA,SAAO,EAAC,UAAS;AACnB;AAMA,SAAS,qCACP,EAAC,IAAG,GACJ,IACgB;AAChB,QAAM,OAAO,IAAI,IAAI,GAAG,EAAE,aAAa,IAAI,MAAM,KAAK,OAAO;AAC7D,SAAO,2BAA2B,MAAM,EAAE;AAC5C;AAEA,SAAS,2BACP,MACA,IACgB;AAChB,SAAO,GAAG,YAAY,QAAQ,IAAI;AACpC;AAEA,SAASC,uBAAsB,UAA6B;AAAC;AAE7D,eAAe,yBACb,eACA,UACA,QACA,UAC+B;AAC/B,QAAM,UAAU,MAAM,qBAAqB;AAAA,IACzC,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACA,UAAQ,WAAW;AACnB,SAAO;AACT;",
|
|
6
|
-
"names": ["v", "db", "resolver", "promiseVoid", "promiseNever", "resolver", "process", "ReadImpl", "WriteImpl", "ReadImpl", "WriteImpl", "ReadImpl", "ReadImpl", "WriteImpl", "json", "Internal", "string", "number", "table", "table", "name", "serverName", "node", "relationship", "binarySearch", "comparator", "Internal", "InvalidMessage", "Error", "SchemaVersionNotSupported", "VersionNotSupported", "resolver", "consoleLogSink", "resolver", "resolver", "resolver", "resolver", "t", "ok", "RWLock", "RWLock", "greaterThan", "greaterThan", "zeroData", "clientID", "localMutations", "latestGCUpdate", "latestGCUpdate", "mainClientGroupID", "perdagLMID", "perdagBaseSnapshot", "memdagBaseSnapshot", "gatheredChunks", "zeroData", "perdagClientGroupHeadHash", "perdagLmid", "perdagClientGroupBaseSnapshot", "gatheredChunks", "memdagBaseSnapshot", "zeroData", "resolver", "process", "requestIdle", "resolver", "compareUTF8", "greaterThan", "scan", "diff", "diff", "newDiff", "greaterThan", "compareUTF8", "noop", "consoleLogSink", "resolver", "hasClientState", "zeroData", "pusherResult", "requestID", "beginPullResponse", "putOpSchema", "delOpSchema", "patchOpSchema", "putOpSchema", "updateOpSchema", "delOpSchema", "clearOpSchema", "table", "resolver", "mergeRelationships", "compare", "iterator", "change", "json", "key", "cmp", "push", "cmp", "table", "array", "impl", "not", "take", "filter", "condition", "table", "resolver", "cleanup", "resolver", "resolver", "clientID", "resolver", "resolver", "nextStatePromise", "compareUTF8", "comparator", "cmp", "key", "compareUTF8", "comparator", "compare", "generateWithOverlay", "add", "compare", "add", "compare", "cmp", "diff", "assertValidRunOptions", "table", "send", "TeeLogSink", "consoleLogSink", "Lock", "version", "version", "consoleLogSink", "options", "TeeLogSink", "version", "resolver", "resolver", "diff", "send", "diff", "reload", "LogContext", "Lock", "Lock", "serverToClient", "version", "resolver", "assertValidRunOptions", "e", "closeError"]
|
|
7
|
-
}
|