@rocicorp/zero 1.12.0-canary.7 → 1.12.0-canary.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/replicache/src/btree/node.d.ts +0 -2
- package/out/replicache/src/btree/node.d.ts.map +1 -1
- package/out/replicache/src/btree/node.js.map +1 -1
- package/out/replicache/src/connection-loop.d.ts.map +1 -1
- package/out/replicache/src/connection-loop.js +1 -1
- package/out/replicache/src/connection-loop.js.map +1 -1
- package/out/replicache/src/db/commit.d.ts +0 -1
- package/out/replicache/src/db/commit.d.ts.map +1 -1
- package/out/replicache/src/db/commit.js +1 -1
- package/out/replicache/src/db/commit.js.map +1 -1
- package/out/replicache/src/db/write.d.ts +0 -2
- package/out/replicache/src/db/write.d.ts.map +1 -1
- package/out/replicache/src/db/write.js +1 -1
- package/out/replicache/src/db/write.js.map +1 -1
- package/out/replicache/src/deleted-clients.d.ts +0 -2
- package/out/replicache/src/deleted-clients.d.ts.map +1 -1
- package/out/replicache/src/deleted-clients.js +1 -1
- package/out/replicache/src/deleted-clients.js.map +1 -1
- package/out/replicache/src/frozen-json.d.ts +0 -1
- package/out/replicache/src/frozen-json.d.ts.map +1 -1
- package/out/replicache/src/frozen-json.js.map +1 -1
- package/out/replicache/src/index-defs.d.ts +0 -2
- package/out/replicache/src/index-defs.d.ts.map +1 -1
- package/out/replicache/src/index-defs.js +1 -1
- package/out/replicache/src/index-defs.js.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts +0 -1
- package/out/replicache/src/kv/expo-sqlite/store.d.ts.map +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js +1 -1
- package/out/replicache/src/kv/expo-sqlite/store.js.map +1 -1
- package/out/replicache/src/kv/idb-store.js +1 -1
- package/out/replicache/src/kv/idb-store.js.map +1 -1
- package/out/replicache/src/kv/throw-if-closed.d.ts +0 -3
- package/out/replicache/src/kv/throw-if-closed.d.ts.map +1 -1
- package/out/replicache/src/kv/throw-if-closed.js.map +1 -1
- package/out/replicache/src/persist/client-group-gc.d.ts +0 -7
- package/out/replicache/src/persist/client-group-gc.d.ts.map +1 -1
- package/out/replicache/src/persist/client-group-gc.js +1 -1
- package/out/replicache/src/persist/client-group-gc.js.map +1 -1
- package/out/replicache/src/process-scheduler.js +1 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +2 -7
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +1 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/replicache/src/sync/patch.d.ts +0 -5
- package/out/replicache/src/sync/patch.d.ts.map +1 -1
- package/out/replicache/src/sync/patch.js +1 -1
- package/out/replicache/src/sync/patch.js.map +1 -1
- package/out/replicache/src/sync/pull.d.ts +0 -1
- package/out/replicache/src/sync/pull.d.ts.map +1 -1
- package/out/replicache/src/sync/pull.js.map +1 -1
- package/out/replicache/src/sync/push.d.ts +2 -1
- package/out/replicache/src/sync/push.d.ts.map +1 -1
- package/out/replicache/src/sync/push.js.map +1 -1
- package/out/replicache/src/types.d.ts +2 -1
- package/out/replicache/src/types.d.ts.map +1 -1
- package/out/shared/src/asserts.d.ts +0 -5
- package/out/shared/src/asserts.d.ts.map +1 -1
- package/out/shared/src/asserts.js +1 -1
- package/out/shared/src/asserts.js.map +1 -1
- package/out/shared/src/browser-env.d.ts +0 -17
- package/out/shared/src/browser-env.d.ts.map +1 -1
- package/out/shared/src/browser-env.js.map +1 -1
- package/out/shared/src/deep-clone.d.ts +0 -1
- package/out/shared/src/deep-clone.d.ts.map +1 -1
- package/out/shared/src/deep-clone.js +1 -1
- package/out/shared/src/deep-clone.js.map +1 -1
- package/out/shared/src/document-visible.js +1 -1
- package/out/shared/src/document-visible.js.map +1 -1
- package/out/shared/src/expand.d.ts +0 -3
- package/out/shared/src/expand.d.ts.map +1 -1
- package/out/shared/src/immutable.d.ts +1 -1
- package/out/shared/src/immutable.d.ts.map +1 -1
- package/out/shared/src/iterables.d.ts +0 -1
- package/out/shared/src/iterables.d.ts.map +1 -1
- package/out/shared/src/iterables.js.map +1 -1
- package/out/shared/src/logging-test-utils.js +1 -1
- package/out/shared/src/logging-test-utils.js.map +1 -1
- package/out/shared/src/options-types.d.ts +1 -1
- package/out/shared/src/options-types.d.ts.map +1 -1
- package/out/shared/src/options.d.ts +2 -3
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/options.js +1 -1
- package/out/shared/src/options.js.map +1 -1
- package/out/shared/src/promise-race.js +1 -1
- package/out/shared/src/promise-race.js.map +1 -1
- package/out/shared/src/queue.js +1 -1
- package/out/shared/src/queue.js.map +1 -1
- package/out/shared/src/resolved-promises.d.ts +0 -4
- package/out/shared/src/resolved-promises.d.ts.map +1 -1
- package/out/shared/src/resolved-promises.js +0 -1
- package/out/shared/src/resolved-promises.js.map +1 -1
- package/out/shared/src/resolver.d.ts +9 -0
- package/out/shared/src/resolver.d.ts.map +1 -0
- package/out/shared/src/resolver.js +6 -0
- package/out/shared/src/resolver.js.map +1 -0
- package/out/shared/src/sleep.js +1 -1
- package/out/shared/src/sleep.js.map +1 -1
- package/out/shared/src/tdigest.d.ts +0 -1
- package/out/shared/src/tdigest.d.ts.map +1 -1
- package/out/shared/src/tdigest.js.map +1 -1
- package/out/z2s/src/sql.d.ts +1 -5
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.js +2 -3
- package/out/zero/package.js.map +1 -1
- package/out/zero/src/zero-cache-dev.js +1 -1
- package/out/zero/src/zero-cache-dev.js.map +1 -1
- package/out/zero-cache/src/config/zero-config.d.ts +14 -11
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +23 -0
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/db/migration-lite.js.map +1 -1
- package/out/zero-cache/src/db/migration.js +1 -1
- package/out/zero-cache/src/db/migration.js.map +1 -1
- package/out/zero-cache/src/db/pg-copy-binary.js +1 -1
- package/out/zero-cache/src/db/pg-copy-binary.js.map +1 -1
- package/out/zero-cache/src/db/pg-type-parser.js.map +1 -1
- package/out/zero-cache/src/db/specs.d.ts +3 -4
- package/out/zero-cache/src/db/specs.d.ts.map +1 -1
- package/out/zero-cache/src/db/specs.js +5 -7
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/db/transaction-pool.js +2 -2
- package/out/zero-cache/src/db/transaction-pool.js.map +1 -1
- package/out/zero-cache/src/observability/events.js +1 -1
- package/out/zero-cache/src/observability/events.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +1 -1
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/main.js +1 -1
- package/out/zero-cache/src/server/main.js.map +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js +1 -1
- package/out/zero-cache/src/server/runner/run-worker.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js +1 -1
- package/out/zero-cache/src/services/change-source/common/backfill-manager.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js +1 -1
- package/out/zero-cache/src/services/change-source/common/change-stream-multiplexer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/common/replica-restore.js.map +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js +1 -1
- package/out/zero-cache/src/services/change-source/custom/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/backfill-stream.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/initial-sync.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.d.ts +0 -2
- package/out/zero-cache/src/services/change-source/pg/lsn.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/lsn.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/replication-slots.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +0 -12
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js +5 -3
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/index-predicate.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts +0 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/validation.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js +1 -1
- package/out/zero-cache/src/services/change-streamer/broadcast.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-service.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/drain-tracker.js +1 -1
- package/out/zero-cache/src/services/change-streamer/drain-tracker.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js +2 -2
- package/out/zero-cache/src/services/change-streamer/litestream3-prometheus-poller.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/restore-admission.js +2 -2
- package/out/zero-cache/src/services/change-streamer/restore-admission.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js +1 -1
- package/out/zero-cache/src/services/change-streamer/schema/tables.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/snapshot-message.js +2 -3
- package/out/zero-cache/src/services/change-streamer/snapshot-message.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js +2 -2
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-catchup.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/sqlite-change-log-read-router.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js +1 -1
- package/out/zero-cache/src/services/change-streamer/storer.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscribe.js +1 -1
- package/out/zero-cache/src/services/change-streamer/subscribe.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js +1 -1
- package/out/zero-cache/src/services/change-streamer/subscriber.js.map +1 -1
- package/out/zero-cache/src/services/life-cycle.js +1 -1
- package/out/zero-cache/src/services/life-cycle.js.map +1 -1
- package/out/zero-cache/src/services/litestream/commands.js +1 -1
- package/out/zero-cache/src/services/litestream/commands.js.map +1 -1
- package/out/zero-cache/src/services/litestream/metrics.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +2 -2
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +57 -14
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/plannerz.d.ts +4 -12
- package/out/zero-cache/src/services/plannerz.d.ts.map +1 -1
- package/out/zero-cache/src/services/plannerz.js +1 -3
- package/out/zero-cache/src/services/plannerz.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-db.js +1 -1
- package/out/zero-cache/src/services/replicator/change-log-db.js.map +1 -1
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js +1 -1
- package/out/zero-cache/src/services/replicator/change-log-stream-writer.js.map +1 -1
- package/out/zero-cache/src/services/replicator/drain-handler.js +1 -1
- package/out/zero-cache/src/services/replicator/drain-handler.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.js +1 -1
- package/out/zero-cache/src/services/replicator/reporter/recorder.js.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts +2 -11
- package/out/zero-cache/src/services/replicator/reporter/report-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/reporter/report-schema.js +1 -1
- package/out/zero-cache/src/services/replicator/reporter/report-schema.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts +0 -10
- package/out/zero-cache/src/services/replicator/schema/change-log.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/change-log.js.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts +0 -7
- package/out/zero-cache/src/services/replicator/schema/column-metadata.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js +1 -1
- package/out/zero-cache/src/services/replicator/schema/column-metadata.js.map +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.js +1 -1
- package/out/zero-cache/src/services/replicator/write-worker-client.js.map +1 -1
- package/out/zero-cache/src/services/running-state.js +1 -1
- package/out/zero-cache/src/services/running-state.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/connection-context-manager.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js +2 -2
- package/out/zero-cache/src/services/view-syncer/drain-coordinator.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/query-stats.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/schema/types.js +3 -17
- package/out/zero-cache/src/services/view-syncer/schema/types.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +13 -10
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/lite.d.ts +0 -1
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +2 -2
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/pg-types.d.ts +0 -40
- package/out/zero-cache/src/types/pg-types.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg-types.js.map +1 -1
- package/out/zero-cache/src/types/poke-chunk.js +1 -1
- package/out/zero-cache/src/types/poke-chunk.js.map +1 -1
- package/out/zero-cache/src/types/row-key.d.ts +0 -5
- package/out/zero-cache/src/types/row-key.d.ts.map +1 -1
- package/out/zero-cache/src/types/row-key.js.map +1 -1
- package/out/zero-cache/src/types/streams.js +1 -1
- package/out/zero-cache/src/types/streams.js.map +1 -1
- package/out/zero-cache/src/types/subscription.js +1 -1
- package/out/zero-cache/src/types/subscription.js.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +0 -6
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +8 -2
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/types/ws.d.ts +2 -1
- package/out/zero-cache/src/types/ws.d.ts.map +1 -1
- package/out/zero-cache/src/types/ws.js +1 -1
- package/out/zero-cache/src/types/ws.js.map +1 -1
- package/out/zero-cache/src/workers/connection.js +4 -1
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/mutator.js +1 -1
- package/out/zero-cache/src/workers/mutator.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +45 -3
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/active-clients-manager.js +1 -1
- package/out/zero-client/src/client/active-clients-manager.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +1 -1
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/crud.d.ts +2 -8
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/crud.js +1 -1
- package/out/zero-client/src/client/crud.js.map +1 -1
- package/out/zero-client/src/client/custom.d.ts +0 -2
- package/out/zero-client/src/client/custom.d.ts.map +1 -1
- package/out/zero-client/src/client/custom.js +1 -1
- package/out/zero-client/src/client/custom.js.map +1 -1
- package/out/zero-client/src/client/enable-analytics.d.ts +0 -1
- package/out/zero-client/src/client/enable-analytics.d.ts.map +1 -1
- package/out/zero-client/src/client/enable-analytics.js +2 -1
- package/out/zero-client/src/client/enable-analytics.js.map +1 -1
- package/out/zero-client/src/client/error.d.ts +4 -5
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/keys.d.ts +0 -1
- package/out/zero-client/src/client/keys.d.ts.map +1 -1
- package/out/zero-client/src/client/keys.js +4 -2
- package/out/zero-client/src/client/keys.js.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.js +1 -1
- package/out/zero-client/src/client/mutation-tracker.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +0 -4
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/replicache-types.d.ts +3 -2
- package/out/zero-client/src/client/replicache-types.d.ts.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero-poke-handler.d.ts +1 -2
- package/out/zero-client/src/client/zero-poke-handler.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js +1 -1
- package/out/zero-client/src/client/zero-poke-handler.js.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +1 -5
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +1 -1
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/out/zero-client/src/types/client-state.d.ts +0 -6
- package/out/zero-client/src/types/client-state.d.ts.map +1 -1
- package/out/zero-permissions/src/permissions.d.ts +1 -12
- package/out/zero-permissions/src/permissions.d.ts.map +1 -1
- package/out/zero-permissions/src/permissions.js +1 -2
- package/out/zero-permissions/src/permissions.js.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +0 -4
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +1 -2
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.d.ts +0 -20
- package/out/zero-protocol/src/change-desired-queries.d.ts.map +1 -1
- package/out/zero-protocol/src/change-desired-queries.js.map +1 -1
- package/out/zero-protocol/src/client-schema.d.ts +2 -5
- package/out/zero-protocol/src/client-schema.d.ts.map +1 -1
- package/out/zero-protocol/src/client-schema.js +1 -1
- package/out/zero-protocol/src/client-schema.js.map +1 -1
- package/out/zero-protocol/src/close-connection.d.ts +0 -8
- package/out/zero-protocol/src/close-connection.d.ts.map +1 -1
- package/out/zero-protocol/src/close-connection.js +1 -1
- package/out/zero-protocol/src/close-connection.js.map +1 -1
- package/out/zero-protocol/src/connect.d.ts +0 -12
- package/out/zero-protocol/src/connect.d.ts.map +1 -1
- package/out/zero-protocol/src/connect.js +1 -1
- package/out/zero-protocol/src/connect.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.d.ts +3 -17
- package/out/zero-protocol/src/custom-queries.d.ts.map +1 -1
- package/out/zero-protocol/src/custom-queries.js +1 -1
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/data.d.ts +0 -1
- package/out/zero-protocol/src/data.d.ts.map +1 -1
- package/out/zero-protocol/src/data.js +1 -1
- package/out/zero-protocol/src/data.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +27 -27
- package/out/zero-protocol/src/inspect-down.d.ts +82 -84
- package/out/zero-protocol/src/inspect-down.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-down.js +1 -1
- package/out/zero-protocol/src/inspect-down.js.map +1 -1
- package/out/zero-protocol/src/inspect-up.d.ts +0 -28
- package/out/zero-protocol/src/inspect-up.d.ts.map +1 -1
- package/out/zero-protocol/src/inspect-up.js +1 -1
- package/out/zero-protocol/src/inspect-up.js.map +1 -1
- package/out/zero-protocol/src/mutate-server.d.ts +0 -21
- package/out/zero-protocol/src/mutate-server.d.ts.map +1 -1
- package/out/zero-protocol/src/mutate-server.js +1 -1
- package/out/zero-protocol/src/mutate-server.js.map +1 -1
- package/out/zero-protocol/src/mutation-type-enum.d.ts +0 -1
- package/out/zero-protocol/src/mutation-type-enum.d.ts.map +1 -1
- package/out/zero-protocol/src/mutation-type-enum.js.map +1 -1
- package/out/zero-protocol/src/mutation.d.ts +2 -4
- package/out/zero-protocol/src/mutation.d.ts.map +1 -1
- package/out/zero-protocol/src/mutation.js +1 -1
- package/out/zero-protocol/src/mutation.js.map +1 -1
- package/out/zero-protocol/src/mutations-patch.d.ts +0 -33
- package/out/zero-protocol/src/mutations-patch.d.ts.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +1 -1
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/ping.d.ts +0 -2
- package/out/zero-protocol/src/ping.d.ts.map +1 -1
- package/out/zero-protocol/src/ping.js +1 -1
- package/out/zero-protocol/src/ping.js.map +1 -1
- package/out/zero-protocol/src/poke.d.ts +3 -2
- package/out/zero-protocol/src/poke.d.ts.map +1 -1
- package/out/zero-protocol/src/poke.js +1 -1
- package/out/zero-protocol/src/poke.js.map +1 -1
- package/out/zero-protocol/src/pong.d.ts +0 -2
- package/out/zero-protocol/src/pong.d.ts.map +1 -1
- package/out/zero-protocol/src/pong.js +1 -1
- package/out/zero-protocol/src/pong.js.map +1 -1
- package/out/zero-protocol/src/pull.d.ts +2 -7
- package/out/zero-protocol/src/pull.d.ts.map +1 -1
- package/out/zero-protocol/src/pull.js +1 -1
- package/out/zero-protocol/src/pull.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +1 -3
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +1 -1
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-protocol/src/queries-patch.d.ts +0 -16
- package/out/zero-protocol/src/queries-patch.d.ts.map +1 -1
- package/out/zero-protocol/src/queries-patch.js +1 -1
- package/out/zero-protocol/src/queries-patch.js.map +1 -1
- package/out/zero-protocol/src/query-server.d.ts +2 -41
- package/out/zero-protocol/src/query-server.d.ts.map +1 -1
- package/out/zero-protocol/src/query-server.js +1 -1
- package/out/zero-protocol/src/query-server.js.map +1 -1
- package/out/zero-protocol/src/up.d.ts +42 -42
- package/out/zero-protocol/src/version.d.ts +0 -1
- package/out/zero-protocol/src/version.d.ts.map +1 -1
- package/out/zero-protocol/src/version.js.map +1 -1
- package/out/zero-react/src/use-query.js +1 -1
- package/out/zero-react/src/use-query.js.map +1 -1
- package/out/zero-schema/src/builder/relationship-builder.d.ts +0 -2
- package/out/zero-schema/src/builder/relationship-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/relationship-builder.js.map +1 -1
- package/out/zero-schema/src/builder/table-builder.d.ts +1 -1
- package/out/zero-schema/src/builder/table-builder.d.ts.map +1 -1
- package/out/zero-schema/src/builder/table-builder.js +1 -1
- package/out/zero-schema/src/builder/table-builder.js.map +1 -1
- package/out/zero-schema/src/schema-config.d.ts +0 -1
- package/out/zero-schema/src/schema-config.d.ts.map +1 -1
- package/out/zero-schema/src/schema-config.js +1 -1
- package/out/zero-schema/src/schema-config.js.map +1 -1
- package/out/zero-schema/src/table-schema.d.ts +3 -11
- package/out/zero-schema/src/table-schema.d.ts.map +1 -1
- package/out/zero-server/src/queries/process-queries.d.ts +2 -4
- package/out/zero-server/src/queries/process-queries.d.ts.map +1 -1
- package/out/zero-server/src/queries/process-queries.js.map +1 -1
- package/out/zero-solid/src/solid-view.d.ts +0 -2
- package/out/zero-solid/src/solid-view.d.ts.map +1 -1
- package/out/zero-solid/src/solid-view.js +1 -1
- package/out/zero-solid/src/solid-view.js.map +1 -1
- package/out/zero-types/src/name-mapper.d.ts +2 -1
- package/out/zero-types/src/name-mapper.d.ts.map +1 -1
- package/out/zero-types/src/name-mapper.js.map +1 -1
- package/out/zero-types/src/schema-value.d.ts +3 -2
- package/out/zero-types/src/schema-value.d.ts.map +1 -1
- package/out/zero-types/src/schema.d.ts +1 -1
- package/out/zero-types/src/schema.d.ts.map +1 -1
- package/out/zql/src/builder/builder.d.ts +1 -11
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +1 -1
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/builder/filter.d.ts +0 -1
- package/out/zql/src/builder/filter.d.ts.map +1 -1
- package/out/zql/src/builder/filter.js.map +1 -1
- package/out/zql/src/error.d.ts +0 -5
- package/out/zql/src/error.d.ts.map +1 -1
- package/out/zql/src/error.js.map +1 -1
- package/out/zql/src/ivm/constraint.d.ts +0 -7
- package/out/zql/src/ivm/constraint.d.ts.map +1 -1
- package/out/zql/src/ivm/constraint.js +1 -1
- package/out/zql/src/ivm/constraint.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts +0 -1
- package/out/zql/src/ivm/data.d.ts.map +1 -1
- package/out/zql/src/ivm/data.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +1 -2
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +1 -1
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/stream.d.ts +0 -1
- package/out/zql/src/ivm/stream.d.ts.map +1 -1
- package/out/zql/src/ivm/stream.js.map +1 -1
- package/out/zql/src/ivm/union-fan-in.d.ts +0 -1
- package/out/zql/src/ivm/union-fan-in.d.ts.map +1 -1
- package/out/zql/src/ivm/union-fan-in.js +1 -1
- package/out/zql/src/ivm/union-fan-in.js.map +1 -1
- package/out/zql/src/ivm/view-apply-change.d.ts +5 -35
- package/out/zql/src/ivm/view-apply-change.d.ts.map +1 -1
- package/out/zql/src/ivm/view-apply-change.js +1 -1
- package/out/zql/src/ivm/view-apply-change.js.map +1 -1
- package/out/zql/src/mutate/crud.d.ts +1 -3
- package/out/zql/src/mutate/crud.d.ts.map +1 -1
- package/out/zql/src/mutate/crud.js +1 -1
- package/out/zql/src/mutate/crud.js.map +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts +1 -1
- package/out/zql/src/mutate/mutator-registry.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator-registry.js.map +1 -1
- package/out/zql/src/mutate/mutator.d.ts +1 -1
- package/out/zql/src/mutate/mutator.d.ts.map +1 -1
- package/out/zql/src/mutate/mutator.js.map +1 -1
- package/out/zql/src/planner/planner-debug.d.ts +10 -9
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -1
- package/out/zql/src/planner/planner-debug.js.map +1 -1
- package/out/zql/src/planner/planner-node.d.ts +0 -1
- package/out/zql/src/planner/planner-node.d.ts.map +1 -1
- package/out/zql/src/planner/planner-node.js.map +1 -1
- package/out/zql/src/planner/planner-warnings.d.ts +3 -3
- package/out/zql/src/planner/planner-warnings.d.ts.map +1 -1
- package/out/zql/src/planner/planner-warnings.js.map +1 -1
- package/out/zql/src/query/expression.d.ts +0 -22
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js +1 -1
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/query-delegate-base.d.ts +0 -7
- package/out/zql/src/query/query-delegate-base.d.ts.map +1 -1
- package/out/zql/src/query/query-delegate-base.js +2 -2
- package/out/zql/src/query/query-delegate-base.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +1 -4
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-internals.d.ts +0 -3
- package/out/zql/src/query/query-internals.d.ts.map +1 -1
- package/out/zql/src/query/query-internals.js.map +1 -1
- package/out/zql/src/query/query-registry.d.ts +5 -5
- package/out/zql/src/query/query-registry.d.ts.map +1 -1
- package/out/zql/src/query/query-registry.js.map +1 -1
- package/out/zql/src/query/query.d.ts +2 -13
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.d.ts +1 -19
- package/out/zql/src/query/runnable-query-impl.d.ts.map +1 -1
- package/out/zql/src/query/runnable-query-impl.js +1 -1
- package/out/zql/src/query/runnable-query-impl.js.map +1 -1
- package/out/zql/src/query/ttl.d.ts +2 -3
- package/out/zql/src/query/ttl.d.ts.map +1 -1
- package/out/zql/src/query/ttl.js.map +1 -1
- package/out/zqlite/src/query-builder.d.ts +0 -2
- package/out/zqlite/src/query-builder.d.ts.map +1 -1
- package/out/zqlite/src/query-builder.js +1 -1
- package/out/zqlite/src/query-builder.js.map +1 -1
- package/out/zqlite/src/table-source.d.ts +0 -1
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +1 -1
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +2 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","names":["defu","v","v.instanceOfAbstractType","v.testOptional","v.toTerminals","v.deepPartial","v.parse","stripAnsi"],"sources":["../../../../shared/src/options.ts"],"sourcesContent":["import {stripVTControlCharacters as stripAnsi} from 'node:util';\nimport type {OptionalLogger} from '@rocicorp/logger';\nimport {template} from 'chalk-template';\nimport type {OptionDefinition} from 'command-line-args';\nimport commandLineArgs from 'command-line-args';\nimport commandLineUsage, {type Section} from 'command-line-usage';\nimport {createDefu} from 'defu';\nimport {toKebabCase, toSnakeCase} from 'kasi';\nimport {assert} from './asserts.ts';\nimport {must} from './must.ts';\nimport type {\n Config,\n Group,\n Option,\n Options,\n WrappedOptionType,\n} from './options-types.ts';\nimport * as v from './valita.ts';\n\nexport type {Config, Group, Option, Options, WrappedOptionType};\n\ntype Primitive = number | string | boolean;\ntype Value = Primitive | Array<Primitive>;\n\ntype RequiredOptionType =\n | v.Type<string>\n | v.Type<number>\n | v.Type<boolean>\n | v.Type<string[]>\n | v.Type<number[]>\n | v.Type<boolean[]>;\n\ntype OptionalOptionType =\n | v.Optional<string>\n | v.Optional<number>\n | v.Optional<boolean>\n | v.Optional<string[]>\n | v.Optional<number[]>\n | v.Optional<boolean[]>;\n\ntype OptionType = RequiredOptionType | OptionalOptionType;\n\n/**\n * Creates a defu instance that overrides arrays instead of merging them.\n */\nconst defu = createDefu((obj, key, value) => {\n if (!Array.isArray(value)) return;\n\n obj[key] = value;\n return true;\n});\n\n/**\n * Converts an Options instance into its corresponding {@link Config} schema.\n */\nfunction configSchema<T extends Options>(\n options: T,\n envNamePrefix: string,\n): v.Type<Config<T>> {\n function makeObjectType(options: Options | Group, group?: string) {\n return v.object(\n Object.fromEntries(\n Object.entries(options).map(\n ([name, value]): [string, OptionType | v.Type] => {\n const addErrorMessage = (t: OptionType) => {\n const {required} = getRequiredOrDefault(t);\n if (required) {\n // Adds an error message for required options that includes the\n // actual name of the option.\n const optionName = toSnakeCase(\n `${envNamePrefix}${group ? group + '_' : ''}${name}`,\n ).toUpperCase();\n return (t as v.Type<string>)\n .optional()\n .assert(\n val => val !== undefined,\n `Missing required option ${optionName}`,\n );\n }\n return t;\n };\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n return [name, addErrorMessage(value)];\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n return [name, addErrorMessage(type)];\n }\n // OptionGroup\n return [name, makeObjectType(value as Group, name)];\n },\n ),\n ),\n );\n }\n return makeObjectType(options) as v.Type<Config<T>>;\n}\n\n/**\n * Converts an Options instance into an \"env schema\", which is an object with\n * ENV names as its keys, mapped to optional or required string values\n * (corresponding to the optionality of the corresponding options).\n *\n * This is used as a format for encoding options for a multi-tenant version\n * of an app, with an envSchema for each tenant.\n */\nexport function envSchema<T extends Options>(options: T, envNamePrefix = '') {\n const fields: [string, v.Type<string> | v.Optional<string>][] = [];\n\n function addField(name: string, type: OptionType, group?: string) {\n const flag = group ? `${group}_${name}` : name;\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n\n const {required} = getRequiredOrDefault(type);\n fields.push([env, required ? v.string() : v.string().optional()]);\n }\n\n function addFields(o: Options | Group, group?: string) {\n Object.entries(o).forEach(([name, value]) => {\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n addField(name, value, group);\n return;\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n addField(name, type, group);\n return;\n }\n // OptionGroup\n addFields(value as Group, name);\n });\n }\n\n addFields(options);\n\n return v.object(Object.fromEntries(fields));\n}\n\nfunction getRequiredOrDefault(type: OptionType) {\n const defaultResult = v.testOptional<Value>(undefined, type);\n return {\n required: !defaultResult.ok,\n defaultValue: defaultResult.ok ? defaultResult.value : undefined,\n };\n}\n\nexport type ParseOptions = {\n /** Defaults to process.argv.slice(2) */\n argv?: string[];\n\n envNamePrefix?: string;\n\n description?: {header: string; content: string}[];\n\n /** Defaults to `false` */\n allowUnknown?: boolean;\n\n /** Defaults to `false` */\n allowPartial?: boolean;\n\n /** Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n\n /** Defaults to `true`. */\n emitDeprecationWarnings?: boolean;\n\n /** Defaults to `true`. When false, excludes default values from both config and env return values. */\n includeDefaults?: boolean;\n\n /** Defaults to `console` */\n logger?: OptionalLogger;\n\n /** Defaults to `process.exit` */\n exit?: (code?: number | string | null) => never;\n};\n\nexport function parseOptions<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): Config<T> {\n return parseOptionsAdvanced(appOptions, opts).config;\n}\n\nexport function parseOptionsAdvanced<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): {config: Config<T>; env: Record<string, string>; unknown?: string[]} {\n const {\n argv = process.argv.slice(2),\n envNamePrefix = '',\n description = [],\n allowUnknown = false,\n allowPartial = false,\n env: processEnv = process.env,\n emitDeprecationWarnings = true,\n includeDefaults = true,\n logger = console,\n exit = process.exit,\n } = opts;\n // The main logic for converting a valita Type spec to an Option (i.e. flag) spec.\n function addOption(field: string, option: WrappedOptionType, group?: string) {\n const {type, desc = [], deprecated, alias, hidden} = option;\n\n // The group name is prepended to the flag name.\n const flag = group ? toKebabCase(`${group}-${field}`) : toKebabCase(field);\n\n const {required, defaultValue} = getRequiredOrDefault(type);\n let multiple = type.name === 'array';\n const literals = new Set<string>();\n const terminalTypes = new Set<string>();\n\n v.toTerminals(type, getTerminalTypes);\n\n function getTerminalTypes(t: v.TerminalType) {\n switch (t.name) {\n case 'undefined':\n case 'optional':\n break;\n case 'array': {\n multiple = true;\n t.prefix.forEach(t => v.toTerminals(t, getTerminalTypes));\n if (t.restType) {\n v.toTerminals(t.restType, getTerminalTypes);\n }\n t.suffix.forEach(t => v.toTerminals(t, getTerminalTypes));\n break;\n }\n case 'literal':\n literals.add(String(t.value));\n terminalTypes.add(typeof t.value);\n break;\n default:\n terminalTypes.add(t.name);\n break;\n }\n }\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n if (terminalTypes.size > 1) {\n throw new TypeError(`${env} has mixed types ${[...terminalTypes]}`);\n }\n assert(terminalTypes.size === 1, 'Expected exactly one terminal type');\n const terminalType = [...terminalTypes][0];\n\n const value = processEnv[env];\n if (value) {\n // Use the `--flag=value` form so that a value starting with `-` (e.g. a\n // nanoid) is not parsed as a cluster of short flags, leaving `--flag`\n // with a `null` value. Array values are comma-separated; technically not\n // water-tight, as it assumes the values themselves don't contain commas.\n const values = multiple ? value.split(',') : [value];\n envArgv.push(...values.map(val => `--${flag}=${val}`));\n }\n names.set(flag, {field, env});\n\n const spec = [\n (required\n ? '{italic required}'\n : defaultValue !== undefined\n ? `default: ${JSON.stringify(defaultValue)}`\n : 'optional') + '\\n',\n ];\n if (desc) {\n spec.push(...desc);\n }\n\n const typeLabel = [\n literals.size\n ? String(Array.from(literals, l => `{underline ${l}}`))\n : multiple\n ? `{underline ${terminalType}[]}`\n : `{underline ${terminalType}}`,\n ` ${env} env`,\n ];\n\n const opt = {\n name: flag,\n alias,\n type: valueParser(\n env,\n terminalType,\n logger,\n emitDeprecationWarnings ? deprecated : undefined,\n ),\n multiple,\n group,\n description: spec.join('\\n') + '\\n',\n typeLabel: typeLabel.join('\\n') + '\\n',\n hidden: hidden === undefined ? deprecated !== undefined : hidden,\n };\n optsWithoutDefaults.push(opt);\n optsWithDefaults.push({...opt, defaultValue});\n }\n\n const names = new Map<string, {field: string; env: string}>();\n const optsWithDefaults: DescribedOptionDefinition[] = [];\n const optsWithoutDefaults: DescribedOptionDefinition[] = [];\n const envArgv: string[] = [];\n\n try {\n for (const [name, val] of Object.entries(appOptions)) {\n const {type} = val as {type: unknown};\n if (v.instanceOfAbstractType(val)) {\n addOption(name, {type: val});\n } else if (v.instanceOfAbstractType(type)) {\n addOption(name, val as WrappedOptionType);\n } else {\n const group = name;\n for (const [name, option] of Object.entries(val as Group)) {\n const wrapped = v.instanceOfAbstractType(option)\n ? {type: option}\n : option;\n addOption(name, wrapped, group);\n }\n }\n }\n\n const [defaults, env1, unknown] = parseArgs(optsWithDefaults, argv, names);\n const [fromEnv, env2] = parseArgs(optsWithoutDefaults, envArgv, names);\n const [withoutDefaults, env3] = parseArgs(optsWithoutDefaults, argv, names);\n\n switch (unknown?.[0]) {\n case undefined:\n break;\n case '--help':\n case '-h':\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n break;\n default:\n if (!allowUnknown) {\n logger.error?.('Invalid arguments:', unknown);\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n }\n break;\n }\n\n const parsedArgs = includeDefaults\n ? defu(withoutDefaults, fromEnv, defaults)\n : defu(withoutDefaults, fromEnv);\n const env = includeDefaults\n ? {...env1, ...env2, ...env3}\n : {...env2, ...env3};\n\n let schema = configSchema(appOptions, envNamePrefix);\n if (allowPartial || !includeDefaults) {\n // TODO: Type configSchema() to return a v.ObjectType<...>\n schema = v.deepPartial(\n schema as v.ObjectType<Record<string, v.Type | v.Optional>, undefined>,\n ) as v.Type<Config<T>>;\n }\n return {\n config: v.parse(parsedArgs, schema),\n env,\n ...(unknown ? {unknown} : {}),\n };\n } catch (e) {\n logger.error?.(String(e));\n showUsage(optsWithDefaults, description, logger);\n throw e;\n }\n}\n\nfunction valueParser(\n optionName: string,\n typeName: string,\n logger: OptionalLogger,\n deprecated: string[] | undefined,\n) {\n return (input: string) => {\n if (deprecated) {\n logger.warn?.(\n template(\n `\\n${optionName} is deprecated:\\n` + deprecated.join('\\n') + '\\n',\n ),\n );\n }\n switch (typeName) {\n case 'string':\n return input;\n case 'boolean':\n return parseBoolean(optionName, input);\n case 'number': {\n const val = Number(input);\n if (Number.isNaN(val)) {\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n }\n return val;\n }\n default:\n // Should be impossible given the constraints of `Option`\n throw new TypeError(\n `${optionName} option has unsupported type ${typeName}`,\n );\n }\n };\n}\n\nfunction parseArgs(\n optionDefs: DescribedOptionDefinition[],\n argv: string[],\n names: Map<string, {field: string; env: string}>,\n) {\n function normalizeFlagValue(value: unknown) {\n // A --flag without value is parsed by commandLineArgs() to `null`,\n // but this is a common convention to set a boolean flag to true.\n return value === null ? true : value;\n }\n\n const {\n _all,\n _none: ungrouped,\n _unknown: unknown,\n ...config\n } = commandLineArgs(optionDefs, {\n argv,\n partial: true,\n });\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const result: Record<string, any> = {};\n const envObj: Record<string, string> = {};\n\n function addFlag(flagName: string, value: unknown, group?: string) {\n const {field, env} = must(names.get(flagName));\n const normalized = normalizeFlagValue(value);\n if (group) {\n result[group][field] = normalized;\n } else {\n result[field] = normalized;\n }\n envObj[env] = String(normalized);\n }\n\n for (const [flagName, value] of Object.entries(ungrouped ?? {})) {\n addFlag(flagName, value);\n }\n\n // Then handle (potentially) grouped flags\n for (const [name, value] of Object.entries(config)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n addFlag(name, value); // Flag, not a group\n } else {\n const group = name;\n result[group] = {};\n for (const [flagName, flagValue] of Object.entries(value)) {\n addFlag(flagName, flagValue, group);\n }\n }\n }\n\n return [result, envObj, unknown] as const;\n}\n\nexport function flagToEnv(prefix: string, flag: string): string {\n return toSnakeCase(prefix + flag).toUpperCase();\n}\n\nexport function parseBoolean(optionName: string, input: string) {\n const bool = input.toLowerCase();\n if (['true', '1'].includes(bool)) {\n return true;\n } else if (['false', '0'].includes(bool)) {\n return false;\n }\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n}\n\nfunction showUsage(\n optionList: DescribedOptionDefinition[],\n description: {header: string; content: string}[] = [],\n logger: OptionalLogger = console,\n) {\n const hide: string[] = [];\n let leftWidth = 35;\n let rightWidth = 70;\n optionList.forEach(({name, typeLabel, description, hidden}) => {\n if (hidden) {\n hide.push(name);\n }\n const text = template(`${name} ${typeLabel ?? ''}`);\n const lines = stripAnsi(text).split('\\n');\n for (const l of lines) {\n leftWidth = Math.max(leftWidth, l.length + 2);\n }\n const desc = stripAnsi(template(description ?? '')).split('\\n');\n for (const l of desc) {\n rightWidth = Math.max(rightWidth, l.length + 2);\n }\n });\n\n const sections: Section[] = [\n {\n optionList,\n reverseNameOrder: true, // Display --flag-name before -alias\n hide,\n tableOptions: {\n columns: [\n {name: 'option', width: leftWidth},\n {name: 'description', width: rightWidth},\n ],\n noTrim: true,\n },\n },\n ];\n\n if (description) {\n sections.unshift(...description);\n }\n\n logger.info?.(commandLineUsage(sections));\n}\n\ntype DescribedOptionDefinition = OptionDefinition & {\n // Additional fields recognized by command-line-usage\n description?: string;\n typeLabel?: string | undefined;\n hidden?: boolean | undefined;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"options.js","names":["defu","v","v.instanceOfAbstractType","v.testOptional","v.toTerminals","v.deepPartial","v.parse","stripAnsi"],"sources":["../../../../shared/src/options.ts"],"sourcesContent":["import {stripVTControlCharacters as stripAnsi} from 'node:util';\nimport type {OptionalLogger} from '@rocicorp/logger';\nimport {template} from 'chalk-template';\nimport type {OptionDefinition} from 'command-line-args';\nimport commandLineArgs from 'command-line-args';\nimport commandLineUsage, {type Section} from 'command-line-usage';\nimport {createDefu} from 'defu';\nimport {toKebabCase, toSnakeCase} from 'kasi';\nimport {assert} from './asserts.ts';\nimport {must} from './must.ts';\nimport type {\n Config,\n Group,\n Options,\n WrappedOptionType,\n} from './options-types.ts';\nimport * as v from './valita.ts';\n\nexport type {Config, Group, Options};\n\ntype Primitive = number | string | boolean;\ntype Value = Primitive | Array<Primitive>;\n\ntype RequiredOptionType =\n | v.Type<string>\n | v.Type<number>\n | v.Type<boolean>\n | v.Type<string[]>\n | v.Type<number[]>\n | v.Type<boolean[]>;\n\ntype OptionalOptionType =\n | v.Optional<string>\n | v.Optional<number>\n | v.Optional<boolean>\n | v.Optional<string[]>\n | v.Optional<number[]>\n | v.Optional<boolean[]>;\n\ntype OptionType = RequiredOptionType | OptionalOptionType;\n\n/**\n * Creates a defu instance that overrides arrays instead of merging them.\n */\nconst defu = createDefu((obj, key, value) => {\n if (!Array.isArray(value)) return;\n\n obj[key] = value;\n return true;\n});\n\n/**\n * Converts an Options instance into its corresponding {@link Config} schema.\n */\nfunction configSchema<T extends Options>(\n options: T,\n envNamePrefix: string,\n): v.Type<Config<T>> {\n function makeObjectType(options: Options | Group, group?: string) {\n return v.object(\n Object.fromEntries(\n Object.entries(options).map(\n ([name, value]): [string, OptionType | v.Type] => {\n const addErrorMessage = (t: OptionType) => {\n const {required} = getRequiredOrDefault(t);\n if (required) {\n // Adds an error message for required options that includes the\n // actual name of the option.\n const optionName = toSnakeCase(\n `${envNamePrefix}${group ? group + '_' : ''}${name}`,\n ).toUpperCase();\n return (t as v.Type<string>)\n .optional()\n .assert(\n val => val !== undefined,\n `Missing required option ${optionName}`,\n );\n }\n return t;\n };\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n return [name, addErrorMessage(value)];\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n return [name, addErrorMessage(type)];\n }\n // OptionGroup\n return [name, makeObjectType(value as Group, name)];\n },\n ),\n ),\n );\n }\n return makeObjectType(options) as v.Type<Config<T>>;\n}\n\n/**\n * Converts an Options instance into an \"env schema\", which is an object with\n * ENV names as its keys, mapped to optional or required string values\n * (corresponding to the optionality of the corresponding options).\n *\n * This is used as a format for encoding options for a multi-tenant version\n * of an app, with an envSchema for each tenant.\n */\nexport function envSchema<T extends Options>(options: T, envNamePrefix = '') {\n const fields: [string, v.Type<string> | v.Optional<string>][] = [];\n\n function addField(name: string, type: OptionType, group?: string) {\n const flag = group ? `${group}_${name}` : name;\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n\n const {required} = getRequiredOrDefault(type);\n fields.push([env, required ? v.string() : v.string().optional()]);\n }\n\n function addFields(o: Options | Group, group?: string) {\n Object.entries(o).forEach(([name, value]) => {\n // OptionType\n if (v.instanceOfAbstractType(value)) {\n addField(name, value, group);\n return;\n }\n // WrappedOptionType\n const {type} = value;\n if (v.instanceOfAbstractType(type)) {\n addField(name, type, group);\n return;\n }\n // OptionGroup\n addFields(value as Group, name);\n });\n }\n\n addFields(options);\n\n return v.object(Object.fromEntries(fields));\n}\n\nfunction getRequiredOrDefault(type: OptionType) {\n const defaultResult = v.testOptional<Value>(undefined, type);\n return {\n required: !defaultResult.ok,\n defaultValue: defaultResult.ok ? defaultResult.value : undefined,\n };\n}\n\nexport type ParseOptions = {\n /** Defaults to process.argv.slice(2) */\n argv?: string[];\n\n envNamePrefix?: string;\n\n description?: {header: string; content: string}[];\n\n /** Defaults to `false` */\n allowUnknown?: boolean;\n\n /** Defaults to `false` */\n allowPartial?: boolean;\n\n /** Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n\n /** Defaults to `true`. */\n emitDeprecationWarnings?: boolean;\n\n /** Defaults to `true`. When false, excludes default values from both config and env return values. */\n includeDefaults?: boolean;\n\n /** Defaults to `console` */\n logger?: OptionalLogger;\n\n /** Defaults to `process.exit` */\n exit?: (code?: number | string | null) => never;\n};\n\nexport function parseOptions<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): Config<T> {\n return parseOptionsAdvanced(appOptions, opts).config;\n}\n\nexport function parseOptionsAdvanced<T extends Options>(\n appOptions: T,\n opts: ParseOptions = {},\n): {config: Config<T>; env: Record<string, string>; unknown?: string[]} {\n const {\n argv = process.argv.slice(2),\n envNamePrefix = '',\n description = [],\n allowUnknown = false,\n allowPartial = false,\n env: processEnv = process.env,\n emitDeprecationWarnings = true,\n includeDefaults = true,\n logger = console,\n exit = process.exit,\n } = opts;\n // The main logic for converting a valita Type spec to an Option (i.e. flag) spec.\n function addOption(field: string, option: WrappedOptionType, group?: string) {\n const {type, desc = [], deprecated, alias, hidden} = option;\n\n // The group name is prepended to the flag name.\n const flag = group ? toKebabCase(`${group}-${field}`) : toKebabCase(field);\n\n const {required, defaultValue} = getRequiredOrDefault(type);\n let multiple = type.name === 'array';\n const literals = new Set<string>();\n const terminalTypes = new Set<string>();\n\n v.toTerminals(type, getTerminalTypes);\n\n function getTerminalTypes(t: v.TerminalType) {\n switch (t.name) {\n case 'undefined':\n case 'optional':\n break;\n case 'array': {\n multiple = true;\n t.prefix.forEach(t => v.toTerminals(t, getTerminalTypes));\n if (t.restType) {\n v.toTerminals(t.restType, getTerminalTypes);\n }\n t.suffix.forEach(t => v.toTerminals(t, getTerminalTypes));\n break;\n }\n case 'literal':\n literals.add(String(t.value));\n terminalTypes.add(typeof t.value);\n break;\n default:\n terminalTypes.add(t.name);\n break;\n }\n }\n const env = toSnakeCase(`${envNamePrefix}${flag}`).toUpperCase();\n if (terminalTypes.size > 1) {\n throw new TypeError(`${env} has mixed types ${[...terminalTypes]}`);\n }\n assert(terminalTypes.size === 1, 'Expected exactly one terminal type');\n const terminalType = [...terminalTypes][0];\n\n const value = processEnv[env];\n if (value) {\n // Use the `--flag=value` form so that a value starting with `-` (e.g. a\n // nanoid) is not parsed as a cluster of short flags, leaving `--flag`\n // with a `null` value. Array values are comma-separated; technically not\n // water-tight, as it assumes the values themselves don't contain commas.\n const values = multiple ? value.split(',') : [value];\n envArgv.push(...values.map(val => `--${flag}=${val}`));\n }\n names.set(flag, {field, env});\n\n const spec = [\n (required\n ? '{italic required}'\n : defaultValue !== undefined\n ? `default: ${JSON.stringify(defaultValue)}`\n : 'optional') + '\\n',\n ];\n if (desc) {\n spec.push(...desc);\n }\n\n const typeLabel = [\n literals.size\n ? String(Array.from(literals, l => `{underline ${l}}`))\n : multiple\n ? `{underline ${terminalType}[]}`\n : `{underline ${terminalType}}`,\n ` ${env} env`,\n ];\n\n const opt = {\n name: flag,\n alias,\n type: valueParser(\n env,\n terminalType,\n logger,\n emitDeprecationWarnings ? deprecated : undefined,\n ),\n multiple,\n group,\n description: spec.join('\\n') + '\\n',\n typeLabel: typeLabel.join('\\n') + '\\n',\n hidden: hidden === undefined ? deprecated !== undefined : hidden,\n };\n optsWithoutDefaults.push(opt);\n optsWithDefaults.push({...opt, defaultValue});\n }\n\n const names = new Map<string, {field: string; env: string}>();\n const optsWithDefaults: DescribedOptionDefinition[] = [];\n const optsWithoutDefaults: DescribedOptionDefinition[] = [];\n const envArgv: string[] = [];\n\n try {\n for (const [name, val] of Object.entries(appOptions)) {\n const {type} = val as {type: unknown};\n if (v.instanceOfAbstractType(val)) {\n addOption(name, {type: val});\n } else if (v.instanceOfAbstractType(type)) {\n addOption(name, val as WrappedOptionType);\n } else {\n const group = name;\n for (const [name, option] of Object.entries(val as Group)) {\n const wrapped = v.instanceOfAbstractType(option)\n ? {type: option}\n : option;\n addOption(name, wrapped, group);\n }\n }\n }\n\n const [defaults, env1, unknown] = parseArgs(optsWithDefaults, argv, names);\n const [fromEnv, env2] = parseArgs(optsWithoutDefaults, envArgv, names);\n const [withoutDefaults, env3] = parseArgs(optsWithoutDefaults, argv, names);\n\n switch (unknown?.[0]) {\n case undefined:\n break;\n case '--help':\n case '-h':\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n break;\n default:\n if (!allowUnknown) {\n logger.error?.('Invalid arguments:', unknown);\n showUsage(optsWithDefaults, description, logger);\n exit(0);\n }\n break;\n }\n\n const parsedArgs = includeDefaults\n ? defu(withoutDefaults, fromEnv, defaults)\n : defu(withoutDefaults, fromEnv);\n const env = includeDefaults\n ? {...env1, ...env2, ...env3}\n : {...env2, ...env3};\n\n let schema = configSchema(appOptions, envNamePrefix);\n if (allowPartial || !includeDefaults) {\n // TODO: Type configSchema() to return a v.ObjectType<...>\n schema = v.deepPartial(\n schema as v.ObjectType<Record<string, v.Type | v.Optional>, undefined>,\n ) as v.Type<Config<T>>;\n }\n return {\n config: v.parse(parsedArgs, schema),\n env,\n ...(unknown ? {unknown} : {}),\n };\n } catch (e) {\n logger.error?.(String(e));\n showUsage(optsWithDefaults, description, logger);\n throw e;\n }\n}\n\nfunction valueParser(\n optionName: string,\n typeName: string,\n logger: OptionalLogger,\n deprecated: string[] | undefined,\n) {\n return (input: string) => {\n if (deprecated) {\n logger.warn?.(\n template(\n `\\n${optionName} is deprecated:\\n` + deprecated.join('\\n') + '\\n',\n ),\n );\n }\n switch (typeName) {\n case 'string':\n return input;\n case 'boolean':\n return parseBoolean(optionName, input);\n case 'number': {\n const val = Number(input);\n if (Number.isNaN(val)) {\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n }\n return val;\n }\n default:\n // Should be impossible given the constraints of `Option`\n throw new TypeError(\n `${optionName} option has unsupported type ${typeName}`,\n );\n }\n };\n}\n\nfunction parseArgs(\n optionDefs: DescribedOptionDefinition[],\n argv: string[],\n names: Map<string, {field: string; env: string}>,\n) {\n function normalizeFlagValue(value: unknown) {\n // A --flag without value is parsed by commandLineArgs() to `null`,\n // but this is a common convention to set a boolean flag to true.\n return value === null ? true : value;\n }\n\n const {\n _all,\n _none: ungrouped,\n _unknown: unknown,\n ...config\n } = commandLineArgs(optionDefs, {\n argv,\n partial: true,\n });\n\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n const result: Record<string, any> = {};\n const envObj: Record<string, string> = {};\n\n function addFlag(flagName: string, value: unknown, group?: string) {\n const {field, env} = must(names.get(flagName));\n const normalized = normalizeFlagValue(value);\n if (group) {\n result[group][field] = normalized;\n } else {\n result[field] = normalized;\n }\n envObj[env] = String(normalized);\n }\n\n for (const [flagName, value] of Object.entries(ungrouped ?? {})) {\n addFlag(flagName, value);\n }\n\n // Then handle (potentially) grouped flags\n for (const [name, value] of Object.entries(config)) {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n addFlag(name, value); // Flag, not a group\n } else {\n const group = name;\n result[group] = {};\n for (const [flagName, flagValue] of Object.entries(value)) {\n addFlag(flagName, flagValue, group);\n }\n }\n }\n\n return [result, envObj, unknown] as const;\n}\n\nexport function flagToEnv(prefix: string, flag: string): string {\n return toSnakeCase(prefix + flag).toUpperCase();\n}\n\nfunction parseBoolean(optionName: string, input: string) {\n const bool = input.toLowerCase();\n if (['true', '1'].includes(bool)) {\n return true;\n } else if (['false', '0'].includes(bool)) {\n return false;\n }\n throw new TypeError(`Invalid input for ${optionName}: \"${input}\"`);\n}\n\nfunction showUsage(\n optionList: DescribedOptionDefinition[],\n description: {header: string; content: string}[] = [],\n logger: OptionalLogger = console,\n) {\n const hide: string[] = [];\n let leftWidth = 35;\n let rightWidth = 70;\n optionList.forEach(({name, typeLabel, description, hidden}) => {\n if (hidden) {\n hide.push(name);\n }\n const text = template(`${name} ${typeLabel ?? ''}`);\n const lines = stripAnsi(text).split('\\n');\n for (const l of lines) {\n leftWidth = Math.max(leftWidth, l.length + 2);\n }\n const desc = stripAnsi(template(description ?? '')).split('\\n');\n for (const l of desc) {\n rightWidth = Math.max(rightWidth, l.length + 2);\n }\n });\n\n const sections: Section[] = [\n {\n optionList,\n reverseNameOrder: true, // Display --flag-name before -alias\n hide,\n tableOptions: {\n columns: [\n {name: 'option', width: leftWidth},\n {name: 'description', width: rightWidth},\n ],\n noTrim: true,\n },\n },\n ];\n\n if (description) {\n sections.unshift(...description);\n }\n\n logger.info?.(commandLineUsage(sections));\n}\n\ntype DescribedOptionDefinition = OptionDefinition & {\n // Additional fields recognized by command-line-usage\n description?: string;\n typeLabel?: string | undefined;\n hidden?: boolean | undefined;\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-race.js","names":[],"sources":["../../../../shared/src/promise-race.ts"],"sourcesContent":["import {resolver} from '
|
|
1
|
+
{"version":3,"file":"promise-race.js","names":[],"sources":["../../../../shared/src/promise-race.ts"],"sourcesContent":["import {resolver} from './resolver.ts';\n\ntype PromiseRaceResult<T extends Record<string, PromiseLike<unknown>>> = {\n [K in Extract<keyof T, string>]: {\n key: K;\n status: 'fulfilled';\n result: Awaited<T[K]>;\n };\n}[Extract<keyof T, string>];\n\nconst NO_PROMISES_MESSAGE = 'No promises to race';\n\nconst wrapPromise = <K extends string, V>(\n key: K,\n promise: PromiseLike<V>,\n): Promise<{key: K; status: 'fulfilled'; result: V}> =>\n Promise.resolve(promise).then(result => ({\n key,\n status: 'fulfilled' as const,\n result,\n }));\n\n/**\n * Race a record of promises and resolve with the first resolved entry.\n *\n * @param promises Record of promises to race.\n * @returns Promise resolving to a discriminated union of key/result pairs.\n * @throws An error if the record is empty or if a promise is rejected.\n */\nexport async function promiseRace<\n T extends Record<string, PromiseLike<unknown>>,\n>(promises: T): Promise<PromiseRaceResult<T> & {}> {\n const keys = Object.keys(promises) as Array<Extract<keyof T, string>>;\n\n if (keys.length === 0) {\n throw new Error(NO_PROMISES_MESSAGE);\n }\n\n const wrapped = keys.map(key =>\n wrapPromise(key, promises[key] as PromiseLike<Awaited<T[typeof key]>>),\n );\n\n return await Promise.race(wrapped);\n}\n\n/**\n * A memory-safe way to race a short-lived `Promise` with one or more\n * long-leved `AbortSignal`s. This works around the unsafe practice\n * of racing a short-lived promise (e.g. in a loop) with a long-lived one,\n * which results in accumulating memory via `then` callbacks on the latter:\n *\n * https://github.com/nodejs/node/issues/17469\n *\n * The safe way to race a short-lived, expected-to-complete Promise against a\n * long-lived termination signal is to control the latter via an\n * {@link AbortController} and race the former against the signal of the\n * latter.\n */\nexport async function promiseOrAbort<T>(\n shortLived: Promise<T>,\n ...longLived: AbortSignal[]\n): Promise<T> {\n const promises: Promise<T>[] = [];\n const cleanup: (() => void)[] = [];\n for (const signal of longLived) {\n if (signal.aborted) {\n promises.push(Promise.reject(signal.reason));\n } else {\n const {promise, reject} = resolver<T>();\n const handler = () => reject(signal.reason);\n signal.addEventListener('abort', handler);\n cleanup.push(() => signal.removeEventListener('abort', handler));\n promises.push(promise);\n }\n }\n\n try {\n return await Promise.race([shortLived, ...promises]);\n } finally {\n cleanup.forEach(fn => fn());\n }\n}\n"],"mappings":";;AAUA,IAAM,sBAAsB;AAE5B,IAAM,eACJ,KACA,YAEA,QAAQ,QAAQ,OAAO,CAAC,CAAC,MAAK,YAAW;CACvC;CACA,QAAQ;CACR;AACF,EAAE;;;;;;;;AASJ,eAAsB,YAEpB,UAAiD;CACjD,MAAM,OAAO,OAAO,KAAK,QAAQ;CAEjC,IAAI,KAAK,WAAW,GAClB,MAAM,IAAI,MAAM,mBAAmB;CAGrC,MAAM,UAAU,KAAK,KAAI,QACvB,YAAY,KAAK,SAAS,IAA2C,CACvE;CAEA,OAAO,MAAM,QAAQ,KAAK,OAAO;AACnC;;;;;;;;;;;;;;AAeA,eAAsB,eACpB,YACA,GAAG,WACS;CACZ,MAAM,WAAyB,CAAC;CAChC,MAAM,UAA0B,CAAC;CACjC,KAAK,MAAM,UAAU,WACnB,IAAI,OAAO,SACT,SAAS,KAAK,QAAQ,OAAO,OAAO,MAAM,CAAC;MACtC;EACL,MAAM,EAAC,SAAS,WAAU,SAAY;EACtC,MAAM,gBAAgB,OAAO,OAAO,MAAM;EAC1C,OAAO,iBAAiB,SAAS,OAAO;EACxC,QAAQ,WAAW,OAAO,oBAAoB,SAAS,OAAO,CAAC;EAC/D,SAAS,KAAK,OAAO;CACvB;CAGF,IAAI;EACF,OAAO,MAAM,QAAQ,KAAK,CAAC,YAAY,GAAG,QAAQ,CAAC;CACrD,UAAU;EACR,QAAQ,SAAQ,OAAM,GAAG,CAAC;CAC5B;AACF"}
|
package/out/shared/src/queue.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assert } from "./asserts.js";
|
|
2
|
+
import { resolver } from "./resolver.js";
|
|
2
3
|
import { RingBuffer } from "./ring-buffer.js";
|
|
3
|
-
import { resolver } from "@rocicorp/resolver";
|
|
4
4
|
//#region ../shared/src/queue.ts
|
|
5
5
|
/**
|
|
6
6
|
* A Queue allows the consumers to await (possibly future) values,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","names":[],"sources":["../../../../shared/src/queue.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"queue.js","names":[],"sources":["../../../../shared/src/queue.ts"],"sourcesContent":["import {assert} from './asserts.ts';\nimport {resolver, type Resolver} from './resolver.ts';\nimport {RingBuffer} from './ring-buffer.ts';\n\n/**\n * A Queue allows the consumers to await (possibly future) values,\n * and producers to await the consumption of their values.\n */\nexport class Queue<T> {\n // Consumers waiting for entries to be produced.\n readonly #consumers = new RingBuffer<Consumer<T>>();\n // Produced entries waiting to be consumed.\n readonly #produced = new RingBuffer<Produced<T>>();\n\n enqueue(value: T): void {\n const consumer = this.#consumers.shift();\n if (consumer) {\n consumer.resolver.resolve(value);\n clearTimeout(consumer.timeoutID);\n return;\n }\n this.#produced.push({value});\n }\n\n enqueueRejection(reason?: unknown): void {\n const consumer = this.#consumers.shift();\n if (consumer) {\n consumer.resolver.reject(reason);\n clearTimeout(consumer.timeoutID);\n return;\n }\n this.#produced.push({rejection: reason});\n }\n\n /**\n * Deletes all unconsumed entries matching the specified `value` based on identity equality.\n * The consumed callback(s) are resolved as if the values were dequeued.\n *\n * Note: deletion of `undefined` values is not supported. This method will assert\n * if `value` is undefined.\n *\n * @returns The number of entries deleted.\n */\n delete(value: T): number {\n assert(value !== undefined, 'Queue delete value must not be undefined');\n\n // Drain, filter, and re-push. This is O(n) but delete() is rare.\n const items = this.#produced.drain();\n let count = 0;\n for (const p of items) {\n if (p.value === value) {\n count++;\n } else {\n this.#produced.push(p);\n }\n }\n return count;\n }\n\n /**\n * @param timeoutValue An optional value to resolve if `timeoutMs` is reached.\n * @param timeoutMs The milliseconds after which the `timeoutValue` is resolved\n * if nothing is produced for the consumer.\n * @returns A Promise that resolves to the next enqueued value.\n */\n dequeue(timeoutValue?: T, timeoutMs: number = 0): Promise<T> | T {\n const produced = this.#produced.shift();\n if (produced) {\n return produced.value ?? Promise.reject(produced.rejection);\n }\n const r = resolver<T>();\n const consumer: Consumer<T> = {resolver: r, timeoutID: undefined};\n const timeoutID =\n timeoutValue === undefined\n ? undefined\n : setTimeout(() => {\n if (this.#consumers.delete(consumer) > 0) {\n consumer.resolver.resolve(timeoutValue);\n }\n }, timeoutMs);\n consumer.timeoutID = timeoutID;\n this.#consumers.push(consumer);\n return r.promise;\n }\n\n /**\n * Drains the entire queue.\n *\n * Usage example:\n * ```ts\n * // A consumer that, when awoken, drains\n * // all entries in the queue in order to\n * // process them in a batch.\n * for (;;) {\n * const value = await queue.dequeue();\n * const rest = queue.drain();\n * }\n * ```\n */\n drain(): (T | undefined)[] {\n return this.#produced.drain().map(p => p.value);\n }\n\n /**\n * @returns The instantaneous number of outstanding values waiting to be\n * dequeued. Note that if a value was enqueued while a consumer\n * was waiting (with `await dequeue()`), the value is immediately\n * handed to the consumer and the Queue's size remains 0.\n */\n size(): number {\n return this.#produced.size;\n }\n\n asAsyncIterable(cleanup = NOOP): AsyncIterable<T> {\n return {[Symbol.asyncIterator]: () => this.asAsyncIterator(cleanup)};\n }\n\n asAsyncIterator(cleanup = NOOP): AsyncIterator<T> {\n return {\n next: async () => {\n try {\n const value = await this.dequeue();\n return {value};\n } catch (e) {\n cleanup();\n throw e;\n }\n },\n return: value => {\n cleanup();\n return Promise.resolve({value, done: true});\n },\n };\n }\n}\n\nconst NOOP = () => {};\n\ntype Consumer<T> = {\n resolver: Resolver<T>;\n timeoutID: ReturnType<typeof setTimeout> | undefined;\n};\n\ntype Produced<T> =\n | {value: T; rejection?: undefined}\n | {value?: undefined; rejection: unknown};\n"],"mappings":";;;;;;;;AAQA,IAAa,QAAb,MAAsB;CAEpB,aAAsB,IAAI,WAAwB;CAElD,YAAqB,IAAI,WAAwB;CAEjD,QAAQ,OAAgB;EACtB,MAAM,WAAW,KAAK,WAAW,MAAM;EACvC,IAAI,UAAU;GACZ,SAAS,SAAS,QAAQ,KAAK;GAC/B,aAAa,SAAS,SAAS;GAC/B;EACF;EACA,KAAK,UAAU,KAAK,EAAC,MAAK,CAAC;CAC7B;CAEA,iBAAiB,QAAwB;EACvC,MAAM,WAAW,KAAK,WAAW,MAAM;EACvC,IAAI,UAAU;GACZ,SAAS,SAAS,OAAO,MAAM;GAC/B,aAAa,SAAS,SAAS;GAC/B;EACF;EACA,KAAK,UAAU,KAAK,EAAC,WAAW,OAAM,CAAC;CACzC;;;;;;;;;;CAWA,OAAO,OAAkB;EACvB,OAAO,UAAU,KAAA,GAAW,0CAA0C;EAGtE,MAAM,QAAQ,KAAK,UAAU,MAAM;EACnC,IAAI,QAAQ;EACZ,KAAK,MAAM,KAAK,OACd,IAAI,EAAE,UAAU,OACd;OAEA,KAAK,UAAU,KAAK,CAAC;EAGzB,OAAO;CACT;;;;;;;CAQA,QAAQ,cAAkB,YAAoB,GAAmB;EAC/D,MAAM,WAAW,KAAK,UAAU,MAAM;EACtC,IAAI,UACF,OAAO,SAAS,SAAS,QAAQ,OAAO,SAAS,SAAS;EAE5D,MAAM,IAAI,SAAY;EACtB,MAAM,WAAwB;GAAC,UAAU;GAAG,WAAW,KAAA;EAAS;EAShE,SAAS,YAPP,iBAAiB,KAAA,IACb,KAAA,IACA,iBAAiB;GACf,IAAI,KAAK,WAAW,OAAO,QAAQ,IAAI,GACrC,SAAS,SAAS,QAAQ,YAAY;EAE1C,GAAG,SAAS;EAElB,KAAK,WAAW,KAAK,QAAQ;EAC7B,OAAO,EAAE;CACX;;;;;;;;;;;;;;;CAgBA,QAA2B;EACzB,OAAO,KAAK,UAAU,MAAM,CAAC,CAAC,KAAI,MAAK,EAAE,KAAK;CAChD;;;;;;;CAQA,OAAe;EACb,OAAO,KAAK,UAAU;CACxB;CAEA,gBAAgB,UAAU,MAAwB;EAChD,OAAO,GAAE,OAAO,sBAAsB,KAAK,gBAAgB,OAAO,EAAC;CACrE;CAEA,gBAAgB,UAAU,MAAwB;EAChD,OAAO;GACL,MAAM,YAAY;IAChB,IAAI;KAEF,OAAO,EAAC,OAAA,MADY,KAAK,QAAQ,EACpB;IACf,SAAS,GAAG;KACV,QAAQ;KACR,MAAM;IACR;GACF;GACA,SAAQ,UAAS;IACf,QAAQ;IACR,OAAO,QAAQ,QAAQ;KAAC;KAAO,MAAM;IAAI,CAAC;GAC5C;EACF;CACF;AACF;AAEA,IAAM,aAAa,CAAC"}
|
|
@@ -2,8 +2,4 @@ export declare const promiseTrue: Promise<true>;
|
|
|
2
2
|
export declare const promiseFalse: Promise<false>;
|
|
3
3
|
export declare const promiseUndefined: Promise<undefined>;
|
|
4
4
|
export declare const promiseVoid: Promise<void>;
|
|
5
|
-
/**
|
|
6
|
-
* A promise that never resolves.
|
|
7
|
-
*/
|
|
8
|
-
export declare const promiseNever: Promise<never>;
|
|
9
5
|
//# sourceMappingURL=resolved-promises.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolved-promises.d.ts","sourceRoot":"","sources":["../../../../shared/src/resolved-promises.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,eAAiC,CAAC;AAC1D,eAAO,MAAM,YAAY,gBAAkC,CAAC;AAC5D,eAAO,MAAM,gBAAgB,oBAA6B,CAAC;AAC3D,eAAO,MAAM,WAAW,eAAoB,CAAC
|
|
1
|
+
{"version":3,"file":"resolved-promises.d.ts","sourceRoot":"","sources":["../../../../shared/src/resolved-promises.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,eAAiC,CAAC;AAC1D,eAAO,MAAM,YAAY,gBAAkC,CAAC;AAC5D,eAAO,MAAM,gBAAgB,oBAA6B,CAAC;AAC3D,eAAO,MAAM,WAAW,eAAoB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolved-promises.js","names":[],"sources":["../../../../shared/src/resolved-promises.ts"],"sourcesContent":["export const promiseTrue = Promise.resolve(true as const);\nexport const promiseFalse = Promise.resolve(false as const);\nexport const promiseUndefined = Promise.resolve(undefined);\nexport const promiseVoid = Promise.resolve();\n
|
|
1
|
+
{"version":3,"file":"resolved-promises.js","names":[],"sources":["../../../../shared/src/resolved-promises.ts"],"sourcesContent":["export const promiseTrue = Promise.resolve(true as const);\nexport const promiseFalse = Promise.resolve(false as const);\nexport const promiseUndefined = Promise.resolve(undefined);\nexport const promiseVoid = Promise.resolve();\n"],"mappings":";AAAA,IAAa,cAAc,QAAQ,QAAQ,IAAa;AACxD,IAAa,eAAe,QAAQ,QAAQ,KAAc;AAC1B,QAAQ,QAAQ,KAAA,CAAS;AACzD,IAAa,cAAc,QAAQ,QAAQ"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface Resolver<R = void, E = unknown> {
|
|
2
|
+
promise: Promise<R>;
|
|
3
|
+
resolve: (res: R) => void;
|
|
4
|
+
reject: (err: E) => void;
|
|
5
|
+
}
|
|
6
|
+
type WithResolvers = <R = void, E = unknown>() => Resolver<R, E>;
|
|
7
|
+
export declare const resolver: WithResolvers;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../../shared/src/resolver.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,OAAO;IAC7C,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;IAC1B,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC;CAC1B;AAED,KAAK,aAAa,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,OAAO,OAAO,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAEjE,eAAO,MAAM,QAAQ,EAAE,aAA6C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","names":[],"sources":["../../../../shared/src/resolver.ts"],"sourcesContent":["export interface Resolver<R = void, E = unknown> {\n promise: Promise<R>;\n resolve: (res: R) => void;\n reject: (err: E) => void;\n}\n\ntype WithResolvers = <R = void, E = unknown>() => Resolver<R, E>;\n\nexport const resolver: WithResolvers = () => Promise.withResolvers();\n"],"mappings":";AAQA,IAAa,iBAAgC,QAAQ,cAAc"}
|
package/out/shared/src/sleep.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sleep.js","names":[],"sources":["../../../../shared/src/sleep.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"sleep.js","names":[],"sources":["../../../../shared/src/sleep.ts"],"sourcesContent":["import {AbortError} from './abort-error.ts';\nimport {resolver} from './resolver.ts';\n\nconst promiseVoid = Promise.resolve();\nconst promiseNever = new Promise<void>(() => undefined);\n\n/**\n * Creates a promise that resolves after `ms` milliseconds. Note that if you\n * pass in `0` no `setTimeout` is used and the promise resolves immediately. In\n * other words no macro task is used in that case.\n *\n * Pass in an AbortSignal to clear the timeout.\n */\nexport function sleep(ms: number, signal?: AbortSignal): Promise<void> {\n const newAbortError = () => new AbortError('Aborted');\n\n if (signal?.aborted) {\n return Promise.reject(newAbortError());\n }\n\n if (ms === 0) {\n return promiseVoid;\n }\n\n return new Promise((resolve, reject) => {\n let handleAbort: () => void;\n if (signal) {\n handleAbort = () => {\n clearTimeout(id);\n reject(newAbortError());\n };\n signal.addEventListener('abort', handleAbort, {once: true});\n }\n\n const id = setTimeout(() => {\n resolve();\n signal?.removeEventListener('abort', handleAbort);\n }, ms);\n });\n}\n\n/**\n * Returns a pair of promises. The first promise resolves after `ms` milliseconds\n * unless the AbortSignal is aborted. The second promise resolves when the AbortSignal\n * is aborted.\n */\nexport function sleepWithAbort(\n ms: number,\n signal: AbortSignal,\n): [ok: Promise<void>, aborted: Promise<void>] {\n if (ms === 0) {\n return [promiseVoid, promiseNever];\n }\n\n const {promise: abortedPromise, resolve: abortedResolve} = resolver<void>();\n\n const sleepPromise = new Promise<void>(resolve => {\n const handleAbort = () => {\n clearTimeout(id);\n abortedResolve();\n };\n\n const id = setTimeout(() => {\n resolve();\n signal.removeEventListener('abort', handleAbort);\n }, ms);\n\n signal.addEventListener('abort', handleAbort, {once: true});\n });\n\n return [sleepPromise, abortedPromise];\n}\n"],"mappings":";;;AAGA,IAAM,cAAc,QAAQ,QAAQ;AACpC,IAAM,eAAe,IAAI,cAAoB,KAAA,CAAS;;;;;;;;AAStD,SAAgB,MAAM,IAAY,QAAqC;CACrE,MAAM,sBAAsB,IAAI,WAAW,SAAS;CAEpD,IAAI,QAAQ,SACV,OAAO,QAAQ,OAAO,cAAc,CAAC;CAGvC,IAAI,OAAO,GACT,OAAO;CAGT,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,IAAI;EACJ,IAAI,QAAQ;GACV,oBAAoB;IAClB,aAAa,EAAE;IACf,OAAO,cAAc,CAAC;GACxB;GACA,OAAO,iBAAiB,SAAS,aAAa,EAAC,MAAM,KAAI,CAAC;EAC5D;EAEA,MAAM,KAAK,iBAAiB;GAC1B,QAAQ;GACR,QAAQ,oBAAoB,SAAS,WAAW;EAClD,GAAG,EAAE;CACP,CAAC;AACH;;;;;;AAOA,SAAgB,eACd,IACA,QAC6C;CAC7C,IAAI,OAAO,GACT,OAAO,CAAC,aAAa,YAAY;CAGnC,MAAM,EAAC,SAAS,gBAAgB,SAAS,mBAAkB,SAAe;CAgB1E,OAAO,CAAC,IAdiB,SAAc,YAAW;EAChD,MAAM,oBAAoB;GACxB,aAAa,EAAE;GACf,eAAe;EACjB;EAEA,MAAM,KAAK,iBAAiB;GAC1B,QAAQ;GACR,OAAO,oBAAoB,SAAS,WAAW;EACjD,GAAG,EAAE;EAEL,OAAO,iBAAiB,SAAS,aAAa,EAAC,MAAM,KAAI,CAAC;CAC5D,CAEQ,GAAc,cAAc;AACtC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tdigest.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAE,KAAK,YAAY,EAAC,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAcD,qBAAa,OAAO;;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAqB7B;;;;;OAKG;IACH,YAAY,WAAW,GAAE,MAAY,EAOpC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CASpD;IAED,KAAK,IAAI,IAAI,CASZ;IAED;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAiB1C;IAED,0DAA0D;IAC1D,eAAe,CAAC,YAAY,EAAE,YAAY,QAIzC;IAED;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAE7B;IAED;;;;QAII;IACJ,KAAK,CAAC,EAAE,EAAE,OAAO,QAShB;IAiHD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,GAAE,YAAiB,GAAG,YAAY,CAO7C;IAED,KAAK,IAAI,MAAM,CAMd;IAED;;;OAGG;IACH,MAAM,IAAI,WAAW,CAOpB;IA6BD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAqC1B;IAED;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA2ErB;CAgBF
|
|
1
|
+
{"version":3,"file":"tdigest.d.ts","sourceRoot":"","sources":["../../../../shared/src/tdigest.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,QAAQ,EAAE,KAAK,YAAY,EAAC,MAAM,eAAe,CAAC;AAC1D,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CACrC;AAcD,qBAAa,OAAO;;IAClB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAqB7B;;;;;OAKG;IACH,YAAY,WAAW,GAAE,MAAY,EAOpC;IAED;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,OAAO,CASpD;IAED,KAAK,IAAI,IAAI,CASZ;IAED;;;OAGG;IACH,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAiB1C;IAED,0DAA0D;IAC1D,eAAe,CAAC,YAAY,EAAE,YAAY,QAIzC;IAED;;;OAGG;IACH,WAAW,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAE7B;IAED;;;;QAII;IACJ,KAAK,CAAC,EAAE,EAAE,OAAO,QAShB;IAiHD;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,GAAE,YAAiB,GAAG,YAAY,CAO7C;IAED,KAAK,IAAI,MAAM,CAMd;IAED;;;OAGG;IACH,MAAM,IAAI,WAAW,CAOpB;IA6BD,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAqC1B;IAED;;OAEG;IACH,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CA2ErB;CAgBF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tdigest.js","names":[],"sources":["../../../../shared/src/tdigest.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\nimport {binarySearch} from './binary-search.ts';\nimport {Centroid, type CentroidList} from './centroid.ts';\nimport type {TDigestJSON} from './tdigest-schema.ts';\n\nexport interface ReadonlyTDigest {\n readonly count: () => number;\n readonly quantile: (q: number) => number;\n readonly cdf: (x: number) => number;\n}\n\n/** Initial capacity of the buffer of unprocessed values. */\nconst INITIAL_CAPACITY = 16;\n\n// TDigest is a data structure for accurate on-line accumulation of\n// rank-based statistics such as quantiles and trimmed means.\n//\n// Unlike the Go original, centroids are kept as parallel arrays of means and\n// weights rather than as objects, so adding a value allocates nothing. New\n// values are buffered in a Float64Array and sorted with its native numeric\n// sort instead of Array.prototype.sort with a comparator. On an engine\n// without a JIT, such as Hermes in React Native, calling the comparator for\n// every comparison is what made adding values expensive.\nexport class TDigest {\n readonly compression: number;\n\n readonly #maxUnprocessed: number;\n\n /** Means of the processed centroids, ascending. */\n #means!: number[];\n /** Weights of the processed centroids, parallel to `#means`. */\n #weights!: number[];\n\n /** Means of the values added since the last `#process`, in order. */\n #unprocessedMeans: Float64Array;\n /** Weights of the unprocessed values, parallel to `#unprocessedMeans`. */\n #unprocessedWeights: Float64Array;\n #unprocessedCount!: number;\n\n #cumulative!: number[];\n #processedWeight!: number;\n #unprocessedWeight!: number;\n #min!: number;\n #max!: number;\n\n /**\n * A digest keeps roughly `compression` centroids, and buffers up to eight\n * times as many values between merges. The Go original defaults to 1000;\n * 100 keeps p50, p95 and p99 within about 0.5% for a tenth of the memory\n * and serialized size, which is plenty for the inspector's percentiles.\n */\n constructor(compression: number = 100) {\n this.compression = compression;\n this.#maxUnprocessed = unprocessedSize(0, this.compression);\n const capacity = Math.min(INITIAL_CAPACITY, this.#maxUnprocessed + 1);\n this.#unprocessedMeans = new Float64Array(capacity);\n this.#unprocessedWeights = new Float64Array(capacity);\n this.reset();\n }\n\n /**\n * fromJSON creates a TDigest from a JSON-serializable representation.\n * The data should be an object with compression and centroids array.\n */\n static fromJSON(data: Readonly<TDigestJSON>): TDigest {\n const digest = new TDigest(data[0]);\n if (data.length % 2 !== 1) {\n throw new Error('Invalid centroids array');\n }\n for (let i = 1; i < data.length; i += 2) {\n digest.add(data[i], data[i + 1]);\n }\n return digest;\n }\n\n reset(): void {\n this.#means = [];\n this.#weights = [];\n this.#unprocessedCount = 0;\n this.#cumulative = [];\n this.#processedWeight = 0;\n this.#unprocessedWeight = 0;\n this.#min = Number.MAX_VALUE;\n this.#max = -Number.MAX_VALUE;\n }\n\n /**\n * Adds a value with the given weight.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n add(mean: number, weight: number = 1): void {\n if (Number.isNaN(mean) || weight <= 0 || !Number.isFinite(weight)) {\n return;\n }\n\n const n = this.#unprocessedCount;\n if (n === this.#unprocessedMeans.length) {\n this.#grow();\n }\n this.#unprocessedMeans[n] = mean;\n this.#unprocessedWeights[n] = weight;\n this.#unprocessedCount = n + 1;\n this.#unprocessedWeight += weight;\n\n if (this.#unprocessedCount > this.#maxUnprocessed) {\n this.#process();\n }\n }\n\n /** AddCentroidList can quickly add multiple centroids. */\n addCentroidList(centroidList: CentroidList) {\n for (const c of centroidList) {\n this.add(c.mean, c.weight);\n }\n }\n\n /**\n * AddCentroid adds a single centroid.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n addCentroid(c: Centroid): void {\n this.add(c.mean, c.weight);\n }\n\n /**\n * Merges the supplied digest into this digest. Functionally equivalent to\n * calling t.AddCentroidList(t2.Centroids(nil)), but avoids making an extra\n * copy of the CentroidList.\n **/\n merge(t2: TDigest) {\n t2.#process();\n // #process replaces the arrays rather than changing them, so these stay\n // intact even if t2 is this digest.\n const means = t2.#means;\n const weights = t2.#weights;\n for (let i = 0; i < means.length; i++) {\n this.add(means[i], weights[i]);\n }\n }\n\n /** Doubles the unprocessed buffer, up to what `add` lets it hold. */\n #grow(): void {\n const capacity = Math.min(\n this.#unprocessedMeans.length * 2,\n this.#maxUnprocessed + 1,\n );\n const means = new Float64Array(capacity);\n means.set(this.#unprocessedMeans);\n this.#unprocessedMeans = means;\n const weights = new Float64Array(capacity);\n weights.set(this.#unprocessedWeights);\n this.#unprocessedWeights = weights;\n }\n\n /**\n * Merges the unprocessed values into the centroids: walks both in order of\n * mean, folding each into the last centroid while that stays within its\n * size limit, and starting a new centroid otherwise.\n */\n #process() {\n if (this.#unprocessedCount === 0) {\n return;\n }\n const [newMeans, newWeights] = this.#sortedUnprocessed();\n const oldMeans = this.#means;\n const oldWeights = this.#weights;\n const n = newMeans.length;\n const p = oldMeans.length;\n this.#unprocessedCount = 0;\n this.#processedWeight += this.#unprocessedWeight;\n this.#unprocessedWeight = 0;\n const total = this.#processedWeight;\n\n const means: number[] = [];\n const weights: number[] = [];\n // The centroid being built, kept in locals rather than in the arrays,\n // which is markedly faster without a JIT. Its weight is 0 until the first\n // value.\n let mean = 0;\n let weight = 0;\n let soFar = 0;\n // A limit of 0 makes the first value start a centroid, whose limit then\n // comes from the same formula as every other's. With soFar at 0 that is\n // integratedQ(1): integratedLocation(0) is exactly 0, since\n // Math.asin(-1) is -Math.PI / 2.\n let limit = 0;\n let i = 0;\n let j = 0;\n while (i < n || j < p) {\n // On a tie the new value goes first, as in the original, which appended\n // the old centroids to the new values and sorted them with a stable sort.\n let m: number;\n let w: number;\n if (i < n && (j === p || newMeans[i] <= oldMeans[j])) {\n m = newMeans[i];\n w = newWeights[i++];\n } else {\n m = oldMeans[j];\n w = oldWeights[j++];\n }\n if (soFar + w <= limit) {\n // Same arithmetic as Centroid.add.\n weight += w;\n mean += (w * (m - mean)) / weight;\n } else {\n if (weight > 0) {\n means.push(mean);\n weights.push(weight);\n }\n const k = this.#integratedLocation(soFar / total);\n limit = total * this.#integratedQ(k + 1);\n mean = m;\n weight = w;\n }\n soFar += w;\n }\n means.push(mean);\n weights.push(weight);\n\n this.#means = means;\n this.#weights = weights;\n this.#min = Math.min(this.#min, means[0]);\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#max = Math.max(this.#max, means.at(-1)!);\n }\n\n /** The unprocessed means and weights, sorted by mean. */\n #sortedUnprocessed(): [Float64Array, Float64Array] {\n const n = this.#unprocessedCount;\n const means = this.#unprocessedMeans.subarray(0, n);\n const weights = this.#unprocessedWeights.subarray(0, n);\n // fromJSON and merge add centroids in order of mean.\n if (isSorted(means)) {\n return [means, weights];\n }\n // With one weight for all the values, sorting the means alone keeps every\n // value with its weight, and the native numeric sort needs no comparator.\n if (allEqual(weights)) {\n means.sort();\n return [means, weights];\n }\n // A stable sort, so values with equal means stay in the order added.\n const order = Array.from(means, (_, k) => k).sort(\n (a, b) => means[a] - means[b],\n );\n return [\n Float64Array.from(order, k => means[k]),\n Float64Array.from(order, k => weights[k]),\n ];\n }\n\n /**\n * Centroids returns a copy of processed centroids.\n * Useful when aggregating multiple t-digests.\n *\n * Centroids are appended to the passed CentroidList; if you're re-using a\n * buffer, be sure to pass cl[:0].\n */\n centroids(cl: CentroidList = []): CentroidList {\n this.#process();\n const result = [...cl];\n for (let i = 0; i < this.#means.length; i++) {\n result.push(new Centroid(this.#means[i], this.#weights[i]));\n }\n return result;\n }\n\n count(): number {\n this.#process();\n\n // this.process always updates this.processedWeight to the total count of all\n // centroids, so we don't need to re-count here.\n return this.#processedWeight;\n }\n\n /**\n * toJSON returns a JSON-serializable representation of the digest.\n * This processes the digest and returns an object with compression and centroid data.\n */\n toJSON(): TDigestJSON {\n this.#process();\n const data: TDigestJSON = [this.compression];\n for (let i = 0; i < this.#means.length; i++) {\n data.push(this.#means[i], this.#weights[i]);\n }\n return data;\n }\n\n #updateCumulative() {\n // Weight can only increase, so the final cumulative value will always be\n // either equal to, or less than, the total weight. If they are the same,\n // then nothing has changed since the last update.\n if (\n this.#cumulative.length > 0 &&\n this.#cumulative.at(-1) === this.#processedWeight\n ) {\n return;\n }\n const n = this.#means.length + 1;\n if (this.#cumulative.length > n) {\n this.#cumulative.length = n;\n }\n\n let prev = 0;\n for (let i = 0; i < this.#means.length; i++) {\n const cur = this.#weights[i];\n this.#cumulative[i] = prev + cur / 2;\n prev += cur;\n }\n this.#cumulative[this.#means.length] = prev;\n }\n\n // Quantile returns the (approximate) quantile of\n // the distribution. Accepted values for q are between 0 and 1.\n // Returns NaN if Count is zero or bad inputs.\n quantile(q: number): number {\n this.#process();\n this.#updateCumulative();\n if (q < 0 || q > 1 || this.#means.length === 0) {\n return NaN;\n }\n if (this.#means.length === 1) {\n return this.#means[0];\n }\n const index = q * this.#processedWeight;\n if (index <= this.#weights[0] / 2) {\n return (\n this.#min +\n ((2 * index) / this.#weights[0]) * (this.#means[0] - this.#min)\n );\n }\n\n const lower = binarySearch(\n this.#cumulative.length,\n (i: number) => -this.#cumulative[i] + index,\n );\n\n if (lower + 1 !== this.#cumulative.length) {\n const z1 = index - this.#cumulative[lower - 1];\n const z2 = this.#cumulative[lower] - index;\n return weightedAverage(\n this.#means[lower - 1],\n z2,\n this.#means[lower],\n z1,\n );\n }\n\n const z1 = index - this.#processedWeight - this.#weights[lower - 1] / 2;\n const z2 = this.#weights[lower - 1] / 2 - z1;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return weightedAverage(this.#means.at(-1)!, z1, this.#max, z2);\n }\n\n /**\n * CDF returns the cumulative distribution function for a given value x.\n */\n cdf(x: number): number {\n this.#process();\n this.#updateCumulative();\n switch (this.#means.length) {\n case 0:\n return 0;\n case 1: {\n const width = this.#max - this.#min;\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n if (x - this.#min <= width) {\n // min and max are too close together to do any viable interpolation\n return 0.5;\n }\n return (x - this.#min) / width;\n }\n }\n\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n const m0 = this.#means[0];\n // Left Tail\n if (x <= m0) {\n if (m0 - this.#min > 0) {\n return (\n (((x - this.#min) / (m0 - this.#min)) * this.#weights[0]) /\n this.#processedWeight /\n 2\n );\n }\n return 0;\n }\n // Right Tail\n // oxlint-disable-next-line typescript/no-non-null-assertion\n const mn = this.#means.at(-1)!;\n if (x >= mn) {\n if (this.#max - mn > 0) {\n return (\n 1 -\n (((this.#max - x) / (this.#max - mn)) *\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#weights.at(-1)!) /\n this.#processedWeight /\n 2\n );\n }\n return 1;\n }\n\n const upper = binarySearch(\n this.#means.length,\n // Treat equals as greater than, so we can use the upper index\n // This is equivalent to:\n // i => this.#means[i] > x ? -1 : 1,\n i => x - this.#means[i] || 1,\n );\n\n const z1 = x - this.#means[upper - 1];\n const z2 = this.#means[upper] - x;\n return (\n weightedAverage(\n this.#cumulative[upper - 1],\n z2,\n this.#cumulative[upper],\n z1,\n ) / this.#processedWeight\n );\n }\n\n #integratedQ(k: number): number {\n return (\n (Math.sin(\n (Math.min(k, this.compression) * Math.PI) / this.compression -\n Math.PI / 2,\n ) +\n 1) /\n 2\n );\n }\n\n #integratedLocation(q: number): number {\n return (this.compression * (Math.asin(2 * q - 1) + Math.PI / 2)) / Math.PI;\n }\n}\n\n// Calculate number of bytes needed for a tdigest of size c,\n// where c is the compression value\nexport function byteSizeForCompression(comp: number): number {\n const c = comp | 0;\n // // A centroid is 2 float64s, so we need 16 bytes for each centroid\n // float_size := 8\n // centroid_size := 2 * float_size\n\n // // Unprocessed and processed can grow up to length c\n // unprocessed_size := centroid_size * c\n // processed_size := unprocessed_size\n\n // // the cumulative field can also be of length c, but each item is a single float64\n // cumulative_size := float_size * c // <- this could also be unprocessed_size / 2\n\n // return unprocessed_size + processed_size + cumulative_size\n\n // // or, more succinctly:\n // return float_size * c * 5\n\n // or even more succinctly\n return c * 40;\n}\n\nfunction isSorted(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] < values[i - 1]) {\n return false;\n }\n }\n return true;\n}\n\nfunction allEqual(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] !== values[0]) {\n return false;\n }\n }\n return true;\n}\n\nfunction weightedAverage(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n if (x1 <= x2) {\n return weightedAverageSorted(x1, w1, x2, w2);\n }\n return weightedAverageSorted(x2, w2, x1, w1);\n}\n\nfunction weightedAverageSorted(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n const x = (x1 * w1 + x2 * w2) / (w1 + w2);\n return Math.max(x1, Math.min(x, x2));\n}\n\nfunction unprocessedSize(size: number, compression: number): number {\n if (size === 0) {\n return Math.ceil(compression) * 8;\n }\n return size;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tdigest.js","names":[],"sources":["../../../../shared/src/tdigest.ts"],"sourcesContent":["// Apache License 2.0\n// https://github.com/influxdata/tdigest\n\nimport {binarySearch} from './binary-search.ts';\nimport {Centroid, type CentroidList} from './centroid.ts';\nimport type {TDigestJSON} from './tdigest-schema.ts';\n\nexport interface ReadonlyTDigest {\n readonly count: () => number;\n readonly quantile: (q: number) => number;\n readonly cdf: (x: number) => number;\n}\n\n/** Initial capacity of the buffer of unprocessed values. */\nconst INITIAL_CAPACITY = 16;\n\n// TDigest is a data structure for accurate on-line accumulation of\n// rank-based statistics such as quantiles and trimmed means.\n//\n// Unlike the Go original, centroids are kept as parallel arrays of means and\n// weights rather than as objects, so adding a value allocates nothing. New\n// values are buffered in a Float64Array and sorted with its native numeric\n// sort instead of Array.prototype.sort with a comparator. On an engine\n// without a JIT, such as Hermes in React Native, calling the comparator for\n// every comparison is what made adding values expensive.\nexport class TDigest {\n readonly compression: number;\n\n readonly #maxUnprocessed: number;\n\n /** Means of the processed centroids, ascending. */\n #means!: number[];\n /** Weights of the processed centroids, parallel to `#means`. */\n #weights!: number[];\n\n /** Means of the values added since the last `#process`, in order. */\n #unprocessedMeans: Float64Array;\n /** Weights of the unprocessed values, parallel to `#unprocessedMeans`. */\n #unprocessedWeights: Float64Array;\n #unprocessedCount!: number;\n\n #cumulative!: number[];\n #processedWeight!: number;\n #unprocessedWeight!: number;\n #min!: number;\n #max!: number;\n\n /**\n * A digest keeps roughly `compression` centroids, and buffers up to eight\n * times as many values between merges. The Go original defaults to 1000;\n * 100 keeps p50, p95 and p99 within about 0.5% for a tenth of the memory\n * and serialized size, which is plenty for the inspector's percentiles.\n */\n constructor(compression: number = 100) {\n this.compression = compression;\n this.#maxUnprocessed = unprocessedSize(0, this.compression);\n const capacity = Math.min(INITIAL_CAPACITY, this.#maxUnprocessed + 1);\n this.#unprocessedMeans = new Float64Array(capacity);\n this.#unprocessedWeights = new Float64Array(capacity);\n this.reset();\n }\n\n /**\n * fromJSON creates a TDigest from a JSON-serializable representation.\n * The data should be an object with compression and centroids array.\n */\n static fromJSON(data: Readonly<TDigestJSON>): TDigest {\n const digest = new TDigest(data[0]);\n if (data.length % 2 !== 1) {\n throw new Error('Invalid centroids array');\n }\n for (let i = 1; i < data.length; i += 2) {\n digest.add(data[i], data[i + 1]);\n }\n return digest;\n }\n\n reset(): void {\n this.#means = [];\n this.#weights = [];\n this.#unprocessedCount = 0;\n this.#cumulative = [];\n this.#processedWeight = 0;\n this.#unprocessedWeight = 0;\n this.#min = Number.MAX_VALUE;\n this.#max = -Number.MAX_VALUE;\n }\n\n /**\n * Adds a value with the given weight.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n add(mean: number, weight: number = 1): void {\n if (Number.isNaN(mean) || weight <= 0 || !Number.isFinite(weight)) {\n return;\n }\n\n const n = this.#unprocessedCount;\n if (n === this.#unprocessedMeans.length) {\n this.#grow();\n }\n this.#unprocessedMeans[n] = mean;\n this.#unprocessedWeights[n] = weight;\n this.#unprocessedCount = n + 1;\n this.#unprocessedWeight += weight;\n\n if (this.#unprocessedCount > this.#maxUnprocessed) {\n this.#process();\n }\n }\n\n /** AddCentroidList can quickly add multiple centroids. */\n addCentroidList(centroidList: CentroidList) {\n for (const c of centroidList) {\n this.add(c.mean, c.weight);\n }\n }\n\n /**\n * AddCentroid adds a single centroid.\n * Weights which are not a number or are <= 0 are ignored, as are NaN means.\n */\n addCentroid(c: Centroid): void {\n this.add(c.mean, c.weight);\n }\n\n /**\n * Merges the supplied digest into this digest. Functionally equivalent to\n * calling t.AddCentroidList(t2.Centroids(nil)), but avoids making an extra\n * copy of the CentroidList.\n **/\n merge(t2: TDigest) {\n t2.#process();\n // #process replaces the arrays rather than changing them, so these stay\n // intact even if t2 is this digest.\n const means = t2.#means;\n const weights = t2.#weights;\n for (let i = 0; i < means.length; i++) {\n this.add(means[i], weights[i]);\n }\n }\n\n /** Doubles the unprocessed buffer, up to what `add` lets it hold. */\n #grow(): void {\n const capacity = Math.min(\n this.#unprocessedMeans.length * 2,\n this.#maxUnprocessed + 1,\n );\n const means = new Float64Array(capacity);\n means.set(this.#unprocessedMeans);\n this.#unprocessedMeans = means;\n const weights = new Float64Array(capacity);\n weights.set(this.#unprocessedWeights);\n this.#unprocessedWeights = weights;\n }\n\n /**\n * Merges the unprocessed values into the centroids: walks both in order of\n * mean, folding each into the last centroid while that stays within its\n * size limit, and starting a new centroid otherwise.\n */\n #process() {\n if (this.#unprocessedCount === 0) {\n return;\n }\n const [newMeans, newWeights] = this.#sortedUnprocessed();\n const oldMeans = this.#means;\n const oldWeights = this.#weights;\n const n = newMeans.length;\n const p = oldMeans.length;\n this.#unprocessedCount = 0;\n this.#processedWeight += this.#unprocessedWeight;\n this.#unprocessedWeight = 0;\n const total = this.#processedWeight;\n\n const means: number[] = [];\n const weights: number[] = [];\n // The centroid being built, kept in locals rather than in the arrays,\n // which is markedly faster without a JIT. Its weight is 0 until the first\n // value.\n let mean = 0;\n let weight = 0;\n let soFar = 0;\n // A limit of 0 makes the first value start a centroid, whose limit then\n // comes from the same formula as every other's. With soFar at 0 that is\n // integratedQ(1): integratedLocation(0) is exactly 0, since\n // Math.asin(-1) is -Math.PI / 2.\n let limit = 0;\n let i = 0;\n let j = 0;\n while (i < n || j < p) {\n // On a tie the new value goes first, as in the original, which appended\n // the old centroids to the new values and sorted them with a stable sort.\n let m: number;\n let w: number;\n if (i < n && (j === p || newMeans[i] <= oldMeans[j])) {\n m = newMeans[i];\n w = newWeights[i++];\n } else {\n m = oldMeans[j];\n w = oldWeights[j++];\n }\n if (soFar + w <= limit) {\n // Same arithmetic as Centroid.add.\n weight += w;\n mean += (w * (m - mean)) / weight;\n } else {\n if (weight > 0) {\n means.push(mean);\n weights.push(weight);\n }\n const k = this.#integratedLocation(soFar / total);\n limit = total * this.#integratedQ(k + 1);\n mean = m;\n weight = w;\n }\n soFar += w;\n }\n means.push(mean);\n weights.push(weight);\n\n this.#means = means;\n this.#weights = weights;\n this.#min = Math.min(this.#min, means[0]);\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#max = Math.max(this.#max, means.at(-1)!);\n }\n\n /** The unprocessed means and weights, sorted by mean. */\n #sortedUnprocessed(): [Float64Array, Float64Array] {\n const n = this.#unprocessedCount;\n const means = this.#unprocessedMeans.subarray(0, n);\n const weights = this.#unprocessedWeights.subarray(0, n);\n // fromJSON and merge add centroids in order of mean.\n if (isSorted(means)) {\n return [means, weights];\n }\n // With one weight for all the values, sorting the means alone keeps every\n // value with its weight, and the native numeric sort needs no comparator.\n if (allEqual(weights)) {\n means.sort();\n return [means, weights];\n }\n // A stable sort, so values with equal means stay in the order added.\n const order = Array.from(means, (_, k) => k).sort(\n (a, b) => means[a] - means[b],\n );\n return [\n Float64Array.from(order, k => means[k]),\n Float64Array.from(order, k => weights[k]),\n ];\n }\n\n /**\n * Centroids returns a copy of processed centroids.\n * Useful when aggregating multiple t-digests.\n *\n * Centroids are appended to the passed CentroidList; if you're re-using a\n * buffer, be sure to pass cl[:0].\n */\n centroids(cl: CentroidList = []): CentroidList {\n this.#process();\n const result = [...cl];\n for (let i = 0; i < this.#means.length; i++) {\n result.push(new Centroid(this.#means[i], this.#weights[i]));\n }\n return result;\n }\n\n count(): number {\n this.#process();\n\n // this.process always updates this.processedWeight to the total count of all\n // centroids, so we don't need to re-count here.\n return this.#processedWeight;\n }\n\n /**\n * toJSON returns a JSON-serializable representation of the digest.\n * This processes the digest and returns an object with compression and centroid data.\n */\n toJSON(): TDigestJSON {\n this.#process();\n const data: TDigestJSON = [this.compression];\n for (let i = 0; i < this.#means.length; i++) {\n data.push(this.#means[i], this.#weights[i]);\n }\n return data;\n }\n\n #updateCumulative() {\n // Weight can only increase, so the final cumulative value will always be\n // either equal to, or less than, the total weight. If they are the same,\n // then nothing has changed since the last update.\n if (\n this.#cumulative.length > 0 &&\n this.#cumulative.at(-1) === this.#processedWeight\n ) {\n return;\n }\n const n = this.#means.length + 1;\n if (this.#cumulative.length > n) {\n this.#cumulative.length = n;\n }\n\n let prev = 0;\n for (let i = 0; i < this.#means.length; i++) {\n const cur = this.#weights[i];\n this.#cumulative[i] = prev + cur / 2;\n prev += cur;\n }\n this.#cumulative[this.#means.length] = prev;\n }\n\n // Quantile returns the (approximate) quantile of\n // the distribution. Accepted values for q are between 0 and 1.\n // Returns NaN if Count is zero or bad inputs.\n quantile(q: number): number {\n this.#process();\n this.#updateCumulative();\n if (q < 0 || q > 1 || this.#means.length === 0) {\n return NaN;\n }\n if (this.#means.length === 1) {\n return this.#means[0];\n }\n const index = q * this.#processedWeight;\n if (index <= this.#weights[0] / 2) {\n return (\n this.#min +\n ((2 * index) / this.#weights[0]) * (this.#means[0] - this.#min)\n );\n }\n\n const lower = binarySearch(\n this.#cumulative.length,\n (i: number) => -this.#cumulative[i] + index,\n );\n\n if (lower + 1 !== this.#cumulative.length) {\n const z1 = index - this.#cumulative[lower - 1];\n const z2 = this.#cumulative[lower] - index;\n return weightedAverage(\n this.#means[lower - 1],\n z2,\n this.#means[lower],\n z1,\n );\n }\n\n const z1 = index - this.#processedWeight - this.#weights[lower - 1] / 2;\n const z2 = this.#weights[lower - 1] / 2 - z1;\n // oxlint-disable-next-line typescript/no-non-null-assertion\n return weightedAverage(this.#means.at(-1)!, z1, this.#max, z2);\n }\n\n /**\n * CDF returns the cumulative distribution function for a given value x.\n */\n cdf(x: number): number {\n this.#process();\n this.#updateCumulative();\n switch (this.#means.length) {\n case 0:\n return 0;\n case 1: {\n const width = this.#max - this.#min;\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n if (x - this.#min <= width) {\n // min and max are too close together to do any viable interpolation\n return 0.5;\n }\n return (x - this.#min) / width;\n }\n }\n\n if (x <= this.#min) {\n return 0;\n }\n if (x >= this.#max) {\n return 1;\n }\n const m0 = this.#means[0];\n // Left Tail\n if (x <= m0) {\n if (m0 - this.#min > 0) {\n return (\n (((x - this.#min) / (m0 - this.#min)) * this.#weights[0]) /\n this.#processedWeight /\n 2\n );\n }\n return 0;\n }\n // Right Tail\n // oxlint-disable-next-line typescript/no-non-null-assertion\n const mn = this.#means.at(-1)!;\n if (x >= mn) {\n if (this.#max - mn > 0) {\n return (\n 1 -\n (((this.#max - x) / (this.#max - mn)) *\n // oxlint-disable-next-line typescript/no-non-null-assertion\n this.#weights.at(-1)!) /\n this.#processedWeight /\n 2\n );\n }\n return 1;\n }\n\n const upper = binarySearch(\n this.#means.length,\n // Treat equals as greater than, so we can use the upper index\n // This is equivalent to:\n // i => this.#means[i] > x ? -1 : 1,\n i => x - this.#means[i] || 1,\n );\n\n const z1 = x - this.#means[upper - 1];\n const z2 = this.#means[upper] - x;\n return (\n weightedAverage(\n this.#cumulative[upper - 1],\n z2,\n this.#cumulative[upper],\n z1,\n ) / this.#processedWeight\n );\n }\n\n #integratedQ(k: number): number {\n return (\n (Math.sin(\n (Math.min(k, this.compression) * Math.PI) / this.compression -\n Math.PI / 2,\n ) +\n 1) /\n 2\n );\n }\n\n #integratedLocation(q: number): number {\n return (this.compression * (Math.asin(2 * q - 1) + Math.PI / 2)) / Math.PI;\n }\n}\n\nfunction isSorted(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] < values[i - 1]) {\n return false;\n }\n }\n return true;\n}\n\nfunction allEqual(values: Float64Array): boolean {\n for (let i = 1; i < values.length; i++) {\n if (values[i] !== values[0]) {\n return false;\n }\n }\n return true;\n}\n\nfunction weightedAverage(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n if (x1 <= x2) {\n return weightedAverageSorted(x1, w1, x2, w2);\n }\n return weightedAverageSorted(x2, w2, x1, w1);\n}\n\nfunction weightedAverageSorted(\n x1: number,\n w1: number,\n x2: number,\n w2: number,\n): number {\n const x = (x1 * w1 + x2 * w2) / (w1 + w2);\n return Math.max(x1, Math.min(x, x2));\n}\n\nfunction unprocessedSize(size: number, compression: number): number {\n if (size === 0) {\n return Math.ceil(compression) * 8;\n }\n return size;\n}\n"],"mappings":"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"}
|
package/out/z2s/src/sql.d.ts
CHANGED
|
@@ -9,11 +9,7 @@ export declare function formatPgInternalConvert(sql: SQLQuery): {
|
|
|
9
9
|
text: string;
|
|
10
10
|
values: unknown[];
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
text: string;
|
|
14
|
-
values: unknown[];
|
|
15
|
-
};
|
|
16
|
-
export type LiteralType = 'boolean' | 'number' | 'string' | 'null';
|
|
12
|
+
type LiteralType = 'boolean' | 'number' | 'string' | 'null';
|
|
17
13
|
export type PluralLiteralType = Exclude<LiteralType, 'null'>;
|
|
18
14
|
export declare function sqlConvertSingularLiteralArg(value: string | boolean | number | null): SQLQuery;
|
|
19
15
|
export declare function sqlConvertPluralLiteralArg(type: PluralLiteralType, value: PluralLiteralType[]): SQLQuery;
|
package/out/z2s/src/sql.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../../../z2s/src/sql.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../../../../z2s/src/sql.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAwB,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AACpE,OAAO,GAAkB,MAAM,gBAAgB,CAAC;AAWhD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,uCAAuC,CAAC;AAE9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,QAAQ;UAsR9B,MAAM;YACJ,OAAO,EAAE;EApRlB;AAED,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,QAAQ;UAiR7C,MAAM;YACJ,OAAO,EAAE;EA/QlB;AAID,KAAK,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAC5D,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAwB7D,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,GACtC,QAAQ,CAQV;AAED,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,iBAAiB,EACvB,KAAK,EAAE,iBAAiB,EAAE,GACzB,QAAQ,CAQV;AAED,wBAAgB,mBAAmB,CACjC,kBAAkB,EAAE,kBAAkB,EACtC,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,OAAO,EACf,YAAY,EAAE,OAAO,GACpB,QAAQ,CASV;AAgMD,OAAO,EAAC,GAAG,EAAC,CAAC"}
|
package/out/z2s/src/sql.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql.js","names":[],"sources":["../../../../z2s/src/sql.ts"],"sourcesContent":["import {\n escapePostgresIdentifier,\n escapeSQLiteIdentifier,\n} from '@databases/escape-identifier';\nimport type {FormatConfig, SQLItem, SQLQuery} from '@databases/sql';\nimport sql, {SQLItemType} from '@databases/sql';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {getOrInsertComputed} from '../../shared/src/map.ts';\nimport {\n isPgBpcharType,\n isPgNativeStringType,\n isPgNumberType,\n isPgStringType,\n isPgTextRepresentedType,\n} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {LiteralValue} from '../../zero-protocol/src/ast.ts';\nimport type {ServerColumnSchema} from '../../zero-types/src/server-schema.ts';\n\nexport function formatPg(sql: SQLQuery) {\n const format = new ReusingFormat(escapePostgresIdentifier);\n return sql.format((items: readonly SQLItem[]) => formatFn(items, format));\n}\n\nexport function formatPgInternalConvert(sql: SQLQuery) {\n const format = new SQLConvertFormat(escapePostgresIdentifier);\n return sql.format((items: readonly SQLItem[]) => formatFn(items, format));\n}\n\nexport function formatSqlite(sql: SQLQuery) {\n const format = new ReusingFormat(escapeSQLiteIdentifier);\n return sql.format((items: readonly SQLItem[]) => formatFn(items, format));\n}\n\nconst sqlConvert = Symbol('fromJson');\n\nexport type LiteralType = 'boolean' | 'number' | 'string' | 'null';\nexport type PluralLiteralType = Exclude<LiteralType, 'null'>;\n\ntype ColumnSqlConvertArg = {\n [sqlConvert]: 'column';\n type: string;\n value: unknown;\n plural: boolean;\n isEnum: boolean;\n isComparison: boolean;\n};\n\ntype SqlConvertArg =\n | ColumnSqlConvertArg\n | {\n [sqlConvert]: 'literal';\n type: LiteralType;\n value: LiteralValue;\n plural: boolean;\n };\n\nfunction isSqlConvert(value: unknown): value is SqlConvertArg {\n return value !== null && typeof value === 'object' && sqlConvert in value;\n}\n\nexport function sqlConvertSingularLiteralArg(\n value: string | boolean | number | null,\n): SQLQuery {\n const arg: SqlConvertArg = {\n [sqlConvert]: 'literal',\n type: value === null ? 'null' : (typeof value as LiteralType),\n value,\n plural: false,\n };\n return sql.value(arg);\n}\n\nexport function sqlConvertPluralLiteralArg(\n type: PluralLiteralType,\n value: PluralLiteralType[],\n): SQLQuery {\n const arg: SqlConvertArg = {\n [sqlConvert]: 'literal',\n type,\n value,\n plural: true,\n };\n return sql.value(arg);\n}\n\nexport function sqlConvertColumnArg(\n serverColumnSchema: ServerColumnSchema,\n value: unknown,\n plural: boolean,\n isComparison: boolean,\n): SQLQuery {\n return sql.value({\n [sqlConvert]: 'column',\n type: serverColumnSchema.type,\n isEnum: serverColumnSchema.isEnum,\n value,\n plural: plural || serverColumnSchema.isArray,\n isComparison,\n });\n}\n\nclass ReusingFormat implements FormatConfig {\n readonly #seen: Map<unknown, number> = new Map();\n readonly escapeIdentifier: (str: string) => string;\n\n constructor(escapeIdentifier: (str: string) => string) {\n this.escapeIdentifier = escapeIdentifier;\n }\n\n formatValue = (value: unknown) => {\n if (this.#seen.has(value)) {\n return {\n placeholder: `$${this.#seen.get(value)}`,\n value: PREVIOUSLY_SEEN_VALUE,\n };\n }\n this.#seen.set(value, this.#seen.size + 1);\n return {placeholder: `$${this.#seen.size}`, value};\n };\n}\n\nfunction stringify(arg: SqlConvertArg): string | null {\n if (arg.value === null) {\n return null;\n }\n if (arg.plural) {\n return JSON.stringify(arg.value);\n }\n if (arg[sqlConvert] === 'literal' && arg.type === 'string') {\n return arg.value as unknown as string;\n }\n if (\n arg[sqlConvert] === 'column' &&\n (arg.isEnum || isPgStringType(arg.type))\n ) {\n return arg.value as string;\n }\n return JSON.stringify(arg.value);\n}\n\nclass SQLConvertFormat implements FormatConfig {\n readonly #seen: Map<unknown, Map<string, number>> = new Map();\n #size = 0;\n readonly escapeIdentifier: (str: string) => string;\n\n constructor(escapeIdentifier: (str: string) => string) {\n this.escapeIdentifier = escapeIdentifier;\n }\n\n formatValue = (value: unknown) => {\n assert(isSqlConvert(value), 'JsonPackedFormat can only take JsonPackArgs.');\n const byType = this.#seen.get(value.value);\n if (byType?.has(value.type)) {\n return {\n placeholder: createPlaceholder(byType.get(value.type)!, value),\n value: PREVIOUSLY_SEEN_VALUE,\n };\n }\n this.#size++;\n if (byType) {\n byType.set(value.type, this.#size);\n } else {\n this.#seen.set(value.value, new Map([[value.type, this.#size]]));\n }\n return {\n placeholder: createPlaceholder(this.#size, value),\n value: stringify(value),\n };\n };\n}\n\nfunction createPlaceholder(index: number, arg: SqlConvertArg) {\n if (arg.type === 'null') {\n assert(arg.value === null, \"Args of type 'null' must have value null\");\n assert(!arg.plural, \"Args of type 'null' must not be plural\");\n return `$${index}`;\n }\n\n if (arg.value === null && arg.plural) {\n return `$${index}`;\n }\n\n if (arg[sqlConvert] === 'literal') {\n const {value} = arg;\n if (Array.isArray(value)) {\n const elType = pgTypeForLiteralType(arg.type);\n return formatPlural(index, `value::${elType}`);\n }\n const type = pgTypeForLiteralType(arg.type);\n return `$${index}::text${type === 'text' ? '' : `::${type}`}`;\n }\n\n const common = formatCommonToSingularAndPlural(index, arg);\n return arg.plural ? formatPlural(index, common) : common;\n}\n\nfunction formatCommonToSingularAndPlural(\n index: number,\n arg: ColumnSqlConvertArg,\n) {\n // Ok, so what is with all the `::text` casts\n // before the final cast?\n // This is to force the statement to describe its arguments\n // as being text. Without the text cast the args are described as\n // being bool/json/numeric/whatever and the bindings try to coerce\n // the inputs to those types.\n const valuePlaceholder = arg.plural ? 'value' : `$${index}`;\n let atTimeZone = ` AT TIME ZONE 'UTC'`;\n switch (arg.type) {\n case 'timestamptz':\n // @ts-expect-error Fallthrough intended\n case 'timestamp with time zone':\n atTimeZone = '';\n // fallthrough\n\n case 'date':\n case 'timestamp':\n case 'timestamp without time zone':\n return `to_timestamp(${valuePlaceholder}::text::numeric / 1000.0)${atTimeZone}`;\n\n case 'timetz':\n // @ts-expect-error Fallthrough intended\n case 'time with time zone':\n atTimeZone = '';\n // fallthrough\n\n case 'time':\n case 'time without time zone':\n return `(${valuePlaceholder}::text::int * interval'1ms')::time${atTimeZone}`;\n\n // uuid: cast to native uuid type for proper comparison and index usage\n case 'uuid':\n return `${valuePlaceholder}::text::uuid`;\n }\n if (arg.isEnum) {\n return `${valuePlaceholder}::text::\"${arg.type}\"`;\n }\n if (isPgNativeStringType(arg.type)) {\n if (!arg.isComparison) {\n return `${valuePlaceholder}::text::${arg.type}`;\n }\n // For comparison cast to an unbounded type, not the specific column\n // type (i.e. `arg.type`), because we don't want to force the value\n // being compared to the size/max-size of the column type before\n // comparison.\n //\n // For `char(n)` that is `bpchar` (not `character`, which means\n // `char(1)`), not `text`: Postgres compares `bpchar` to `text` by\n // casting the column to `text`, which prevents it from using the\n // column's indexes.\n // https://www.postgresql.org/docs/current/datatype-character.html\n return `${valuePlaceholder}::text${isPgBpcharType(arg.type) ? '::bpchar' : ''}`;\n }\n if (isPgTextRepresentedType(arg.type)) {\n return `${valuePlaceholder}::text::${arg.type}`;\n }\n if (isPgNumberType(arg.type)) {\n // For comparison cast to `double precision` which uses IEEE 754 (the same\n // representation as JavaScript numbers which will accurately\n // represent any number value from zql) not the specific column type\n // (i.e. `arg.type`), because we don't want to force the value being\n // compared to the range and precision of the column type before comparison.\n return arg.isComparison\n ? `${valuePlaceholder}::text::double precision`\n : `${valuePlaceholder}::text::${arg.type}`;\n }\n return `${valuePlaceholder}::text::${arg.type}`;\n}\n\nfunction formatPlural(index: number, select: string) {\n return `ARRAY(\n SELECT ${select} FROM jsonb_array_elements_text($${index}::text::jsonb)\n )`;\n}\n\nfunction pgTypeForLiteralType(type: Exclude<LiteralType, 'null'>) {\n switch (type) {\n case 'boolean':\n return 'boolean';\n case 'number':\n // `double precision` uses IEEE 754, the same representation as JavaScript\n // numbers, and so this will accurately represent any number value\n // from zql\n return 'double precision';\n case 'string':\n return 'text';\n default:\n unreachable(type);\n }\n}\n\nexport {sql};\n\nconst PREVIOUSLY_SEEN_VALUE = Symbol('PREVIOUSLY_SEEN_VALUE');\n\nconst whitespacePrefixRe = /^\\s*/;\n\nfunction formatFn(\n items: readonly SQLItem[],\n {escapeIdentifier, formatValue}: FormatConfig,\n): {\n text: string;\n values: unknown[];\n} {\n // Create an empty query object.\n let text = '';\n const values = [];\n\n const localIdentifiers = new Map<unknown, string>();\n\n for (const item of items) {\n switch (item.type) {\n // If this is just raw text, we add it directly to the query text.\n case SQLItemType.RAW: {\n text += item.text;\n break;\n }\n\n // If we got a value SQL item, add a placeholder and add the value to our\n // placeholder values array.\n case SQLItemType.VALUE: {\n const {placeholder, value} = formatValue(item.value, values.length);\n text += placeholder;\n if (value !== PREVIOUSLY_SEEN_VALUE) {\n values.push(value);\n }\n\n break;\n }\n\n // If we got an identifier type, escape the strings and get a local\n // identifier for non-string identifiers.\n case SQLItemType.IDENTIFIER: {\n // This is a specific addition for Zero as Zero\n // does not support dots in identifiers.\n // If a dot is found, we assume it is a namespace\n // and split the identifier into its parts.\n const names =\n item.names.length === 1 &&\n typeof item.names[0] === 'string' &&\n item.names[0].includes('.')\n ? item.names[0].split('.')\n : item.names;\n\n text += names\n .map((name): string => {\n if (typeof name === 'string') return escapeIdentifier(name);\n\n return escapeIdentifier(\n getOrInsertComputed(\n localIdentifiers,\n name,\n () => `__local_${localIdentifiers.size}__`,\n ),\n );\n })\n .join('.');\n break;\n }\n }\n }\n\n if (text.trim()) {\n const lines = text.split('\\n');\n const min = Math.min(\n ...lines\n .filter(l => l.trim() !== '')\n .map(l => whitespacePrefixRe.exec(l)![0].length),\n );\n if (min) {\n text = lines.map(line => line.substr(min)).join('\\n');\n }\n }\n return {\n text: text.trim(),\n values,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sql.js","names":[],"sources":["../../../../z2s/src/sql.ts"],"sourcesContent":["import {escapePostgresIdentifier} from '@databases/escape-identifier';\nimport type {FormatConfig, SQLItem, SQLQuery} from '@databases/sql';\nimport sql, {SQLItemType} from '@databases/sql';\nimport {assert, unreachable} from '../../shared/src/asserts.ts';\nimport {getOrInsertComputed} from '../../shared/src/map.ts';\nimport {\n isPgBpcharType,\n isPgNativeStringType,\n isPgNumberType,\n isPgStringType,\n isPgTextRepresentedType,\n} from '../../zero-cache/src/types/pg-data-type.ts';\nimport type {LiteralValue} from '../../zero-protocol/src/ast.ts';\nimport type {ServerColumnSchema} from '../../zero-types/src/server-schema.ts';\n\nexport function formatPg(sql: SQLQuery) {\n const format = new ReusingFormat(escapePostgresIdentifier);\n return sql.format((items: readonly SQLItem[]) => formatFn(items, format));\n}\n\nexport function formatPgInternalConvert(sql: SQLQuery) {\n const format = new SQLConvertFormat(escapePostgresIdentifier);\n return sql.format((items: readonly SQLItem[]) => formatFn(items, format));\n}\n\nconst sqlConvert = Symbol('fromJson');\n\ntype LiteralType = 'boolean' | 'number' | 'string' | 'null';\nexport type PluralLiteralType = Exclude<LiteralType, 'null'>;\n\ntype ColumnSqlConvertArg = {\n [sqlConvert]: 'column';\n type: string;\n value: unknown;\n plural: boolean;\n isEnum: boolean;\n isComparison: boolean;\n};\n\ntype SqlConvertArg =\n | ColumnSqlConvertArg\n | {\n [sqlConvert]: 'literal';\n type: LiteralType;\n value: LiteralValue;\n plural: boolean;\n };\n\nfunction isSqlConvert(value: unknown): value is SqlConvertArg {\n return value !== null && typeof value === 'object' && sqlConvert in value;\n}\n\nexport function sqlConvertSingularLiteralArg(\n value: string | boolean | number | null,\n): SQLQuery {\n const arg: SqlConvertArg = {\n [sqlConvert]: 'literal',\n type: value === null ? 'null' : (typeof value as LiteralType),\n value,\n plural: false,\n };\n return sql.value(arg);\n}\n\nexport function sqlConvertPluralLiteralArg(\n type: PluralLiteralType,\n value: PluralLiteralType[],\n): SQLQuery {\n const arg: SqlConvertArg = {\n [sqlConvert]: 'literal',\n type,\n value,\n plural: true,\n };\n return sql.value(arg);\n}\n\nexport function sqlConvertColumnArg(\n serverColumnSchema: ServerColumnSchema,\n value: unknown,\n plural: boolean,\n isComparison: boolean,\n): SQLQuery {\n return sql.value({\n [sqlConvert]: 'column',\n type: serverColumnSchema.type,\n isEnum: serverColumnSchema.isEnum,\n value,\n plural: plural || serverColumnSchema.isArray,\n isComparison,\n });\n}\n\nclass ReusingFormat implements FormatConfig {\n readonly #seen: Map<unknown, number> = new Map();\n readonly escapeIdentifier: (str: string) => string;\n\n constructor(escapeIdentifier: (str: string) => string) {\n this.escapeIdentifier = escapeIdentifier;\n }\n\n formatValue = (value: unknown) => {\n if (this.#seen.has(value)) {\n return {\n placeholder: `$${this.#seen.get(value)}`,\n value: PREVIOUSLY_SEEN_VALUE,\n };\n }\n this.#seen.set(value, this.#seen.size + 1);\n return {placeholder: `$${this.#seen.size}`, value};\n };\n}\n\nfunction stringify(arg: SqlConvertArg): string | null {\n if (arg.value === null) {\n return null;\n }\n if (arg.plural) {\n return JSON.stringify(arg.value);\n }\n if (arg[sqlConvert] === 'literal' && arg.type === 'string') {\n return arg.value as unknown as string;\n }\n if (\n arg[sqlConvert] === 'column' &&\n (arg.isEnum || isPgStringType(arg.type))\n ) {\n return arg.value as string;\n }\n return JSON.stringify(arg.value);\n}\n\nclass SQLConvertFormat implements FormatConfig {\n readonly #seen: Map<unknown, Map<string, number>> = new Map();\n #size = 0;\n readonly escapeIdentifier: (str: string) => string;\n\n constructor(escapeIdentifier: (str: string) => string) {\n this.escapeIdentifier = escapeIdentifier;\n }\n\n formatValue = (value: unknown) => {\n assert(isSqlConvert(value), 'JsonPackedFormat can only take JsonPackArgs.');\n const byType = this.#seen.get(value.value);\n if (byType?.has(value.type)) {\n return {\n placeholder: createPlaceholder(byType.get(value.type)!, value),\n value: PREVIOUSLY_SEEN_VALUE,\n };\n }\n this.#size++;\n if (byType) {\n byType.set(value.type, this.#size);\n } else {\n this.#seen.set(value.value, new Map([[value.type, this.#size]]));\n }\n return {\n placeholder: createPlaceholder(this.#size, value),\n value: stringify(value),\n };\n };\n}\n\nfunction createPlaceholder(index: number, arg: SqlConvertArg) {\n if (arg.type === 'null') {\n assert(arg.value === null, \"Args of type 'null' must have value null\");\n assert(!arg.plural, \"Args of type 'null' must not be plural\");\n return `$${index}`;\n }\n\n if (arg.value === null && arg.plural) {\n return `$${index}`;\n }\n\n if (arg[sqlConvert] === 'literal') {\n const {value} = arg;\n if (Array.isArray(value)) {\n const elType = pgTypeForLiteralType(arg.type);\n return formatPlural(index, `value::${elType}`);\n }\n const type = pgTypeForLiteralType(arg.type);\n return `$${index}::text${type === 'text' ? '' : `::${type}`}`;\n }\n\n const common = formatCommonToSingularAndPlural(index, arg);\n return arg.plural ? formatPlural(index, common) : common;\n}\n\nfunction formatCommonToSingularAndPlural(\n index: number,\n arg: ColumnSqlConvertArg,\n) {\n // Ok, so what is with all the `::text` casts\n // before the final cast?\n // This is to force the statement to describe its arguments\n // as being text. Without the text cast the args are described as\n // being bool/json/numeric/whatever and the bindings try to coerce\n // the inputs to those types.\n const valuePlaceholder = arg.plural ? 'value' : `$${index}`;\n let atTimeZone = ` AT TIME ZONE 'UTC'`;\n switch (arg.type) {\n case 'timestamptz':\n // @ts-expect-error Fallthrough intended\n case 'timestamp with time zone':\n atTimeZone = '';\n // fallthrough\n\n case 'date':\n case 'timestamp':\n case 'timestamp without time zone':\n return `to_timestamp(${valuePlaceholder}::text::numeric / 1000.0)${atTimeZone}`;\n\n case 'timetz':\n // @ts-expect-error Fallthrough intended\n case 'time with time zone':\n atTimeZone = '';\n // fallthrough\n\n case 'time':\n case 'time without time zone':\n return `(${valuePlaceholder}::text::int * interval'1ms')::time${atTimeZone}`;\n\n // uuid: cast to native uuid type for proper comparison and index usage\n case 'uuid':\n return `${valuePlaceholder}::text::uuid`;\n }\n if (arg.isEnum) {\n return `${valuePlaceholder}::text::\"${arg.type}\"`;\n }\n if (isPgNativeStringType(arg.type)) {\n if (!arg.isComparison) {\n return `${valuePlaceholder}::text::${arg.type}`;\n }\n // For comparison cast to an unbounded type, not the specific column\n // type (i.e. `arg.type`), because we don't want to force the value\n // being compared to the size/max-size of the column type before\n // comparison.\n //\n // For `char(n)` that is `bpchar` (not `character`, which means\n // `char(1)`), not `text`: Postgres compares `bpchar` to `text` by\n // casting the column to `text`, which prevents it from using the\n // column's indexes.\n // https://www.postgresql.org/docs/current/datatype-character.html\n return `${valuePlaceholder}::text${isPgBpcharType(arg.type) ? '::bpchar' : ''}`;\n }\n if (isPgTextRepresentedType(arg.type)) {\n return `${valuePlaceholder}::text::${arg.type}`;\n }\n if (isPgNumberType(arg.type)) {\n // For comparison cast to `double precision` which uses IEEE 754 (the same\n // representation as JavaScript numbers which will accurately\n // represent any number value from zql) not the specific column type\n // (i.e. `arg.type`), because we don't want to force the value being\n // compared to the range and precision of the column type before comparison.\n return arg.isComparison\n ? `${valuePlaceholder}::text::double precision`\n : `${valuePlaceholder}::text::${arg.type}`;\n }\n return `${valuePlaceholder}::text::${arg.type}`;\n}\n\nfunction formatPlural(index: number, select: string) {\n return `ARRAY(\n SELECT ${select} FROM jsonb_array_elements_text($${index}::text::jsonb)\n )`;\n}\n\nfunction pgTypeForLiteralType(type: Exclude<LiteralType, 'null'>) {\n switch (type) {\n case 'boolean':\n return 'boolean';\n case 'number':\n // `double precision` uses IEEE 754, the same representation as JavaScript\n // numbers, and so this will accurately represent any number value\n // from zql\n return 'double precision';\n case 'string':\n return 'text';\n default:\n unreachable(type);\n }\n}\n\nexport {sql};\n\nconst PREVIOUSLY_SEEN_VALUE = Symbol('PREVIOUSLY_SEEN_VALUE');\n\nconst whitespacePrefixRe = /^\\s*/;\n\nfunction formatFn(\n items: readonly SQLItem[],\n {escapeIdentifier, formatValue}: FormatConfig,\n): {\n text: string;\n values: unknown[];\n} {\n // Create an empty query object.\n let text = '';\n const values = [];\n\n const localIdentifiers = new Map<unknown, string>();\n\n for (const item of items) {\n switch (item.type) {\n // If this is just raw text, we add it directly to the query text.\n case SQLItemType.RAW: {\n text += item.text;\n break;\n }\n\n // If we got a value SQL item, add a placeholder and add the value to our\n // placeholder values array.\n case SQLItemType.VALUE: {\n const {placeholder, value} = formatValue(item.value, values.length);\n text += placeholder;\n if (value !== PREVIOUSLY_SEEN_VALUE) {\n values.push(value);\n }\n\n break;\n }\n\n // If we got an identifier type, escape the strings and get a local\n // identifier for non-string identifiers.\n case SQLItemType.IDENTIFIER: {\n // This is a specific addition for Zero as Zero\n // does not support dots in identifiers.\n // If a dot is found, we assume it is a namespace\n // and split the identifier into its parts.\n const names =\n item.names.length === 1 &&\n typeof item.names[0] === 'string' &&\n item.names[0].includes('.')\n ? item.names[0].split('.')\n : item.names;\n\n text += names\n .map((name): string => {\n if (typeof name === 'string') return escapeIdentifier(name);\n\n return escapeIdentifier(\n getOrInsertComputed(\n localIdentifiers,\n name,\n () => `__local_${localIdentifiers.size}__`,\n ),\n );\n })\n .join('.');\n break;\n }\n }\n }\n\n if (text.trim()) {\n const lines = text.split('\\n');\n const min = Math.min(\n ...lines\n .filter(l => l.trim() !== '')\n .map(l => whitespacePrefixRe.exec(l)![0].length),\n );\n if (min) {\n text = lines.map(line => line.substr(min)).join('\\n');\n }\n }\n return {\n text: text.trim(),\n values,\n };\n}\n"],"mappings":"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"}
|
package/out/zero/package.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region package.json
|
|
2
2
|
var name = "@rocicorp/zero";
|
|
3
|
-
var version = "1.12.0-canary.
|
|
3
|
+
var version = "1.12.0-canary.9";
|
|
4
4
|
var description = "Zero is a web framework for serverless web development.";
|
|
5
5
|
var homepage = "https://zero.rocicorp.dev";
|
|
6
6
|
var bugs = { "url": "https://bugs.rocicorp.dev" };
|
|
@@ -132,9 +132,8 @@ var dependencies = {
|
|
|
132
132
|
"@opentelemetry/sdk-trace-node": "2.12.0",
|
|
133
133
|
"@opentelemetry/semantic-conventions": "1.43.0",
|
|
134
134
|
"@postgresql-typed/oids": "^0.2.0",
|
|
135
|
-
"@rocicorp/lock": "^
|
|
135
|
+
"@rocicorp/lock": "^2.0.1",
|
|
136
136
|
"@rocicorp/logger": "^6.1.0",
|
|
137
|
-
"@rocicorp/resolver": "^1.0.2",
|
|
138
137
|
"@rocicorp/zero-sqlite3": "^1.1.7",
|
|
139
138
|
"@standard-schema/spec": "^1.1.0",
|
|
140
139
|
"@types/basic-auth": "^1.1.8",
|
package/out/zero/package.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.12.0-canary.
|
|
1
|
+
{"version":3,"file":"package.js","names":[],"sources":["../../package.json"],"sourcesContent":["{\n \"name\": \"@rocicorp/zero\",\n \"version\": \"1.12.0-canary.9\",\n \"description\": \"Zero is a web framework for serverless web development.\",\n \"homepage\": \"https://zero.rocicorp.dev\",\n \"bugs\": {\n \"url\": \"https://bugs.rocicorp.dev\"\n },\n \"license\": \"Apache-2.0\",\n \"author\": \"Rocicorp, Inc.\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/rocicorp/mono.git\",\n \"directory\": \"packages/zero\"\n },\n \"bin\": {\n \"ast-to-zql\": \"./out/zero/src/ast-to-zql.js\",\n \"transform-query\": \"./out/zero/src/transform-query.js\",\n \"zero-build-schema\": \"./out/zero/src/build-schema.js\",\n \"zero-cache\": \"./out/zero/src/cli.js\",\n \"zero-cache-dev\": \"./out/zero/src/zero-cache-dev.js\",\n \"zero-deploy-permissions\": \"./out/zero/src/deploy-permissions.js\",\n \"zero-out\": \"./out/zero/src/zero-out.js\"\n },\n \"files\": [\n \"out\",\n \"!*.tsbuildinfo\"\n ],\n \"type\": \"module\",\n \"main\": \"out/zero/src/zero.js\",\n \"module\": \"out/zero/src/zero.js\",\n \"types\": \"out/zero/src/zero.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./out/zero/src/zero.d.ts\",\n \"default\": \"./out/zero/src/zero.js\"\n },\n \"./analyze\": {\n \"types\": \"./out/zero/src/analyze.d.ts\",\n \"default\": \"./out/zero/src/analyze.js\"\n },\n \"./bindings\": {\n \"types\": \"./out/zero/src/bindings.d.ts\",\n \"default\": \"./out/zero/src/bindings.js\"\n },\n \"./change-protocol/v0\": {\n \"types\": \"./out/zero/src/change-protocol/v0.d.ts\",\n \"default\": \"./out/zero/src/change-protocol/v0.js\"\n },\n \"./expo-sqlite\": {\n \"types\": \"./out/zero/src/expo-sqlite.d.ts\",\n \"default\": \"./out/zero/src/expo-sqlite.js\"\n },\n \"./op-sqlite\": {\n \"types\": \"./out/zero/src/op-sqlite.d.ts\",\n \"default\": \"./out/zero/src/op-sqlite.js\"\n },\n \"./pg\": {\n \"types\": \"./out/zero/src/pg.d.ts\",\n \"default\": \"./out/zero/src/pg.js\"\n },\n \"./react\": {\n \"types\": \"./out/zero/src/react.d.ts\",\n \"default\": \"./out/zero/src/react.js\"\n },\n \"./react-native\": {\n \"types\": \"./out/zero/src/react-native.d.ts\",\n \"default\": \"./out/zero/src/react-native.js\"\n },\n \"./server\": {\n \"types\": \"./out/zero/src/server.d.ts\",\n \"default\": \"./out/zero/src/server.js\"\n },\n \"./server/adapters/drizzle\": {\n \"types\": \"./out/zero/src/adapters/drizzle.d.ts\",\n \"default\": \"./out/zero/src/adapters/drizzle.js\"\n },\n \"./server/adapters/kysely\": {\n \"types\": \"./out/zero/src/adapters/kysely.d.ts\",\n \"default\": \"./out/zero/src/adapters/kysely.js\"\n },\n \"./server/adapters/prisma\": {\n \"types\": \"./out/zero/src/adapters/prisma.d.ts\",\n \"default\": \"./out/zero/src/adapters/prisma.js\"\n },\n \"./server/adapters/pg\": {\n \"types\": \"./out/zero/src/adapters/pg.d.ts\",\n \"default\": \"./out/zero/src/adapters/pg.js\"\n },\n \"./server/adapters/postgresjs\": {\n \"types\": \"./out/zero/src/adapters/postgresjs.d.ts\",\n \"default\": \"./out/zero/src/adapters/postgresjs.js\"\n },\n \"./solid\": {\n \"types\": \"./out/zero/src/solid.d.ts\",\n \"default\": \"./out/zero/src/solid.js\"\n },\n \"./sqlite\": {\n \"types\": \"./out/zero/src/sqlite.d.ts\",\n \"default\": \"./out/zero/src/sqlite.js\"\n },\n \"./zqlite\": {\n \"types\": \"./out/zero/src/zqlite.d.ts\",\n \"default\": \"./out/zero/src/zqlite.js\"\n }\n },\n \"scripts\": {\n \"build\": \"node --experimental-strip-types --no-warnings tool/build.ts\",\n \"build:watch\": \"node --experimental-strip-types --no-warnings tool/build.ts --watch\",\n \"check-types\": \"tsc -p tsconfig.client.json && tsc -p tsconfig.server.json\",\n \"check-types:client:watch\": \"tsc -p tsconfig.client.json --watch\",\n \"check-types:server:watch\": \"tsc -p tsconfig.server.json --watch\",\n \"format\": \"oxfmt .\",\n \"check-format\": \"oxfmt --check .\",\n \"lint\": \"oxlint --quiet --config ../../oxlint.config.ts src/\",\n \"docs\": \"node --experimental-strip-types --no-warnings tool/generate-docs.ts\",\n \"docs:server\": \"node --watch --experimental-strip-types --no-warnings tool/generate-docs.ts --server\",\n \"fmt\": \"oxfmt .\",\n \"check-fmt\": \"oxfmt --check .\"\n },\n \"dependencies\": {\n \"@badrap/valita\": \"0.5.5\",\n \"@databases/escape-identifier\": \"^1.0.3\",\n \"@databases/sql\": \"^3.3.0\",\n \"@dotenvx/dotenvx\": \"^1.66.0\",\n \"@drdgvhbh/postgres-error-codes\": \"^0.0.6\",\n \"@fastify/cors\": \"^10.1.0\",\n \"@fastify/websocket\": \"^11.2.0\",\n \"@google-cloud/precise-date\": \"^4.0.0\",\n \"@opentelemetry/api\": \"1.9.1\",\n \"@opentelemetry/api-logs\": \"0.223.0\",\n \"@opentelemetry/auto-instrumentations-node\": \"0.81.2\",\n \"@opentelemetry/exporter-metrics-otlp-http\": \"0.223.0\",\n \"@opentelemetry/resources\": \"2.12.0\",\n \"@opentelemetry/sdk-metrics\": \"2.12.0\",\n \"@opentelemetry/sdk-node\": \"0.223.0\",\n \"@opentelemetry/sdk-trace-node\": \"2.12.0\",\n \"@opentelemetry/semantic-conventions\": \"1.43.0\",\n \"@postgresql-typed/oids\": \"^0.2.0\",\n \"@rocicorp/lock\": \"^2.0.1\",\n \"@rocicorp/logger\": \"^6.1.0\",\n \"@rocicorp/zero-sqlite3\": \"^1.1.7\",\n \"@standard-schema/spec\": \"^1.1.0\",\n \"@types/basic-auth\": \"^1.1.8\",\n \"@types/ws\": \"^8.18.1\",\n \"basic-auth\": \"^2.0.1\",\n \"chalk-template\": \"^1.1.2\",\n \"chokidar\": \"^4.0.3\",\n \"cloudevents\": \"^10.0.0\",\n \"command-line-args\": \"^6.0.2\",\n \"command-line-usage\": \"^7.0.4\",\n \"compare-utf8\": \"^0.2.3\",\n \"defu\": \"^6.1.7\",\n \"eventemitter3\": \"^5.0.4\",\n \"fastify\": \"^5.12.7\",\n \"is-in-subnet\": \"^4.0.1\",\n \"jose\": \"^5.10.0\",\n \"json-custom-numbers\": \"^3.1.1\",\n \"kasi\": \"^1.1.2\",\n \"nanoid\": \"^5.1.16\",\n \"oxc-parser\": \"^0.129.0\",\n \"oxfmt\": \"^0.74.0\",\n \"parse-prometheus-text-format\": \"^1.1.1\",\n \"pg-format\": \"npm:pg-format-fix@^1.0.5\",\n \"postgres\": \"3.4.7\",\n \"semver\": \"^7.8.0\",\n \"url-pattern\": \"^1.0.3\",\n \"urlpattern-polyfill\": \"^10.1.0\",\n \"ws\": \"^8.22.0\"\n },\n \"devDependencies\": {\n \"@op-engineering/op-sqlite\": \"^18.2.5\",\n \"analyze-query\": \"workspace:*\",\n \"ast-to-zql\": \"workspace:*\",\n \"expo\": \"^58.0.14\",\n \"expo-sqlite\": \"^58.0.13\",\n \"react-native\": \"^0.88.0\",\n \"replicache\": \"workspace:*\",\n \"shared\": \"workspace:*\",\n \"syncpack\": \"^14.3.1\",\n \"typedoc\": \"^0.28.19\",\n \"typescript\": \"~7.0.2\",\n \"vite\": \"^8.3.4\",\n \"vitest\": \"^5.0.5\",\n \"zero-cache\": \"workspace:*\",\n \"zero-client\": \"workspace:*\",\n \"zero-pg\": \"workspace:*\",\n \"zero-react\": \"workspace:*\",\n \"zero-server\": \"workspace:*\",\n \"zero-solid\": \"workspace:*\",\n \"zqlite\": \"workspace:*\"\n },\n \"engines\": {\n \"node\": \">=22\"\n },\n \"packageManager\": \"pnpm@11.11.0\"\n}\n"],"mappings":""}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { resolver } from "../../shared/src/resolver.js";
|
|
2
3
|
import { valita_exports } from "../../shared/src/valita.js";
|
|
3
4
|
import "../../shared/src/dotenv.js";
|
|
4
5
|
import { createLogContext } from "../../shared/src/logging.js";
|
|
5
6
|
import { parseOptionsAdvanced } from "../../shared/src/options.js";
|
|
6
7
|
import { ZERO_ENV_VAR_PREFIX, zeroOptions } from "../../zero-cache/src/config/zero-config.js";
|
|
7
8
|
import { deployPermissionsOptions } from "../../zero-cache/src/scripts/permissions.js";
|
|
8
|
-
import { resolver } from "@rocicorp/resolver";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { watch } from "chokidar";
|
|
11
11
|
//#region src/zero-cache-dev.ts
|