@rocicorp/zero 0.0.0-202410031711
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/deps/sqlite3/sqlite3.c +260574 -0
- package/deps/sqlite3/sqlite3.h +13572 -0
- package/deps/sqlite3/sqlite3ext.h +719 -0
- package/out/btree/b+tree.d.ts +471 -0
- package/out/btree/b+tree.d.ts.map +1 -0
- package/out/btree/b+tree.js +1708 -0
- package/out/btree/b+tree.js.map +1 -0
- package/out/btree/interfaces.d.ts +270 -0
- package/out/btree/interfaces.d.ts.map +1 -0
- package/out/btree/interfaces.js +3 -0
- package/out/btree/interfaces.js.map +1 -0
- package/out/chunk-2RUT5EQV.js +28 -0
- package/out/chunk-2RUT5EQV.js.map +7 -0
- package/out/datadog/src/datadog-log-sink.d.ts +20 -0
- package/out/datadog/src/datadog-log-sink.d.ts.map +1 -0
- package/out/datadog/src/datadog-log-sink.js +231 -0
- package/out/datadog/src/datadog-log-sink.js.map +1 -0
- package/out/datadog/src/mod.d.ts +2 -0
- package/out/datadog/src/mod.d.ts.map +1 -0
- package/out/react.js +108 -0
- package/out/react.js.map +7 -0
- package/out/replicache/src/async-iterable-to-array.d.ts +2 -0
- package/out/replicache/src/async-iterable-to-array.d.ts.map +1 -0
- package/out/replicache/src/bg-interval.d.ts +3 -0
- package/out/replicache/src/bg-interval.d.ts.map +1 -0
- package/out/replicache/src/binary-search.d.ts +15 -0
- package/out/replicache/src/binary-search.d.ts.map +1 -0
- package/out/replicache/src/broadcast-channel.d.ts +3 -0
- package/out/replicache/src/broadcast-channel.d.ts.map +1 -0
- package/out/replicache/src/btree/diff.d.ts +4 -0
- package/out/replicache/src/btree/diff.d.ts.map +1 -0
- package/out/replicache/src/btree/node.d.ts +125 -0
- package/out/replicache/src/btree/node.d.ts.map +1 -0
- package/out/replicache/src/btree/read.d.ts +32 -0
- package/out/replicache/src/btree/read.d.ts.map +1 -0
- package/out/replicache/src/btree/splice.d.ts +9 -0
- package/out/replicache/src/btree/splice.d.ts.map +1 -0
- package/out/replicache/src/btree/write.d.ts +24 -0
- package/out/replicache/src/btree/write.d.ts.map +1 -0
- package/out/replicache/src/call-default-fetch.d.ts +6 -0
- package/out/replicache/src/call-default-fetch.d.ts.map +1 -0
- package/out/replicache/src/config.d.ts +13 -0
- package/out/replicache/src/config.d.ts.map +1 -0
- package/out/replicache/src/connection-loop-delegates.d.ts +20 -0
- package/out/replicache/src/connection-loop-delegates.d.ts.map +1 -0
- package/out/replicache/src/connection-loop.d.ts +28 -0
- package/out/replicache/src/connection-loop.d.ts.map +1 -0
- package/out/replicache/src/cookies.d.ts +29 -0
- package/out/replicache/src/cookies.d.ts.map +1 -0
- package/out/replicache/src/dag/chunk.d.ts +35 -0
- package/out/replicache/src/dag/chunk.d.ts.map +1 -0
- package/out/replicache/src/dag/gc.d.ts +42 -0
- package/out/replicache/src/dag/gc.d.ts.map +1 -0
- package/out/replicache/src/dag/key.d.ts +26 -0
- package/out/replicache/src/dag/key.d.ts.map +1 -0
- package/out/replicache/src/dag/lazy-store.d.ts +181 -0
- package/out/replicache/src/dag/lazy-store.d.ts.map +1 -0
- package/out/replicache/src/dag/store-impl.d.ts +38 -0
- package/out/replicache/src/dag/store-impl.d.ts.map +1 -0
- package/out/replicache/src/dag/store.d.ts +36 -0
- package/out/replicache/src/dag/store.d.ts.map +1 -0
- package/out/replicache/src/dag/visitor.d.ts +13 -0
- package/out/replicache/src/dag/visitor.d.ts.map +1 -0
- package/out/replicache/src/db/commit.d.ts +133 -0
- package/out/replicache/src/db/commit.d.ts.map +1 -0
- package/out/replicache/src/db/index.d.ts +33 -0
- package/out/replicache/src/db/index.d.ts.map +1 -0
- package/out/replicache/src/db/read.d.ts +24 -0
- package/out/replicache/src/db/read.d.ts.map +1 -0
- package/out/replicache/src/db/rebase.d.ts +10 -0
- package/out/replicache/src/db/rebase.d.ts.map +1 -0
- package/out/replicache/src/db/scan.d.ts +15 -0
- package/out/replicache/src/db/scan.d.ts.map +1 -0
- package/out/replicache/src/db/write.d.ts +39 -0
- package/out/replicache/src/db/write.d.ts.map +1 -0
- package/out/replicache/src/error-responses.d.ts +26 -0
- package/out/replicache/src/error-responses.d.ts.map +1 -0
- package/out/replicache/src/filter-async-iterable.d.ts +10 -0
- package/out/replicache/src/filter-async-iterable.d.ts.map +1 -0
- package/out/replicache/src/format-version.d.ts +9 -0
- package/out/replicache/src/format-version.d.ts.map +1 -0
- package/out/replicache/src/frozen-json.d.ts +35 -0
- package/out/replicache/src/frozen-json.d.ts.map +1 -0
- package/out/replicache/src/get-default-puller.d.ts +14 -0
- package/out/replicache/src/get-default-puller.d.ts.map +1 -0
- package/out/replicache/src/get-default-pusher.d.ts +10 -0
- package/out/replicache/src/get-default-pusher.d.ts.map +1 -0
- package/out/replicache/src/hash.d.ts +29 -0
- package/out/replicache/src/hash.d.ts.map +1 -0
- package/out/replicache/src/http-request-info.d.ts +6 -0
- package/out/replicache/src/http-request-info.d.ts.map +1 -0
- package/out/replicache/src/impl.d.ts +4 -0
- package/out/replicache/src/impl.d.ts.map +1 -0
- package/out/replicache/src/index-defs.d.ts +36 -0
- package/out/replicache/src/index-defs.d.ts.map +1 -0
- package/out/replicache/src/iterable-union.d.ts +5 -0
- package/out/replicache/src/iterable-union.d.ts.map +1 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts +25 -0
- package/out/replicache/src/kv/idb-store-with-mem-fallback.d.ts.map +1 -0
- package/out/replicache/src/kv/idb-store.d.ts +18 -0
- package/out/replicache/src/kv/idb-store.d.ts.map +1 -0
- package/out/replicache/src/kv/mem-store.d.ts +23 -0
- package/out/replicache/src/kv/mem-store.d.ts.map +1 -0
- package/out/replicache/src/kv/read-impl.d.ts +11 -0
- package/out/replicache/src/kv/read-impl.d.ts.map +1 -0
- package/out/replicache/src/kv/store.d.ts +76 -0
- package/out/replicache/src/kv/store.d.ts.map +1 -0
- package/out/replicache/src/kv/write-impl-base.d.ts +18 -0
- package/out/replicache/src/kv/write-impl-base.d.ts.map +1 -0
- package/out/replicache/src/kv/write-impl.d.ts +9 -0
- package/out/replicache/src/kv/write-impl.d.ts.map +1 -0
- package/out/replicache/src/lazy.d.ts +2 -0
- package/out/replicache/src/lazy.d.ts.map +1 -0
- package/out/replicache/src/log-options.d.ts +10 -0
- package/out/replicache/src/log-options.d.ts.map +1 -0
- package/out/replicache/src/merge-async-iterables.d.ts +16 -0
- package/out/replicache/src/merge-async-iterables.d.ts.map +1 -0
- package/out/replicache/src/mod.d.ts +38 -0
- package/out/replicache/src/mod.d.ts.map +1 -0
- package/out/replicache/src/mutation-recovery.d.ts +43 -0
- package/out/replicache/src/mutation-recovery.d.ts.map +1 -0
- package/out/replicache/src/new-client-channel.d.ts +6 -0
- package/out/replicache/src/new-client-channel.d.ts.map +1 -0
- package/out/replicache/src/on-persist-channel.d.ts +10 -0
- package/out/replicache/src/on-persist-channel.d.ts.map +1 -0
- package/out/replicache/src/patch-operation.d.ts +32 -0
- package/out/replicache/src/patch-operation.d.ts.map +1 -0
- package/out/replicache/src/pending-mutations.d.ts +14 -0
- package/out/replicache/src/pending-mutations.d.ts.map +1 -0
- package/out/replicache/src/persist/client-gc.d.ts +17 -0
- package/out/replicache/src/persist/client-gc.d.ts.map +1 -0
- package/out/replicache/src/persist/client-group-gc.d.ts +10 -0
- package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -0
- package/out/replicache/src/persist/client-groups.d.ts +72 -0
- package/out/replicache/src/persist/client-groups.d.ts.map +1 -0
- package/out/replicache/src/persist/clients.d.ts +155 -0
- package/out/replicache/src/persist/clients.d.ts.map +1 -0
- package/out/replicache/src/persist/collect-idb-databases.d.ts +91 -0
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.d.ts +12 -0
- package/out/replicache/src/persist/gather-mem-only-visitor.d.ts.map +1 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.d.ts +17 -0
- package/out/replicache/src/persist/gather-not-cached-visitor.d.ts.map +1 -0
- package/out/replicache/src/persist/heartbeat.d.ts +9 -0
- package/out/replicache/src/persist/heartbeat.d.ts.map +1 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.d.ts +5 -0
- package/out/replicache/src/persist/idb-databases-store-db-name.d.ts.map +1 -0
- package/out/replicache/src/persist/idb-databases-store.d.ts +24 -0
- package/out/replicache/src/persist/idb-databases-store.d.ts.map +1 -0
- package/out/replicache/src/persist/make-client-id.d.ts +6 -0
- package/out/replicache/src/persist/make-client-id.d.ts.map +1 -0
- package/out/replicache/src/persist/persist.d.ts +26 -0
- package/out/replicache/src/persist/persist.d.ts.map +1 -0
- package/out/replicache/src/persist/refresh.d.ts +13 -0
- package/out/replicache/src/persist/refresh.d.ts.map +1 -0
- package/out/replicache/src/process-scheduler.d.ts +20 -0
- package/out/replicache/src/process-scheduler.d.ts.map +1 -0
- package/out/replicache/src/puller.d.ts +61 -0
- package/out/replicache/src/puller.d.ts.map +1 -0
- package/out/replicache/src/pusher.d.ts +33 -0
- package/out/replicache/src/pusher.d.ts.map +1 -0
- package/out/replicache/src/replicache-impl.d.ts +321 -0
- package/out/replicache/src/replicache-impl.d.ts.map +1 -0
- package/out/replicache/src/replicache-options.d.ts +209 -0
- package/out/replicache/src/replicache-options.d.ts.map +1 -0
- package/out/replicache/src/replicache.d.ts +298 -0
- package/out/replicache/src/replicache.d.ts.map +1 -0
- package/out/replicache/src/request-idle.d.ts +6 -0
- package/out/replicache/src/request-idle.d.ts.map +1 -0
- package/out/replicache/src/scan-iterator.d.ts +127 -0
- package/out/replicache/src/scan-iterator.d.ts.map +1 -0
- package/out/replicache/src/scan-options.d.ts +67 -0
- package/out/replicache/src/scan-options.d.ts.map +1 -0
- package/out/replicache/src/set-interval-with-signal.d.ts +2 -0
- package/out/replicache/src/set-interval-with-signal.d.ts.map +1 -0
- package/out/replicache/src/size-of-value.d.ts +19 -0
- package/out/replicache/src/size-of-value.d.ts.map +1 -0
- package/out/replicache/src/subscriptions.d.ts +140 -0
- package/out/replicache/src/subscriptions.d.ts.map +1 -0
- package/out/replicache/src/sync/diff.d.ts +31 -0
- package/out/replicache/src/sync/diff.d.ts.map +1 -0
- package/out/replicache/src/sync/ids.d.ts +13 -0
- package/out/replicache/src/sync/ids.d.ts.map +1 -0
- package/out/replicache/src/sync/patch.d.ts +5 -0
- package/out/replicache/src/sync/patch.d.ts.map +1 -0
- package/out/replicache/src/sync/pull-error.d.ts +9 -0
- package/out/replicache/src/sync/pull-error.d.ts.map +1 -0
- package/out/replicache/src/sync/pull.d.ts +82 -0
- package/out/replicache/src/sync/pull.d.ts.map +1 -0
- package/out/replicache/src/sync/push.d.ts +65 -0
- package/out/replicache/src/sync/push.d.ts.map +1 -0
- package/out/replicache/src/sync/request-id.d.ts +10 -0
- package/out/replicache/src/sync/request-id.d.ts.map +1 -0
- package/out/replicache/src/sync/sync-head-name.d.ts +2 -0
- package/out/replicache/src/sync/sync-head-name.d.ts.map +1 -0
- package/out/replicache/src/test-license-key.d.ts +3 -0
- package/out/replicache/src/test-license-key.d.ts.map +1 -0
- package/out/replicache/src/to-error.d.ts +2 -0
- package/out/replicache/src/to-error.d.ts.map +1 -0
- package/out/replicache/src/transaction-closed-error.d.ts +12 -0
- package/out/replicache/src/transaction-closed-error.d.ts.map +1 -0
- package/out/replicache/src/transactions.d.ts +156 -0
- package/out/replicache/src/transactions.d.ts.map +1 -0
- package/out/replicache/src/types.d.ts +57 -0
- package/out/replicache/src/types.d.ts.map +1 -0
- package/out/replicache/src/version.d.ts +5 -0
- package/out/replicache/src/version.d.ts.map +1 -0
- package/out/replicache/src/with-transactions.d.ts +23 -0
- package/out/replicache/src/with-transactions.d.ts.map +1 -0
- package/out/shared/src/abort-error.d.ts +4 -0
- package/out/shared/src/abort-error.d.ts.map +1 -0
- package/out/shared/src/abort-error.js +4 -0
- package/out/shared/src/abort-error.js.map +1 -0
- package/out/shared/src/asserts.d.ts +17 -0
- package/out/shared/src/asserts.d.ts.map +1 -0
- package/out/shared/src/asserts.js +73 -0
- package/out/shared/src/asserts.js.map +1 -0
- package/out/shared/src/browser-env.d.ts +3 -0
- package/out/shared/src/browser-env.d.ts.map +1 -0
- package/out/shared/src/config.d.ts +3 -0
- package/out/shared/src/config.d.ts.map +1 -0
- package/out/shared/src/config.js +3 -0
- package/out/shared/src/config.js.map +1 -0
- package/out/shared/src/custom-key-map.d.ts +26 -0
- package/out/shared/src/custom-key-map.d.ts.map +1 -0
- package/out/shared/src/custom-key-map.js +65 -0
- package/out/shared/src/custom-key-map.js.map +1 -0
- package/out/shared/src/deep-clone.d.ts +4 -0
- package/out/shared/src/deep-clone.d.ts.map +1 -0
- package/out/shared/src/document-visible.d.ts +9 -0
- package/out/shared/src/document-visible.d.ts.map +1 -0
- package/out/shared/src/has-own.d.ts +5 -0
- package/out/shared/src/has-own.d.ts.map +1 -0
- package/out/shared/src/has-own.js +8 -0
- package/out/shared/src/has-own.js.map +1 -0
- package/out/shared/src/immutable.d.ts +11 -0
- package/out/shared/src/immutable.d.ts.map +1 -0
- package/out/shared/src/iterables.d.ts +11 -0
- package/out/shared/src/iterables.d.ts.map +1 -0
- package/out/shared/src/json-schema.d.ts +5 -0
- package/out/shared/src/json-schema.d.ts.map +1 -0
- package/out/shared/src/json-schema.js +36 -0
- package/out/shared/src/json-schema.js.map +1 -0
- package/out/shared/src/json.d.ts +55 -0
- package/out/shared/src/json.d.ts.map +1 -0
- package/out/shared/src/json.js +164 -0
- package/out/shared/src/json.js.map +1 -0
- package/out/shared/src/must.d.ts +2 -0
- package/out/shared/src/must.d.ts.map +1 -0
- package/out/shared/src/must.js +8 -0
- package/out/shared/src/must.js.map +1 -0
- package/out/shared/src/navigator.d.ts +7 -0
- package/out/shared/src/navigator.d.ts.map +1 -0
- package/out/shared/src/parse-big-int.d.ts +2 -0
- package/out/shared/src/parse-big-int.d.ts.map +1 -0
- package/out/shared/src/parse-big-int.js +11 -0
- package/out/shared/src/parse-big-int.js.map +1 -0
- package/out/shared/src/queue.d.ts +40 -0
- package/out/shared/src/queue.d.ts.map +1 -0
- package/out/shared/src/queue.js +118 -0
- package/out/shared/src/queue.js.map +1 -0
- package/out/shared/src/rand.d.ts +7 -0
- package/out/shared/src/rand.d.ts.map +1 -0
- package/out/shared/src/rand.js +11 -0
- package/out/shared/src/rand.js.map +1 -0
- package/out/shared/src/random-uint64.d.ts +2 -0
- package/out/shared/src/random-uint64.d.ts.map +1 -0
- package/out/shared/src/random-values.d.ts +2 -0
- package/out/shared/src/random-values.d.ts.map +1 -0
- package/out/shared/src/resolved-promises.d.ts +5 -0
- package/out/shared/src/resolved-promises.d.ts.map +1 -0
- package/out/shared/src/resolved-promises.js +5 -0
- package/out/shared/src/resolved-promises.js.map +1 -0
- package/out/shared/src/set-utils.d.ts +9 -0
- package/out/shared/src/set-utils.d.ts.map +1 -0
- package/out/shared/src/set-utils.js +60 -0
- package/out/shared/src/set-utils.js.map +1 -0
- package/out/shared/src/sleep.d.ts +15 -0
- package/out/shared/src/sleep.d.ts.map +1 -0
- package/out/shared/src/sleep.js +54 -0
- package/out/shared/src/sleep.js.map +1 -0
- package/out/shared/src/string-compare.d.ts +2 -0
- package/out/shared/src/string-compare.d.ts.map +1 -0
- package/out/shared/src/string-compare.js +10 -0
- package/out/shared/src/string-compare.js.map +1 -0
- package/out/shared/src/types.d.ts +2 -0
- package/out/shared/src/types.d.ts.map +1 -0
- package/out/shared/src/valita.d.ts +27 -0
- package/out/shared/src/valita.d.ts.map +1 -0
- package/out/shared/src/valita.js +118 -0
- package/out/shared/src/valita.js.map +1 -0
- package/out/shared/src/xxhash.d.ts +3 -0
- package/out/shared/src/xxhash.d.ts.map +1 -0
- package/out/shared/src/xxhash.js +4 -0
- package/out/shared/src/xxhash.js.map +1 -0
- package/out/zero/src/cli.d.ts +3 -0
- package/out/zero/src/cli.d.ts.map +1 -0
- package/out/zero/src/cli.js +3 -0
- package/out/zero/src/cli.js.map +1 -0
- package/out/zero/src/react.d.ts +2 -0
- package/out/zero/src/react.d.ts.map +1 -0
- package/out/zero/src/server/change-streamer.d.ts +2 -0
- package/out/zero/src/server/change-streamer.d.ts.map +1 -0
- package/out/zero/src/server/change-streamer.js +2 -0
- package/out/zero/src/server/change-streamer.js.map +1 -0
- package/out/zero/src/server/main.d.ts +2 -0
- package/out/zero/src/server/main.d.ts.map +1 -0
- package/out/zero/src/server/main.js +2 -0
- package/out/zero/src/server/main.js.map +1 -0
- package/out/zero/src/server/replicator.d.ts +2 -0
- package/out/zero/src/server/replicator.d.ts.map +1 -0
- package/out/zero/src/server/replicator.js +2 -0
- package/out/zero/src/server/replicator.js.map +1 -0
- package/out/zero/src/server/syncer.d.ts +2 -0
- package/out/zero/src/server/syncer.d.ts.map +1 -0
- package/out/zero/src/server/syncer.js +2 -0
- package/out/zero/src/server/syncer.js.map +1 -0
- package/out/zero/src/zero.d.ts +2 -0
- package/out/zero/src/zero.d.ts.map +1 -0
- package/out/zero-cache/src/config/zero-config.d.ts +1509 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -0
- package/out/zero-cache/src/config/zero-config.js +227 -0
- package/out/zero-cache/src/config/zero-config.js.map +1 -0
- package/out/zero-cache/src/db/lite-tables.d.ts +5 -0
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -0
- package/out/zero-cache/src/db/lite-tables.js +75 -0
- package/out/zero-cache/src/db/lite-tables.js.map +1 -0
- package/out/zero-cache/src/db/migration-lite.d.ts +38 -0
- package/out/zero-cache/src/db/migration-lite.d.ts.map +1 -0
- package/out/zero-cache/src/db/migration-lite.js +161 -0
- package/out/zero-cache/src/db/migration-lite.js.map +1 -0
- package/out/zero-cache/src/db/migration.d.ts +38 -0
- package/out/zero-cache/src/db/migration.d.ts.map +1 -0
- package/out/zero-cache/src/db/migration.js +139 -0
- package/out/zero-cache/src/db/migration.js.map +1 -0
- package/out/zero-cache/src/db/statements.d.ts +31 -0
- package/out/zero-cache/src/db/statements.d.ts.map +1 -0
- package/out/zero-cache/src/db/statements.js +48 -0
- package/out/zero-cache/src/db/statements.js.map +1 -0
- package/out/zero-cache/src/db/transaction-pool.d.ts +187 -0
- package/out/zero-cache/src/db/transaction-pool.d.ts.map +1 -0
- package/out/zero-cache/src/db/transaction-pool.js +445 -0
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -0
- package/out/zero-cache/src/server/change-streamer.d.ts +3 -0
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -0
- package/out/zero-cache/src/server/change-streamer.js +30 -0
- package/out/zero-cache/src/server/change-streamer.js.map +1 -0
- package/out/zero-cache/src/server/logging.d.ts +6 -0
- package/out/zero-cache/src/server/logging.d.ts.map +1 -0
- package/out/zero-cache/src/server/logging.js +23 -0
- package/out/zero-cache/src/server/logging.js.map +1 -0
- package/out/zero-cache/src/server/main.d.ts +2 -0
- package/out/zero-cache/src/server/main.d.ts.map +1 -0
- package/out/zero-cache/src/server/main.js +92 -0
- package/out/zero-cache/src/server/main.js.map +1 -0
- package/out/zero-cache/src/server/replicator.d.ts +3 -0
- package/out/zero-cache/src/server/replicator.d.ts.map +1 -0
- package/out/zero-cache/src/server/replicator.js +35 -0
- package/out/zero-cache/src/server/replicator.js.map +1 -0
- package/out/zero-cache/src/server/syncer.d.ts +3 -0
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -0
- package/out/zero-cache/src/server/syncer.js +45 -0
- package/out/zero-cache/src/server/syncer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +23 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +98 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts +39 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +212 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts +110 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +7 -0
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.js +56 -0
- package/out/zero-cache/src/services/change-streamer/forwarder.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/change-source.d.ts +14 -0
- package/out/zero-cache/src/services/change-streamer/pg/change-source.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/change-source.js +206 -0
- package/out/zero-cache/src/services/change-streamer/pg/change-source.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.d.ts +6 -0
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.js +192 -0
- package/out/zero-cache/src/services/change-streamer/pg/initial-sync.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/lsn.d.ts +17 -0
- package/out/zero-cache/src/services/change-streamer/pg/lsn.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/lsn.js +17 -0
- package/out/zero-cache/src/services/change-streamer/pg/lsn.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/create.d.ts +6 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/create.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/create.js +29 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/create.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.d.ts +79 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js +237 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/ddl.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/lite.d.ts +5 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/lite.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/lite.js +111 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/lite.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/published.d.ts +26 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/published.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/published.js +185 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/published.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/zero.d.ts +11 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/zero.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/zero.js +86 -0
- package/out/zero-cache/src/services/change-streamer/pg/schema/zero.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/shard-config.d.ts +19 -0
- package/out/zero-cache/src/services/change-streamer/pg/shard-config.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/shard-config.js +2 -0
- package/out/zero-cache/src/services/change-streamer/pg/shard-config.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/sync-schema.d.ts +4 -0
- package/out/zero-cache/src/services/change-streamer/pg/sync-schema.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/pg/sync-schema.js +12 -0
- package/out/zero-cache/src/services/change-streamer/pg/sync-schema.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/change.d.ts +31 -0
- package/out/zero-cache/src/services/change-streamer/schema/change.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/change.js +2 -0
- package/out/zero-cache/src/services/change-streamer/schema/change.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.d.ts +4 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.js +10 -0
- package/out/zero-cache/src/services/change-streamer/schema/init.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts +22 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +49 -0
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/storer.d.ts +22 -0
- package/out/zero-cache/src/services/change-streamer/storer.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/storer.js +157 -0
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts +27 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.js +70 -0
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -0
- package/out/zero-cache/src/services/dispatcher/connect-params.d.ts +20 -0
- package/out/zero-cache/src/services/dispatcher/connect-params.d.ts.map +1 -0
- package/out/zero-cache/src/services/dispatcher/connect-params.js +36 -0
- package/out/zero-cache/src/services/dispatcher/connect-params.js.map +1 -0
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts +19 -0
- package/out/zero-cache/src/services/dispatcher/dispatcher.d.ts.map +1 -0
- package/out/zero-cache/src/services/dispatcher/dispatcher.js +55 -0
- package/out/zero-cache/src/services/dispatcher/dispatcher.js.map +1 -0
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts +11 -0
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.d.ts.map +1 -0
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.js +33 -0
- package/out/zero-cache/src/services/dispatcher/websocket-handoff.js.map +1 -0
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.d.ts +57 -0
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.d.ts.map +1 -0
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js +130 -0
- package/out/zero-cache/src/services/limiter/sliding-window-limiter.js.map +1 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts +24 -0
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -0
- package/out/zero-cache/src/services/mutagen/mutagen.js +247 -0
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -0
- package/out/zero-cache/src/services/mutagen/write-authorizer.d.ts +20 -0
- package/out/zero-cache/src/services/mutagen/write-authorizer.d.ts.map +1 -0
- package/out/zero-cache/src/services/mutagen/write-authorizer.js +187 -0
- package/out/zero-cache/src/services/mutagen/write-authorizer.js.map +1 -0
- package/out/zero-cache/src/services/replicator/checkpointer.d.ts +79 -0
- package/out/zero-cache/src/services/replicator/checkpointer.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/checkpointer.js +124 -0
- package/out/zero-cache/src/services/replicator/checkpointer.js.map +1 -0
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts +39 -0
- package/out/zero-cache/src/services/replicator/incremental-sync.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/incremental-sync.js +342 -0
- package/out/zero-cache/src/services/replicator/incremental-sync.js.map +1 -0
- package/out/zero-cache/src/services/replicator/notifier.d.ts +30 -0
- package/out/zero-cache/src/services/replicator/notifier.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/notifier.js +54 -0
- package/out/zero-cache/src/services/replicator/notifier.js.map +1 -0
- package/out/zero-cache/src/services/replicator/replicator.d.ts +65 -0
- package/out/zero-cache/src/services/replicator/replicator.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/replicator.js +27 -0
- package/out/zero-cache/src/services/replicator/replicator.js.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +35 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.js +78 -0
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts +25 -0
- package/out/zero-cache/src/services/replicator/schema/replication-state.d.ts.map +1 -0
- package/out/zero-cache/src/services/replicator/schema/replication-state.js +90 -0
- package/out/zero-cache/src/services/replicator/schema/replication-state.js.map +1 -0
- package/out/zero-cache/src/services/runner.d.ts +21 -0
- package/out/zero-cache/src/services/runner.d.ts.map +1 -0
- package/out/zero-cache/src/services/runner.js +63 -0
- package/out/zero-cache/src/services/runner.js.map +1 -0
- package/out/zero-cache/src/services/running-state.d.ts +56 -0
- package/out/zero-cache/src/services/running-state.d.ts.map +1 -0
- package/out/zero-cache/src/services/running-state.js +106 -0
- package/out/zero-cache/src/services/running-state.js.map +1 -0
- package/out/zero-cache/src/services/service.d.ts +29 -0
- package/out/zero-cache/src/services/service.d.ts.map +1 -0
- package/out/zero-cache/src/services/service.js +2 -0
- package/out/zero-cache/src/services/service.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +53 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.js +184 -0
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +44 -0
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +386 -0
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts +146 -0
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/cvr.js +446 -0
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/database-storage.d.ts +22 -0
- package/out/zero-cache/src/services/view-syncer/database-storage.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/database-storage.js +129 -0
- package/out/zero-cache/src/services/view-syncer/database-storage.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +103 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +290 -0
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts +54 -0
- package/out/zero-cache/src/services/view-syncer/schema/cvr.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +181 -0
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/pg-migrations.d.ts +4 -0
- package/out/zero-cache/src/services/view-syncer/schema/pg-migrations.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/pg-migrations.js +12 -0
- package/out/zero-cache/src/services/view-syncer/schema/pg-migrations.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts +783 -0
- package/out/zero-cache/src/services/view-syncer/schema/types.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/schema/types.js +213 -0
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +166 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +374 -0
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -0
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +37 -0
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -0
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +522 -0
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -0
- package/out/zero-cache/src/types/bigint-json.d.ts +26 -0
- package/out/zero-cache/src/types/bigint-json.d.ts.map +1 -0
- package/out/zero-cache/src/types/bigint-json.js +49 -0
- package/out/zero-cache/src/types/bigint-json.js.map +1 -0
- package/out/zero-cache/src/types/error-for-client.d.ts +7 -0
- package/out/zero-cache/src/types/error-for-client.d.ts.map +1 -0
- package/out/zero-cache/src/types/error-for-client.js +17 -0
- package/out/zero-cache/src/types/error-for-client.js.map +1 -0
- package/out/zero-cache/src/types/lexi-version.d.ts +29 -0
- package/out/zero-cache/src/types/lexi-version.d.ts.map +1 -0
- package/out/zero-cache/src/types/lexi-version.js +36 -0
- package/out/zero-cache/src/types/lexi-version.js.map +1 -0
- package/out/zero-cache/src/types/lite.d.ts +11 -0
- package/out/zero-cache/src/types/lite.d.ts.map +1 -0
- package/out/zero-cache/src/types/lite.js +26 -0
- package/out/zero-cache/src/types/lite.js.map +1 -0
- package/out/zero-cache/src/types/names.d.ts +5 -0
- package/out/zero-cache/src/types/names.d.ts.map +1 -0
- package/out/zero-cache/src/types/names.js +4 -0
- package/out/zero-cache/src/types/names.js.map +1 -0
- package/out/zero-cache/src/types/pg.d.ts +31 -0
- package/out/zero-cache/src/types/pg.d.ts.map +1 -0
- package/out/zero-cache/src/types/pg.js +60 -0
- package/out/zero-cache/src/types/pg.js.map +1 -0
- package/out/zero-cache/src/types/processes.d.ts +57 -0
- package/out/zero-cache/src/types/processes.d.ts.map +1 -0
- package/out/zero-cache/src/types/processes.js +121 -0
- package/out/zero-cache/src/types/processes.js.map +1 -0
- package/out/zero-cache/src/types/row-key.d.ts +37 -0
- package/out/zero-cache/src/types/row-key.d.ts.map +1 -0
- package/out/zero-cache/src/types/row-key.js +64 -0
- package/out/zero-cache/src/types/row-key.js.map +1 -0
- package/out/zero-cache/src/types/satisfies.d.ts +14 -0
- package/out/zero-cache/src/types/satisfies.d.ts.map +1 -0
- package/out/zero-cache/src/types/satisfies.js +2 -0
- package/out/zero-cache/src/types/satisfies.js.map +1 -0
- package/out/zero-cache/src/types/specs.d.ts +29 -0
- package/out/zero-cache/src/types/specs.d.ts.map +1 -0
- package/out/zero-cache/src/types/specs.js +2 -0
- package/out/zero-cache/src/types/specs.js.map +1 -0
- package/out/zero-cache/src/types/sql.d.ts +11 -0
- package/out/zero-cache/src/types/sql.d.ts.map +1 -0
- package/out/zero-cache/src/types/sql.js +15 -0
- package/out/zero-cache/src/types/sql.js.map +1 -0
- package/out/zero-cache/src/types/streams.d.ts +33 -0
- package/out/zero-cache/src/types/streams.d.ts.map +1 -0
- package/out/zero-cache/src/types/streams.js +141 -0
- package/out/zero-cache/src/types/streams.js.map +1 -0
- package/out/zero-cache/src/types/subscription.d.ts +158 -0
- package/out/zero-cache/src/types/subscription.d.ts.map +1 -0
- package/out/zero-cache/src/types/subscription.js +233 -0
- package/out/zero-cache/src/types/subscription.js.map +1 -0
- package/out/zero-cache/src/types/timeout.d.ts +11 -0
- package/out/zero-cache/src/types/timeout.d.ts.map +1 -0
- package/out/zero-cache/src/types/timeout.js +23 -0
- package/out/zero-cache/src/types/timeout.js.map +1 -0
- package/out/zero-cache/src/types/url-params.d.ts +10 -0
- package/out/zero-cache/src/types/url-params.d.ts.map +1 -0
- package/out/zero-cache/src/types/url-params.js +35 -0
- package/out/zero-cache/src/types/url-params.js.map +1 -0
- package/out/zero-cache/src/workers/connection.d.ts +25 -0
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -0
- package/out/zero-cache/src/workers/connection.js +189 -0
- package/out/zero-cache/src/workers/connection.js.map +1 -0
- package/out/zero-cache/src/workers/replicator.d.ts +17 -0
- package/out/zero-cache/src/workers/replicator.d.ts.map +1 -0
- package/out/zero-cache/src/workers/replicator.js +105 -0
- package/out/zero-cache/src/workers/replicator.js.map +1 -0
- package/out/zero-cache/src/workers/syncer.d.ts +28 -0
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -0
- package/out/zero-cache/src/workers/syncer.js +72 -0
- package/out/zero-cache/src/workers/syncer.js.map +1 -0
- package/out/zero-client/src/client/context.d.ts +23 -0
- package/out/zero-client/src/client/context.d.ts.map +1 -0
- package/out/zero-client/src/client/crud.d.ts +52 -0
- package/out/zero-client/src/client/crud.d.ts.map +1 -0
- package/out/zero-client/src/client/enable-analytics.d.ts +3 -0
- package/out/zero-client/src/client/enable-analytics.d.ts.map +1 -0
- package/out/zero-client/src/client/http-string.d.ts +7 -0
- package/out/zero-client/src/client/http-string.d.ts.map +1 -0
- package/out/zero-client/src/client/keys.d.ts +11 -0
- package/out/zero-client/src/client/keys.d.ts.map +1 -0
- package/out/zero-client/src/client/log-options.d.ts +12 -0
- package/out/zero-client/src/client/log-options.d.ts.map +1 -0
- package/out/zero-client/src/client/metrics.d.ts +115 -0
- package/out/zero-client/src/client/metrics.d.ts.map +1 -0
- package/out/zero-client/src/client/options.d.ts +94 -0
- package/out/zero-client/src/client/options.d.ts.map +1 -0
- package/out/zero-client/src/client/query-manager.d.ts +16 -0
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -0
- package/out/zero-client/src/client/reload-error-handler.d.ts +5 -0
- package/out/zero-client/src/client/reload-error-handler.d.ts.map +1 -0
- package/out/zero-client/src/client/replicache-types.d.ts +48 -0
- package/out/zero-client/src/client/replicache-types.d.ts.map +1 -0
- package/out/zero-client/src/client/server-error.d.ts +12 -0
- package/out/zero-client/src/client/server-error.d.ts.map +1 -0
- package/out/zero-client/src/client/server-option.d.ts +3 -0
- package/out/zero-client/src/client/server-option.d.ts.map +1 -0
- package/out/zero-client/src/client/version.d.ts +5 -0
- package/out/zero-client/src/client/version.d.ts.map +1 -0
- package/out/zero-client/src/client/zero-poke-handler.d.ts +28 -0
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -0
- package/out/zero-client/src/client/zero.d.ts +183 -0
- package/out/zero-client/src/client/zero.d.ts.map +1 -0
- package/out/zero-client/src/mod.d.ts +9 -0
- package/out/zero-client/src/mod.d.ts.map +1 -0
- package/out/zero-client/src/util/nanoid.d.ts +2 -0
- package/out/zero-client/src/util/nanoid.d.ts.map +1 -0
- package/out/zero-client/src/util/socket.d.ts +3 -0
- package/out/zero-client/src/util/socket.d.ts.map +1 -0
- package/out/zero-protocol/src/ast.d.ts +69 -0
- package/out/zero-protocol/src/ast.d.ts.map +1 -0
- package/out/zero-protocol/src/ast.js +64 -0
- package/out/zero-protocol/src/ast.js.map +1 -0
- package/out/zero-protocol/src/change-desired-queries.d.ts +71 -0
- package/out/zero-protocol/src/change-desired-queries.d.ts.map +1 -0
- package/out/zero-protocol/src/change-desired-queries.js +10 -0
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -0
- package/out/zero-protocol/src/clients-patch.d.ts +37 -0
- package/out/zero-protocol/src/clients-patch.d.ts.map +1 -0
- package/out/zero-protocol/src/clients-patch.js +15 -0
- package/out/zero-protocol/src/clients-patch.js.map +1 -0
- package/out/zero-protocol/src/connect.d.ts +88 -0
- package/out/zero-protocol/src/connect.d.ts.map +1 -0
- package/out/zero-protocol/src/connect.js +25 -0
- package/out/zero-protocol/src/connect.js.map +1 -0
- package/out/zero-protocol/src/delete-clients.d.ts +11 -0
- package/out/zero-protocol/src/delete-clients.d.ts.map +1 -0
- package/out/zero-protocol/src/delete-clients.js +9 -0
- package/out/zero-protocol/src/delete-clients.js.map +1 -0
- package/out/zero-protocol/src/down.d.ts +110 -0
- package/out/zero-protocol/src/down.d.ts.map +1 -0
- package/out/zero-protocol/src/down.js +8 -0
- package/out/zero-protocol/src/down.js.map +1 -0
- package/out/zero-protocol/src/entities-patch.d.ts +66 -0
- package/out/zero-protocol/src/entities-patch.d.ts.map +1 -0
- package/out/zero-protocol/src/entities-patch.js +27 -0
- package/out/zero-protocol/src/entities-patch.js.map +1 -0
- package/out/zero-protocol/src/entity.d.ts +9 -0
- package/out/zero-protocol/src/entity.d.ts.map +1 -0
- package/out/zero-protocol/src/entity.js +8 -0
- package/out/zero-protocol/src/entity.js.map +1 -0
- package/out/zero-protocol/src/error.d.ts +19 -0
- package/out/zero-protocol/src/error.d.ts.map +1 -0
- package/out/zero-protocol/src/error.js +26 -0
- package/out/zero-protocol/src/error.js.map +1 -0
- package/out/zero-protocol/src/mod.d.ts +16 -0
- package/out/zero-protocol/src/mod.d.ts.map +1 -0
- package/out/zero-protocol/src/mod.js +16 -0
- package/out/zero-protocol/src/mod.js.map +1 -0
- package/out/zero-protocol/src/ping.d.ts +6 -0
- package/out/zero-protocol/src/ping.d.ts.map +1 -0
- package/out/zero-protocol/src/ping.js +4 -0
- package/out/zero-protocol/src/ping.js.map +1 -0
- package/out/zero-protocol/src/poke.d.ts +236 -0
- package/out/zero-protocol/src/poke.d.ts.map +1 -0
- package/out/zero-protocol/src/poke.js +69 -0
- package/out/zero-protocol/src/poke.js.map +1 -0
- package/out/zero-protocol/src/pong.d.ts +6 -0
- package/out/zero-protocol/src/pong.d.ts.map +1 -0
- package/out/zero-protocol/src/pong.js +4 -0
- package/out/zero-protocol/src/pong.js.map +1 -0
- package/out/zero-protocol/src/pull.d.ts +26 -0
- package/out/zero-protocol/src/pull.d.ts.map +1 -0
- package/out/zero-protocol/src/pull.js +24 -0
- package/out/zero-protocol/src/pull.js.map +1 -0
- package/out/zero-protocol/src/push.d.ts +257 -0
- package/out/zero-protocol/src/push.d.ts.map +1 -0
- package/out/zero-protocol/src/push.js +77 -0
- package/out/zero-protocol/src/push.js.map +1 -0
- package/out/zero-protocol/src/queries-patch.d.ts +103 -0
- package/out/zero-protocol/src/queries-patch.d.ts.map +1 -0
- package/out/zero-protocol/src/queries-patch.js +17 -0
- package/out/zero-protocol/src/queries-patch.js.map +1 -0
- package/out/zero-protocol/src/up.d.ts +116 -0
- package/out/zero-protocol/src/up.d.ts.map +1 -0
- package/out/zero-protocol/src/up.js +9 -0
- package/out/zero-protocol/src/up.js.map +1 -0
- package/out/zero-protocol/src/version.d.ts +6 -0
- package/out/zero-protocol/src/version.d.ts.map +1 -0
- package/out/zero-protocol/src/version.js +4 -0
- package/out/zero-protocol/src/version.js.map +1 -0
- package/out/zero-react/src/mod.d.ts +3 -0
- package/out/zero-react/src/mod.d.ts.map +1 -0
- package/out/zero-react/src/use-query.d.ts +3 -0
- package/out/zero-react/src/use-query.d.ts.map +1 -0
- package/out/zero-react/src/use-zero.d.ts +8 -0
- package/out/zero-react/src/use-zero.d.ts.map +1 -0
- package/out/zero.js +7000 -0
- package/out/zero.js.map +7 -0
- package/out/zql/src/zql/ast/ast.d.ts +84 -0
- package/out/zql/src/zql/ast/ast.d.ts.map +1 -0
- package/out/zql/src/zql/ast/ast.js +54 -0
- package/out/zql/src/zql/ast/ast.js.map +1 -0
- package/out/zql/src/zql/builder/builder.d.ts +56 -0
- package/out/zql/src/zql/builder/builder.d.ts.map +1 -0
- package/out/zql/src/zql/builder/builder.js +112 -0
- package/out/zql/src/zql/builder/builder.js.map +1 -0
- package/out/zql/src/zql/builder/error.d.ts +3 -0
- package/out/zql/src/zql/builder/error.d.ts.map +1 -0
- package/out/zql/src/zql/builder/error.js +3 -0
- package/out/zql/src/zql/builder/error.js.map +1 -0
- package/out/zql/src/zql/builder/filter.d.ts +6 -0
- package/out/zql/src/zql/builder/filter.d.ts.map +1 -0
- package/out/zql/src/zql/builder/filter.js +53 -0
- package/out/zql/src/zql/builder/filter.js.map +1 -0
- package/out/zql/src/zql/builder/like.d.ts +3 -0
- package/out/zql/src/zql/builder/like.d.ts.map +1 -0
- package/out/zql/src/zql/builder/like.js +60 -0
- package/out/zql/src/zql/builder/like.js.map +1 -0
- package/out/zql/src/zql/ivm/array-view.d.ts +42 -0
- package/out/zql/src/zql/ivm/array-view.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/change.d.ts +44 -0
- package/out/zql/src/zql/ivm/change.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/change.js +2 -0
- package/out/zql/src/zql/ivm/change.js.map +1 -0
- package/out/zql/src/zql/ivm/data.d.ts +72 -0
- package/out/zql/src/zql/ivm/data.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/data.js +84 -0
- package/out/zql/src/zql/ivm/data.js.map +1 -0
- package/out/zql/src/zql/ivm/filter.d.ts +27 -0
- package/out/zql/src/zql/ivm/filter.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/filter.js +60 -0
- package/out/zql/src/zql/ivm/filter.js.map +1 -0
- package/out/zql/src/zql/ivm/join.d.ts +37 -0
- package/out/zql/src/zql/ivm/join.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/join.js +228 -0
- package/out/zql/src/zql/ivm/join.js.map +1 -0
- package/out/zql/src/zql/ivm/lookahead-iterator.d.ts +13 -0
- package/out/zql/src/zql/ivm/lookahead-iterator.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/lookahead-iterator.js +45 -0
- package/out/zql/src/zql/ivm/lookahead-iterator.js.map +1 -0
- package/out/zql/src/zql/ivm/maybe-split-and-push-edit-change.d.ts +10 -0
- package/out/zql/src/zql/ivm/maybe-split-and-push-edit-change.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/maybe-split-and-push-edit-change.js +34 -0
- package/out/zql/src/zql/ivm/maybe-split-and-push-edit-change.js.map +1 -0
- package/out/zql/src/zql/ivm/memory-source.d.ts +65 -0
- package/out/zql/src/zql/ivm/memory-source.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/memory-source.js +508 -0
- package/out/zql/src/zql/ivm/memory-source.js.map +1 -0
- package/out/zql/src/zql/ivm/memory-storage.d.ts +18 -0
- package/out/zql/src/zql/ivm/memory-storage.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/operator.d.ts +89 -0
- package/out/zql/src/zql/ivm/operator.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/operator.js +2 -0
- package/out/zql/src/zql/ivm/operator.js.map +1 -0
- package/out/zql/src/zql/ivm/schema.d.ts +29 -0
- package/out/zql/src/zql/ivm/schema.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/schema.js +3 -0
- package/out/zql/src/zql/ivm/schema.js.map +1 -0
- package/out/zql/src/zql/ivm/skip.d.ts +24 -0
- package/out/zql/src/zql/ivm/skip.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/skip.js +113 -0
- package/out/zql/src/zql/ivm/skip.js.map +1 -0
- package/out/zql/src/zql/ivm/source.d.ts +57 -0
- package/out/zql/src/zql/ivm/source.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/source.js +2 -0
- package/out/zql/src/zql/ivm/source.js.map +1 -0
- package/out/zql/src/zql/ivm/stream.d.ts +11 -0
- package/out/zql/src/zql/ivm/stream.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/stream.js +19 -0
- package/out/zql/src/zql/ivm/stream.js.map +1 -0
- package/out/zql/src/zql/ivm/take.d.ts +24 -0
- package/out/zql/src/zql/ivm/take.d.ts.map +1 -0
- package/out/zql/src/zql/ivm/take.js +453 -0
- package/out/zql/src/zql/ivm/take.js.map +1 -0
- package/out/zql/src/zql/query/query-impl.d.ts +45 -0
- package/out/zql/src/zql/query/query-impl.d.ts.map +1 -0
- package/out/zql/src/zql/query/query.d.ts +130 -0
- package/out/zql/src/zql/query/query.d.ts.map +1 -0
- package/out/zql/src/zql/query/schema.d.ts +53 -0
- package/out/zql/src/zql/query/schema.d.ts.map +1 -0
- package/out/zql/src/zql/query/typed-view.d.ts +10 -0
- package/out/zql/src/zql/query/typed-view.d.ts.map +1 -0
- package/out/zqlite/src/db.d.ts +23 -0
- package/out/zqlite/src/db.d.ts.map +1 -0
- package/out/zqlite/src/db.js +117 -0
- package/out/zqlite/src/db.js.map +1 -0
- package/out/zqlite/src/internal/sql.d.ts +9 -0
- package/out/zqlite/src/internal/sql.d.ts.map +1 -0
- package/out/zqlite/src/internal/sql.js +14 -0
- package/out/zqlite/src/internal/sql.js.map +1 -0
- package/out/zqlite/src/internal/statement-cache.d.ts +67 -0
- package/out/zqlite/src/internal/statement-cache.d.ts.map +1 -0
- package/out/zqlite/src/internal/statement-cache.js +119 -0
- package/out/zqlite/src/internal/statement-cache.js.map +1 -0
- package/out/zqlite/src/table-source.d.ts +43 -0
- package/out/zqlite/src/table-source.d.ts.map +1 -0
- package/out/zqlite/src/table-source.js +393 -0
- package/out/zqlite/src/table-source.js.map +1 -0
- package/package.json +79 -0
- package/tool/install-sqlite3.js +37 -0
|
@@ -0,0 +1,1708 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compares DefaultComparables to form a strict partial ordering.
|
|
3
|
+
*
|
|
4
|
+
* Handles +/-0 and NaN like Map: NaN is equal to NaN, and -0 is equal to +0.
|
|
5
|
+
*
|
|
6
|
+
* Arrays are compared using '<' and '>', which may cause unexpected equality:
|
|
7
|
+
* for example [1] will be considered equal to ['1'].
|
|
8
|
+
*
|
|
9
|
+
* Two objects with equal valueOf compare the same, but compare unequal to
|
|
10
|
+
* primitives that have the same value.
|
|
11
|
+
*/
|
|
12
|
+
export function defaultComparator(a, b) {
|
|
13
|
+
// Special case finite numbers first for performance.
|
|
14
|
+
// Note that the trick of using 'a - b' and checking for NaN to detect non-numbers
|
|
15
|
+
// does not work if the strings are numeric (ex: "5"). This would leading most
|
|
16
|
+
// comparison functions using that approach to fail to have transitivity.
|
|
17
|
+
if (Number.isFinite(a) && Number.isFinite(b)) {
|
|
18
|
+
return a - b;
|
|
19
|
+
}
|
|
20
|
+
// The default < and > operators are not totally ordered. To allow types to be mixed
|
|
21
|
+
// in a single collection, compare types and order values of different types by type.
|
|
22
|
+
let ta = typeof a;
|
|
23
|
+
let tb = typeof b;
|
|
24
|
+
if (ta !== tb) {
|
|
25
|
+
return ta < tb ? -1 : 1;
|
|
26
|
+
}
|
|
27
|
+
if (ta === 'object') {
|
|
28
|
+
// standardized JavaScript bug: null is not an object, but typeof says it is
|
|
29
|
+
if (a === null)
|
|
30
|
+
return b === null ? 0 : -1;
|
|
31
|
+
else if (b === null)
|
|
32
|
+
return 1;
|
|
33
|
+
a = a.valueOf();
|
|
34
|
+
b = b.valueOf();
|
|
35
|
+
ta = typeof a;
|
|
36
|
+
tb = typeof b;
|
|
37
|
+
// Deal with the two valueOf()s producing different types
|
|
38
|
+
if (ta !== tb) {
|
|
39
|
+
return ta < tb ? -1 : 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// a and b are now the same type, and will be a number, string or array
|
|
43
|
+
// (which we assume holds numbers or strings), or something unsupported.
|
|
44
|
+
if (a < b)
|
|
45
|
+
return -1;
|
|
46
|
+
if (a > b)
|
|
47
|
+
return 1;
|
|
48
|
+
if (a === b)
|
|
49
|
+
return 0;
|
|
50
|
+
// Order NaN less than other numbers
|
|
51
|
+
if (Number.isNaN(a))
|
|
52
|
+
return Number.isNaN(b) ? 0 : -1;
|
|
53
|
+
else if (Number.isNaN(b))
|
|
54
|
+
return 1;
|
|
55
|
+
// This could be two objects (e.g. [7] and ['7']) that aren't ordered
|
|
56
|
+
return Array.isArray(a) ? 0 : Number.NaN;
|
|
57
|
+
}
|
|
58
|
+
export function simpleComparator(a, b) {
|
|
59
|
+
return a > b ? 1 : a < b ? -1 : 0;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* A reasonably fast collection of key-value pairs with a powerful API.
|
|
63
|
+
* Largely compatible with the standard Map. BTree is a B+ tree data structure,
|
|
64
|
+
* so the collection is sorted by key.
|
|
65
|
+
*
|
|
66
|
+
* B+ trees tend to use memory more efficiently than hashtables such as the
|
|
67
|
+
* standard Map, especially when the collection contains a large number of
|
|
68
|
+
* items. However, maintaining the sort order makes them modestly slower:
|
|
69
|
+
* O(log size) rather than O(1). This B+ tree implementation supports O(1)
|
|
70
|
+
* fast cloning. It also supports freeze(), which can be used to ensure that
|
|
71
|
+
* a BTree is not changed accidentally.
|
|
72
|
+
*
|
|
73
|
+
* Confusingly, the ES6 Map.forEach(c) method calls c(value,key) instead of
|
|
74
|
+
* c(key,value), in contrast to other methods such as set() and entries()
|
|
75
|
+
* which put the key first. I can only assume that the order was reversed on
|
|
76
|
+
* the theory that users would usually want to examine values and ignore keys.
|
|
77
|
+
* BTree's forEach() therefore works the same way, but a second method
|
|
78
|
+
* `.forEachPair((key,value)=>{...})` is provided which sends you the key
|
|
79
|
+
* first and the value second; this method is slightly faster because it is
|
|
80
|
+
* the "native" for-each method for this class.
|
|
81
|
+
*
|
|
82
|
+
* Out of the box, BTree supports keys that are numbers, strings, arrays of
|
|
83
|
+
* numbers/strings, Date, and objects that have a valueOf() method returning a
|
|
84
|
+
* number or string. Other data types, such as arrays of Date or custom
|
|
85
|
+
* objects, require a custom comparator, which you must pass as the second
|
|
86
|
+
* argument to the constructor (the first argument is an optional list of
|
|
87
|
+
* initial items). Symbols cannot be used as keys because they are unordered
|
|
88
|
+
* (one Symbol is never "greater" or "less" than another).
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* Given a {name: string, age: number} object, you can create a tree sorted by
|
|
92
|
+
* name and then by age like this:
|
|
93
|
+
*
|
|
94
|
+
* var tree = new BTree(undefined, (a, b) => {
|
|
95
|
+
* if (a.name > b.name)
|
|
96
|
+
* return 1; // Return a number >0 when a > b
|
|
97
|
+
* else if (a.name < b.name)
|
|
98
|
+
* return -1; // Return a number <0 when a < b
|
|
99
|
+
* else // names are equal (or incomparable)
|
|
100
|
+
* return a.age - b.age; // Return >0 when a.age > b.age
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* tree.set({name:"Bill", age:17}, "happy");
|
|
104
|
+
* tree.set({name:"Fran", age:40}, "busy & stressed");
|
|
105
|
+
* tree.set({name:"Bill", age:55}, "recently laid off");
|
|
106
|
+
* tree.forEachPair((k, v) => {
|
|
107
|
+
* console.log(`Name: ${k.name} Age: ${k.age} Status: ${v}`);
|
|
108
|
+
* });
|
|
109
|
+
*
|
|
110
|
+
* @description
|
|
111
|
+
* The "range" methods (`forEach, forRange, editRange`) will return the number
|
|
112
|
+
* of elements that were scanned. In addition, the callback can return {break:R}
|
|
113
|
+
* to stop early and return R from the outer function.
|
|
114
|
+
*
|
|
115
|
+
* - TODO: Test performance of preallocating values array at max size
|
|
116
|
+
* - TODO: Add fast initialization when a sorted array is provided to constructor
|
|
117
|
+
*
|
|
118
|
+
* For more documentation see https://github.com/qwertie/btree-typescript
|
|
119
|
+
*
|
|
120
|
+
* Are you a C# developer? You might like the similar data structures I made for C#:
|
|
121
|
+
* BDictionary, BList, etc. See http://core.loyc.net/collections/
|
|
122
|
+
*
|
|
123
|
+
* @author David Piepgrass
|
|
124
|
+
*/
|
|
125
|
+
export default class BTree {
|
|
126
|
+
_root = EmptyLeaf;
|
|
127
|
+
_size = 0;
|
|
128
|
+
_maxNodeSize;
|
|
129
|
+
/**
|
|
130
|
+
* provides a total order over keys (and a strict partial order over the type K)
|
|
131
|
+
* @returns a negative value if a < b, 0 if a === b and a positive value if a > b
|
|
132
|
+
*/
|
|
133
|
+
_compare;
|
|
134
|
+
/**
|
|
135
|
+
* Initializes an empty B+ tree.
|
|
136
|
+
* @param compare Custom function to compare pairs of elements in the tree.
|
|
137
|
+
* If not specified, defaultComparator will be used which is valid as long as K extends DefaultComparable.
|
|
138
|
+
* @param entries A set of key-value pairs to initialize the tree
|
|
139
|
+
* @param maxNodeSize Branching factor (maximum items or children per node)
|
|
140
|
+
* Must be in range 4..256. If undefined or <4 then default is used; if >256 then 256.
|
|
141
|
+
*/
|
|
142
|
+
constructor(entries, compare, maxNodeSize) {
|
|
143
|
+
this._maxNodeSize = maxNodeSize >= 4 ? Math.min(maxNodeSize, 256) : 32;
|
|
144
|
+
this._compare =
|
|
145
|
+
compare || defaultComparator;
|
|
146
|
+
if (entries)
|
|
147
|
+
this.setPairs(entries);
|
|
148
|
+
}
|
|
149
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
150
|
+
// ES6 Map<K,V> methods /////////////////////////////////////////////////////
|
|
151
|
+
/** Gets the number of key-value pairs in the tree. */
|
|
152
|
+
get size() {
|
|
153
|
+
return this._size;
|
|
154
|
+
}
|
|
155
|
+
/** Gets the number of key-value pairs in the tree. */
|
|
156
|
+
get length() {
|
|
157
|
+
return this._size;
|
|
158
|
+
}
|
|
159
|
+
/** Returns true iff the tree contains no key-value pairs. */
|
|
160
|
+
get isEmpty() {
|
|
161
|
+
return this._size === 0;
|
|
162
|
+
}
|
|
163
|
+
/** Releases the tree so that its size is 0. */
|
|
164
|
+
clear() {
|
|
165
|
+
this._root = EmptyLeaf;
|
|
166
|
+
this._size = 0;
|
|
167
|
+
}
|
|
168
|
+
/** Runs a function for each key-value pair, in order from smallest to
|
|
169
|
+
* largest key. For compatibility with ES6 Map, the argument order to
|
|
170
|
+
* the callback is backwards: value first, then key. Call forEachPair
|
|
171
|
+
* instead to receive the key as the first argument.
|
|
172
|
+
* @param thisArg If provided, this parameter is assigned as the `this`
|
|
173
|
+
* value for each callback.
|
|
174
|
+
* @returns the number of values that were sent to the callback,
|
|
175
|
+
* or the R value if the callback returned {break:R}. */
|
|
176
|
+
forEach(callback, thisArg) {
|
|
177
|
+
if (thisArg !== undefined)
|
|
178
|
+
callback = callback.bind(thisArg);
|
|
179
|
+
return this.forEachPair((k, v) => callback(v, k, this));
|
|
180
|
+
}
|
|
181
|
+
/** Runs a function for each key-value pair, in order from smallest to
|
|
182
|
+
* largest key. The callback can return {break:R} (where R is any value
|
|
183
|
+
* except undefined) to stop immediately and return R from forEachPair.
|
|
184
|
+
* @param onFound A function that is called for each key-value pair. This
|
|
185
|
+
* function can return {break:R} to stop early with result R.
|
|
186
|
+
* The reason that you must return {break:R} instead of simply R
|
|
187
|
+
* itself is for consistency with editRange(), which allows
|
|
188
|
+
* multiple actions, not just breaking.
|
|
189
|
+
* @param initialCounter This is the value of the third argument of
|
|
190
|
+
* `onFound` the first time it is called. The counter increases
|
|
191
|
+
* by one each time `onFound` is called. Default value: 0
|
|
192
|
+
* @returns the number of pairs sent to the callback (plus initialCounter,
|
|
193
|
+
* if you provided one). If the callback returned {break:R} then
|
|
194
|
+
* the R value is returned instead. */
|
|
195
|
+
forEachPair(callback, initialCounter) {
|
|
196
|
+
var low = this.minKey(), high = this.maxKey();
|
|
197
|
+
return this.forRange(low, high, true, callback, initialCounter);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Finds a pair in the tree and returns the associated value.
|
|
201
|
+
* @param defaultValue a value to return if the key was not found.
|
|
202
|
+
* @returns the value, or defaultValue if the key was not found.
|
|
203
|
+
* @description Computational complexity: O(log size)
|
|
204
|
+
*/
|
|
205
|
+
get(key, defaultValue) {
|
|
206
|
+
return this._root.get(key, defaultValue, this);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Adds or overwrites a key-value pair in the B+ tree.
|
|
210
|
+
* @param key the key is used to determine the sort order of
|
|
211
|
+
* data in the tree.
|
|
212
|
+
* @param value data to associate with the key (optional)
|
|
213
|
+
* @param overwrite Whether to overwrite an existing key-value pair
|
|
214
|
+
* (default: true). If this is false and there is an existing
|
|
215
|
+
* key-value pair then this method has no effect.
|
|
216
|
+
* @returns true if a new key-value pair was added.
|
|
217
|
+
* @description Computational complexity: O(log size)
|
|
218
|
+
* Note: when overwriting a previous entry, the key is updated
|
|
219
|
+
* as well as the value. This has no effect unless the new key
|
|
220
|
+
* has data that does not affect its sort order.
|
|
221
|
+
*/
|
|
222
|
+
set(key, value, overwrite) {
|
|
223
|
+
if (this._root.isShared)
|
|
224
|
+
this._root = this._root.clone();
|
|
225
|
+
var result = this._root.set(key, value, overwrite, this);
|
|
226
|
+
if (result === true || result === false)
|
|
227
|
+
return result;
|
|
228
|
+
// Root node has split, so create a new root node.
|
|
229
|
+
this._root = new BNodeInternal([this._root, result]);
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Returns true if the key exists in the B+ tree, false if not.
|
|
234
|
+
* Use get() for best performance; use has() if you need to
|
|
235
|
+
* distinguish between "undefined value" and "key not present".
|
|
236
|
+
* @param key Key to detect
|
|
237
|
+
* @description Computational complexity: O(log size)
|
|
238
|
+
*/
|
|
239
|
+
has(key) {
|
|
240
|
+
return this.forRange(key, key, true, undefined) !== 0;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Removes a single key-value pair from the B+ tree.
|
|
244
|
+
* @param key Key to find
|
|
245
|
+
* @returns true if a pair was found and removed, false otherwise.
|
|
246
|
+
* @description Computational complexity: O(log size)
|
|
247
|
+
*/
|
|
248
|
+
delete(key) {
|
|
249
|
+
return this.editRange(key, key, true, DeleteRange) !== 0;
|
|
250
|
+
}
|
|
251
|
+
with(key, value, overwrite) {
|
|
252
|
+
let nu = this.clone();
|
|
253
|
+
return nu.set(key, value, overwrite) || overwrite ? nu : this;
|
|
254
|
+
}
|
|
255
|
+
/** Returns a copy of the tree with the specified key-value pairs set. */
|
|
256
|
+
withPairs(pairs, overwrite) {
|
|
257
|
+
let nu = this.clone();
|
|
258
|
+
return nu.setPairs(pairs, overwrite) !== 0 || overwrite ? nu : this;
|
|
259
|
+
}
|
|
260
|
+
/** Returns a copy of the tree with the specified keys present.
|
|
261
|
+
* @param keys The keys to add. If a key is already present in the tree,
|
|
262
|
+
* neither the existing key nor the existing value is modified.
|
|
263
|
+
* @param returnThisIfUnchanged if true, returns this if all keys already
|
|
264
|
+
* existed. Performance note: due to the architecture of this class, all
|
|
265
|
+
* node(s) leading to existing keys are cloned even if the collection is
|
|
266
|
+
* ultimately unchanged.
|
|
267
|
+
*/
|
|
268
|
+
withKeys(keys, returnThisIfUnchanged) {
|
|
269
|
+
let nu = this.clone(), changed = false;
|
|
270
|
+
for (var i = 0; i < keys.length; i++)
|
|
271
|
+
changed = nu.set(keys[i], undefined, false) || changed;
|
|
272
|
+
return returnThisIfUnchanged && !changed ? this : nu;
|
|
273
|
+
}
|
|
274
|
+
/** Returns a copy of the tree with the specified key removed.
|
|
275
|
+
* @param returnThisIfUnchanged if true, returns this if the key didn't exist.
|
|
276
|
+
* Performance note: due to the architecture of this class, node(s) leading
|
|
277
|
+
* to where the key would have been stored are cloned even when the key
|
|
278
|
+
* turns out not to exist and the collection is unchanged.
|
|
279
|
+
*/
|
|
280
|
+
without(key, returnThisIfUnchanged) {
|
|
281
|
+
return this.withoutRange(key, key, true, returnThisIfUnchanged);
|
|
282
|
+
}
|
|
283
|
+
/** Returns a copy of the tree with the specified keys removed.
|
|
284
|
+
* @param returnThisIfUnchanged if true, returns this if none of the keys
|
|
285
|
+
* existed. Performance note: due to the architecture of this class,
|
|
286
|
+
* node(s) leading to where the key would have been stored are cloned
|
|
287
|
+
* even when the key turns out not to exist.
|
|
288
|
+
*/
|
|
289
|
+
withoutKeys(keys, returnThisIfUnchanged) {
|
|
290
|
+
let nu = this.clone();
|
|
291
|
+
return nu.deleteKeys(keys) || !returnThisIfUnchanged ? nu : this;
|
|
292
|
+
}
|
|
293
|
+
/** Returns a copy of the tree with the specified range of keys removed. */
|
|
294
|
+
withoutRange(low, high, includeHigh, returnThisIfUnchanged) {
|
|
295
|
+
let nu = this.clone();
|
|
296
|
+
if (nu.deleteRange(low, high, includeHigh) === 0 && returnThisIfUnchanged)
|
|
297
|
+
return this;
|
|
298
|
+
return nu;
|
|
299
|
+
}
|
|
300
|
+
/** Returns a copy of the tree with pairs removed whenever the callback
|
|
301
|
+
* function returns false. `where()` is a synonym for this method. */
|
|
302
|
+
filter(callback, returnThisIfUnchanged) {
|
|
303
|
+
var nu = this.greedyClone();
|
|
304
|
+
var del;
|
|
305
|
+
nu.editAll((k, v, i) => {
|
|
306
|
+
if (!callback(k, v, i))
|
|
307
|
+
return (del = Delete);
|
|
308
|
+
return undefined;
|
|
309
|
+
});
|
|
310
|
+
if (!del && returnThisIfUnchanged)
|
|
311
|
+
return this;
|
|
312
|
+
return nu;
|
|
313
|
+
}
|
|
314
|
+
/** Returns a copy of the tree with all values altered by a callback function. */
|
|
315
|
+
mapValues(callback) {
|
|
316
|
+
var tmp = {};
|
|
317
|
+
var nu = this.greedyClone();
|
|
318
|
+
nu.editAll((k, v, i) => {
|
|
319
|
+
return (tmp.value = callback(v, k, i)), tmp;
|
|
320
|
+
});
|
|
321
|
+
return nu;
|
|
322
|
+
}
|
|
323
|
+
reduce(callback, initialValue) {
|
|
324
|
+
let i = 0, p = initialValue;
|
|
325
|
+
var it = this.entries(this.minKey(), ReusedArray), next;
|
|
326
|
+
while (!(next = it.next()).done)
|
|
327
|
+
p = callback(p, next.value, i++, this);
|
|
328
|
+
return p;
|
|
329
|
+
}
|
|
330
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
331
|
+
// Iterator methods /////////////////////////////////////////////////////////
|
|
332
|
+
/** Returns an iterator that provides items in order (ascending order if
|
|
333
|
+
* the collection's comparator uses ascending order, as is the default.)
|
|
334
|
+
* @param lowestKey First key to be iterated, or undefined to start at
|
|
335
|
+
* minKey(). If the specified key doesn't exist then iteration
|
|
336
|
+
* starts at the next higher key (according to the comparator).
|
|
337
|
+
* @param reusedArray Optional array used repeatedly to store key-value
|
|
338
|
+
* pairs, to avoid creating a new array on every iteration.
|
|
339
|
+
*/
|
|
340
|
+
entries(lowestKey, reusedArray) {
|
|
341
|
+
var info = this.findPath(lowestKey);
|
|
342
|
+
if (info === undefined)
|
|
343
|
+
return iterator();
|
|
344
|
+
var { nodequeue, nodeindex, leaf } = info;
|
|
345
|
+
var state = reusedArray !== undefined ? 1 : 0;
|
|
346
|
+
var i = lowestKey === undefined
|
|
347
|
+
? -1
|
|
348
|
+
: leaf.indexOf(lowestKey, 0, this._compare) - 1;
|
|
349
|
+
return iterator(() => {
|
|
350
|
+
jump: for (;;) {
|
|
351
|
+
switch (state) {
|
|
352
|
+
case 0:
|
|
353
|
+
if (++i < leaf.keys.length)
|
|
354
|
+
return { done: false, value: [leaf.keys[i], leaf.values[i]] };
|
|
355
|
+
state = 2;
|
|
356
|
+
continue;
|
|
357
|
+
// @ts-ignore
|
|
358
|
+
case 1:
|
|
359
|
+
if (++i < leaf.keys.length) {
|
|
360
|
+
(reusedArray[0] = leaf.keys[i]),
|
|
361
|
+
(reusedArray[1] = leaf.values[i]);
|
|
362
|
+
return { done: false, value: reusedArray };
|
|
363
|
+
}
|
|
364
|
+
state = 2;
|
|
365
|
+
case 2:
|
|
366
|
+
// Advance to the next leaf node
|
|
367
|
+
for (var level = -1;;) {
|
|
368
|
+
if (++level >= nodequeue.length) {
|
|
369
|
+
state = 3;
|
|
370
|
+
continue jump;
|
|
371
|
+
}
|
|
372
|
+
if (++nodeindex[level] < nodequeue[level].length)
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
for (; level > 0; level--) {
|
|
376
|
+
nodequeue[level - 1] = nodequeue[level][nodeindex[level]].children;
|
|
377
|
+
nodeindex[level - 1] = 0;
|
|
378
|
+
}
|
|
379
|
+
leaf = nodequeue[0][nodeindex[0]];
|
|
380
|
+
i = -1;
|
|
381
|
+
state = reusedArray !== undefined ? 1 : 0;
|
|
382
|
+
continue;
|
|
383
|
+
case 3:
|
|
384
|
+
return { done: true, value: undefined };
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/** Returns an iterator that provides items in reversed order.
|
|
390
|
+
* @param highestKey Key at which to start iterating, or undefined to
|
|
391
|
+
* start at maxKey(). If the specified key doesn't exist then iteration
|
|
392
|
+
* starts at the next lower key (according to the comparator).
|
|
393
|
+
* @param reusedArray Optional array used repeatedly to store key-value
|
|
394
|
+
* pairs, to avoid creating a new array on every iteration.
|
|
395
|
+
* @param skipHighest Iff this flag is true and the highestKey exists in the
|
|
396
|
+
* collection, the pair matching highestKey is skipped, not iterated.
|
|
397
|
+
*/
|
|
398
|
+
entriesReversed(highestKey, reusedArray, skipHighest) {
|
|
399
|
+
if (highestKey === undefined) {
|
|
400
|
+
highestKey = this.maxKey();
|
|
401
|
+
skipHighest = undefined;
|
|
402
|
+
if (highestKey === undefined)
|
|
403
|
+
return iterator(); // collection is empty
|
|
404
|
+
}
|
|
405
|
+
var { nodequeue, nodeindex, leaf } = this.findPath(highestKey) || this.findPath(this.maxKey());
|
|
406
|
+
check(!nodequeue[0] || leaf === nodequeue[0][nodeindex[0]], 'wat!');
|
|
407
|
+
var i = leaf.indexOf(highestKey, 0, this._compare);
|
|
408
|
+
if (!skipHighest &&
|
|
409
|
+
i < leaf.keys.length &&
|
|
410
|
+
this._compare(leaf.keys[i], highestKey) <= 0)
|
|
411
|
+
i++;
|
|
412
|
+
var state = reusedArray !== undefined ? 1 : 0;
|
|
413
|
+
return iterator(() => {
|
|
414
|
+
jump: for (;;) {
|
|
415
|
+
switch (state) {
|
|
416
|
+
case 0:
|
|
417
|
+
if (--i >= 0)
|
|
418
|
+
return { done: false, value: [leaf.keys[i], leaf.values[i]] };
|
|
419
|
+
state = 2;
|
|
420
|
+
continue;
|
|
421
|
+
// @ts-ignore
|
|
422
|
+
case 1:
|
|
423
|
+
if (--i >= 0) {
|
|
424
|
+
(reusedArray[0] = leaf.keys[i]),
|
|
425
|
+
(reusedArray[1] = leaf.values[i]);
|
|
426
|
+
return { done: false, value: reusedArray };
|
|
427
|
+
}
|
|
428
|
+
state = 2;
|
|
429
|
+
case 2:
|
|
430
|
+
// Advance to the next leaf node
|
|
431
|
+
for (var level = -1;;) {
|
|
432
|
+
if (++level >= nodequeue.length) {
|
|
433
|
+
state = 3;
|
|
434
|
+
continue jump;
|
|
435
|
+
}
|
|
436
|
+
if (--nodeindex[level] >= 0)
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
439
|
+
for (; level > 0; level--) {
|
|
440
|
+
nodequeue[level - 1] = nodequeue[level][nodeindex[level]].children;
|
|
441
|
+
nodeindex[level - 1] = nodequeue[level - 1].length - 1;
|
|
442
|
+
}
|
|
443
|
+
leaf = nodequeue[0][nodeindex[0]];
|
|
444
|
+
i = leaf.keys.length;
|
|
445
|
+
state = reusedArray !== undefined ? 1 : 0;
|
|
446
|
+
continue;
|
|
447
|
+
case 3:
|
|
448
|
+
return { done: true, value: undefined };
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
/* Used by entries() and entriesReversed() to prepare to start iterating.
|
|
454
|
+
* It develops a "node queue" for each non-leaf level of the tree.
|
|
455
|
+
* Levels are numbered "bottom-up" so that level 0 is a list of leaf
|
|
456
|
+
* nodes from a low-level non-leaf node. The queue at a given level L
|
|
457
|
+
* consists of nodequeue[L] which is the children of a BNodeInternal,
|
|
458
|
+
* and nodeindex[L], the current index within that child list, such
|
|
459
|
+
* such that nodequeue[L-1] === nodequeue[L][nodeindex[L]].children.
|
|
460
|
+
* (However inside this function the order is reversed.)
|
|
461
|
+
*/
|
|
462
|
+
findPath(key) {
|
|
463
|
+
var nextnode = this._root;
|
|
464
|
+
var nodequeue, nodeindex;
|
|
465
|
+
if (nextnode.isLeaf) {
|
|
466
|
+
(nodequeue = EmptyArray), (nodeindex = EmptyArray); // avoid allocations
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
(nodequeue = []), (nodeindex = []);
|
|
470
|
+
for (var d = 0; !nextnode.isLeaf; d++) {
|
|
471
|
+
nodequeue[d] = nextnode.children;
|
|
472
|
+
nodeindex[d] =
|
|
473
|
+
key === undefined ? 0 : nextnode.indexOf(key, 0, this._compare);
|
|
474
|
+
if (nodeindex[d] >= nodequeue[d].length)
|
|
475
|
+
return; // first key > maxKey()
|
|
476
|
+
nextnode = nodequeue[d][nodeindex[d]];
|
|
477
|
+
}
|
|
478
|
+
nodequeue.reverse();
|
|
479
|
+
nodeindex.reverse();
|
|
480
|
+
}
|
|
481
|
+
return { nodequeue, nodeindex, leaf: nextnode };
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Computes the differences between `this` and `other`.
|
|
485
|
+
* For efficiency, the diff is returned via invocations of supplied handlers.
|
|
486
|
+
* The computation is optimized for the case in which the two trees have large amounts
|
|
487
|
+
* of shared data (obtained by calling the `clone` or `with` APIs) and will avoid
|
|
488
|
+
* any iteration of shared state.
|
|
489
|
+
* The handlers can cause computation to early exit by returning {break: R}.
|
|
490
|
+
* Neither of the collections should be changed during the comparison process (in your callbacks), as this method assumes they will not be mutated.
|
|
491
|
+
* @param other The tree to compute a diff against.
|
|
492
|
+
* @param onlyThis Callback invoked for all keys only present in `this`.
|
|
493
|
+
* @param onlyOther Callback invoked for all keys only present in `other`.
|
|
494
|
+
* @param different Callback invoked for all keys with differing values.
|
|
495
|
+
*/
|
|
496
|
+
diffAgainst(other, onlyThis, onlyOther, different) {
|
|
497
|
+
if (other._compare !== this._compare) {
|
|
498
|
+
throw new Error('Tree comparators are not the same.');
|
|
499
|
+
}
|
|
500
|
+
if (this.isEmpty || other.isEmpty) {
|
|
501
|
+
if (this.isEmpty && other.isEmpty)
|
|
502
|
+
return undefined;
|
|
503
|
+
// If one tree is empty, everything will be an onlyThis/onlyOther.
|
|
504
|
+
if (this.isEmpty)
|
|
505
|
+
return onlyOther === undefined
|
|
506
|
+
? undefined
|
|
507
|
+
: BTree.stepToEnd(BTree.makeDiffCursor(other), onlyOther);
|
|
508
|
+
return onlyThis === undefined
|
|
509
|
+
? undefined
|
|
510
|
+
: BTree.stepToEnd(BTree.makeDiffCursor(this), onlyThis);
|
|
511
|
+
}
|
|
512
|
+
// Cursor-based diff algorithm is as follows:
|
|
513
|
+
// - Until neither cursor has navigated to the end of the tree, do the following:
|
|
514
|
+
// - If the `this` cursor is "behind" the `other` cursor (strictly <, via compare), advance it.
|
|
515
|
+
// - Otherwise, advance the `other` cursor.
|
|
516
|
+
// - Any time a cursor is stepped, perform the following:
|
|
517
|
+
// - If either cursor points to a key/value pair:
|
|
518
|
+
// - If thisCursor === otherCursor and the values differ, it is a Different.
|
|
519
|
+
// - If thisCursor > otherCursor and otherCursor is at a key/value pair, it is an OnlyOther.
|
|
520
|
+
// - If thisCursor < otherCursor and thisCursor is at a key/value pair, it is an OnlyThis as long as the most recent
|
|
521
|
+
// cursor step was *not* otherCursor advancing from a tie. The extra condition avoids erroneous OnlyOther calls
|
|
522
|
+
// that would occur due to otherCursor being the "leader".
|
|
523
|
+
// - Otherwise, if both cursors point to nodes, compare them. If they are equal by reference (shared), skip
|
|
524
|
+
// both cursors to the next node in the walk.
|
|
525
|
+
// - Once one cursor has finished stepping, any remaining steps (if any) are taken and key/value pairs are logged
|
|
526
|
+
// as OnlyOther (if otherCursor is stepping) or OnlyThis (if thisCursor is stepping).
|
|
527
|
+
// This algorithm gives the critical guarantee that all locations (both nodes and key/value pairs) in both trees that
|
|
528
|
+
// are identical by value (and possibly by reference) will be visited *at the same time* by the cursors.
|
|
529
|
+
// This removes the possibility of emitting incorrect diffs, as well as allowing for skipping shared nodes.
|
|
530
|
+
const { _compare } = this;
|
|
531
|
+
const thisCursor = BTree.makeDiffCursor(this);
|
|
532
|
+
const otherCursor = BTree.makeDiffCursor(other);
|
|
533
|
+
// It doesn't matter how thisSteppedLast is initialized.
|
|
534
|
+
// Step order is only used when either cursor is at a leaf, and cursors always start at a node.
|
|
535
|
+
let thisSuccess = true, otherSuccess = true, prevCursorOrder = BTree.compare(thisCursor, otherCursor, _compare);
|
|
536
|
+
while (thisSuccess && otherSuccess) {
|
|
537
|
+
const cursorOrder = BTree.compare(thisCursor, otherCursor, _compare);
|
|
538
|
+
const { leaf: thisLeaf, internalSpine: thisInternalSpine, levelIndices: thisLevelIndices, } = thisCursor;
|
|
539
|
+
const { leaf: otherLeaf, internalSpine: otherInternalSpine, levelIndices: otherLevelIndices, } = otherCursor;
|
|
540
|
+
if (thisLeaf || otherLeaf) {
|
|
541
|
+
// If the cursors were at the same location last step, then there is no work to be done.
|
|
542
|
+
if (prevCursorOrder !== 0) {
|
|
543
|
+
if (cursorOrder === 0) {
|
|
544
|
+
if (thisLeaf && otherLeaf && different) {
|
|
545
|
+
// Equal keys, check for modifications
|
|
546
|
+
const valThis = thisLeaf.values[thisLevelIndices[thisLevelIndices.length - 1]];
|
|
547
|
+
const valOther = otherLeaf.values[otherLevelIndices[otherLevelIndices.length - 1]];
|
|
548
|
+
if (!Object.is(valThis, valOther)) {
|
|
549
|
+
const result = different(thisCursor.currentKey, valThis, valOther);
|
|
550
|
+
if (result && result.break)
|
|
551
|
+
return result.break;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
else if (cursorOrder > 0) {
|
|
556
|
+
// If this is the case, we know that either:
|
|
557
|
+
// 1. otherCursor stepped last from a starting position that trailed thisCursor, and is still behind, or
|
|
558
|
+
// 2. thisCursor stepped last and leapfrogged otherCursor
|
|
559
|
+
// Either of these cases is an "only other"
|
|
560
|
+
if (otherLeaf && onlyOther) {
|
|
561
|
+
const otherVal = otherLeaf.values[otherLevelIndices[otherLevelIndices.length - 1]];
|
|
562
|
+
const result = onlyOther(otherCursor.currentKey, otherVal);
|
|
563
|
+
if (result && result.break)
|
|
564
|
+
return result.break;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
else if (onlyThis) {
|
|
568
|
+
if (thisLeaf && prevCursorOrder !== 0) {
|
|
569
|
+
const valThis = thisLeaf.values[thisLevelIndices[thisLevelIndices.length - 1]];
|
|
570
|
+
const result = onlyThis(thisCursor.currentKey, valThis);
|
|
571
|
+
if (result && result.break)
|
|
572
|
+
return result.break;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
else if (!thisLeaf && !otherLeaf && cursorOrder === 0) {
|
|
578
|
+
const lastThis = thisInternalSpine.length - 1;
|
|
579
|
+
const lastOther = otherInternalSpine.length - 1;
|
|
580
|
+
const nodeThis = thisInternalSpine[lastThis][thisLevelIndices[lastThis]];
|
|
581
|
+
const nodeOther = otherInternalSpine[lastOther][otherLevelIndices[lastOther]];
|
|
582
|
+
if (nodeOther === nodeThis) {
|
|
583
|
+
prevCursorOrder = 0;
|
|
584
|
+
thisSuccess = BTree.step(thisCursor, true);
|
|
585
|
+
otherSuccess = BTree.step(otherCursor, true);
|
|
586
|
+
continue;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
prevCursorOrder = cursorOrder;
|
|
590
|
+
if (cursorOrder < 0) {
|
|
591
|
+
thisSuccess = BTree.step(thisCursor);
|
|
592
|
+
}
|
|
593
|
+
else {
|
|
594
|
+
otherSuccess = BTree.step(otherCursor);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
if (thisSuccess && onlyThis)
|
|
598
|
+
return BTree.finishCursorWalk(thisCursor, otherCursor, _compare, onlyThis);
|
|
599
|
+
if (otherSuccess && onlyOther)
|
|
600
|
+
return BTree.finishCursorWalk(otherCursor, thisCursor, _compare, onlyOther);
|
|
601
|
+
return undefined;
|
|
602
|
+
}
|
|
603
|
+
///////////////////////////////////////////////////////////////////////////
|
|
604
|
+
// Helper methods for diffAgainst /////////////////////////////////////////
|
|
605
|
+
static finishCursorWalk(cursor, cursorFinished, compareKeys, callback) {
|
|
606
|
+
const compared = BTree.compare(cursor, cursorFinished, compareKeys);
|
|
607
|
+
if (compared === 0) {
|
|
608
|
+
if (!BTree.step(cursor))
|
|
609
|
+
return undefined;
|
|
610
|
+
}
|
|
611
|
+
else if (compared < 0) {
|
|
612
|
+
check(false, 'cursor walk terminated early');
|
|
613
|
+
}
|
|
614
|
+
return BTree.stepToEnd(cursor, callback);
|
|
615
|
+
}
|
|
616
|
+
static stepToEnd(cursor, callback) {
|
|
617
|
+
let canStep = true;
|
|
618
|
+
while (canStep) {
|
|
619
|
+
const { leaf, levelIndices, currentKey } = cursor;
|
|
620
|
+
if (leaf) {
|
|
621
|
+
const value = leaf.values[levelIndices[levelIndices.length - 1]];
|
|
622
|
+
const result = callback(currentKey, value);
|
|
623
|
+
if (result && result.break)
|
|
624
|
+
return result.break;
|
|
625
|
+
}
|
|
626
|
+
canStep = BTree.step(cursor);
|
|
627
|
+
}
|
|
628
|
+
return undefined;
|
|
629
|
+
}
|
|
630
|
+
static makeDiffCursor(tree) {
|
|
631
|
+
const { _root, height } = tree;
|
|
632
|
+
return {
|
|
633
|
+
height: height,
|
|
634
|
+
internalSpine: [[_root]],
|
|
635
|
+
levelIndices: [0],
|
|
636
|
+
leaf: undefined,
|
|
637
|
+
currentKey: _root.maxKey(),
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Advances the cursor to the next step in the walk of its tree.
|
|
642
|
+
* Cursors are walked backwards in sort order, as this allows them to leverage maxKey() in order to be compared in O(1).
|
|
643
|
+
* @param cursor The cursor to step
|
|
644
|
+
* @param stepToNode If true, the cursor will be advanced to the next node (skipping values)
|
|
645
|
+
* @returns true if the step was completed and false if the step would have caused the cursor to move beyond the end of the tree.
|
|
646
|
+
*/
|
|
647
|
+
static step(cursor, stepToNode) {
|
|
648
|
+
const { internalSpine, levelIndices, leaf } = cursor;
|
|
649
|
+
if (stepToNode === true || leaf) {
|
|
650
|
+
const levelsLength = levelIndices.length;
|
|
651
|
+
// Step to the next node only if:
|
|
652
|
+
// - We are explicitly directed to via stepToNode, or
|
|
653
|
+
// - There are no key/value pairs left to step to in this leaf
|
|
654
|
+
if (stepToNode === true || levelIndices[levelsLength - 1] === 0) {
|
|
655
|
+
const spineLength = internalSpine.length;
|
|
656
|
+
// Root is leaf
|
|
657
|
+
if (spineLength === 0)
|
|
658
|
+
return false;
|
|
659
|
+
// Walk back up the tree until we find a new subtree to descend into
|
|
660
|
+
const nodeLevelIndex = spineLength - 1;
|
|
661
|
+
let levelIndexWalkBack = nodeLevelIndex;
|
|
662
|
+
while (levelIndexWalkBack >= 0) {
|
|
663
|
+
if (levelIndices[levelIndexWalkBack] > 0) {
|
|
664
|
+
if (levelIndexWalkBack < levelsLength - 1) {
|
|
665
|
+
// Remove leaf state from cursor
|
|
666
|
+
cursor.leaf = undefined;
|
|
667
|
+
levelIndices.pop();
|
|
668
|
+
}
|
|
669
|
+
// If we walked upwards past any internal node, slice them out
|
|
670
|
+
if (levelIndexWalkBack < nodeLevelIndex)
|
|
671
|
+
cursor.internalSpine = internalSpine.slice(0, levelIndexWalkBack + 1);
|
|
672
|
+
// Move to new internal node
|
|
673
|
+
cursor.currentKey =
|
|
674
|
+
internalSpine[levelIndexWalkBack][--levelIndices[levelIndexWalkBack]].maxKey();
|
|
675
|
+
return true;
|
|
676
|
+
}
|
|
677
|
+
levelIndexWalkBack--;
|
|
678
|
+
}
|
|
679
|
+
// Cursor is in the far left leaf of the tree, no more nodes to enumerate
|
|
680
|
+
return false;
|
|
681
|
+
}
|
|
682
|
+
else {
|
|
683
|
+
// Move to new leaf value
|
|
684
|
+
const valueIndex = --levelIndices[levelsLength - 1];
|
|
685
|
+
cursor.currentKey = leaf.keys[valueIndex];
|
|
686
|
+
return true;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
// Cursor does not point to a value in a leaf, so move downwards
|
|
691
|
+
const nextLevel = internalSpine.length;
|
|
692
|
+
const currentLevel = nextLevel - 1;
|
|
693
|
+
const node = internalSpine[currentLevel][levelIndices[currentLevel]];
|
|
694
|
+
if (node.isLeaf) {
|
|
695
|
+
// Entering into a leaf. Set the cursor to point at the last key/value pair.
|
|
696
|
+
cursor.leaf = node;
|
|
697
|
+
const valueIndex = (levelIndices[nextLevel] = node.values.length - 1);
|
|
698
|
+
cursor.currentKey = node.keys[valueIndex];
|
|
699
|
+
}
|
|
700
|
+
else {
|
|
701
|
+
const children = node.children;
|
|
702
|
+
internalSpine[nextLevel] = children;
|
|
703
|
+
const childIndex = children.length - 1;
|
|
704
|
+
levelIndices[nextLevel] = childIndex;
|
|
705
|
+
cursor.currentKey = children[childIndex].maxKey();
|
|
706
|
+
}
|
|
707
|
+
return true;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Compares the two cursors. Returns a value indicating which cursor is ahead in a walk.
|
|
712
|
+
* Note that cursors are advanced in reverse sorting order.
|
|
713
|
+
*/
|
|
714
|
+
static compare(cursorA, cursorB, compareKeys) {
|
|
715
|
+
const { height: heightA, currentKey: currentKeyA, levelIndices: levelIndicesA, } = cursorA;
|
|
716
|
+
const { height: heightB, currentKey: currentKeyB, levelIndices: levelIndicesB, } = cursorB;
|
|
717
|
+
// Reverse the comparison order, as cursors are advanced in reverse sorting order
|
|
718
|
+
const keyComparison = compareKeys(currentKeyB, currentKeyA);
|
|
719
|
+
if (keyComparison !== 0) {
|
|
720
|
+
return keyComparison;
|
|
721
|
+
}
|
|
722
|
+
// Normalize depth values relative to the shortest tree.
|
|
723
|
+
// This ensures that concurrent cursor walks of trees of differing heights can reliably land on shared nodes at the same time.
|
|
724
|
+
// To accomplish this, a cursor that is on an internal node at depth D1 with maxKey X is considered "behind" a cursor on an
|
|
725
|
+
// internal node at depth D2 with maxKey Y, when D1 < D2. Thus, always walking the cursor that is "behind" will allow the cursor
|
|
726
|
+
// at shallower depth (but equal maxKey) to "catch up" and land on shared nodes.
|
|
727
|
+
const heightMin = heightA < heightB ? heightA : heightB;
|
|
728
|
+
const depthANormalized = levelIndicesA.length - (heightA - heightMin);
|
|
729
|
+
const depthBNormalized = levelIndicesB.length - (heightB - heightMin);
|
|
730
|
+
return depthANormalized - depthBNormalized;
|
|
731
|
+
}
|
|
732
|
+
// End of helper methods for diffAgainst //////////////////////////////////
|
|
733
|
+
///////////////////////////////////////////////////////////////////////////
|
|
734
|
+
/** Returns a new iterator for iterating the keys of each pair in ascending order.
|
|
735
|
+
* @param firstKey: Minimum key to include in the output. */
|
|
736
|
+
keys(firstKey) {
|
|
737
|
+
var it = this.entries(firstKey, ReusedArray);
|
|
738
|
+
return iterator(() => {
|
|
739
|
+
var n = it.next();
|
|
740
|
+
if (n.value)
|
|
741
|
+
n.value = n.value[0];
|
|
742
|
+
return n;
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
/** Returns a new iterator for iterating the values of each pair in order by key.
|
|
746
|
+
* @param firstKey: Minimum key whose associated value is included in the output. */
|
|
747
|
+
values(firstKey) {
|
|
748
|
+
var it = this.entries(firstKey, ReusedArray);
|
|
749
|
+
return iterator(() => {
|
|
750
|
+
var n = it.next();
|
|
751
|
+
if (n.value)
|
|
752
|
+
n.value = n.value[1];
|
|
753
|
+
return n;
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
757
|
+
// Additional methods ///////////////////////////////////////////////////////
|
|
758
|
+
/** Returns the maximum number of children/values before nodes will split. */
|
|
759
|
+
get maxNodeSize() {
|
|
760
|
+
return this._maxNodeSize;
|
|
761
|
+
}
|
|
762
|
+
/** Gets the lowest key in the tree. Complexity: O(log size) */
|
|
763
|
+
minKey() {
|
|
764
|
+
return this._root.minKey();
|
|
765
|
+
}
|
|
766
|
+
/** Gets the highest key in the tree. Complexity: O(1) */
|
|
767
|
+
maxKey() {
|
|
768
|
+
return this._root.maxKey();
|
|
769
|
+
}
|
|
770
|
+
/** Quickly clones the tree by marking the root node as shared.
|
|
771
|
+
* Both copies remain editable. When you modify either copy, any
|
|
772
|
+
* nodes that are shared (or potentially shared) between the two
|
|
773
|
+
* copies are cloned so that the changes do not affect other copies.
|
|
774
|
+
* This is known as copy-on-write behavior, or "lazy copying". */
|
|
775
|
+
clone() {
|
|
776
|
+
this._root.isShared = true;
|
|
777
|
+
var result = new BTree(undefined, this._compare, this._maxNodeSize);
|
|
778
|
+
result._root = this._root;
|
|
779
|
+
result._size = this._size;
|
|
780
|
+
return result;
|
|
781
|
+
}
|
|
782
|
+
/** Performs a greedy clone, immediately duplicating any nodes that are
|
|
783
|
+
* not currently marked as shared, in order to avoid marking any
|
|
784
|
+
* additional nodes as shared.
|
|
785
|
+
* @param force Clone all nodes, even shared ones.
|
|
786
|
+
*/
|
|
787
|
+
greedyClone(force) {
|
|
788
|
+
var result = new BTree(undefined, this._compare, this._maxNodeSize);
|
|
789
|
+
result._root = this._root.greedyClone(force);
|
|
790
|
+
result._size = this._size;
|
|
791
|
+
return result;
|
|
792
|
+
}
|
|
793
|
+
/** Gets an array filled with the contents of the tree, sorted by key */
|
|
794
|
+
toArray(maxLength = 0x7fffffff) {
|
|
795
|
+
let min = this.minKey(), max = this.maxKey();
|
|
796
|
+
if (min !== undefined)
|
|
797
|
+
return this.getRange(min, max, true, maxLength);
|
|
798
|
+
return [];
|
|
799
|
+
}
|
|
800
|
+
/** Gets an array of all keys, sorted */
|
|
801
|
+
keysArray() {
|
|
802
|
+
var results = [];
|
|
803
|
+
this._root.forRange(this.minKey(), this.maxKey(), true, false, this, 0, (k, _v) => {
|
|
804
|
+
results.push(k);
|
|
805
|
+
});
|
|
806
|
+
return results;
|
|
807
|
+
}
|
|
808
|
+
/** Gets an array of all values, sorted by key */
|
|
809
|
+
valuesArray() {
|
|
810
|
+
var results = [];
|
|
811
|
+
this._root.forRange(this.minKey(), this.maxKey(), true, false, this, 0, (_k, v) => {
|
|
812
|
+
results.push(v);
|
|
813
|
+
});
|
|
814
|
+
return results;
|
|
815
|
+
}
|
|
816
|
+
/** Gets a string representing the tree's data based on toArray(). */
|
|
817
|
+
toString() {
|
|
818
|
+
return this.toArray().toString();
|
|
819
|
+
}
|
|
820
|
+
/** Stores a key-value pair only if the key doesn't already exist in the tree.
|
|
821
|
+
* @returns true if a new key was added
|
|
822
|
+
*/
|
|
823
|
+
setIfNotPresent(key, value) {
|
|
824
|
+
return this.set(key, value, false);
|
|
825
|
+
}
|
|
826
|
+
/** Returns the next pair whose key is larger than the specified key (or undefined if there is none).
|
|
827
|
+
* If key === undefined, this function returns the lowest pair.
|
|
828
|
+
* @param key The key to search for.
|
|
829
|
+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
|
|
830
|
+
* avoid creating a new array on every iteration.
|
|
831
|
+
*/
|
|
832
|
+
nextHigherPair(key, reusedArray) {
|
|
833
|
+
reusedArray = reusedArray || [];
|
|
834
|
+
if (key === undefined) {
|
|
835
|
+
return this._root.minPair(reusedArray);
|
|
836
|
+
}
|
|
837
|
+
return this._root.getPairOrNextHigher(key, this._compare, false, reusedArray);
|
|
838
|
+
}
|
|
839
|
+
/** Returns the next key larger than the specified key, or undefined if there is none.
|
|
840
|
+
* Also, nextHigherKey(undefined) returns the lowest key.
|
|
841
|
+
*/
|
|
842
|
+
nextHigherKey(key) {
|
|
843
|
+
var p = this.nextHigherPair(key, ReusedArray);
|
|
844
|
+
return p && p[0];
|
|
845
|
+
}
|
|
846
|
+
/** Returns the next pair whose key is smaller than the specified key (or undefined if there is none).
|
|
847
|
+
* If key === undefined, this function returns the highest pair.
|
|
848
|
+
* @param key The key to search for.
|
|
849
|
+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
|
|
850
|
+
* avoid creating a new array each time you call this method.
|
|
851
|
+
*/
|
|
852
|
+
nextLowerPair(key, reusedArray) {
|
|
853
|
+
reusedArray = reusedArray || [];
|
|
854
|
+
if (key === undefined) {
|
|
855
|
+
return this._root.maxPair(reusedArray);
|
|
856
|
+
}
|
|
857
|
+
return this._root.getPairOrNextLower(key, this._compare, false, reusedArray);
|
|
858
|
+
}
|
|
859
|
+
/** Returns the next key smaller than the specified key, or undefined if there is none.
|
|
860
|
+
* Also, nextLowerKey(undefined) returns the highest key.
|
|
861
|
+
*/
|
|
862
|
+
nextLowerKey(key) {
|
|
863
|
+
var p = this.nextLowerPair(key, ReusedArray);
|
|
864
|
+
return p && p[0];
|
|
865
|
+
}
|
|
866
|
+
/** Returns the key-value pair associated with the supplied key if it exists
|
|
867
|
+
* or the pair associated with the next lower pair otherwise. If there is no
|
|
868
|
+
* next lower pair, undefined is returned.
|
|
869
|
+
* @param key The key to search for.
|
|
870
|
+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
|
|
871
|
+
* avoid creating a new array each time you call this method.
|
|
872
|
+
* */
|
|
873
|
+
getPairOrNextLower(key, reusedArray) {
|
|
874
|
+
return this._root.getPairOrNextLower(key, this._compare, true, reusedArray || []);
|
|
875
|
+
}
|
|
876
|
+
/** Returns the key-value pair associated with the supplied key if it exists
|
|
877
|
+
* or the pair associated with the next lower pair otherwise. If there is no
|
|
878
|
+
* next lower pair, undefined is returned.
|
|
879
|
+
* @param key The key to search for.
|
|
880
|
+
* @param reusedArray Optional array used repeatedly to store key-value pairs, to
|
|
881
|
+
* avoid creating a new array each time you call this method.
|
|
882
|
+
* */
|
|
883
|
+
getPairOrNextHigher(key, reusedArray) {
|
|
884
|
+
return this._root.getPairOrNextHigher(key, this._compare, true, reusedArray || []);
|
|
885
|
+
}
|
|
886
|
+
/** Edits the value associated with a key in the tree, if it already exists.
|
|
887
|
+
* @returns true if the key existed, false if not.
|
|
888
|
+
*/
|
|
889
|
+
changeIfPresent(key, value) {
|
|
890
|
+
return this.editRange(key, key, true, (_k, _v) => ({ value })) !== 0;
|
|
891
|
+
}
|
|
892
|
+
/**
|
|
893
|
+
* Builds an array of pairs from the specified range of keys, sorted by key.
|
|
894
|
+
* Each returned pair is also an array: pair[0] is the key, pair[1] is the value.
|
|
895
|
+
* @param low The first key in the array will be greater than or equal to `low`.
|
|
896
|
+
* @param high This method returns when a key larger than this is reached.
|
|
897
|
+
* @param includeHigh If the `high` key is present, its pair will be included
|
|
898
|
+
* in the output if and only if this parameter is true. Note: if the
|
|
899
|
+
* `low` key is present, it is always included in the output.
|
|
900
|
+
* @param maxLength Length limit. getRange will stop scanning the tree when
|
|
901
|
+
* the array reaches this size.
|
|
902
|
+
* @description Computational complexity: O(result.length + log size)
|
|
903
|
+
*/
|
|
904
|
+
getRange(low, high, includeHigh, maxLength = 0x3ffffff) {
|
|
905
|
+
var results = [];
|
|
906
|
+
this._root.forRange(low, high, includeHigh, false, this, 0, (k, v) => {
|
|
907
|
+
results.push([k, v]);
|
|
908
|
+
return results.length > maxLength ? Break : undefined;
|
|
909
|
+
});
|
|
910
|
+
return results;
|
|
911
|
+
}
|
|
912
|
+
/** Adds all pairs from a list of key-value pairs.
|
|
913
|
+
* @param pairs Pairs to add to this tree. If there are duplicate keys,
|
|
914
|
+
* later pairs currently overwrite earlier ones (e.g. [[0,1],[0,7]]
|
|
915
|
+
* associates 0 with 7.)
|
|
916
|
+
* @param overwrite Whether to overwrite pairs that already exist (if false,
|
|
917
|
+
* pairs[i] is ignored when the key pairs[i][0] already exists.)
|
|
918
|
+
* @returns The number of pairs added to the collection.
|
|
919
|
+
* @description Computational complexity: O(pairs.length * log(size + pairs.length))
|
|
920
|
+
*/
|
|
921
|
+
setPairs(pairs, overwrite) {
|
|
922
|
+
var added = 0;
|
|
923
|
+
for (var i = 0; i < pairs.length; i++)
|
|
924
|
+
if (this.set(pairs[i][0], pairs[i][1], overwrite))
|
|
925
|
+
added++;
|
|
926
|
+
return added;
|
|
927
|
+
}
|
|
928
|
+
/**
|
|
929
|
+
* Scans the specified range of keys, in ascending order by key.
|
|
930
|
+
* Note: the callback `onFound` must not insert or remove items in the
|
|
931
|
+
* collection. Doing so may cause incorrect data to be sent to the
|
|
932
|
+
* callback afterward.
|
|
933
|
+
* @param low The first key scanned will be greater than or equal to `low`.
|
|
934
|
+
* @param high Scanning stops when a key larger than this is reached.
|
|
935
|
+
* @param includeHigh If the `high` key is present, `onFound` is called for
|
|
936
|
+
* that final pair if and only if this parameter is true.
|
|
937
|
+
* @param onFound A function that is called for each key-value pair. This
|
|
938
|
+
* function can return {break:R} to stop early with result R.
|
|
939
|
+
* @param initialCounter Initial third argument of onFound. This value
|
|
940
|
+
* increases by one each time `onFound` is called. Default: 0
|
|
941
|
+
* @returns The number of values found, or R if the callback returned
|
|
942
|
+
* `{break:R}` to stop early.
|
|
943
|
+
* @description Computational complexity: O(number of items scanned + log size)
|
|
944
|
+
*/
|
|
945
|
+
forRange(low, high, includeHigh, onFound, initialCounter) {
|
|
946
|
+
var r = this._root.forRange(low, high, includeHigh, false, this, initialCounter || 0, onFound);
|
|
947
|
+
return typeof r === 'number' ? r : r.break;
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* Scans and potentially modifies values for a subsequence of keys.
|
|
951
|
+
* Note: the callback `onFound` should ideally be a pure function.
|
|
952
|
+
* Specfically, it must not insert items, call clone(), or change
|
|
953
|
+
* the collection except via return value; out-of-band editing may
|
|
954
|
+
* cause an exception or may cause incorrect data to be sent to
|
|
955
|
+
* the callback (duplicate or missed items). It must not cause a
|
|
956
|
+
* clone() of the collection, otherwise the clone could be modified
|
|
957
|
+
* by changes requested by the callback.
|
|
958
|
+
* @param low The first key scanned will be greater than or equal to `low`.
|
|
959
|
+
* @param high Scanning stops when a key larger than this is reached.
|
|
960
|
+
* @param includeHigh If the `high` key is present, `onFound` is called for
|
|
961
|
+
* that final pair if and only if this parameter is true.
|
|
962
|
+
* @param onFound A function that is called for each key-value pair. This
|
|
963
|
+
* function can return `{value:v}` to change the value associated
|
|
964
|
+
* with the current key, `{delete:true}` to delete the current pair,
|
|
965
|
+
* `{break:R}` to stop early with result R, or it can return nothing
|
|
966
|
+
* (undefined or {}) to cause no effect and continue iterating.
|
|
967
|
+
* `{break:R}` can be combined with one of the other two commands.
|
|
968
|
+
* The third argument `counter` is the number of items iterated
|
|
969
|
+
* previously; it equals 0 when `onFound` is called the first time.
|
|
970
|
+
* @returns The number of values scanned, or R if the callback returned
|
|
971
|
+
* `{break:R}` to stop early.
|
|
972
|
+
* @description
|
|
973
|
+
* Computational complexity: O(number of items scanned + log size)
|
|
974
|
+
* Note: if the tree has been cloned with clone(), any shared
|
|
975
|
+
* nodes are copied before `onFound` is called. This takes O(n) time
|
|
976
|
+
* where n is proportional to the amount of shared data scanned.
|
|
977
|
+
*/
|
|
978
|
+
editRange(low, high, includeHigh, onFound, initialCounter) {
|
|
979
|
+
var root = this._root;
|
|
980
|
+
if (root.isShared)
|
|
981
|
+
this._root = root = root.clone();
|
|
982
|
+
try {
|
|
983
|
+
var r = root.forRange(low, high, includeHigh, true, this, initialCounter || 0, onFound);
|
|
984
|
+
return typeof r === 'number' ? r : r.break;
|
|
985
|
+
}
|
|
986
|
+
finally {
|
|
987
|
+
let isShared;
|
|
988
|
+
while (root.keys.length <= 1 && !root.isLeaf) {
|
|
989
|
+
isShared ||= root.isShared;
|
|
990
|
+
this._root = root =
|
|
991
|
+
root.keys.length === 0
|
|
992
|
+
? EmptyLeaf
|
|
993
|
+
: root.children[0];
|
|
994
|
+
}
|
|
995
|
+
// If any ancestor of the new root was shared, the new root must also be shared
|
|
996
|
+
if (isShared) {
|
|
997
|
+
root.isShared = true;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
/** Same as `editRange` except that the callback is called for all pairs. */
|
|
1002
|
+
editAll(onFound, initialCounter) {
|
|
1003
|
+
return this.editRange(this.minKey(), this.maxKey(), true, onFound, initialCounter);
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Removes a range of key-value pairs from the B+ tree.
|
|
1007
|
+
* @param low The first key scanned will be greater than or equal to `low`.
|
|
1008
|
+
* @param high Scanning stops when a key larger than this is reached.
|
|
1009
|
+
* @param includeHigh Specifies whether the `high` key, if present, is deleted.
|
|
1010
|
+
* @returns The number of key-value pairs that were deleted.
|
|
1011
|
+
* @description Computational complexity: O(log size + number of items deleted)
|
|
1012
|
+
*/
|
|
1013
|
+
deleteRange(low, high, includeHigh) {
|
|
1014
|
+
return this.editRange(low, high, includeHigh, DeleteRange);
|
|
1015
|
+
}
|
|
1016
|
+
/** Deletes a series of keys from the collection. */
|
|
1017
|
+
deleteKeys(keys) {
|
|
1018
|
+
for (var i = 0, r = 0; i < keys.length; i++)
|
|
1019
|
+
if (this.delete(keys[i]))
|
|
1020
|
+
r++;
|
|
1021
|
+
return r;
|
|
1022
|
+
}
|
|
1023
|
+
/** Gets the height of the tree: the number of internal nodes between the
|
|
1024
|
+
* BTree object and its leaf nodes (zero if there are no internal nodes). */
|
|
1025
|
+
get height() {
|
|
1026
|
+
let node = this._root;
|
|
1027
|
+
let height = -1;
|
|
1028
|
+
while (node) {
|
|
1029
|
+
height++;
|
|
1030
|
+
node = node.isLeaf
|
|
1031
|
+
? undefined
|
|
1032
|
+
: node.children[0];
|
|
1033
|
+
}
|
|
1034
|
+
return height;
|
|
1035
|
+
}
|
|
1036
|
+
/** Makes the object read-only to ensure it is not accidentally modified.
|
|
1037
|
+
* Freezing does not have to be permanent; unfreeze() reverses the effect.
|
|
1038
|
+
* This is accomplished by replacing mutator functions with a function
|
|
1039
|
+
* that throws an Error. Compared to using a property (e.g. this.isFrozen)
|
|
1040
|
+
* this implementation gives better performance in non-frozen BTrees.
|
|
1041
|
+
*/
|
|
1042
|
+
freeze() {
|
|
1043
|
+
var t = this;
|
|
1044
|
+
// Note: all other mutators ultimately call set() or editRange()
|
|
1045
|
+
// so we don't need to override those others.
|
|
1046
|
+
t.clear =
|
|
1047
|
+
t.set =
|
|
1048
|
+
t.editRange =
|
|
1049
|
+
function () {
|
|
1050
|
+
throw new Error('Attempted to modify a frozen BTree');
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
/** Ensures mutations are allowed, reversing the effect of freeze(). */
|
|
1054
|
+
unfreeze() {
|
|
1055
|
+
// @ts-ignore "The operand of a 'delete' operator must be optional."
|
|
1056
|
+
// (wrong: delete does not affect the prototype.)
|
|
1057
|
+
delete this.clear;
|
|
1058
|
+
// @ts-ignore
|
|
1059
|
+
delete this.set;
|
|
1060
|
+
// @ts-ignore
|
|
1061
|
+
delete this.editRange;
|
|
1062
|
+
}
|
|
1063
|
+
/** Returns true if the tree appears to be frozen. */
|
|
1064
|
+
get isFrozen() {
|
|
1065
|
+
return this.hasOwnProperty('editRange');
|
|
1066
|
+
}
|
|
1067
|
+
/** Scans the tree for signs of serious bugs (e.g. this.size doesn't match
|
|
1068
|
+
* number of elements, internal nodes not caching max element properly...)
|
|
1069
|
+
* Computational complexity: O(number of nodes), i.e. O(size). This method
|
|
1070
|
+
* skips the most expensive test - whether all keys are sorted - but it
|
|
1071
|
+
* does check that maxKey() of the children of internal nodes are sorted. */
|
|
1072
|
+
checkValid() {
|
|
1073
|
+
var size = this._root.checkValid(0, this, 0);
|
|
1074
|
+
check(size === this.size, 'size mismatch: counted ', size, 'but stored', this.size);
|
|
1075
|
+
}
|
|
1076
|
+
[Symbol.iterator] = this.entries.bind(this);
|
|
1077
|
+
where = this.filter.bind(this);
|
|
1078
|
+
setRange = this.setPairs.bind(this);
|
|
1079
|
+
add = this.set.bind(this); // for compatibility with ISetSink<K>
|
|
1080
|
+
}
|
|
1081
|
+
/** A TypeScript helper function that simply returns its argument, typed as
|
|
1082
|
+
* `ISortedSet<K>` if the BTree implements it, as it does if `V extends undefined`.
|
|
1083
|
+
* If `V` cannot be `undefined`, it returns `unknown` instead. Or at least, that
|
|
1084
|
+
* was the intention, but TypeScript is acting weird and may return `ISortedSet<K>`
|
|
1085
|
+
* even if `V` can't be `undefined` (discussion: btree-typescript issue #14) */
|
|
1086
|
+
export function asSet(btree) {
|
|
1087
|
+
return btree;
|
|
1088
|
+
}
|
|
1089
|
+
function iterator(next = () => ({ done: true, value: undefined })) {
|
|
1090
|
+
var result = { next };
|
|
1091
|
+
if (Symbol && Symbol.iterator)
|
|
1092
|
+
result[Symbol.iterator] = function () {
|
|
1093
|
+
return this;
|
|
1094
|
+
};
|
|
1095
|
+
return result;
|
|
1096
|
+
}
|
|
1097
|
+
/** Leaf node / base class. **************************************************/
|
|
1098
|
+
class BNode {
|
|
1099
|
+
// If this is an internal node, _keys[i] is the highest key in children[i].
|
|
1100
|
+
keys;
|
|
1101
|
+
values;
|
|
1102
|
+
// True if this node might be within multiple `BTree`s (or have multiple parents).
|
|
1103
|
+
// If so, it must be cloned before being mutated to avoid changing an unrelated tree.
|
|
1104
|
+
// This is transitive: if it's true, children are also shared even if `isShared!=true`
|
|
1105
|
+
// in those children. (Certain operations will propagate isShared=true to children.)
|
|
1106
|
+
isShared;
|
|
1107
|
+
get isLeaf() {
|
|
1108
|
+
return this.children === undefined;
|
|
1109
|
+
}
|
|
1110
|
+
constructor(keys = [], values) {
|
|
1111
|
+
this.keys = keys;
|
|
1112
|
+
this.values = values || undefVals;
|
|
1113
|
+
this.isShared = undefined;
|
|
1114
|
+
}
|
|
1115
|
+
///////////////////////////////////////////////////////////////////////////
|
|
1116
|
+
// Shared methods /////////////////////////////////////////////////////////
|
|
1117
|
+
maxKey() {
|
|
1118
|
+
return this.keys[this.keys.length - 1];
|
|
1119
|
+
}
|
|
1120
|
+
// If key not found, returns i^failXor where i is the insertion index.
|
|
1121
|
+
// Callers that don't care whether there was a match will set failXor=0.
|
|
1122
|
+
indexOf(key, failXor, cmp) {
|
|
1123
|
+
const keys = this.keys;
|
|
1124
|
+
var lo = 0, hi = keys.length, mid = hi >> 1;
|
|
1125
|
+
while (lo < hi) {
|
|
1126
|
+
var c = cmp(keys[mid], key);
|
|
1127
|
+
if (c < 0)
|
|
1128
|
+
lo = mid + 1;
|
|
1129
|
+
else if (c > 0)
|
|
1130
|
+
// key < keys[mid]
|
|
1131
|
+
hi = mid;
|
|
1132
|
+
else if (c === 0)
|
|
1133
|
+
return mid;
|
|
1134
|
+
else {
|
|
1135
|
+
// c is NaN or otherwise invalid
|
|
1136
|
+
if (key === key)
|
|
1137
|
+
// at least the search key is not NaN
|
|
1138
|
+
return keys.length;
|
|
1139
|
+
else
|
|
1140
|
+
throw new Error('BTree: NaN was used as a key');
|
|
1141
|
+
}
|
|
1142
|
+
mid = (lo + hi) >> 1;
|
|
1143
|
+
}
|
|
1144
|
+
return mid ^ failXor;
|
|
1145
|
+
// Unrolled version: benchmarks show same speed, not worth using
|
|
1146
|
+
/*var i = 1, c: number = 0, sum = 0;
|
|
1147
|
+
if (keys.length >= 4) {
|
|
1148
|
+
i = 3;
|
|
1149
|
+
if (keys.length >= 8) {
|
|
1150
|
+
i = 7;
|
|
1151
|
+
if (keys.length >= 16) {
|
|
1152
|
+
i = 15;
|
|
1153
|
+
if (keys.length >= 32) {
|
|
1154
|
+
i = 31;
|
|
1155
|
+
if (keys.length >= 64) {
|
|
1156
|
+
i = 127;
|
|
1157
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 64 : -64;
|
|
1158
|
+
sum += c;
|
|
1159
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 32 : -32;
|
|
1160
|
+
sum += c;
|
|
1161
|
+
}
|
|
1162
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 16 : -16;
|
|
1163
|
+
sum += c;
|
|
1164
|
+
}
|
|
1165
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 8 : -8;
|
|
1166
|
+
sum += c;
|
|
1167
|
+
}
|
|
1168
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 4 : -4;
|
|
1169
|
+
sum += c;
|
|
1170
|
+
}
|
|
1171
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 2 : -2;
|
|
1172
|
+
sum += c;
|
|
1173
|
+
}
|
|
1174
|
+
i += (c = i < keys.length ? cmp(keys[i], key) : 1) < 0 ? 1 : -1;
|
|
1175
|
+
c = i < keys.length ? cmp(keys[i], key) : 1;
|
|
1176
|
+
sum += c;
|
|
1177
|
+
if (c < 0) {
|
|
1178
|
+
++i;
|
|
1179
|
+
c = i < keys.length ? cmp(keys[i], key) : 1;
|
|
1180
|
+
sum += c;
|
|
1181
|
+
}
|
|
1182
|
+
if (sum !== sum) {
|
|
1183
|
+
if (key === key) // at least the search key is not NaN
|
|
1184
|
+
return keys.length ^ failXor;
|
|
1185
|
+
else
|
|
1186
|
+
throw new Error("BTree: NaN was used as a key");
|
|
1187
|
+
}
|
|
1188
|
+
return c === 0 ? i : i ^ failXor;*/
|
|
1189
|
+
}
|
|
1190
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1191
|
+
// Leaf Node: misc //////////////////////////////////////////////////////////
|
|
1192
|
+
minKey() {
|
|
1193
|
+
return this.keys[0];
|
|
1194
|
+
}
|
|
1195
|
+
minPair(reusedArray) {
|
|
1196
|
+
if (this.keys.length === 0)
|
|
1197
|
+
return undefined;
|
|
1198
|
+
reusedArray[0] = this.keys[0];
|
|
1199
|
+
reusedArray[1] = this.values[0];
|
|
1200
|
+
return reusedArray;
|
|
1201
|
+
}
|
|
1202
|
+
maxPair(reusedArray) {
|
|
1203
|
+
if (this.keys.length === 0)
|
|
1204
|
+
return undefined;
|
|
1205
|
+
const lastIndex = this.keys.length - 1;
|
|
1206
|
+
reusedArray[0] = this.keys[lastIndex];
|
|
1207
|
+
reusedArray[1] = this.values[lastIndex];
|
|
1208
|
+
return reusedArray;
|
|
1209
|
+
}
|
|
1210
|
+
clone() {
|
|
1211
|
+
var v = this.values;
|
|
1212
|
+
return new BNode(this.keys.slice(0), v === undefVals ? v : v.slice(0));
|
|
1213
|
+
}
|
|
1214
|
+
greedyClone(force) {
|
|
1215
|
+
return this.isShared && !force ? this : this.clone();
|
|
1216
|
+
}
|
|
1217
|
+
get(key, defaultValue, tree) {
|
|
1218
|
+
var i = this.indexOf(key, -1, tree._compare);
|
|
1219
|
+
return i < 0 ? defaultValue : this.values[i];
|
|
1220
|
+
}
|
|
1221
|
+
getPairOrNextLower(key, compare, inclusive, reusedArray) {
|
|
1222
|
+
var i = this.indexOf(key, -1, compare);
|
|
1223
|
+
const indexOrLower = i < 0 ? ~i - 1 : inclusive ? i : i - 1;
|
|
1224
|
+
if (indexOrLower >= 0) {
|
|
1225
|
+
reusedArray[0] = this.keys[indexOrLower];
|
|
1226
|
+
reusedArray[1] = this.values[indexOrLower];
|
|
1227
|
+
return reusedArray;
|
|
1228
|
+
}
|
|
1229
|
+
return undefined;
|
|
1230
|
+
}
|
|
1231
|
+
getPairOrNextHigher(key, compare, inclusive, reusedArray) {
|
|
1232
|
+
var i = this.indexOf(key, -1, compare);
|
|
1233
|
+
const indexOrLower = i < 0 ? ~i : inclusive ? i : i + 1;
|
|
1234
|
+
const keys = this.keys;
|
|
1235
|
+
if (indexOrLower < keys.length) {
|
|
1236
|
+
reusedArray[0] = keys[indexOrLower];
|
|
1237
|
+
reusedArray[1] = this.values[indexOrLower];
|
|
1238
|
+
return reusedArray;
|
|
1239
|
+
}
|
|
1240
|
+
return undefined;
|
|
1241
|
+
}
|
|
1242
|
+
checkValid(depth, _tree, baseIndex) {
|
|
1243
|
+
var kL = this.keys.length, vL = this.values.length;
|
|
1244
|
+
check(this.values === undefVals ? kL <= vL : kL === vL, 'keys/values length mismatch: depth', depth, 'with lengths', kL, vL, 'and baseIndex', baseIndex);
|
|
1245
|
+
// Note: we don't check for "node too small" because sometimes a node
|
|
1246
|
+
// can legitimately have size 1. This occurs if there is a batch
|
|
1247
|
+
// deletion, leaving a node of size 1, and the siblings are full so
|
|
1248
|
+
// it can't be merged with adjacent nodes. However, the parent will
|
|
1249
|
+
// verify that the average node size is at least half of the maximum.
|
|
1250
|
+
check(depth == 0 || kL > 0, 'empty leaf at depth', depth, 'and baseIndex', baseIndex);
|
|
1251
|
+
return kL;
|
|
1252
|
+
}
|
|
1253
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1254
|
+
// Leaf Node: set & node splitting //////////////////////////////////////////
|
|
1255
|
+
set(key, value, overwrite, tree) {
|
|
1256
|
+
var i = this.indexOf(key, -1, tree._compare);
|
|
1257
|
+
if (i < 0) {
|
|
1258
|
+
// key does not exist yet
|
|
1259
|
+
i = ~i;
|
|
1260
|
+
tree._size++;
|
|
1261
|
+
if (this.keys.length < tree._maxNodeSize) {
|
|
1262
|
+
return this.insertInLeaf(i, key, value, tree);
|
|
1263
|
+
}
|
|
1264
|
+
else {
|
|
1265
|
+
// This leaf node is full and must split
|
|
1266
|
+
var newRightSibling = this.splitOffRightSide(), target = this;
|
|
1267
|
+
if (i > this.keys.length) {
|
|
1268
|
+
i -= this.keys.length;
|
|
1269
|
+
target = newRightSibling;
|
|
1270
|
+
}
|
|
1271
|
+
target.insertInLeaf(i, key, value, tree);
|
|
1272
|
+
return newRightSibling;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
else {
|
|
1276
|
+
// Key already exists
|
|
1277
|
+
if (overwrite !== false) {
|
|
1278
|
+
if (value !== undefined)
|
|
1279
|
+
this.reifyValues();
|
|
1280
|
+
// usually this is a no-op, but some users may wish to edit the key
|
|
1281
|
+
this.keys[i] = key;
|
|
1282
|
+
this.values[i] = value;
|
|
1283
|
+
}
|
|
1284
|
+
return false;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
reifyValues() {
|
|
1288
|
+
if (this.values === undefVals)
|
|
1289
|
+
return (this.values = this.values.slice(0, this.keys.length));
|
|
1290
|
+
return this.values;
|
|
1291
|
+
}
|
|
1292
|
+
insertInLeaf(i, key, value, tree) {
|
|
1293
|
+
this.keys.splice(i, 0, key);
|
|
1294
|
+
if (this.values === undefVals) {
|
|
1295
|
+
while (undefVals.length < tree._maxNodeSize)
|
|
1296
|
+
undefVals.push(undefined);
|
|
1297
|
+
if (value === undefined) {
|
|
1298
|
+
return true;
|
|
1299
|
+
}
|
|
1300
|
+
else {
|
|
1301
|
+
this.values = undefVals.slice(0, this.keys.length - 1);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
this.values.splice(i, 0, value);
|
|
1305
|
+
return true;
|
|
1306
|
+
}
|
|
1307
|
+
takeFromRight(rhs) {
|
|
1308
|
+
// Reminder: parent node must update its copy of key for this node
|
|
1309
|
+
// assert: neither node is shared
|
|
1310
|
+
// assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)
|
|
1311
|
+
var v = this.values;
|
|
1312
|
+
if (rhs.values === undefVals) {
|
|
1313
|
+
if (v !== undefVals)
|
|
1314
|
+
v.push(undefined);
|
|
1315
|
+
}
|
|
1316
|
+
else {
|
|
1317
|
+
v = this.reifyValues();
|
|
1318
|
+
v.push(rhs.values.shift());
|
|
1319
|
+
}
|
|
1320
|
+
this.keys.push(rhs.keys.shift());
|
|
1321
|
+
}
|
|
1322
|
+
takeFromLeft(lhs) {
|
|
1323
|
+
// Reminder: parent node must update its copy of key for this node
|
|
1324
|
+
// assert: neither node is shared
|
|
1325
|
+
// assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)
|
|
1326
|
+
var v = this.values;
|
|
1327
|
+
if (lhs.values === undefVals) {
|
|
1328
|
+
if (v !== undefVals)
|
|
1329
|
+
v.unshift(undefined);
|
|
1330
|
+
}
|
|
1331
|
+
else {
|
|
1332
|
+
v = this.reifyValues();
|
|
1333
|
+
v.unshift(lhs.values.pop());
|
|
1334
|
+
}
|
|
1335
|
+
this.keys.unshift(lhs.keys.pop());
|
|
1336
|
+
}
|
|
1337
|
+
splitOffRightSide() {
|
|
1338
|
+
// Reminder: parent node must update its copy of key for this node
|
|
1339
|
+
var half = this.keys.length >> 1, keys = this.keys.splice(half);
|
|
1340
|
+
var values = this.values === undefVals ? undefVals : this.values.splice(half);
|
|
1341
|
+
return new BNode(keys, values);
|
|
1342
|
+
}
|
|
1343
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1344
|
+
// Leaf Node: scanning & deletions //////////////////////////////////////////
|
|
1345
|
+
forRange(low, high, includeHigh, editMode, tree, count, onFound) {
|
|
1346
|
+
var cmp = tree._compare;
|
|
1347
|
+
var iLow, iHigh;
|
|
1348
|
+
if (high === low) {
|
|
1349
|
+
if (!includeHigh)
|
|
1350
|
+
return count;
|
|
1351
|
+
iHigh = (iLow = this.indexOf(low, -1, cmp)) + 1;
|
|
1352
|
+
if (iLow < 0)
|
|
1353
|
+
return count;
|
|
1354
|
+
}
|
|
1355
|
+
else {
|
|
1356
|
+
iLow = this.indexOf(low, 0, cmp);
|
|
1357
|
+
iHigh = this.indexOf(high, -1, cmp);
|
|
1358
|
+
if (iHigh < 0)
|
|
1359
|
+
iHigh = ~iHigh;
|
|
1360
|
+
else if (includeHigh === true)
|
|
1361
|
+
iHigh++;
|
|
1362
|
+
}
|
|
1363
|
+
var keys = this.keys, values = this.values;
|
|
1364
|
+
if (onFound !== undefined) {
|
|
1365
|
+
for (var i = iLow; i < iHigh; i++) {
|
|
1366
|
+
var key = keys[i];
|
|
1367
|
+
var result = onFound(key, values[i], count++);
|
|
1368
|
+
if (result !== undefined) {
|
|
1369
|
+
if (editMode === true) {
|
|
1370
|
+
if (key !== keys[i] || this.isShared === true)
|
|
1371
|
+
throw new Error('BTree illegally changed or cloned in editRange');
|
|
1372
|
+
if (result.delete) {
|
|
1373
|
+
this.keys.splice(i, 1);
|
|
1374
|
+
if (this.values !== undefVals)
|
|
1375
|
+
this.values.splice(i, 1);
|
|
1376
|
+
tree._size--;
|
|
1377
|
+
i--;
|
|
1378
|
+
iHigh--;
|
|
1379
|
+
}
|
|
1380
|
+
else if (result.hasOwnProperty('value')) {
|
|
1381
|
+
values[i] = result.value;
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
if (result.break !== undefined)
|
|
1385
|
+
return result;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
else
|
|
1390
|
+
count += iHigh - iLow;
|
|
1391
|
+
return count;
|
|
1392
|
+
}
|
|
1393
|
+
/** Adds entire contents of right-hand sibling (rhs is left unchanged) */
|
|
1394
|
+
mergeSibling(rhs, _) {
|
|
1395
|
+
this.keys.push.apply(this.keys, rhs.keys);
|
|
1396
|
+
if (this.values === undefVals) {
|
|
1397
|
+
if (rhs.values === undefVals)
|
|
1398
|
+
return;
|
|
1399
|
+
this.values = this.values.slice(0, this.keys.length);
|
|
1400
|
+
}
|
|
1401
|
+
this.values.push.apply(this.values, rhs.reifyValues());
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
/** Internal node (non-leaf node) ********************************************/
|
|
1405
|
+
class BNodeInternal extends BNode {
|
|
1406
|
+
// Note: conventionally B+ trees have one fewer key than the number of
|
|
1407
|
+
// children, but I find it easier to keep the array lengths equal: each
|
|
1408
|
+
// keys[i] caches the value of children[i].maxKey().
|
|
1409
|
+
children;
|
|
1410
|
+
/**
|
|
1411
|
+
* This does not mark `children` as shared, so it is the responsibility of the caller
|
|
1412
|
+
* to ensure children are either marked shared, or aren't included in another tree.
|
|
1413
|
+
*/
|
|
1414
|
+
constructor(children, keys) {
|
|
1415
|
+
if (!keys) {
|
|
1416
|
+
keys = [];
|
|
1417
|
+
for (var i = 0; i < children.length; i++)
|
|
1418
|
+
keys[i] = children[i].maxKey();
|
|
1419
|
+
}
|
|
1420
|
+
super(keys);
|
|
1421
|
+
this.children = children;
|
|
1422
|
+
}
|
|
1423
|
+
clone() {
|
|
1424
|
+
var children = this.children.slice(0);
|
|
1425
|
+
for (var i = 0; i < children.length; i++)
|
|
1426
|
+
children[i].isShared = true;
|
|
1427
|
+
return new BNodeInternal(children, this.keys.slice(0));
|
|
1428
|
+
}
|
|
1429
|
+
greedyClone(force) {
|
|
1430
|
+
if (this.isShared && !force)
|
|
1431
|
+
return this;
|
|
1432
|
+
var nu = new BNodeInternal(this.children.slice(0), this.keys.slice(0));
|
|
1433
|
+
for (var i = 0; i < nu.children.length; i++)
|
|
1434
|
+
nu.children[i] = nu.children[i].greedyClone(force);
|
|
1435
|
+
return nu;
|
|
1436
|
+
}
|
|
1437
|
+
minKey() {
|
|
1438
|
+
return this.children[0].minKey();
|
|
1439
|
+
}
|
|
1440
|
+
minPair(reusedArray) {
|
|
1441
|
+
return this.children[0].minPair(reusedArray);
|
|
1442
|
+
}
|
|
1443
|
+
maxPair(reusedArray) {
|
|
1444
|
+
return this.children[this.children.length - 1].maxPair(reusedArray);
|
|
1445
|
+
}
|
|
1446
|
+
get(key, defaultValue, tree) {
|
|
1447
|
+
var i = this.indexOf(key, 0, tree._compare), children = this.children;
|
|
1448
|
+
return i < children.length
|
|
1449
|
+
? children[i].get(key, defaultValue, tree)
|
|
1450
|
+
: undefined;
|
|
1451
|
+
}
|
|
1452
|
+
getPairOrNextLower(key, compare, inclusive, reusedArray) {
|
|
1453
|
+
var i = this.indexOf(key, 0, compare), children = this.children;
|
|
1454
|
+
if (i >= children.length)
|
|
1455
|
+
return this.maxPair(reusedArray);
|
|
1456
|
+
const result = children[i].getPairOrNextLower(key, compare, inclusive, reusedArray);
|
|
1457
|
+
if (result === undefined && i > 0) {
|
|
1458
|
+
return children[i - 1].maxPair(reusedArray);
|
|
1459
|
+
}
|
|
1460
|
+
return result;
|
|
1461
|
+
}
|
|
1462
|
+
getPairOrNextHigher(key, compare, inclusive, reusedArray) {
|
|
1463
|
+
var i = this.indexOf(key, 0, compare), children = this.children, length = children.length;
|
|
1464
|
+
if (i >= length)
|
|
1465
|
+
return undefined;
|
|
1466
|
+
const result = children[i].getPairOrNextHigher(key, compare, inclusive, reusedArray);
|
|
1467
|
+
if (result === undefined && i < length - 1) {
|
|
1468
|
+
return children[i + 1].minPair(reusedArray);
|
|
1469
|
+
}
|
|
1470
|
+
return result;
|
|
1471
|
+
}
|
|
1472
|
+
checkValid(depth, tree, baseIndex) {
|
|
1473
|
+
let kL = this.keys.length, cL = this.children.length;
|
|
1474
|
+
check(kL === cL, 'keys/children length mismatch: depth', depth, 'lengths', kL, cL, 'baseIndex', baseIndex);
|
|
1475
|
+
check(kL > 1 || depth > 0, 'internal node has length', kL, 'at depth', depth, 'baseIndex', baseIndex);
|
|
1476
|
+
let size = 0, c = this.children, k = this.keys, childSize = 0;
|
|
1477
|
+
for (var i = 0; i < cL; i++) {
|
|
1478
|
+
size += c[i].checkValid(depth + 1, tree, baseIndex + size);
|
|
1479
|
+
childSize += c[i].keys.length;
|
|
1480
|
+
check(size >= childSize, 'wtf', baseIndex); // no way this will ever fail
|
|
1481
|
+
check(i === 0 || c[i - 1].constructor === c[i].constructor, 'type mismatch, baseIndex:', baseIndex);
|
|
1482
|
+
if (c[i].maxKey() != k[i])
|
|
1483
|
+
check(false, 'keys[', i, '] =', k[i], 'is wrong, should be ', c[i].maxKey(), 'at depth', depth, 'baseIndex', baseIndex);
|
|
1484
|
+
if (!(i === 0 || tree._compare(k[i - 1], k[i]) < 0))
|
|
1485
|
+
check(false, 'sort violation at depth', depth, 'index', i, 'keys', k[i - 1], k[i]);
|
|
1486
|
+
}
|
|
1487
|
+
// 2020/08: BTree doesn't always avoid grossly undersized nodes,
|
|
1488
|
+
// but AFAIK such nodes are pretty harmless, so accept them.
|
|
1489
|
+
let toofew = childSize === 0; // childSize < (tree.maxNodeSize >> 1)*cL;
|
|
1490
|
+
if (toofew || childSize > tree.maxNodeSize * cL)
|
|
1491
|
+
check(false, toofew ? 'too few' : 'too many', 'children (', childSize, size, ') at depth', depth, 'maxNodeSize:', tree.maxNodeSize, 'children.length:', cL, 'baseIndex:', baseIndex);
|
|
1492
|
+
return size;
|
|
1493
|
+
}
|
|
1494
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1495
|
+
// Internal Node: set & node splitting //////////////////////////////////////
|
|
1496
|
+
set(key, value, overwrite, tree) {
|
|
1497
|
+
var c = this.children, max = tree._maxNodeSize, cmp = tree._compare;
|
|
1498
|
+
var i = Math.min(this.indexOf(key, 0, cmp), c.length - 1), child = c[i];
|
|
1499
|
+
if (child.isShared)
|
|
1500
|
+
c[i] = child = child.clone();
|
|
1501
|
+
if (child.keys.length >= max) {
|
|
1502
|
+
// child is full; inserting anything else will cause a split.
|
|
1503
|
+
// Shifting an item to the left or right sibling may avoid a split.
|
|
1504
|
+
// We can do a shift if the adjacent node is not full and if the
|
|
1505
|
+
// current key can still be placed in the same node after the shift.
|
|
1506
|
+
var other;
|
|
1507
|
+
if (i > 0 &&
|
|
1508
|
+
(other = c[i - 1]).keys.length < max &&
|
|
1509
|
+
cmp(child.keys[0], key) < 0) {
|
|
1510
|
+
if (other.isShared)
|
|
1511
|
+
c[i - 1] = other = other.clone();
|
|
1512
|
+
other.takeFromRight(child);
|
|
1513
|
+
this.keys[i - 1] = other.maxKey();
|
|
1514
|
+
}
|
|
1515
|
+
else if ((other = c[i + 1]) !== undefined &&
|
|
1516
|
+
other.keys.length < max &&
|
|
1517
|
+
cmp(child.maxKey(), key) < 0) {
|
|
1518
|
+
if (other.isShared)
|
|
1519
|
+
c[i + 1] = other = other.clone();
|
|
1520
|
+
other.takeFromLeft(child);
|
|
1521
|
+
this.keys[i] = c[i].maxKey();
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
var result = child.set(key, value, overwrite, tree);
|
|
1525
|
+
if (result === false)
|
|
1526
|
+
return false;
|
|
1527
|
+
this.keys[i] = child.maxKey();
|
|
1528
|
+
if (result === true)
|
|
1529
|
+
return true;
|
|
1530
|
+
// The child has split and `result` is a new right child... does it fit?
|
|
1531
|
+
if (this.keys.length < max) {
|
|
1532
|
+
// yes
|
|
1533
|
+
this.insert(i + 1, result);
|
|
1534
|
+
return true;
|
|
1535
|
+
}
|
|
1536
|
+
else {
|
|
1537
|
+
// no, we must split also
|
|
1538
|
+
var newRightSibling = this.splitOffRightSide(), target = this;
|
|
1539
|
+
if (cmp(result.maxKey(), this.maxKey()) > 0) {
|
|
1540
|
+
target = newRightSibling;
|
|
1541
|
+
i -= this.keys.length;
|
|
1542
|
+
}
|
|
1543
|
+
target.insert(i + 1, result);
|
|
1544
|
+
return newRightSibling;
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
/**
|
|
1548
|
+
* Inserts `child` at index `i`.
|
|
1549
|
+
* This does not mark `child` as shared, so it is the responsibility of the caller
|
|
1550
|
+
* to ensure that either child is marked shared, or it is not included in another tree.
|
|
1551
|
+
*/
|
|
1552
|
+
insert(i, child) {
|
|
1553
|
+
this.children.splice(i, 0, child);
|
|
1554
|
+
this.keys.splice(i, 0, child.maxKey());
|
|
1555
|
+
}
|
|
1556
|
+
/**
|
|
1557
|
+
* Split this node.
|
|
1558
|
+
* Modifies this to remove the second half of the items, returning a separate node containing them.
|
|
1559
|
+
*/
|
|
1560
|
+
splitOffRightSide() {
|
|
1561
|
+
// assert !this.isShared;
|
|
1562
|
+
var half = this.children.length >> 1;
|
|
1563
|
+
return new BNodeInternal(this.children.splice(half), this.keys.splice(half));
|
|
1564
|
+
}
|
|
1565
|
+
takeFromRight(rhs) {
|
|
1566
|
+
// Reminder: parent node must update its copy of key for this node
|
|
1567
|
+
// assert: neither node is shared
|
|
1568
|
+
// assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)
|
|
1569
|
+
this.keys.push(rhs.keys.shift());
|
|
1570
|
+
this.children.push(rhs.children.shift());
|
|
1571
|
+
}
|
|
1572
|
+
takeFromLeft(lhs) {
|
|
1573
|
+
// Reminder: parent node must update its copy of key for this node
|
|
1574
|
+
// assert: neither node is shared
|
|
1575
|
+
// assert rhs.keys.length > (maxNodeSize/2 && this.keys.length<maxNodeSize)
|
|
1576
|
+
this.keys.unshift(lhs.keys.pop());
|
|
1577
|
+
this.children.unshift(lhs.children.pop());
|
|
1578
|
+
}
|
|
1579
|
+
/////////////////////////////////////////////////////////////////////////////
|
|
1580
|
+
// Internal Node: scanning & deletions //////////////////////////////////////
|
|
1581
|
+
// Note: `count` is the next value of the third argument to `onFound`.
|
|
1582
|
+
// A leaf node's `forRange` function returns a new value for this counter,
|
|
1583
|
+
// unless the operation is to stop early.
|
|
1584
|
+
forRange(low, high, includeHigh, editMode, tree, count, onFound) {
|
|
1585
|
+
var cmp = tree._compare;
|
|
1586
|
+
var keys = this.keys, children = this.children;
|
|
1587
|
+
var iLow = this.indexOf(low, 0, cmp), i = iLow;
|
|
1588
|
+
var iHigh = Math.min(high === low ? iLow : this.indexOf(high, 0, cmp), keys.length - 1);
|
|
1589
|
+
if (!editMode) {
|
|
1590
|
+
// Simple case
|
|
1591
|
+
for (; i <= iHigh; i++) {
|
|
1592
|
+
var result = children[i].forRange(low, high, includeHigh, editMode, tree, count, onFound);
|
|
1593
|
+
if (typeof result !== 'number')
|
|
1594
|
+
return result;
|
|
1595
|
+
count = result;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
else if (i <= iHigh) {
|
|
1599
|
+
try {
|
|
1600
|
+
for (; i <= iHigh; i++) {
|
|
1601
|
+
if (children[i].isShared)
|
|
1602
|
+
children[i] = children[i].clone();
|
|
1603
|
+
var result = children[i].forRange(low, high, includeHigh, editMode, tree, count, onFound);
|
|
1604
|
+
// Note: if children[i] is empty then keys[i]=undefined.
|
|
1605
|
+
// This is an invalid state, but it is fixed below.
|
|
1606
|
+
keys[i] = children[i].maxKey();
|
|
1607
|
+
if (typeof result !== 'number')
|
|
1608
|
+
return result;
|
|
1609
|
+
count = result;
|
|
1610
|
+
}
|
|
1611
|
+
}
|
|
1612
|
+
finally {
|
|
1613
|
+
// Deletions may have occurred, so look for opportunities to merge nodes.
|
|
1614
|
+
var half = tree._maxNodeSize >> 1;
|
|
1615
|
+
if (iLow > 0)
|
|
1616
|
+
iLow--;
|
|
1617
|
+
for (i = iHigh; i >= iLow; i--) {
|
|
1618
|
+
if (children[i].keys.length <= half) {
|
|
1619
|
+
if (children[i].keys.length !== 0) {
|
|
1620
|
+
this.tryMerge(i, tree._maxNodeSize);
|
|
1621
|
+
}
|
|
1622
|
+
else {
|
|
1623
|
+
// child is empty! delete it!
|
|
1624
|
+
keys.splice(i, 1);
|
|
1625
|
+
children.splice(i, 1);
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
if (children.length !== 0 && children[0].keys.length === 0)
|
|
1630
|
+
check(false, 'emptiness bug');
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
return count;
|
|
1634
|
+
}
|
|
1635
|
+
/** Merges child i with child i+1 if their combined size is not too large */
|
|
1636
|
+
tryMerge(i, maxSize) {
|
|
1637
|
+
var children = this.children;
|
|
1638
|
+
if (i >= 0 && i + 1 < children.length) {
|
|
1639
|
+
if (children[i].keys.length + children[i + 1].keys.length <= maxSize) {
|
|
1640
|
+
if (children[i].isShared)
|
|
1641
|
+
// cloned already UNLESS i is outside scan range
|
|
1642
|
+
children[i] = children[i].clone();
|
|
1643
|
+
children[i].mergeSibling(children[i + 1], maxSize);
|
|
1644
|
+
children.splice(i + 1, 1);
|
|
1645
|
+
this.keys.splice(i + 1, 1);
|
|
1646
|
+
this.keys[i] = children[i].maxKey();
|
|
1647
|
+
return true;
|
|
1648
|
+
}
|
|
1649
|
+
}
|
|
1650
|
+
return false;
|
|
1651
|
+
}
|
|
1652
|
+
/**
|
|
1653
|
+
* Move children from `rhs` into this.
|
|
1654
|
+
* `rhs` must be part of this tree, and be removed from it after this call
|
|
1655
|
+
* (otherwise isShared for its children could be incorrect).
|
|
1656
|
+
*/
|
|
1657
|
+
mergeSibling(rhs, maxNodeSize) {
|
|
1658
|
+
// assert !this.isShared;
|
|
1659
|
+
var oldLength = this.keys.length;
|
|
1660
|
+
this.keys.push.apply(this.keys, rhs.keys);
|
|
1661
|
+
const rhsChildren = rhs.children;
|
|
1662
|
+
this.children.push.apply(this.children, rhsChildren);
|
|
1663
|
+
if (rhs.isShared && !this.isShared) {
|
|
1664
|
+
// All children of a shared node are implicitly shared, and since their new
|
|
1665
|
+
// parent is not shared, they must now be explicitly marked as shared.
|
|
1666
|
+
for (var i = 0; i < rhsChildren.length; i++)
|
|
1667
|
+
rhsChildren[i].isShared = true;
|
|
1668
|
+
}
|
|
1669
|
+
// If our children are themselves almost empty due to a mass-delete,
|
|
1670
|
+
// they may need to be merged too (but only the oldLength-1 and its
|
|
1671
|
+
// right sibling should need this).
|
|
1672
|
+
this.tryMerge(oldLength - 1, maxNodeSize);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
// Optimization: this array of `undefined`s is used instead of a normal
|
|
1676
|
+
// array of values in nodes where `undefined` is the only value.
|
|
1677
|
+
// Its length is extended to max node size on first use; since it can
|
|
1678
|
+
// be shared between trees with different maximums, its length can only
|
|
1679
|
+
// increase, never decrease. Its type should be undefined[] but strangely
|
|
1680
|
+
// TypeScript won't allow the comparison V[] === undefined[]. To prevent
|
|
1681
|
+
// users from making this array too large, BTree has a maximum node size.
|
|
1682
|
+
//
|
|
1683
|
+
// FAQ: undefVals[i] is already undefined, so why increase the array size?
|
|
1684
|
+
// Reading outside the bounds of an array is relatively slow because it
|
|
1685
|
+
// has the side effect of scanning the prototype chain.
|
|
1686
|
+
var undefVals = [];
|
|
1687
|
+
const Delete = { delete: true }, DeleteRange = () => Delete;
|
|
1688
|
+
const Break = { break: true };
|
|
1689
|
+
const EmptyLeaf = (function () {
|
|
1690
|
+
var n = new BNode();
|
|
1691
|
+
n.isShared = true;
|
|
1692
|
+
return n;
|
|
1693
|
+
})();
|
|
1694
|
+
const EmptyArray = [];
|
|
1695
|
+
const ReusedArray = []; // assumed thread-local
|
|
1696
|
+
function check(fact, ...args) {
|
|
1697
|
+
if (!fact) {
|
|
1698
|
+
args.unshift('B+ tree'); // at beginning of message
|
|
1699
|
+
throw new Error(args.join(' '));
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
/** A BTree frozen in the empty state. */
|
|
1703
|
+
export const EmptyBTree = (() => {
|
|
1704
|
+
let t = new BTree();
|
|
1705
|
+
t.freeze();
|
|
1706
|
+
return t;
|
|
1707
|
+
})();
|
|
1708
|
+
//# sourceMappingURL=b+tree.js.map
|