@rocicorp/zero 0.24.2025102200 → 0.25.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/{chunk-PIXC6O7W.js → chunk-55BOUNXO.js} +3 -3
- package/out/chunk-55BOUNXO.js.map +7 -0
- package/out/{chunk-JS2ABYXG.js → chunk-AIPM77UE.js} +2762 -674
- package/out/chunk-AIPM77UE.js.map +7 -0
- package/out/{chunk-VHLCXJ6Q.js → chunk-TJFNGO7E.js} +4 -2
- package/out/{chunk-VHLCXJ6Q.js.map → chunk-TJFNGO7E.js.map} +2 -2
- package/out/{lazy-inspector-NCBESZMS.js → lazy-inspector-OXIFYSSQ.js} +2 -2
- package/out/react.js +16 -4
- package/out/react.js.map +4 -4
- package/out/replicache/src/dag/lazy-store.d.ts +1 -1
- package/out/replicache/src/dag/lazy-store.d.ts.map +1 -1
- package/out/replicache/src/log-options.d.ts +1 -1
- package/out/replicache/src/log-options.d.ts.map +1 -1
- package/out/replicache/src/persist/collect-idb-databases.d.ts +3 -3
- package/out/replicache/src/persist/collect-idb-databases.d.ts.map +1 -1
- package/out/replicache/src/replicache-options.d.ts +1 -1
- package/out/replicache/src/replicache-options.d.ts.map +1 -1
- package/out/shared/src/options.d.ts +1 -1
- package/out/shared/src/options.d.ts.map +1 -1
- package/out/shared/src/promise-race.d.ts +17 -0
- package/out/shared/src/promise-race.d.ts.map +1 -0
- package/out/solid.js +19 -6
- package/out/solid.js.map +4 -4
- package/out/z2s/src/compiler.d.ts +1 -1
- package/out/z2s/src/compiler.d.ts.map +1 -1
- package/out/z2s/src/compiler.js +1 -1
- package/out/z2s/src/compiler.js.map +1 -1
- package/out/z2s/src/sql.d.ts.map +1 -1
- package/out/z2s/src/sql.js +1 -1
- package/out/z2s/src/sql.js.map +1 -1
- package/out/zero/package.json +5 -4
- package/out/zero-cache/src/config/zero-config.d.ts +12 -0
- package/out/zero-cache/src/config/zero-config.d.ts.map +1 -1
- package/out/zero-cache/src/config/zero-config.js +36 -0
- package/out/zero-cache/src/config/zero-config.js.map +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +3 -1
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +101 -24
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts +2 -6
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +42 -41
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/db/create.d.ts +4 -0
- package/out/zero-cache/src/db/create.d.ts.map +1 -1
- package/out/zero-cache/src/db/create.js +7 -9
- package/out/zero-cache/src/db/create.js.map +1 -1
- package/out/zero-cache/src/db/lite-tables.d.ts.map +1 -1
- package/out/zero-cache/src/db/lite-tables.js +38 -17
- package/out/zero-cache/src/db/lite-tables.js.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.d.ts.map +1 -1
- package/out/zero-cache/src/db/pg-to-lite.js +7 -6
- package/out/zero-cache/src/db/pg-to-lite.js.map +1 -1
- package/out/zero-cache/src/db/specs.d.ts +24 -19
- package/out/zero-cache/src/db/specs.d.ts.map +1 -1
- package/out/zero-cache/src/db/specs.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +1 -1
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +5 -1
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +1 -1
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts +65 -0
- package/out/zero-cache/src/services/change-source/column-metadata.d.ts.map +1 -0
- package/out/zero-cache/src/services/change-source/column-metadata.js +198 -0
- package/out/zero-cache/src/services/change-source/column-metadata.js.map +1 -0
- package/out/zero-cache/src/services/change-source/pg/change-source.js +1 -0
- package/out/zero-cache/src/services/change-source/pg/change-source.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.d.ts +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js +1 -1
- package/out/zero-cache/src/services/change-source/pg/logical-replication/binary-reader.js.map +1 -1
- package/out/zero-cache/src/services/change-source/pg/schema/ddl.d.ts +25 -25
- package/out/zero-cache/src/services/change-source/pg/schema/published.d.ts +10 -10
- package/out/zero-cache/src/services/change-source/pg/schema/shard.d.ts +5 -5
- package/out/zero-cache/src/services/change-source/protocol/current/data.d.ts +16 -16
- package/out/zero-cache/src/services/change-source/protocol/current/downstream.d.ts +24 -24
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts +2 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +18 -2
- 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.d.ts +8 -8
- package/out/zero-cache/src/services/mutagen/mutagen.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/mutagen.js +9 -7
- package/out/zero-cache/src/services/mutagen/mutagen.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts +4 -4
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +74 -56
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts +3 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-handler.js +10 -6
- package/out/zero-cache/src/services/view-syncer/client-handler.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/client-schema.js +7 -4
- package/out/zero-cache/src/services/view-syncer/client-schema.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts +4 -4
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +15 -6
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +4 -2
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/key-columns.js +4 -2
- package/out/zero-cache/src/services/view-syncer/key-columns.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +2 -2
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +57 -27
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts +11 -6
- package/out/zero-cache/src/services/view-syncer/snapshotter.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/snapshotter.js +34 -22
- package/out/zero-cache/src/services/view-syncer/snapshotter.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +4 -4
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +111 -51
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts +9 -0
- package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -0
- package/out/zero-cache/src/types/error-with-level.js +24 -0
- package/out/zero-cache/src/types/error-with-level.js.map +1 -0
- package/out/zero-cache/src/types/lite.d.ts +15 -13
- package/out/zero-cache/src/types/lite.d.ts.map +1 -1
- package/out/zero-cache/src/types/lite.js +17 -5
- package/out/zero-cache/src/types/lite.js.map +1 -1
- package/out/zero-cache/src/types/pg-data-type.d.ts +73 -0
- package/out/zero-cache/src/types/pg-data-type.d.ts.map +1 -0
- package/out/zero-cache/src/types/pg-data-type.js +76 -0
- package/out/zero-cache/src/types/pg-data-type.js.map +1 -0
- package/out/zero-cache/src/types/pg.d.ts +1 -73
- package/out/zero-cache/src/types/pg.d.ts.map +1 -1
- package/out/zero-cache/src/types/pg.js +0 -77
- package/out/zero-cache/src/types/pg.js.map +1 -1
- package/out/zero-cache/src/types/processes.d.ts +1 -1
- package/out/zero-cache/src/types/processes.d.ts.map +1 -1
- package/out/zero-cache/src/types/processes.js.map +1 -1
- package/out/zero-cache/src/types/schema-versions.d.ts +7 -3
- package/out/zero-cache/src/types/schema-versions.d.ts.map +1 -1
- package/out/zero-cache/src/types/schema-versions.js +7 -5
- package/out/zero-cache/src/types/schema-versions.js.map +1 -1
- package/out/zero-cache/src/types/subscription.d.ts +1 -1
- package/out/zero-cache/src/types/subscription.js +1 -1
- package/out/zero-cache/src/types/websocket-handoff.d.ts +3 -3
- package/out/zero-cache/src/types/websocket-handoff.d.ts.map +1 -1
- package/out/zero-cache/src/types/websocket-handoff.js +6 -4
- package/out/zero-cache/src/types/websocket-handoff.js.map +1 -1
- package/out/zero-cache/src/workers/connection.d.ts +6 -1
- package/out/zero-cache/src/workers/connection.d.ts.map +1 -1
- package/out/zero-cache/src/workers/connection.js +26 -9
- package/out/zero-cache/src/workers/connection.js.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js +7 -1
- package/out/zero-cache/src/workers/syncer-ws-message-handler.js.map +1 -1
- package/out/zero-cache/src/workers/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/workers/syncer.js +21 -1
- package/out/zero-cache/src/workers/syncer.js.map +1 -1
- package/out/zero-client/src/client/client-error-kind-enum.d.ts +27 -0
- package/out/zero-client/src/client/client-error-kind-enum.d.ts.map +1 -0
- package/out/zero-client/src/client/client-error-kind.d.ts +5 -0
- package/out/zero-client/src/client/client-error-kind.d.ts.map +1 -0
- package/out/zero-client/src/client/connection-manager.d.ts +138 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts +11 -0
- package/out/zero-client/src/client/connection-status-enum.d.ts.map +1 -0
- package/out/zero-client/src/client/connection-status.d.ts +5 -0
- package/out/zero-client/src/client/connection-status.d.ts.map +1 -0
- package/out/zero-client/src/client/connection.d.ts +45 -0
- package/out/zero-client/src/client/connection.d.ts.map +1 -0
- package/out/zero-client/src/client/crud.d.ts.map +1 -1
- package/out/zero-client/src/client/error.d.ts +192 -0
- package/out/zero-client/src/client/error.d.ts.map +1 -0
- package/out/zero-client/src/client/ivm-branch.d.ts +2 -2
- package/out/zero-client/src/client/ivm-branch.d.ts.map +1 -1
- package/out/zero-client/src/client/metric-name.d.ts +5 -0
- package/out/zero-client/src/client/metric-name.d.ts.map +1 -0
- package/out/zero-client/src/client/metrics.d.ts +12 -9
- package/out/zero-client/src/client/metrics.d.ts.map +1 -1
- package/out/zero-client/src/client/mutation-tracker.d.ts +5 -4
- package/out/zero-client/src/client/mutation-tracker.d.ts.map +1 -1
- package/out/zero-client/src/client/options.d.ts +6 -2
- package/out/zero-client/src/client/options.d.ts.map +1 -1
- package/out/zero-client/src/client/query-manager.d.ts +5 -4
- package/out/zero-client/src/client/query-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/zero-rep.d.ts +1 -1
- package/out/zero-client/src/client/zero-rep.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.d.ts +55 -11
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/mod.d.ts +9 -1
- package/out/zero-client/src/mod.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.d.ts +2 -0
- package/out/zero-protocol/src/ast.d.ts.map +1 -1
- package/out/zero-protocol/src/ast.js +1 -0
- package/out/zero-protocol/src/ast.js.map +1 -1
- package/out/zero-protocol/src/custom-queries.d.ts +75 -4
- package/out/zero-protocol/src/custom-queries.d.ts.map +1 -1
- package/out/zero-protocol/src/custom-queries.js +18 -1
- package/out/zero-protocol/src/custom-queries.js.map +1 -1
- package/out/zero-protocol/src/down.d.ts +1 -1
- package/out/zero-protocol/src/error-kind-enum.d.ts +65 -0
- package/out/zero-protocol/src/error-kind-enum.d.ts.map +1 -1
- package/out/zero-protocol/src/error-kind-enum.js +2 -0
- package/out/zero-protocol/src/error-kind-enum.js.map +1 -1
- package/out/zero-protocol/src/error-origin-enum.d.ts +7 -0
- package/out/zero-protocol/src/error-origin-enum.d.ts.map +1 -0
- package/out/zero-protocol/src/error-origin-enum.js +4 -0
- package/out/zero-protocol/src/error-origin-enum.js.map +1 -0
- package/out/zero-protocol/src/error-origin.d.ts +5 -0
- package/out/zero-protocol/src/error-origin.d.ts.map +1 -0
- package/out/zero-protocol/src/error-origin.js +3 -0
- package/out/zero-protocol/src/error-origin.js.map +1 -0
- package/out/zero-protocol/src/error-reason-enum.d.ts +15 -0
- package/out/zero-protocol/src/error-reason-enum.d.ts.map +1 -0
- package/out/zero-protocol/src/error-reason-enum.js +8 -0
- package/out/zero-protocol/src/error-reason-enum.js.map +1 -0
- package/out/zero-protocol/src/error-reason.d.ts +5 -0
- package/out/zero-protocol/src/error-reason.d.ts.map +1 -0
- package/out/zero-protocol/src/error-reason.js +3 -0
- package/out/zero-protocol/src/error-reason.js.map +1 -0
- package/out/zero-protocol/src/error.d.ts +139 -1
- package/out/zero-protocol/src/error.d.ts.map +1 -1
- package/out/zero-protocol/src/error.js +64 -2
- package/out/zero-protocol/src/error.js.map +1 -1
- package/out/zero-protocol/src/mutation-id.d.ts +7 -0
- package/out/zero-protocol/src/mutation-id.d.ts.map +1 -0
- package/out/zero-protocol/src/mutation-id.js +6 -0
- package/out/zero-protocol/src/mutation-id.js.map +1 -0
- package/out/zero-protocol/src/mutations-patch.d.ts +3 -3
- package/out/zero-protocol/src/mutations-patch.d.ts.map +1 -1
- package/out/zero-protocol/src/mutations-patch.js +2 -1
- package/out/zero-protocol/src/mutations-patch.js.map +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts +1 -1
- package/out/zero-protocol/src/protocol-version.d.ts.map +1 -1
- package/out/zero-protocol/src/protocol-version.js +2 -1
- package/out/zero-protocol/src/protocol-version.js.map +1 -1
- package/out/zero-protocol/src/push.d.ts +138 -13
- package/out/zero-protocol/src/push.d.ts.map +1 -1
- package/out/zero-protocol/src/push.js +34 -13
- package/out/zero-protocol/src/push.js.map +1 -1
- package/out/zero-react/src/mod.d.ts +2 -1
- package/out/zero-react/src/mod.d.ts.map +1 -1
- package/out/zero-react/src/use-zero-connection-state.d.ts +9 -0
- package/out/zero-react/src/use-zero-connection-state.d.ts.map +1 -0
- package/out/zero-react/src/use-zero-online.d.ts +2 -0
- package/out/zero-react/src/use-zero-online.d.ts.map +1 -1
- package/out/zero-schema/src/builder/relationship-builder.d.ts +20 -18
- 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-server/src/adapters/drizzle.d.ts +2 -3
- package/out/zero-server/src/adapters/drizzle.d.ts.map +1 -1
- package/out/zero-server/src/adapters/drizzle.js.map +1 -1
- package/out/zero-server/src/adapters/pg.d.ts +1 -0
- package/out/zero-server/src/adapters/pg.d.ts.map +1 -1
- package/out/zero-server/src/adapters/pg.js.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.d.ts +1 -0
- package/out/zero-server/src/adapters/postgresjs.d.ts.map +1 -1
- package/out/zero-server/src/adapters/postgresjs.js.map +1 -1
- package/out/zero-server/src/process-mutations.d.ts +3 -3
- package/out/zero-server/src/process-mutations.d.ts.map +1 -1
- package/out/zero-server/src/process-mutations.js.map +1 -1
- package/out/zero-server/src/schema.js +1 -1
- package/out/zero-server/src/schema.js.map +1 -1
- package/out/zero-server/src/zql-database.d.ts +1 -1
- package/out/zero-server/src/zql-database.d.ts.map +1 -1
- package/out/zero-server/src/zql-database.js.map +1 -1
- package/out/zero-solid/src/mod.d.ts +3 -2
- package/out/zero-solid/src/mod.d.ts.map +1 -1
- package/out/zero-solid/src/use-zero-connection-state.d.ts +10 -0
- package/out/zero-solid/src/use-zero-connection-state.d.ts.map +1 -0
- package/out/zero-solid/src/use-zero-online.d.ts +1 -7
- package/out/zero-solid/src/use-zero-online.d.ts.map +1 -1
- package/out/zero.js +13 -3
- package/out/zql/src/builder/builder.d.ts +14 -1
- package/out/zql/src/builder/builder.d.ts.map +1 -1
- package/out/zql/src/builder/builder.js +33 -2
- package/out/zql/src/builder/builder.js.map +1 -1
- package/out/zql/src/ivm/data.d.ts +1 -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/filter-push.d.ts +1 -1
- package/out/zql/src/ivm/filter-push.d.ts.map +1 -1
- package/out/zql/src/ivm/filter-push.js.map +1 -1
- package/out/zql/src/ivm/memory-source.d.ts +5 -5
- package/out/zql/src/ivm/memory-source.d.ts.map +1 -1
- package/out/zql/src/ivm/memory-source.js +0 -16
- package/out/zql/src/ivm/memory-source.js.map +1 -1
- package/out/zql/src/ivm/source.d.ts +2 -6
- package/out/zql/src/ivm/source.d.ts.map +1 -1
- package/out/zql/src/ivm/take.d.ts +1 -1
- package/out/zql/src/ivm/take.d.ts.map +1 -1
- package/out/zql/src/ivm/take.js.map +1 -1
- package/out/zql/src/planner/planner-builder.d.ts +14 -0
- package/out/zql/src/planner/planner-builder.d.ts.map +1 -0
- package/out/zql/src/planner/planner-builder.js +180 -0
- package/out/zql/src/planner/planner-builder.js.map +1 -0
- package/out/zql/src/planner/planner-connection.d.ts +119 -0
- package/out/zql/src/planner/planner-connection.d.ts.map +1 -0
- package/out/zql/src/planner/planner-connection.js +301 -0
- package/out/zql/src/planner/planner-connection.js.map +1 -0
- package/out/zql/src/planner/planner-constraint.d.ts +14 -0
- package/out/zql/src/planner/planner-constraint.d.ts.map +1 -0
- package/out/zql/src/planner/planner-constraint.js +12 -0
- package/out/zql/src/planner/planner-constraint.js.map +1 -0
- package/out/zql/src/planner/planner-debug.d.ts +118 -0
- package/out/zql/src/planner/planner-debug.d.ts.map +1 -0
- package/out/zql/src/planner/planner-debug.js +125 -0
- package/out/zql/src/planner/planner-debug.js.map +1 -0
- package/out/zql/src/planner/planner-fan-in.d.ts +37 -0
- package/out/zql/src/planner/planner-fan-in.d.ts.map +1 -0
- package/out/zql/src/planner/planner-fan-in.js +149 -0
- package/out/zql/src/planner/planner-fan-in.js.map +1 -0
- package/out/zql/src/planner/planner-fan-out.d.ts +21 -0
- package/out/zql/src/planner/planner-fan-out.d.ts.map +1 -0
- package/out/zql/src/planner/planner-fan-out.js +45 -0
- package/out/zql/src/planner/planner-fan-out.js.map +1 -0
- package/out/zql/src/planner/planner-graph.d.ts +103 -0
- package/out/zql/src/planner/planner-graph.d.ts.map +1 -0
- package/out/zql/src/planner/planner-graph.js +411 -0
- package/out/zql/src/planner/planner-graph.js.map +1 -0
- package/out/zql/src/planner/planner-join.d.ts +81 -0
- package/out/zql/src/planner/planner-join.d.ts.map +1 -0
- package/out/zql/src/planner/planner-join.js +246 -0
- package/out/zql/src/planner/planner-join.js.map +1 -0
- package/out/zql/src/planner/planner-node.d.ts +21 -0
- package/out/zql/src/planner/planner-node.d.ts.map +1 -0
- package/out/zql/src/planner/planner-node.js +2 -0
- package/out/zql/src/planner/planner-node.js.map +1 -0
- package/out/zql/src/planner/planner-source.d.ts +11 -0
- package/out/zql/src/planner/planner-source.d.ts.map +1 -0
- package/out/zql/src/planner/planner-source.js +13 -0
- package/out/zql/src/planner/planner-source.js.map +1 -0
- package/out/zql/src/planner/planner-terminus.d.ts +16 -0
- package/out/zql/src/planner/planner-terminus.d.ts.map +1 -0
- package/out/zql/src/planner/planner-terminus.js +28 -0
- package/out/zql/src/planner/planner-terminus.js.map +1 -0
- package/out/zql/src/query/expression.d.ts +2 -2
- package/out/zql/src/query/expression.d.ts.map +1 -1
- package/out/zql/src/query/expression.js.map +1 -1
- package/out/zql/src/query/query-delegate.d.ts +3 -3
- package/out/zql/src/query/query-delegate.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.d.ts +8 -8
- package/out/zql/src/query/query-impl.d.ts.map +1 -1
- package/out/zql/src/query/query-impl.js +0 -6
- package/out/zql/src/query/query-impl.js.map +1 -1
- package/out/zql/src/query/query.d.ts +3 -3
- package/out/zql/src/query/query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.d.ts +1 -1
- package/out/zql/src/query/static-query.d.ts.map +1 -1
- package/out/zql/src/query/static-query.js.map +1 -1
- package/out/zql/src/query/typed-view.d.ts +1 -1
- package/out/zql/src/query/typed-view.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.d.ts +1 -1
- package/out/zqlite/src/query-delegate.d.ts.map +1 -1
- package/out/zqlite/src/query-delegate.js.map +1 -1
- package/out/zqlite/src/sqlite-cost-model.d.ts +17 -0
- package/out/zqlite/src/sqlite-cost-model.d.ts.map +1 -0
- package/out/zqlite/src/sqlite-cost-model.js +134 -0
- package/out/zqlite/src/sqlite-cost-model.js.map +1 -0
- package/out/zqlite/src/table-source.d.ts +4 -4
- package/out/zqlite/src/table-source.d.ts.map +1 -1
- package/out/zqlite/src/table-source.js +0 -16
- package/out/zqlite/src/table-source.js.map +1 -1
- package/package.json +5 -4
- package/out/chunk-JS2ABYXG.js.map +0 -7
- package/out/chunk-PIXC6O7W.js.map +0 -7
- package/out/zero-cache/src/types/error-for-client.d.ts +0 -23
- package/out/zero-cache/src/types/error-for-client.d.ts.map +0 -1
- package/out/zero-cache/src/types/error-for-client.js +0 -28
- package/out/zero-cache/src/types/error-for-client.js.map +0 -1
- package/out/zero-client/src/client/connection-state-enum.d.ts +0 -7
- package/out/zero-client/src/client/connection-state-enum.d.ts.map +0 -1
- package/out/zero-client/src/client/ping-result-enum.d.ts +0 -5
- package/out/zero-client/src/client/ping-result-enum.d.ts.map +0 -1
- package/out/zero-client/src/client/server-error.d.ts +0 -15
- package/out/zero-client/src/client/server-error.d.ts.map +0 -1
- package/out/zql/src/query/assert-no-not-exists.d.ts +0 -17
- package/out/zql/src/query/assert-no-not-exists.d.ts.map +0 -1
- package/out/zql/src/query/assert-no-not-exists.js +0 -40
- package/out/zql/src/query/assert-no-not-exists.js.map +0 -1
- /package/out/{lazy-inspector-NCBESZMS.js.map → lazy-inspector-OXIFYSSQ.js.map} +0 -0
|
@@ -96,6 +96,7 @@ import {
|
|
|
96
96
|
normalizeAST,
|
|
97
97
|
once,
|
|
98
98
|
parse,
|
|
99
|
+
planIdSymbol,
|
|
99
100
|
primaryKeySchema,
|
|
100
101
|
primaryKeyValueRecordSchema,
|
|
101
102
|
readFromDefaultHead,
|
|
@@ -123,7 +124,7 @@ import {
|
|
|
123
124
|
withWrite,
|
|
124
125
|
withWriteNoImplicitCommit,
|
|
125
126
|
wrapIterable
|
|
126
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-TJFNGO7E.js";
|
|
127
128
|
import {
|
|
128
129
|
assert,
|
|
129
130
|
assertArray,
|
|
@@ -1511,6 +1512,223 @@ function rejectIfClosed(tx) {
|
|
|
1511
1512
|
return tx.closed ? Promise.reject(new TransactionClosedError()) : void 0;
|
|
1512
1513
|
}
|
|
1513
1514
|
|
|
1515
|
+
// ../zero-protocol/src/error-kind-enum.ts
|
|
1516
|
+
var error_kind_enum_exports = {};
|
|
1517
|
+
__export(error_kind_enum_exports, {
|
|
1518
|
+
AuthInvalidated: () => AuthInvalidated,
|
|
1519
|
+
ClientNotFound: () => ClientNotFound,
|
|
1520
|
+
Internal: () => Internal,
|
|
1521
|
+
InvalidConnectionRequest: () => InvalidConnectionRequest,
|
|
1522
|
+
InvalidConnectionRequestBaseCookie: () => InvalidConnectionRequestBaseCookie,
|
|
1523
|
+
InvalidConnectionRequestClientDeleted: () => InvalidConnectionRequestClientDeleted,
|
|
1524
|
+
InvalidConnectionRequestLastMutationID: () => InvalidConnectionRequestLastMutationID,
|
|
1525
|
+
InvalidMessage: () => InvalidMessage,
|
|
1526
|
+
InvalidPush: () => InvalidPush,
|
|
1527
|
+
MutationFailed: () => MutationFailed,
|
|
1528
|
+
MutationRateLimited: () => MutationRateLimited,
|
|
1529
|
+
PushFailed: () => PushFailed,
|
|
1530
|
+
Rebalance: () => Rebalance,
|
|
1531
|
+
Rehome: () => Rehome,
|
|
1532
|
+
SchemaVersionNotSupported: () => SchemaVersionNotSupported,
|
|
1533
|
+
ServerOverloaded: () => ServerOverloaded,
|
|
1534
|
+
TransformFailed: () => TransformFailed,
|
|
1535
|
+
Unauthorized: () => Unauthorized,
|
|
1536
|
+
VersionNotSupported: () => VersionNotSupported
|
|
1537
|
+
});
|
|
1538
|
+
var AuthInvalidated = "AuthInvalidated";
|
|
1539
|
+
var ClientNotFound = "ClientNotFound";
|
|
1540
|
+
var InvalidConnectionRequest = "InvalidConnectionRequest";
|
|
1541
|
+
var InvalidConnectionRequestBaseCookie = "InvalidConnectionRequestBaseCookie";
|
|
1542
|
+
var InvalidConnectionRequestLastMutationID = "InvalidConnectionRequestLastMutationID";
|
|
1543
|
+
var InvalidConnectionRequestClientDeleted = "InvalidConnectionRequestClientDeleted";
|
|
1544
|
+
var InvalidMessage = "InvalidMessage";
|
|
1545
|
+
var InvalidPush = "InvalidPush";
|
|
1546
|
+
var PushFailed = "PushFailed";
|
|
1547
|
+
var MutationFailed = "MutationFailed";
|
|
1548
|
+
var MutationRateLimited = "MutationRateLimited";
|
|
1549
|
+
var Rebalance = "Rebalance";
|
|
1550
|
+
var Rehome = "Rehome";
|
|
1551
|
+
var TransformFailed = "TransformFailed";
|
|
1552
|
+
var Unauthorized = "Unauthorized";
|
|
1553
|
+
var VersionNotSupported = "VersionNotSupported";
|
|
1554
|
+
var SchemaVersionNotSupported = "SchemaVersionNotSupported";
|
|
1555
|
+
var ServerOverloaded = "ServerOverloaded";
|
|
1556
|
+
var Internal = "Internal";
|
|
1557
|
+
|
|
1558
|
+
// ../zero-protocol/src/error-origin-enum.ts
|
|
1559
|
+
var error_origin_enum_exports = {};
|
|
1560
|
+
__export(error_origin_enum_exports, {
|
|
1561
|
+
Client: () => Client,
|
|
1562
|
+
Server: () => Server,
|
|
1563
|
+
ZeroCache: () => ZeroCache
|
|
1564
|
+
});
|
|
1565
|
+
var Client = "client";
|
|
1566
|
+
var Server = "server";
|
|
1567
|
+
var ZeroCache = "zeroCache";
|
|
1568
|
+
|
|
1569
|
+
// ../zero-protocol/src/error-reason-enum.ts
|
|
1570
|
+
var error_reason_enum_exports = {};
|
|
1571
|
+
__export(error_reason_enum_exports, {
|
|
1572
|
+
Database: () => Database,
|
|
1573
|
+
HTTP: () => HTTP,
|
|
1574
|
+
Internal: () => Internal2,
|
|
1575
|
+
OutOfOrderMutation: () => OutOfOrderMutation,
|
|
1576
|
+
Parse: () => Parse,
|
|
1577
|
+
Timeout: () => Timeout,
|
|
1578
|
+
UnsupportedPushVersion: () => UnsupportedPushVersion
|
|
1579
|
+
});
|
|
1580
|
+
var Database = "database";
|
|
1581
|
+
var Parse = "parse";
|
|
1582
|
+
var OutOfOrderMutation = "oooMutation";
|
|
1583
|
+
var UnsupportedPushVersion = "unsupportedPushVersion";
|
|
1584
|
+
var Internal2 = "internal";
|
|
1585
|
+
var HTTP = "http";
|
|
1586
|
+
var Timeout = "timeout";
|
|
1587
|
+
|
|
1588
|
+
// ../zero-protocol/src/mutation-id.ts
|
|
1589
|
+
var mutationIDSchema = valita_exports.object({
|
|
1590
|
+
id: valita_exports.number(),
|
|
1591
|
+
clientID: valita_exports.string()
|
|
1592
|
+
});
|
|
1593
|
+
|
|
1594
|
+
// ../zero-protocol/src/error.ts
|
|
1595
|
+
var basicErrorKindSchema = literalUnion(
|
|
1596
|
+
error_kind_enum_exports.AuthInvalidated,
|
|
1597
|
+
error_kind_enum_exports.ClientNotFound,
|
|
1598
|
+
error_kind_enum_exports.InvalidConnectionRequest,
|
|
1599
|
+
error_kind_enum_exports.InvalidConnectionRequestBaseCookie,
|
|
1600
|
+
error_kind_enum_exports.InvalidConnectionRequestLastMutationID,
|
|
1601
|
+
error_kind_enum_exports.InvalidConnectionRequestClientDeleted,
|
|
1602
|
+
error_kind_enum_exports.InvalidMessage,
|
|
1603
|
+
error_kind_enum_exports.InvalidPush,
|
|
1604
|
+
error_kind_enum_exports.MutationRateLimited,
|
|
1605
|
+
error_kind_enum_exports.MutationFailed,
|
|
1606
|
+
error_kind_enum_exports.Unauthorized,
|
|
1607
|
+
error_kind_enum_exports.VersionNotSupported,
|
|
1608
|
+
error_kind_enum_exports.SchemaVersionNotSupported,
|
|
1609
|
+
error_kind_enum_exports.Internal
|
|
1610
|
+
);
|
|
1611
|
+
var basicErrorBodySchema = valita_exports.object({
|
|
1612
|
+
kind: basicErrorKindSchema,
|
|
1613
|
+
message: valita_exports.string(),
|
|
1614
|
+
// this is optional for backwards compatibility
|
|
1615
|
+
origin: literalUnion(error_origin_enum_exports.Server, error_origin_enum_exports.ZeroCache).optional()
|
|
1616
|
+
});
|
|
1617
|
+
var backoffErrorKindSchema = literalUnion(
|
|
1618
|
+
error_kind_enum_exports.Rebalance,
|
|
1619
|
+
error_kind_enum_exports.Rehome,
|
|
1620
|
+
error_kind_enum_exports.ServerOverloaded
|
|
1621
|
+
);
|
|
1622
|
+
var backoffBodySchema = valita_exports.object({
|
|
1623
|
+
kind: backoffErrorKindSchema,
|
|
1624
|
+
message: valita_exports.string(),
|
|
1625
|
+
minBackoffMs: valita_exports.number().optional(),
|
|
1626
|
+
maxBackoffMs: valita_exports.number().optional(),
|
|
1627
|
+
// Query parameters to send in the next reconnect. In the event of
|
|
1628
|
+
// a conflict, these will be overridden by the parameters used by
|
|
1629
|
+
// the client; it is the responsibility of the server to avoid
|
|
1630
|
+
// parameter name conflicts.
|
|
1631
|
+
//
|
|
1632
|
+
// The parameters will only be added to the immediately following
|
|
1633
|
+
// reconnect, and not after that.
|
|
1634
|
+
reconnectParams: valita_exports.record(valita_exports.string()).optional(),
|
|
1635
|
+
origin: valita_exports.literal(error_origin_enum_exports.ZeroCache).optional()
|
|
1636
|
+
});
|
|
1637
|
+
var pushFailedErrorKindSchema = valita_exports.literal(error_kind_enum_exports.PushFailed);
|
|
1638
|
+
var transformFailedErrorKindSchema = valita_exports.literal(error_kind_enum_exports.TransformFailed);
|
|
1639
|
+
var errorKindSchema = valita_exports.union(
|
|
1640
|
+
basicErrorKindSchema,
|
|
1641
|
+
backoffErrorKindSchema,
|
|
1642
|
+
pushFailedErrorKindSchema,
|
|
1643
|
+
transformFailedErrorKindSchema
|
|
1644
|
+
);
|
|
1645
|
+
var pushFailedBaseSchema = valita_exports.object({
|
|
1646
|
+
kind: pushFailedErrorKindSchema,
|
|
1647
|
+
details: jsonSchema.optional(),
|
|
1648
|
+
mutationIDs: valita_exports.array(mutationIDSchema),
|
|
1649
|
+
message: valita_exports.string()
|
|
1650
|
+
});
|
|
1651
|
+
var pushFailedBodySchema = valita_exports.union(
|
|
1652
|
+
pushFailedBaseSchema.extend({
|
|
1653
|
+
origin: valita_exports.literal(error_origin_enum_exports.Server),
|
|
1654
|
+
reason: literalUnion(
|
|
1655
|
+
error_reason_enum_exports.Database,
|
|
1656
|
+
error_reason_enum_exports.Parse,
|
|
1657
|
+
error_reason_enum_exports.OutOfOrderMutation,
|
|
1658
|
+
error_reason_enum_exports.UnsupportedPushVersion,
|
|
1659
|
+
error_reason_enum_exports.Internal
|
|
1660
|
+
)
|
|
1661
|
+
}),
|
|
1662
|
+
pushFailedBaseSchema.extend({
|
|
1663
|
+
origin: valita_exports.literal(error_origin_enum_exports.ZeroCache),
|
|
1664
|
+
reason: valita_exports.literal(error_reason_enum_exports.HTTP),
|
|
1665
|
+
status: valita_exports.number(),
|
|
1666
|
+
bodyPreview: valita_exports.string().optional()
|
|
1667
|
+
}),
|
|
1668
|
+
pushFailedBaseSchema.extend({
|
|
1669
|
+
origin: valita_exports.literal(error_origin_enum_exports.ZeroCache),
|
|
1670
|
+
reason: literalUnion(
|
|
1671
|
+
error_reason_enum_exports.Timeout,
|
|
1672
|
+
error_reason_enum_exports.Parse,
|
|
1673
|
+
error_reason_enum_exports.Internal
|
|
1674
|
+
)
|
|
1675
|
+
})
|
|
1676
|
+
);
|
|
1677
|
+
var transformFailedBaseSchema = valita_exports.object({
|
|
1678
|
+
kind: transformFailedErrorKindSchema,
|
|
1679
|
+
details: jsonSchema.optional(),
|
|
1680
|
+
queryIDs: valita_exports.array(valita_exports.string()),
|
|
1681
|
+
message: valita_exports.string()
|
|
1682
|
+
});
|
|
1683
|
+
var transformFailedBodySchema = valita_exports.union(
|
|
1684
|
+
transformFailedBaseSchema.extend({
|
|
1685
|
+
origin: valita_exports.literal(error_origin_enum_exports.Server),
|
|
1686
|
+
reason: literalUnion(
|
|
1687
|
+
error_reason_enum_exports.Database,
|
|
1688
|
+
error_reason_enum_exports.Parse,
|
|
1689
|
+
error_reason_enum_exports.Internal
|
|
1690
|
+
)
|
|
1691
|
+
}),
|
|
1692
|
+
transformFailedBaseSchema.extend({
|
|
1693
|
+
origin: valita_exports.literal(error_origin_enum_exports.ZeroCache),
|
|
1694
|
+
reason: valita_exports.literal(error_reason_enum_exports.HTTP),
|
|
1695
|
+
status: valita_exports.number(),
|
|
1696
|
+
bodyPreview: valita_exports.string().optional()
|
|
1697
|
+
}),
|
|
1698
|
+
transformFailedBaseSchema.extend({
|
|
1699
|
+
origin: valita_exports.literal(error_origin_enum_exports.ZeroCache),
|
|
1700
|
+
reason: literalUnion(
|
|
1701
|
+
error_reason_enum_exports.Timeout,
|
|
1702
|
+
error_reason_enum_exports.Parse,
|
|
1703
|
+
error_reason_enum_exports.Internal
|
|
1704
|
+
)
|
|
1705
|
+
})
|
|
1706
|
+
);
|
|
1707
|
+
var errorBodySchema = valita_exports.union(
|
|
1708
|
+
basicErrorBodySchema,
|
|
1709
|
+
backoffBodySchema,
|
|
1710
|
+
pushFailedBodySchema,
|
|
1711
|
+
transformFailedBodySchema
|
|
1712
|
+
);
|
|
1713
|
+
var errorMessageSchema = valita_exports.tuple([
|
|
1714
|
+
valita_exports.literal("error"),
|
|
1715
|
+
errorBodySchema
|
|
1716
|
+
]);
|
|
1717
|
+
var ProtocolError = class extends Error {
|
|
1718
|
+
errorBody;
|
|
1719
|
+
constructor(errorBody, options) {
|
|
1720
|
+
super(errorBody.message, options);
|
|
1721
|
+
this.name = "ProtocolError";
|
|
1722
|
+
this.errorBody = errorBody;
|
|
1723
|
+
}
|
|
1724
|
+
get kind() {
|
|
1725
|
+
return this.errorBody.kind;
|
|
1726
|
+
}
|
|
1727
|
+
};
|
|
1728
|
+
function isProtocolError(error) {
|
|
1729
|
+
return error instanceof ProtocolError;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1514
1732
|
// ../zero-protocol/src/custom-queries.ts
|
|
1515
1733
|
var transformRequestBodySchema = valita_exports.array(
|
|
1516
1734
|
valita_exports.object({
|
|
@@ -1531,16 +1749,25 @@ var appQueryErrorSchema = valita_exports.object({
|
|
|
1531
1749
|
details: jsonSchema
|
|
1532
1750
|
});
|
|
1533
1751
|
var zeroErrorSchema = valita_exports.object({
|
|
1752
|
+
/** @deprecated */
|
|
1534
1753
|
error: valita_exports.literal("zero"),
|
|
1754
|
+
/** @deprecated */
|
|
1535
1755
|
id: valita_exports.string(),
|
|
1756
|
+
/** @deprecated */
|
|
1536
1757
|
name: valita_exports.string(),
|
|
1758
|
+
/** @deprecated */
|
|
1537
1759
|
details: jsonSchema
|
|
1538
1760
|
});
|
|
1539
1761
|
var httpQueryErrorSchema = valita_exports.object({
|
|
1762
|
+
/** @deprecated */
|
|
1540
1763
|
error: valita_exports.literal("http"),
|
|
1764
|
+
/** @deprecated */
|
|
1541
1765
|
id: valita_exports.string(),
|
|
1766
|
+
/** @deprecated */
|
|
1542
1767
|
name: valita_exports.string(),
|
|
1768
|
+
/** @deprecated */
|
|
1543
1769
|
status: valita_exports.number(),
|
|
1770
|
+
/** @deprecated */
|
|
1544
1771
|
details: jsonSchema
|
|
1545
1772
|
});
|
|
1546
1773
|
var erroredQuerySchema = valita_exports.union(
|
|
@@ -1559,49 +1786,18 @@ var transformErrorMessageSchema = valita_exports.tuple([
|
|
|
1559
1786
|
valita_exports.literal("transformError"),
|
|
1560
1787
|
valita_exports.array(erroredQuerySchema)
|
|
1561
1788
|
]);
|
|
1562
|
-
var
|
|
1789
|
+
var transformFailedMessageSchema = valita_exports.tuple([
|
|
1790
|
+
valita_exports.literal("transformFailed"),
|
|
1791
|
+
transformFailedBodySchema
|
|
1792
|
+
]);
|
|
1793
|
+
var transformOkMessageSchema = valita_exports.tuple([
|
|
1563
1794
|
valita_exports.literal("transformed"),
|
|
1564
1795
|
transformResponseBodySchema
|
|
1565
1796
|
]);
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
AuthInvalidated: () => AuthInvalidated,
|
|
1571
|
-
ClientNotFound: () => ClientNotFound,
|
|
1572
|
-
Internal: () => Internal,
|
|
1573
|
-
InvalidConnectionRequest: () => InvalidConnectionRequest,
|
|
1574
|
-
InvalidConnectionRequestBaseCookie: () => InvalidConnectionRequestBaseCookie,
|
|
1575
|
-
InvalidConnectionRequestClientDeleted: () => InvalidConnectionRequestClientDeleted,
|
|
1576
|
-
InvalidConnectionRequestLastMutationID: () => InvalidConnectionRequestLastMutationID,
|
|
1577
|
-
InvalidMessage: () => InvalidMessage,
|
|
1578
|
-
InvalidPush: () => InvalidPush,
|
|
1579
|
-
MutationFailed: () => MutationFailed,
|
|
1580
|
-
MutationRateLimited: () => MutationRateLimited,
|
|
1581
|
-
Rebalance: () => Rebalance,
|
|
1582
|
-
Rehome: () => Rehome,
|
|
1583
|
-
SchemaVersionNotSupported: () => SchemaVersionNotSupported,
|
|
1584
|
-
ServerOverloaded: () => ServerOverloaded,
|
|
1585
|
-
Unauthorized: () => Unauthorized,
|
|
1586
|
-
VersionNotSupported: () => VersionNotSupported
|
|
1587
|
-
});
|
|
1588
|
-
var AuthInvalidated = "AuthInvalidated";
|
|
1589
|
-
var ClientNotFound = "ClientNotFound";
|
|
1590
|
-
var InvalidConnectionRequest = "InvalidConnectionRequest";
|
|
1591
|
-
var InvalidConnectionRequestBaseCookie = "InvalidConnectionRequestBaseCookie";
|
|
1592
|
-
var InvalidConnectionRequestLastMutationID = "InvalidConnectionRequestLastMutationID";
|
|
1593
|
-
var InvalidConnectionRequestClientDeleted = "InvalidConnectionRequestClientDeleted";
|
|
1594
|
-
var InvalidMessage = "InvalidMessage";
|
|
1595
|
-
var InvalidPush = "InvalidPush";
|
|
1596
|
-
var MutationFailed = "MutationFailed";
|
|
1597
|
-
var MutationRateLimited = "MutationRateLimited";
|
|
1598
|
-
var Rebalance = "Rebalance";
|
|
1599
|
-
var Rehome = "Rehome";
|
|
1600
|
-
var Unauthorized = "Unauthorized";
|
|
1601
|
-
var VersionNotSupported = "VersionNotSupported";
|
|
1602
|
-
var SchemaVersionNotSupported = "SchemaVersionNotSupported";
|
|
1603
|
-
var ServerOverloaded = "ServerOverloaded";
|
|
1604
|
-
var Internal = "Internal";
|
|
1797
|
+
var transformResponseMessageSchema = valita_exports.union(
|
|
1798
|
+
transformOkMessageSchema,
|
|
1799
|
+
transformFailedMessageSchema
|
|
1800
|
+
);
|
|
1605
1801
|
|
|
1606
1802
|
// ../zero-schema/src/builder/table-builder.ts
|
|
1607
1803
|
function table(name) {
|
|
@@ -1611,14 +1807,14 @@ function table(name) {
|
|
|
1611
1807
|
primaryKey: []
|
|
1612
1808
|
});
|
|
1613
1809
|
}
|
|
1614
|
-
function
|
|
1810
|
+
function string4() {
|
|
1615
1811
|
return new ColumnBuilder({
|
|
1616
1812
|
type: "string",
|
|
1617
1813
|
optional: false,
|
|
1618
1814
|
customType: null
|
|
1619
1815
|
});
|
|
1620
1816
|
}
|
|
1621
|
-
function
|
|
1817
|
+
function number4() {
|
|
1622
1818
|
return new ColumnBuilder({
|
|
1623
1819
|
type: "number",
|
|
1624
1820
|
optional: false,
|
|
@@ -2172,6 +2368,170 @@ function makeID(row, schema) {
|
|
|
2172
2368
|
return JSON.stringify(schema.primaryKey.map((k) => row[k]));
|
|
2173
2369
|
}
|
|
2174
2370
|
|
|
2371
|
+
// ../zero-client/src/client/client-error-kind-enum.ts
|
|
2372
|
+
var client_error_kind_enum_exports = {};
|
|
2373
|
+
__export(client_error_kind_enum_exports, {
|
|
2374
|
+
AbruptClose: () => AbruptClose,
|
|
2375
|
+
CleanClose: () => CleanClose,
|
|
2376
|
+
ClientClosed: () => ClientClosed,
|
|
2377
|
+
ConnectTimeout: () => ConnectTimeout,
|
|
2378
|
+
DisconnectTimeout: () => DisconnectTimeout,
|
|
2379
|
+
Hidden: () => Hidden,
|
|
2380
|
+
Internal: () => Internal3,
|
|
2381
|
+
InvalidMessage: () => InvalidMessage2,
|
|
2382
|
+
NoSocketOrigin: () => NoSocketOrigin,
|
|
2383
|
+
PingTimeout: () => PingTimeout,
|
|
2384
|
+
PullTimeout: () => PullTimeout,
|
|
2385
|
+
UnexpectedBaseCookie: () => UnexpectedBaseCookie,
|
|
2386
|
+
UserDisconnect: () => UserDisconnect
|
|
2387
|
+
});
|
|
2388
|
+
var AbruptClose = "AbruptClose";
|
|
2389
|
+
var CleanClose = "CleanClose";
|
|
2390
|
+
var ClientClosed = "ClientClosed";
|
|
2391
|
+
var ConnectTimeout = "ConnectTimeout";
|
|
2392
|
+
var DisconnectTimeout = "DisconnectTimeout";
|
|
2393
|
+
var UnexpectedBaseCookie = "UnexpectedBaseCookie";
|
|
2394
|
+
var PingTimeout = "PingTimeout";
|
|
2395
|
+
var PullTimeout = "PullTimeout";
|
|
2396
|
+
var Hidden = "Hidden";
|
|
2397
|
+
var NoSocketOrigin = "NoSocketOrigin";
|
|
2398
|
+
var InvalidMessage2 = "InvalidMessage";
|
|
2399
|
+
var UserDisconnect = "UserDisconnect";
|
|
2400
|
+
var Internal3 = "Internal";
|
|
2401
|
+
|
|
2402
|
+
// ../zero-client/src/client/connection-status-enum.ts
|
|
2403
|
+
var connection_status_enum_exports = {};
|
|
2404
|
+
__export(connection_status_enum_exports, {
|
|
2405
|
+
Closed: () => Closed,
|
|
2406
|
+
Connected: () => Connected,
|
|
2407
|
+
Connecting: () => Connecting,
|
|
2408
|
+
Disconnected: () => Disconnected,
|
|
2409
|
+
Error: () => Error2
|
|
2410
|
+
});
|
|
2411
|
+
var Disconnected = "disconnected";
|
|
2412
|
+
var Connecting = "connecting";
|
|
2413
|
+
var Connected = "connected";
|
|
2414
|
+
var Error2 = "error";
|
|
2415
|
+
var Closed = "closed";
|
|
2416
|
+
|
|
2417
|
+
// ../zero-client/src/client/error.ts
|
|
2418
|
+
var ClientError = class extends Error {
|
|
2419
|
+
errorBody;
|
|
2420
|
+
constructor(errorBody, options) {
|
|
2421
|
+
super(errorBody.message, options);
|
|
2422
|
+
this.name = "ClientError";
|
|
2423
|
+
this.errorBody = { ...errorBody, origin: error_origin_enum_exports.Client };
|
|
2424
|
+
}
|
|
2425
|
+
get kind() {
|
|
2426
|
+
return this.errorBody.kind;
|
|
2427
|
+
}
|
|
2428
|
+
};
|
|
2429
|
+
function isServerError(ex) {
|
|
2430
|
+
return isProtocolError(ex) && (ex.errorBody.origin === error_origin_enum_exports.Server || ex.errorBody.origin === error_origin_enum_exports.ZeroCache);
|
|
2431
|
+
}
|
|
2432
|
+
function isAuthError(ex) {
|
|
2433
|
+
if (isServerError(ex)) {
|
|
2434
|
+
if (isAuthErrorKind(ex.errorBody.kind)) {
|
|
2435
|
+
return true;
|
|
2436
|
+
}
|
|
2437
|
+
if ((ex.errorBody.kind === error_kind_enum_exports.PushFailed || ex.errorBody.kind === error_kind_enum_exports.TransformFailed) && ex.errorBody.reason === error_reason_enum_exports.HTTP && (ex.errorBody.status === 401 || ex.errorBody.status === 403)) {
|
|
2438
|
+
return true;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
return false;
|
|
2442
|
+
}
|
|
2443
|
+
function isAuthErrorKind(kind) {
|
|
2444
|
+
return kind === error_kind_enum_exports.AuthInvalidated || kind === error_kind_enum_exports.Unauthorized;
|
|
2445
|
+
}
|
|
2446
|
+
function getBackoffParams(error) {
|
|
2447
|
+
if (isServerError(error)) {
|
|
2448
|
+
switch (error.errorBody.kind) {
|
|
2449
|
+
case error_kind_enum_exports.Rebalance:
|
|
2450
|
+
case error_kind_enum_exports.Rehome:
|
|
2451
|
+
case error_kind_enum_exports.ServerOverloaded:
|
|
2452
|
+
return error.errorBody;
|
|
2453
|
+
}
|
|
2454
|
+
}
|
|
2455
|
+
return void 0;
|
|
2456
|
+
}
|
|
2457
|
+
function isClientError(ex) {
|
|
2458
|
+
return ex instanceof ClientError && ex.errorBody.origin === error_origin_enum_exports.Client;
|
|
2459
|
+
}
|
|
2460
|
+
var NO_STATUS_TRANSITION = "NO_STATUS_TRANSITION";
|
|
2461
|
+
function getErrorConnectionTransition(ex) {
|
|
2462
|
+
if (isClientError(ex)) {
|
|
2463
|
+
switch (ex.kind) {
|
|
2464
|
+
// Connecting errors that should continue in the current state
|
|
2465
|
+
case client_error_kind_enum_exports.AbruptClose:
|
|
2466
|
+
case client_error_kind_enum_exports.CleanClose:
|
|
2467
|
+
case client_error_kind_enum_exports.ConnectTimeout:
|
|
2468
|
+
case client_error_kind_enum_exports.PingTimeout:
|
|
2469
|
+
case client_error_kind_enum_exports.PullTimeout:
|
|
2470
|
+
case client_error_kind_enum_exports.Hidden:
|
|
2471
|
+
case client_error_kind_enum_exports.NoSocketOrigin:
|
|
2472
|
+
return { status: NO_STATUS_TRANSITION, reason: ex };
|
|
2473
|
+
// Fatal errors that should transition to error state
|
|
2474
|
+
case client_error_kind_enum_exports.UnexpectedBaseCookie:
|
|
2475
|
+
case client_error_kind_enum_exports.Internal:
|
|
2476
|
+
case client_error_kind_enum_exports.InvalidMessage:
|
|
2477
|
+
case client_error_kind_enum_exports.UserDisconnect:
|
|
2478
|
+
return { status: connection_status_enum_exports.Error, reason: ex };
|
|
2479
|
+
// Disconnected error (this should already result in a disconnected state)
|
|
2480
|
+
case client_error_kind_enum_exports.DisconnectTimeout:
|
|
2481
|
+
return { status: connection_status_enum_exports.Disconnected, reason: ex };
|
|
2482
|
+
// Closed error (this should already result in a closed state)
|
|
2483
|
+
case client_error_kind_enum_exports.ClientClosed:
|
|
2484
|
+
return { status: connection_status_enum_exports.Closed, reason: ex };
|
|
2485
|
+
default:
|
|
2486
|
+
unreachable(ex.kind);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
if (isAuthError(ex)) {
|
|
2490
|
+
return { status: NO_STATUS_TRANSITION, reason: ex };
|
|
2491
|
+
}
|
|
2492
|
+
if (isServerError(ex)) {
|
|
2493
|
+
switch (ex.kind) {
|
|
2494
|
+
// Errors that should transition to error state
|
|
2495
|
+
case error_kind_enum_exports.ClientNotFound:
|
|
2496
|
+
case error_kind_enum_exports.InvalidConnectionRequest:
|
|
2497
|
+
case error_kind_enum_exports.InvalidConnectionRequestBaseCookie:
|
|
2498
|
+
case error_kind_enum_exports.InvalidConnectionRequestLastMutationID:
|
|
2499
|
+
case error_kind_enum_exports.InvalidConnectionRequestClientDeleted:
|
|
2500
|
+
case error_kind_enum_exports.InvalidMessage:
|
|
2501
|
+
case error_kind_enum_exports.InvalidPush:
|
|
2502
|
+
case error_kind_enum_exports.VersionNotSupported:
|
|
2503
|
+
case error_kind_enum_exports.SchemaVersionNotSupported:
|
|
2504
|
+
case error_kind_enum_exports.Internal:
|
|
2505
|
+
case error_kind_enum_exports.PushFailed:
|
|
2506
|
+
case error_kind_enum_exports.TransformFailed:
|
|
2507
|
+
return { status: connection_status_enum_exports.Error, reason: ex };
|
|
2508
|
+
// Errors that should continue with backoff/retry
|
|
2509
|
+
case error_kind_enum_exports.Rebalance:
|
|
2510
|
+
case error_kind_enum_exports.Rehome:
|
|
2511
|
+
case error_kind_enum_exports.ServerOverloaded:
|
|
2512
|
+
return { status: NO_STATUS_TRANSITION, reason: ex };
|
|
2513
|
+
// Auth errors will eventually transition to needs-auth state
|
|
2514
|
+
// For now, treat them as non-fatal so we can retry
|
|
2515
|
+
case error_kind_enum_exports.AuthInvalidated:
|
|
2516
|
+
case error_kind_enum_exports.Unauthorized:
|
|
2517
|
+
return { status: NO_STATUS_TRANSITION, reason: ex };
|
|
2518
|
+
// Mutation-specific errors don't affect connection state
|
|
2519
|
+
case error_kind_enum_exports.MutationRateLimited:
|
|
2520
|
+
case error_kind_enum_exports.MutationFailed:
|
|
2521
|
+
return { status: NO_STATUS_TRANSITION, reason: ex };
|
|
2522
|
+
default:
|
|
2523
|
+
unreachable(ex.kind);
|
|
2524
|
+
}
|
|
2525
|
+
}
|
|
2526
|
+
return {
|
|
2527
|
+
status: connection_status_enum_exports.Error,
|
|
2528
|
+
reason: new ClientError({
|
|
2529
|
+
kind: client_error_kind_enum_exports.Internal,
|
|
2530
|
+
message: "Unexpected internal error: " + (ex instanceof Error ? ex.message : typeof ex === "string" ? ex : String(ex ?? "Unknown error"))
|
|
2531
|
+
})
|
|
2532
|
+
};
|
|
2533
|
+
}
|
|
2534
|
+
|
|
2175
2535
|
// ../zero-client/src/client/update-needed-reason-type-enum.ts
|
|
2176
2536
|
var update_needed_reason_type_enum_exports = {};
|
|
2177
2537
|
__export(update_needed_reason_type_enum_exports, {
|
|
@@ -2185,7 +2545,7 @@ var SchemaVersionNotSupported2 = "SchemaVersionNotSupported";
|
|
|
2185
2545
|
|
|
2186
2546
|
// ../zero-client/src/client/zero.ts
|
|
2187
2547
|
import "@rocicorp/logger";
|
|
2188
|
-
import { resolver as
|
|
2548
|
+
import { resolver as resolver11 } from "@rocicorp/resolver";
|
|
2189
2549
|
|
|
2190
2550
|
// ../replicache/src/replicache-impl.ts
|
|
2191
2551
|
import { Lock } from "@rocicorp/lock";
|
|
@@ -6283,6 +6643,24 @@ function validateOptions(options) {
|
|
|
6283
6643
|
}
|
|
6284
6644
|
}
|
|
6285
6645
|
|
|
6646
|
+
// ../shared/src/promise-race.ts
|
|
6647
|
+
var NO_PROMISES_MESSAGE = "No promises to race";
|
|
6648
|
+
var wrapPromise = (key, promise) => Promise.resolve(promise).then((result) => ({
|
|
6649
|
+
key,
|
|
6650
|
+
status: "fulfilled",
|
|
6651
|
+
result
|
|
6652
|
+
}));
|
|
6653
|
+
async function promiseRace(promises) {
|
|
6654
|
+
const keys = Object.keys(promises);
|
|
6655
|
+
if (keys.length === 0) {
|
|
6656
|
+
throw new Error(NO_PROMISES_MESSAGE);
|
|
6657
|
+
}
|
|
6658
|
+
const wrapped = keys.map(
|
|
6659
|
+
(key) => wrapPromise(key, promises[key])
|
|
6660
|
+
);
|
|
6661
|
+
return await Promise.race(wrapped);
|
|
6662
|
+
}
|
|
6663
|
+
|
|
6286
6664
|
// ../shared/src/sentinels.ts
|
|
6287
6665
|
function emptyFunction() {
|
|
6288
6666
|
}
|
|
@@ -6292,38 +6670,6 @@ function identity(x) {
|
|
|
6292
6670
|
return x;
|
|
6293
6671
|
}
|
|
6294
6672
|
|
|
6295
|
-
// ../shared/src/subscribable.ts
|
|
6296
|
-
var Subscribable = class {
|
|
6297
|
-
_listeners = /* @__PURE__ */ new Set();
|
|
6298
|
-
/**
|
|
6299
|
-
* Subscribe to the subscribable.
|
|
6300
|
-
*
|
|
6301
|
-
* @param listener - The listener to subscribe to.
|
|
6302
|
-
* @returns A function to unsubscribe from the subscribable.
|
|
6303
|
-
*/
|
|
6304
|
-
subscribe = (listener) => {
|
|
6305
|
-
this._listeners.add(listener);
|
|
6306
|
-
return () => {
|
|
6307
|
-
this._listeners.delete(listener);
|
|
6308
|
-
};
|
|
6309
|
-
};
|
|
6310
|
-
/**
|
|
6311
|
-
* Notify all listeners.
|
|
6312
|
-
*
|
|
6313
|
-
* @param update - The update to notify listeners with.
|
|
6314
|
-
*/
|
|
6315
|
-
notify = (update) => {
|
|
6316
|
-
this._listeners.forEach((listener) => listener(update));
|
|
6317
|
-
};
|
|
6318
|
-
hasListeners = () => this._listeners.size > 0;
|
|
6319
|
-
/**
|
|
6320
|
-
* Unsubscribe all listeners.
|
|
6321
|
-
*/
|
|
6322
|
-
cleanup = () => {
|
|
6323
|
-
this._listeners.clear();
|
|
6324
|
-
};
|
|
6325
|
-
};
|
|
6326
|
-
|
|
6327
6673
|
// ../zero-protocol/src/delete-clients.ts
|
|
6328
6674
|
var deleteClientsBodySchema = valita_exports.union(
|
|
6329
6675
|
readonlyObject({
|
|
@@ -6401,56 +6747,6 @@ function encodeSecProtocols(initConnectionMessage, authToken) {
|
|
|
6401
6747
|
return encodeURIComponent(btoa(s));
|
|
6402
6748
|
}
|
|
6403
6749
|
|
|
6404
|
-
// ../zero-protocol/src/error.ts
|
|
6405
|
-
var basicErrorKindSchema = literalUnion(
|
|
6406
|
-
error_kind_enum_exports.AuthInvalidated,
|
|
6407
|
-
error_kind_enum_exports.ClientNotFound,
|
|
6408
|
-
error_kind_enum_exports.InvalidConnectionRequest,
|
|
6409
|
-
error_kind_enum_exports.InvalidConnectionRequestBaseCookie,
|
|
6410
|
-
error_kind_enum_exports.InvalidConnectionRequestLastMutationID,
|
|
6411
|
-
error_kind_enum_exports.InvalidConnectionRequestClientDeleted,
|
|
6412
|
-
error_kind_enum_exports.InvalidMessage,
|
|
6413
|
-
error_kind_enum_exports.InvalidPush,
|
|
6414
|
-
error_kind_enum_exports.MutationRateLimited,
|
|
6415
|
-
error_kind_enum_exports.MutationFailed,
|
|
6416
|
-
error_kind_enum_exports.Unauthorized,
|
|
6417
|
-
error_kind_enum_exports.VersionNotSupported,
|
|
6418
|
-
error_kind_enum_exports.SchemaVersionNotSupported,
|
|
6419
|
-
error_kind_enum_exports.Internal
|
|
6420
|
-
);
|
|
6421
|
-
var basicErrorBodySchema = valita_exports.object({
|
|
6422
|
-
kind: basicErrorKindSchema,
|
|
6423
|
-
message: valita_exports.string()
|
|
6424
|
-
});
|
|
6425
|
-
var backoffErrorKindSchema = literalUnion(
|
|
6426
|
-
error_kind_enum_exports.Rebalance,
|
|
6427
|
-
error_kind_enum_exports.Rehome,
|
|
6428
|
-
error_kind_enum_exports.ServerOverloaded
|
|
6429
|
-
);
|
|
6430
|
-
var backoffBodySchema = valita_exports.object({
|
|
6431
|
-
kind: backoffErrorKindSchema,
|
|
6432
|
-
message: valita_exports.string(),
|
|
6433
|
-
minBackoffMs: valita_exports.number().optional(),
|
|
6434
|
-
maxBackoffMs: valita_exports.number().optional(),
|
|
6435
|
-
// Query parameters to send in the next reconnect. In the event of
|
|
6436
|
-
// a conflict, these will be overridden by the parameters used by
|
|
6437
|
-
// the client; it is the responsibility of the server to avoid
|
|
6438
|
-
// parameter name conflicts.
|
|
6439
|
-
//
|
|
6440
|
-
// The parameters will only be added to the immediately following
|
|
6441
|
-
// reconnect, and not after that.
|
|
6442
|
-
reconnectParams: valita_exports.record(valita_exports.string()).optional()
|
|
6443
|
-
});
|
|
6444
|
-
var errorKindSchema = valita_exports.union(
|
|
6445
|
-
basicErrorKindSchema,
|
|
6446
|
-
backoffErrorKindSchema
|
|
6447
|
-
);
|
|
6448
|
-
var errorBodySchema = valita_exports.union(basicErrorBodySchema, backoffBodySchema);
|
|
6449
|
-
var errorMessageSchema = valita_exports.tuple([
|
|
6450
|
-
valita_exports.literal("error"),
|
|
6451
|
-
errorBodySchema
|
|
6452
|
-
]);
|
|
6453
|
-
|
|
6454
6750
|
// ../zero-protocol/src/mutation-type-enum.ts
|
|
6455
6751
|
var CRUD = "crud";
|
|
6456
6752
|
var Custom = "custom";
|
|
@@ -6522,17 +6818,17 @@ var pushBodySchema = valita_exports.object({
|
|
|
6522
6818
|
requestID: valita_exports.string()
|
|
6523
6819
|
});
|
|
6524
6820
|
var pushMessageSchema = valita_exports.tuple([valita_exports.literal("push"), pushBodySchema]);
|
|
6525
|
-
var mutationIDSchema = valita_exports.object({
|
|
6526
|
-
id: valita_exports.number(),
|
|
6527
|
-
clientID: valita_exports.string()
|
|
6528
|
-
});
|
|
6529
6821
|
var appErrorSchema = valita_exports.object({
|
|
6530
6822
|
error: valita_exports.literal("app"),
|
|
6531
6823
|
// The user can return any additional data here
|
|
6532
6824
|
details: jsonSchema.optional()
|
|
6533
6825
|
});
|
|
6534
6826
|
var zeroErrorSchema2 = valita_exports.object({
|
|
6535
|
-
error:
|
|
6827
|
+
error: valita_exports.union(
|
|
6828
|
+
/** @deprecated push oooMutation errors are now represented as ['error', { ... }] messages */
|
|
6829
|
+
valita_exports.literal("oooMutation"),
|
|
6830
|
+
valita_exports.literal("alreadyProcessed")
|
|
6831
|
+
),
|
|
6536
6832
|
details: jsonSchema.optional()
|
|
6537
6833
|
});
|
|
6538
6834
|
var mutationOkSchema = valita_exports.object({
|
|
@@ -6552,28 +6848,33 @@ var pushOkSchema = valita_exports.object({
|
|
|
6552
6848
|
mutations: valita_exports.array(mutationResponseSchema)
|
|
6553
6849
|
});
|
|
6554
6850
|
var unsupportedPushVersionSchema = valita_exports.object({
|
|
6851
|
+
/** @deprecated */
|
|
6555
6852
|
error: valita_exports.literal("unsupportedPushVersion"),
|
|
6556
|
-
|
|
6557
|
-
// This field is included so the client knows which mutations
|
|
6558
|
-
// were not processed by the server.
|
|
6853
|
+
/** @deprecated */
|
|
6559
6854
|
mutationIDs: valita_exports.array(mutationIDSchema).optional()
|
|
6560
6855
|
});
|
|
6561
6856
|
var unsupportedSchemaVersionSchema = valita_exports.object({
|
|
6857
|
+
/** @deprecated */
|
|
6562
6858
|
error: valita_exports.literal("unsupportedSchemaVersion"),
|
|
6563
|
-
|
|
6564
|
-
// This field is included so the client knows which mutations
|
|
6565
|
-
// were not processed by the server.
|
|
6859
|
+
/** @deprecated */
|
|
6566
6860
|
mutationIDs: valita_exports.array(mutationIDSchema).optional()
|
|
6567
6861
|
});
|
|
6568
6862
|
var httpErrorSchema = valita_exports.object({
|
|
6863
|
+
/** @deprecated */
|
|
6569
6864
|
error: valita_exports.literal("http"),
|
|
6865
|
+
/** @deprecated */
|
|
6570
6866
|
status: valita_exports.number(),
|
|
6867
|
+
/** @deprecated */
|
|
6571
6868
|
details: valita_exports.string(),
|
|
6869
|
+
/** @deprecated */
|
|
6572
6870
|
mutationIDs: valita_exports.array(mutationIDSchema).optional()
|
|
6573
6871
|
});
|
|
6574
6872
|
var zeroPusherErrorSchema = valita_exports.object({
|
|
6873
|
+
/** @deprecated */
|
|
6575
6874
|
error: valita_exports.literal("zeroPusher"),
|
|
6875
|
+
/** @deprecated */
|
|
6576
6876
|
details: valita_exports.string(),
|
|
6877
|
+
/** @deprecated */
|
|
6577
6878
|
mutationIDs: valita_exports.array(mutationIDSchema).optional()
|
|
6578
6879
|
});
|
|
6579
6880
|
var pushErrorSchema = valita_exports.union(
|
|
@@ -6582,10 +6883,14 @@ var pushErrorSchema = valita_exports.union(
|
|
|
6582
6883
|
httpErrorSchema,
|
|
6583
6884
|
zeroPusherErrorSchema
|
|
6584
6885
|
);
|
|
6585
|
-
var
|
|
6886
|
+
var pushResponseBodySchema = valita_exports.union(pushOkSchema, pushErrorSchema);
|
|
6887
|
+
var pushResponseSchema = valita_exports.union(
|
|
6888
|
+
pushResponseBodySchema,
|
|
6889
|
+
pushFailedBodySchema
|
|
6890
|
+
);
|
|
6586
6891
|
var pushResponseMessageSchema = valita_exports.tuple([
|
|
6587
6892
|
valita_exports.literal("pushResponse"),
|
|
6588
|
-
|
|
6893
|
+
pushResponseBodySchema
|
|
6589
6894
|
]);
|
|
6590
6895
|
var ackMutationResponsesMessageSchema = valita_exports.tuple([
|
|
6591
6896
|
valita_exports.literal("ackMutationResponses"),
|
|
@@ -6750,7 +7055,7 @@ var downstreamSchema = valita_exports.union(
|
|
|
6750
7055
|
);
|
|
6751
7056
|
|
|
6752
7057
|
// ../zero-protocol/src/protocol-version.ts
|
|
6753
|
-
var PROTOCOL_VERSION =
|
|
7058
|
+
var PROTOCOL_VERSION = 38;
|
|
6754
7059
|
var MIN_SERVER_SUPPORTED_SYNC_PROTOCOL = 18;
|
|
6755
7060
|
assert(MIN_SERVER_SUPPORTED_SYNC_PROTOCOL < PROTOCOL_VERSION);
|
|
6756
7061
|
|
|
@@ -9302,200 +9607,1450 @@ var UnionFanOut = class {
|
|
|
9302
9607
|
}
|
|
9303
9608
|
};
|
|
9304
9609
|
|
|
9305
|
-
// ../zql/src/
|
|
9306
|
-
var
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9610
|
+
// ../zql/src/planner/planner-fan-in.ts
|
|
9611
|
+
var PlannerFanIn = class {
|
|
9612
|
+
kind = "fan-in";
|
|
9613
|
+
#type;
|
|
9614
|
+
#output;
|
|
9615
|
+
#inputs;
|
|
9616
|
+
constructor(inputs) {
|
|
9617
|
+
this.#type = "FI";
|
|
9618
|
+
this.#inputs = inputs;
|
|
9311
9619
|
}
|
|
9312
|
-
get
|
|
9313
|
-
return this;
|
|
9620
|
+
get type() {
|
|
9621
|
+
return this.#type;
|
|
9314
9622
|
}
|
|
9315
|
-
|
|
9316
|
-
return
|
|
9623
|
+
closestJoinOrSource() {
|
|
9624
|
+
return "join";
|
|
9317
9625
|
}
|
|
9318
|
-
|
|
9319
|
-
|
|
9320
|
-
type: "simple",
|
|
9321
|
-
left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
|
|
9322
|
-
right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
|
|
9323
|
-
op
|
|
9324
|
-
};
|
|
9626
|
+
setOutput(node) {
|
|
9627
|
+
this.#output = node;
|
|
9325
9628
|
}
|
|
9326
|
-
|
|
9327
|
-
|
|
9328
|
-
|
|
9329
|
-
exists = (relationship, cb, options) => this.#exists(relationship, cb, options);
|
|
9330
|
-
};
|
|
9331
|
-
function and(...conditions) {
|
|
9332
|
-
const expressions = filterTrue(filterUndefined(conditions));
|
|
9333
|
-
if (expressions.length === 1) {
|
|
9334
|
-
return expressions[0];
|
|
9629
|
+
get output() {
|
|
9630
|
+
assert(this.#output !== void 0, "Output not set");
|
|
9631
|
+
return this.#output;
|
|
9335
9632
|
}
|
|
9336
|
-
|
|
9337
|
-
|
|
9633
|
+
reset() {
|
|
9634
|
+
this.#type = "FI";
|
|
9338
9635
|
}
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
function or(...conditions) {
|
|
9342
|
-
const expressions = filterFalse(filterUndefined(conditions));
|
|
9343
|
-
if (expressions.length === 1) {
|
|
9344
|
-
return expressions[0];
|
|
9636
|
+
convertToUFI() {
|
|
9637
|
+
this.#type = "UFI";
|
|
9345
9638
|
}
|
|
9346
|
-
|
|
9347
|
-
|
|
9639
|
+
/**
|
|
9640
|
+
* Propagate unlimiting when a parent join is flipped.
|
|
9641
|
+
* Fan-in propagates to all of its inputs.
|
|
9642
|
+
*/
|
|
9643
|
+
propagateUnlimitFromFlippedJoin() {
|
|
9644
|
+
for (const input of this.#inputs) {
|
|
9645
|
+
if ("propagateUnlimitFromFlippedJoin" in input && typeof input.propagateUnlimitFromFlippedJoin === "function") {
|
|
9646
|
+
input.propagateUnlimitFromFlippedJoin();
|
|
9647
|
+
}
|
|
9648
|
+
}
|
|
9348
9649
|
}
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9650
|
+
estimateCost(branchPattern) {
|
|
9651
|
+
let totalCost = {
|
|
9652
|
+
rows: 0,
|
|
9653
|
+
runningCost: 0,
|
|
9654
|
+
startupCost: 0,
|
|
9655
|
+
selectivity: 0,
|
|
9656
|
+
limit: void 0
|
|
9657
|
+
};
|
|
9658
|
+
branchPattern = branchPattern ?? [];
|
|
9659
|
+
if (this.#type === "FI") {
|
|
9660
|
+
const updatedPattern = [0, ...branchPattern];
|
|
9661
|
+
let maxrows = 0;
|
|
9662
|
+
let maxRunningCost = 0;
|
|
9663
|
+
let maxStartupCost = 0;
|
|
9664
|
+
let noMatchProb = 1;
|
|
9665
|
+
for (const input of this.#inputs) {
|
|
9666
|
+
const cost = input.estimateCost(updatedPattern);
|
|
9667
|
+
if (cost.rows > maxrows) {
|
|
9668
|
+
maxrows = cost.rows;
|
|
9669
|
+
}
|
|
9670
|
+
if (cost.runningCost > maxRunningCost) {
|
|
9671
|
+
maxRunningCost = cost.runningCost;
|
|
9672
|
+
}
|
|
9673
|
+
if (cost.startupCost > maxStartupCost) {
|
|
9674
|
+
maxStartupCost = cost.startupCost;
|
|
9675
|
+
}
|
|
9676
|
+
noMatchProb *= 1 - cost.selectivity;
|
|
9677
|
+
assert(
|
|
9678
|
+
totalCost.limit === void 0 || cost.limit === totalCost.limit,
|
|
9679
|
+
"All FanIn inputs should have the same limit"
|
|
9680
|
+
);
|
|
9681
|
+
totalCost.limit = cost.limit;
|
|
9682
|
+
}
|
|
9683
|
+
totalCost.rows = maxrows;
|
|
9684
|
+
totalCost.runningCost = maxRunningCost;
|
|
9685
|
+
totalCost.startupCost = maxStartupCost;
|
|
9686
|
+
totalCost.selectivity = 1 - noMatchProb;
|
|
9687
|
+
} else {
|
|
9688
|
+
let i = 0;
|
|
9689
|
+
let noMatchProb = 1;
|
|
9690
|
+
for (const input of this.#inputs) {
|
|
9691
|
+
const updatedPattern = [i, ...branchPattern];
|
|
9692
|
+
const cost = input.estimateCost(updatedPattern);
|
|
9693
|
+
totalCost.rows += cost.rows;
|
|
9694
|
+
totalCost.runningCost += cost.runningCost;
|
|
9695
|
+
totalCost.startupCost += cost.startupCost;
|
|
9696
|
+
noMatchProb *= 1 - cost.selectivity;
|
|
9697
|
+
assert(
|
|
9698
|
+
totalCost.limit === void 0 || cost.limit === totalCost.limit,
|
|
9699
|
+
"All FanIn inputs should have the same limit"
|
|
9700
|
+
);
|
|
9701
|
+
totalCost.limit = cost.limit;
|
|
9702
|
+
i++;
|
|
9703
|
+
}
|
|
9704
|
+
totalCost.selectivity = 1 - noMatchProb;
|
|
9705
|
+
}
|
|
9706
|
+
return totalCost;
|
|
9376
9707
|
}
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9708
|
+
propagateConstraints(branchPattern, constraint, from) {
|
|
9709
|
+
if (this.#type === "FI") {
|
|
9710
|
+
const updatedPattern = [0, ...branchPattern];
|
|
9711
|
+
for (const input of this.#inputs) {
|
|
9712
|
+
input.propagateConstraints(updatedPattern, constraint, from);
|
|
9713
|
+
}
|
|
9714
|
+
return;
|
|
9715
|
+
}
|
|
9716
|
+
let i = 0;
|
|
9717
|
+
for (const input of this.#inputs) {
|
|
9718
|
+
input.propagateConstraints([i, ...branchPattern], constraint, from);
|
|
9719
|
+
i++;
|
|
9720
|
+
}
|
|
9385
9721
|
}
|
|
9386
|
-
return {
|
|
9387
|
-
type: "simple",
|
|
9388
|
-
left: { type: "column", name: field },
|
|
9389
|
-
right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
|
|
9390
|
-
op
|
|
9391
|
-
};
|
|
9392
|
-
}
|
|
9393
|
-
function isParameterReference(value) {
|
|
9394
|
-
return value !== null && typeof value === "object" && value[toStaticParam];
|
|
9395
|
-
}
|
|
9396
|
-
var TRUE = {
|
|
9397
|
-
type: "and",
|
|
9398
|
-
conditions: []
|
|
9399
|
-
};
|
|
9400
|
-
var FALSE = {
|
|
9401
|
-
type: "or",
|
|
9402
|
-
conditions: []
|
|
9403
9722
|
};
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
9408
|
-
|
|
9409
|
-
|
|
9410
|
-
|
|
9411
|
-
|
|
9412
|
-
|
|
9723
|
+
|
|
9724
|
+
// ../zql/src/planner/planner-fan-out.ts
|
|
9725
|
+
var PlannerFanOut = class {
|
|
9726
|
+
kind = "fan-out";
|
|
9727
|
+
#type;
|
|
9728
|
+
#outputs = [];
|
|
9729
|
+
#input;
|
|
9730
|
+
constructor(input) {
|
|
9731
|
+
this.#type = "FO";
|
|
9732
|
+
this.#input = input;
|
|
9413
9733
|
}
|
|
9414
|
-
|
|
9415
|
-
return
|
|
9734
|
+
get type() {
|
|
9735
|
+
return this.#type;
|
|
9416
9736
|
}
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
return FALSE;
|
|
9737
|
+
addOutput(node) {
|
|
9738
|
+
this.#outputs.push(node);
|
|
9420
9739
|
}
|
|
9421
|
-
|
|
9422
|
-
return
|
|
9740
|
+
get outputs() {
|
|
9741
|
+
return this.#outputs;
|
|
9423
9742
|
}
|
|
9424
|
-
|
|
9425
|
-
|
|
9426
|
-
|
|
9427
|
-
|
|
9428
|
-
|
|
9429
|
-
|
|
9430
|
-
|
|
9431
|
-
|
|
9432
|
-
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9743
|
+
closestJoinOrSource() {
|
|
9744
|
+
return this.#input.closestJoinOrSource();
|
|
9745
|
+
}
|
|
9746
|
+
propagateConstraints(branchPattern, constraint, _from) {
|
|
9747
|
+
this.#input.propagateConstraints(branchPattern, constraint, this);
|
|
9748
|
+
}
|
|
9749
|
+
estimateCost(branchPattern) {
|
|
9750
|
+
return this.#input.estimateCost(branchPattern);
|
|
9751
|
+
}
|
|
9752
|
+
convertToUFO() {
|
|
9753
|
+
this.#type = "UFO";
|
|
9754
|
+
}
|
|
9755
|
+
reset() {
|
|
9756
|
+
this.#type = "FO";
|
|
9757
|
+
}
|
|
9758
|
+
/**
|
|
9759
|
+
* Propagate unlimiting when a parent join is flipped.
|
|
9760
|
+
* Fan-out propagates to its input.
|
|
9761
|
+
*/
|
|
9762
|
+
propagateUnlimitFromFlippedJoin() {
|
|
9763
|
+
if ("propagateUnlimitFromFlippedJoin" in this.#input && typeof this.#input.propagateUnlimitFromFlippedJoin === "function") {
|
|
9764
|
+
this.#input.propagateUnlimitFromFlippedJoin();
|
|
9436
9765
|
}
|
|
9437
9766
|
}
|
|
9438
|
-
return flattened;
|
|
9439
|
-
}
|
|
9440
|
-
var negateSimpleOperatorMap = {
|
|
9441
|
-
["="]: "!=",
|
|
9442
|
-
["!="]: "=",
|
|
9443
|
-
["<"]: ">=",
|
|
9444
|
-
[">"]: "<=",
|
|
9445
|
-
[">="]: "<",
|
|
9446
|
-
["<="]: ">",
|
|
9447
|
-
["IN"]: "NOT IN",
|
|
9448
|
-
["NOT IN"]: "IN",
|
|
9449
|
-
["LIKE"]: "NOT LIKE",
|
|
9450
|
-
["NOT LIKE"]: "LIKE",
|
|
9451
|
-
["ILIKE"]: "NOT ILIKE",
|
|
9452
|
-
["NOT ILIKE"]: "ILIKE",
|
|
9453
|
-
["IS"]: "IS NOT",
|
|
9454
|
-
["IS NOT"]: "IS"
|
|
9455
|
-
};
|
|
9456
|
-
var negateOperatorMap = {
|
|
9457
|
-
...negateSimpleOperatorMap,
|
|
9458
|
-
["EXISTS"]: "NOT EXISTS",
|
|
9459
|
-
["NOT EXISTS"]: "EXISTS"
|
|
9460
9767
|
};
|
|
9461
|
-
function negateOperator(op) {
|
|
9462
|
-
return must(negateOperatorMap[op]);
|
|
9463
|
-
}
|
|
9464
|
-
function filterUndefined(array9) {
|
|
9465
|
-
return array9.filter((e) => e !== void 0);
|
|
9466
|
-
}
|
|
9467
|
-
function filterTrue(conditions) {
|
|
9468
|
-
return conditions.filter((c) => !isAlwaysTrue(c));
|
|
9469
|
-
}
|
|
9470
|
-
function filterFalse(conditions) {
|
|
9471
|
-
return conditions.filter((c) => !isAlwaysFalse(c));
|
|
9472
|
-
}
|
|
9473
9768
|
|
|
9474
|
-
// ../zql/src/
|
|
9475
|
-
function
|
|
9476
|
-
|
|
9477
|
-
|
|
9478
|
-
|
|
9479
|
-
return op(String(lhs));
|
|
9480
|
-
};
|
|
9769
|
+
// ../zql/src/planner/planner-constraint.ts
|
|
9770
|
+
function mergeConstraints(a, b) {
|
|
9771
|
+
if (!a) return b;
|
|
9772
|
+
if (!b) return a;
|
|
9773
|
+
return { ...a, ...b };
|
|
9481
9774
|
}
|
|
9482
|
-
|
|
9483
|
-
|
|
9484
|
-
|
|
9485
|
-
|
|
9486
|
-
|
|
9775
|
+
|
|
9776
|
+
// ../zql/src/planner/planner-connection.ts
|
|
9777
|
+
var PlannerConnection = class {
|
|
9778
|
+
kind = "connection";
|
|
9779
|
+
// ========================================================================
|
|
9780
|
+
// IMMUTABLE STRUCTURE (set during construction, never changes)
|
|
9781
|
+
// ========================================================================
|
|
9782
|
+
#sort;
|
|
9783
|
+
#filters;
|
|
9784
|
+
#model;
|
|
9785
|
+
table;
|
|
9786
|
+
name;
|
|
9787
|
+
// Human-readable name for debugging (defaults to table name)
|
|
9788
|
+
#baseConstraints;
|
|
9789
|
+
// Constraints from parent correlation
|
|
9790
|
+
#baseLimit;
|
|
9791
|
+
// Original limit from query structure (never modified)
|
|
9792
|
+
selectivity;
|
|
9793
|
+
// Fraction of rows passing filters (1.0 = no filtering)
|
|
9794
|
+
#output;
|
|
9795
|
+
// Set once during graph construction
|
|
9796
|
+
// ========================================================================
|
|
9797
|
+
// MUTABLE PLANNING STATE (changes during plan search)
|
|
9798
|
+
// ========================================================================
|
|
9799
|
+
/**
|
|
9800
|
+
* Current limit during planning. Can be cleared (set to undefined) when a
|
|
9801
|
+
* parent join is flipped, indicating this connection is now in an outer loop
|
|
9802
|
+
* and should not be limited by EXISTS semantics.
|
|
9803
|
+
*/
|
|
9804
|
+
limit;
|
|
9805
|
+
/**
|
|
9806
|
+
* Constraints accumulated from parent joins during planning.
|
|
9807
|
+
* Key is a path through the graph (e.g., "0,1" for branch pattern [0,1]).
|
|
9808
|
+
*
|
|
9809
|
+
* Undefined constraints are possible when a FO converts to UFO and only
|
|
9810
|
+
* a single join in the UFO is flipped - other branches report undefined.
|
|
9811
|
+
*/
|
|
9812
|
+
#constraints;
|
|
9813
|
+
/**
|
|
9814
|
+
* Cached total cost (sum of all branches) to avoid redundant calculations.
|
|
9815
|
+
* Invalidated when constraints change.
|
|
9816
|
+
*/
|
|
9817
|
+
#cachedTotalCost = void 0;
|
|
9818
|
+
/**
|
|
9819
|
+
* Cached per-constraint costs to avoid redundant cost model calls.
|
|
9820
|
+
* Maps constraint key (branch pattern string) to computed cost.
|
|
9821
|
+
* Invalidated when constraints change.
|
|
9822
|
+
*/
|
|
9823
|
+
#cachedConstraintCosts = /* @__PURE__ */ new Map();
|
|
9824
|
+
#costDirty = true;
|
|
9825
|
+
constructor(table2, model, sort, filters, baseConstraints, limit, name) {
|
|
9826
|
+
this.table = table2;
|
|
9827
|
+
this.name = name ?? table2;
|
|
9828
|
+
this.#sort = sort;
|
|
9829
|
+
this.#filters = filters;
|
|
9830
|
+
this.#model = model;
|
|
9831
|
+
this.#baseConstraints = baseConstraints;
|
|
9832
|
+
this.#baseLimit = limit;
|
|
9833
|
+
this.limit = limit;
|
|
9834
|
+
this.#constraints = /* @__PURE__ */ new Map();
|
|
9835
|
+
if (limit !== void 0 && filters) {
|
|
9836
|
+
const costWithFilters = model(table2, sort, filters, void 0);
|
|
9837
|
+
const costWithoutFilters = model(table2, sort, void 0, void 0);
|
|
9838
|
+
this.selectivity = costWithoutFilters.rows > 0 ? costWithFilters.rows / costWithoutFilters.rows : 1;
|
|
9839
|
+
} else {
|
|
9840
|
+
this.selectivity = 1;
|
|
9487
9841
|
}
|
|
9488
|
-
return (lhs) => lhs === pattern;
|
|
9489
9842
|
}
|
|
9490
|
-
|
|
9491
|
-
|
|
9492
|
-
}
|
|
9493
|
-
|
|
9494
|
-
|
|
9495
|
-
|
|
9496
|
-
|
|
9497
|
-
|
|
9498
|
-
|
|
9843
|
+
setOutput(node) {
|
|
9844
|
+
this.#output = node;
|
|
9845
|
+
}
|
|
9846
|
+
get output() {
|
|
9847
|
+
assert(this.#output !== void 0, "Output not set");
|
|
9848
|
+
return this.#output;
|
|
9849
|
+
}
|
|
9850
|
+
closestJoinOrSource() {
|
|
9851
|
+
return "connection";
|
|
9852
|
+
}
|
|
9853
|
+
/**
|
|
9854
|
+
* Constraints are uniquely identified by their path through the
|
|
9855
|
+
* graph.
|
|
9856
|
+
*
|
|
9857
|
+
* FO represents all sub-joins as a single path.
|
|
9858
|
+
* UFO represents each sub-join as a separate path.
|
|
9859
|
+
* The first branch in a UFO will match the path of FO so no re-set needs to happen
|
|
9860
|
+
* when swapping from FO to UFO.
|
|
9861
|
+
*
|
|
9862
|
+
* FO swaps to UFO when a join inside FO-FI gets flipped.
|
|
9863
|
+
*
|
|
9864
|
+
* The max of the last element of the paths is the number of
|
|
9865
|
+
* root branches.
|
|
9866
|
+
*/
|
|
9867
|
+
propagateConstraints(path, c) {
|
|
9868
|
+
const key = path.join(",");
|
|
9869
|
+
this.#constraints.set(key, c);
|
|
9870
|
+
this.#cachedTotalCost = void 0;
|
|
9871
|
+
this.#cachedConstraintCosts.clear();
|
|
9872
|
+
this.#costDirty = true;
|
|
9873
|
+
}
|
|
9874
|
+
estimateCost(branchPattern) {
|
|
9875
|
+
if (branchPattern === void 0) {
|
|
9876
|
+
if (!this.#costDirty && this.#cachedTotalCost !== void 0) {
|
|
9877
|
+
return this.#cachedTotalCost;
|
|
9878
|
+
}
|
|
9879
|
+
let totalRows = 0;
|
|
9880
|
+
let maxStartupCost = 0;
|
|
9881
|
+
if (this.#constraints.size === 0) {
|
|
9882
|
+
const key2 = "";
|
|
9883
|
+
let cost2 = this.#cachedConstraintCosts.get(key2);
|
|
9884
|
+
if (cost2 === void 0) {
|
|
9885
|
+
const { startupCost: startupCost2, rows: rows2 } = this.#model(
|
|
9886
|
+
this.table,
|
|
9887
|
+
this.#sort,
|
|
9888
|
+
this.#filters,
|
|
9889
|
+
this.#baseConstraints
|
|
9890
|
+
);
|
|
9891
|
+
cost2 = {
|
|
9892
|
+
rows: rows2,
|
|
9893
|
+
runningCost: rows2,
|
|
9894
|
+
startupCost: startupCost2,
|
|
9895
|
+
selectivity: this.selectivity,
|
|
9896
|
+
limit: this.limit
|
|
9897
|
+
};
|
|
9898
|
+
this.#cachedConstraintCosts.set(key2, cost2);
|
|
9899
|
+
}
|
|
9900
|
+
totalRows = cost2.rows;
|
|
9901
|
+
maxStartupCost = cost2.startupCost;
|
|
9902
|
+
} else {
|
|
9903
|
+
for (const [key2, constraint2] of this.#constraints.entries()) {
|
|
9904
|
+
let cost2 = this.#cachedConstraintCosts.get(key2);
|
|
9905
|
+
if (cost2 === void 0) {
|
|
9906
|
+
const mergedConstraint2 = mergeConstraints(
|
|
9907
|
+
this.#baseConstraints,
|
|
9908
|
+
constraint2
|
|
9909
|
+
);
|
|
9910
|
+
const { startupCost: startupCost2, rows: rows2 } = this.#model(
|
|
9911
|
+
this.table,
|
|
9912
|
+
this.#sort,
|
|
9913
|
+
this.#filters,
|
|
9914
|
+
mergedConstraint2
|
|
9915
|
+
);
|
|
9916
|
+
cost2 = {
|
|
9917
|
+
rows: rows2,
|
|
9918
|
+
runningCost: rows2,
|
|
9919
|
+
startupCost: startupCost2,
|
|
9920
|
+
selectivity: this.selectivity,
|
|
9921
|
+
limit: this.limit
|
|
9922
|
+
};
|
|
9923
|
+
this.#cachedConstraintCosts.set(key2, cost2);
|
|
9924
|
+
}
|
|
9925
|
+
totalRows += cost2.rows;
|
|
9926
|
+
maxStartupCost = Math.max(maxStartupCost, cost2.startupCost);
|
|
9927
|
+
}
|
|
9928
|
+
}
|
|
9929
|
+
const ret = {
|
|
9930
|
+
rows: totalRows,
|
|
9931
|
+
runningCost: totalRows,
|
|
9932
|
+
startupCost: maxStartupCost,
|
|
9933
|
+
selectivity: this.selectivity,
|
|
9934
|
+
limit: this.limit
|
|
9935
|
+
};
|
|
9936
|
+
this.#cachedTotalCost = ret;
|
|
9937
|
+
this.#costDirty = false;
|
|
9938
|
+
return ret;
|
|
9939
|
+
}
|
|
9940
|
+
const key = branchPattern.join(",");
|
|
9941
|
+
let cost = this.#cachedConstraintCosts.get(key);
|
|
9942
|
+
if (cost !== void 0) {
|
|
9943
|
+
return cost;
|
|
9944
|
+
}
|
|
9945
|
+
const constraint = this.#constraints.get(key);
|
|
9946
|
+
const mergedConstraint = mergeConstraints(
|
|
9947
|
+
this.#baseConstraints,
|
|
9948
|
+
constraint
|
|
9949
|
+
);
|
|
9950
|
+
const { startupCost, rows } = this.#model(
|
|
9951
|
+
this.table,
|
|
9952
|
+
this.#sort,
|
|
9953
|
+
this.#filters,
|
|
9954
|
+
mergedConstraint
|
|
9955
|
+
);
|
|
9956
|
+
cost = {
|
|
9957
|
+
rows,
|
|
9958
|
+
runningCost: rows,
|
|
9959
|
+
startupCost,
|
|
9960
|
+
selectivity: this.selectivity,
|
|
9961
|
+
limit: this.limit
|
|
9962
|
+
};
|
|
9963
|
+
this.#cachedConstraintCosts.set(key, cost);
|
|
9964
|
+
return cost;
|
|
9965
|
+
}
|
|
9966
|
+
/**
|
|
9967
|
+
* Remove the limit from this connection.
|
|
9968
|
+
* Called when a parent join is flipped, making this connection part of an
|
|
9969
|
+
* outer loop that should produce all rows rather than stopping at the limit.
|
|
9970
|
+
*/
|
|
9971
|
+
unlimit() {
|
|
9972
|
+
if (this.limit !== void 0) {
|
|
9973
|
+
this.limit = void 0;
|
|
9974
|
+
}
|
|
9975
|
+
}
|
|
9976
|
+
/**
|
|
9977
|
+
* Propagate unlimiting when a parent join is flipped.
|
|
9978
|
+
* For connections, we simply remove the limit.
|
|
9979
|
+
*/
|
|
9980
|
+
propagateUnlimitFromFlippedJoin() {
|
|
9981
|
+
this.unlimit();
|
|
9982
|
+
}
|
|
9983
|
+
reset() {
|
|
9984
|
+
this.#constraints.clear();
|
|
9985
|
+
this.limit = this.#baseLimit;
|
|
9986
|
+
this.#cachedTotalCost = void 0;
|
|
9987
|
+
this.#cachedConstraintCosts.clear();
|
|
9988
|
+
this.#costDirty = true;
|
|
9989
|
+
}
|
|
9990
|
+
/**
|
|
9991
|
+
* Capture constraint state for snapshotting.
|
|
9992
|
+
* Used by PlannerGraph to save/restore planning state.
|
|
9993
|
+
*/
|
|
9994
|
+
captureConstraints() {
|
|
9995
|
+
return new Map(this.#constraints);
|
|
9996
|
+
}
|
|
9997
|
+
/**
|
|
9998
|
+
* Restore constraint state from a snapshot.
|
|
9999
|
+
* Used by PlannerGraph to restore planning state.
|
|
10000
|
+
*/
|
|
10001
|
+
restoreConstraints(constraints) {
|
|
10002
|
+
this.#constraints.clear();
|
|
10003
|
+
for (const [key, value] of constraints) {
|
|
10004
|
+
this.#constraints.set(key, value);
|
|
10005
|
+
}
|
|
10006
|
+
this.#cachedTotalCost = void 0;
|
|
10007
|
+
this.#cachedConstraintCosts.clear();
|
|
10008
|
+
this.#costDirty = true;
|
|
10009
|
+
}
|
|
10010
|
+
/**
|
|
10011
|
+
* Get current constraints for debugging.
|
|
10012
|
+
* Returns a copy of the constraints map.
|
|
10013
|
+
*/
|
|
10014
|
+
getConstraintsForDebug() {
|
|
10015
|
+
return new Map(this.#constraints);
|
|
10016
|
+
}
|
|
10017
|
+
/**
|
|
10018
|
+
* Get estimated cost for each constraint branch.
|
|
10019
|
+
* Returns a map of constraint key to cost estimate.
|
|
10020
|
+
* Forces cost calculation if not already cached.
|
|
10021
|
+
*/
|
|
10022
|
+
getConstraintCostsForDebug() {
|
|
10023
|
+
this.estimateCost(void 0);
|
|
10024
|
+
return new Map(this.#cachedConstraintCosts);
|
|
10025
|
+
}
|
|
10026
|
+
};
|
|
10027
|
+
|
|
10028
|
+
// ../zql/src/planner/planner-source.ts
|
|
10029
|
+
var PlannerSource = class {
|
|
10030
|
+
name;
|
|
10031
|
+
#model;
|
|
10032
|
+
constructor(name, model) {
|
|
10033
|
+
this.name = name;
|
|
10034
|
+
this.#model = model;
|
|
10035
|
+
}
|
|
10036
|
+
connect(sort, filters, baseConstraints, limit) {
|
|
10037
|
+
return new PlannerConnection(
|
|
10038
|
+
this.name,
|
|
10039
|
+
this.#model,
|
|
10040
|
+
sort,
|
|
10041
|
+
filters,
|
|
10042
|
+
baseConstraints,
|
|
10043
|
+
limit
|
|
10044
|
+
);
|
|
10045
|
+
}
|
|
10046
|
+
};
|
|
10047
|
+
|
|
10048
|
+
// ../zql/src/planner/planner-graph.ts
|
|
10049
|
+
var MAX_FLIPPABLE_JOINS = 13;
|
|
10050
|
+
var PlannerGraph = class {
|
|
10051
|
+
// Sources indexed by table name
|
|
10052
|
+
#sources = /* @__PURE__ */ new Map();
|
|
10053
|
+
// The final output node where constraint propagation starts
|
|
10054
|
+
#terminus = void 0;
|
|
10055
|
+
// Collections of nodes with mutable planning state
|
|
10056
|
+
joins = [];
|
|
10057
|
+
fanOuts = [];
|
|
10058
|
+
fanIns = [];
|
|
10059
|
+
connections = [];
|
|
10060
|
+
/**
|
|
10061
|
+
* Reset all planning state back to initial values for another planning pass.
|
|
10062
|
+
* Resets only mutable planning state - graph structure is unchanged.
|
|
10063
|
+
*
|
|
10064
|
+
* This allows replanning the same query graph with different strategies.
|
|
10065
|
+
*/
|
|
10066
|
+
resetPlanningState() {
|
|
10067
|
+
for (const j of this.joins) j.reset();
|
|
10068
|
+
for (const fo of this.fanOuts) fo.reset();
|
|
10069
|
+
for (const fi of this.fanIns) fi.reset();
|
|
10070
|
+
for (const c of this.connections) c.reset();
|
|
10071
|
+
}
|
|
10072
|
+
/**
|
|
10073
|
+
* Create and register a source (table) in the graph.
|
|
10074
|
+
*/
|
|
10075
|
+
addSource(name, model) {
|
|
10076
|
+
assert(
|
|
10077
|
+
!this.#sources.has(name),
|
|
10078
|
+
`Source ${name} already exists in the graph`
|
|
10079
|
+
);
|
|
10080
|
+
const source = new PlannerSource(name, model);
|
|
10081
|
+
this.#sources.set(name, source);
|
|
10082
|
+
return source;
|
|
10083
|
+
}
|
|
10084
|
+
/**
|
|
10085
|
+
* Get a source by table name.
|
|
10086
|
+
*/
|
|
10087
|
+
getSource(name) {
|
|
10088
|
+
const source = this.#sources.get(name);
|
|
10089
|
+
assert(source !== void 0, `Source ${name} not found in the graph`);
|
|
10090
|
+
return source;
|
|
10091
|
+
}
|
|
10092
|
+
/**
|
|
10093
|
+
* Check if a source exists by table name.
|
|
10094
|
+
*/
|
|
10095
|
+
hasSource(name) {
|
|
10096
|
+
return this.#sources.has(name);
|
|
10097
|
+
}
|
|
10098
|
+
/**
|
|
10099
|
+
* Set the terminus (final output) node of the graph.
|
|
10100
|
+
* Constraint propagation starts from this node.
|
|
10101
|
+
*/
|
|
10102
|
+
setTerminus(terminus) {
|
|
10103
|
+
this.#terminus = terminus;
|
|
10104
|
+
}
|
|
10105
|
+
/**
|
|
10106
|
+
* Initiate constraint propagation from the terminus node.
|
|
10107
|
+
* This sends constraints up through the graph to update
|
|
10108
|
+
* connection cost estimates.
|
|
10109
|
+
*/
|
|
10110
|
+
propagateConstraints() {
|
|
10111
|
+
assert(
|
|
10112
|
+
this.#terminus !== void 0,
|
|
10113
|
+
"Cannot propagate constraints without a terminus node"
|
|
10114
|
+
);
|
|
10115
|
+
this.#terminus.propagateConstraints();
|
|
10116
|
+
}
|
|
10117
|
+
/**
|
|
10118
|
+
* Calculate total cost of the current plan.
|
|
10119
|
+
* Total cost includes both startup cost (one-time, e.g., sorting) and running cost.
|
|
10120
|
+
*/
|
|
10121
|
+
getTotalCost() {
|
|
10122
|
+
const estimate = must(this.#terminus).estimateCost();
|
|
10123
|
+
return estimate.startupCost + estimate.runningCost;
|
|
10124
|
+
}
|
|
10125
|
+
/**
|
|
10126
|
+
* Capture a lightweight snapshot of the current planning state.
|
|
10127
|
+
* Used for backtracking during multi-start greedy search.
|
|
10128
|
+
*
|
|
10129
|
+
* Captures mutable state including pinned flags, join types, and
|
|
10130
|
+
* constraint maps to avoid needing repropagation on restore.
|
|
10131
|
+
*
|
|
10132
|
+
* @returns A snapshot that can be restored via restorePlanningSnapshot()
|
|
10133
|
+
*/
|
|
10134
|
+
capturePlanningSnapshot() {
|
|
10135
|
+
return {
|
|
10136
|
+
connections: this.connections.map((c) => ({
|
|
10137
|
+
limit: c.limit
|
|
10138
|
+
})),
|
|
10139
|
+
joins: this.joins.map((j) => ({ type: j.type })),
|
|
10140
|
+
fanOuts: this.fanOuts.map((fo) => ({ type: fo.type })),
|
|
10141
|
+
fanIns: this.fanIns.map((fi) => ({ type: fi.type })),
|
|
10142
|
+
connectionConstraints: this.connections.map((c) => c.captureConstraints())
|
|
10143
|
+
};
|
|
10144
|
+
}
|
|
10145
|
+
/**
|
|
10146
|
+
* Restore planning state from a previously captured snapshot.
|
|
10147
|
+
* Used for backtracking when a planning attempt fails.
|
|
10148
|
+
*
|
|
10149
|
+
* Restores pinned flags, join types, and constraint maps, eliminating
|
|
10150
|
+
* the need for repropagation.
|
|
10151
|
+
*
|
|
10152
|
+
* @param state - Snapshot created by capturePlanningSnapshot()
|
|
10153
|
+
*/
|
|
10154
|
+
restorePlanningSnapshot(state) {
|
|
10155
|
+
this.#validateSnapshotShape(state);
|
|
10156
|
+
this.#restoreConnections(state);
|
|
10157
|
+
this.#restoreJoins(state);
|
|
10158
|
+
this.#restoreFanNodes(state);
|
|
10159
|
+
}
|
|
10160
|
+
/**
|
|
10161
|
+
* Collect cost estimates from all nodes in the graph for debugging.
|
|
10162
|
+
*/
|
|
10163
|
+
#collectNodeCosts() {
|
|
10164
|
+
const costs = [];
|
|
10165
|
+
for (const c of this.connections) {
|
|
10166
|
+
costs.push({
|
|
10167
|
+
node: c.name,
|
|
10168
|
+
nodeType: "connection",
|
|
10169
|
+
costEstimate: c.estimateCost(void 0)
|
|
10170
|
+
});
|
|
10171
|
+
}
|
|
10172
|
+
for (const j of this.joins) {
|
|
10173
|
+
costs.push({
|
|
10174
|
+
node: j.getName(),
|
|
10175
|
+
nodeType: "join",
|
|
10176
|
+
costEstimate: j.estimateCost(void 0)
|
|
10177
|
+
});
|
|
10178
|
+
}
|
|
10179
|
+
for (const fo of this.fanOuts) {
|
|
10180
|
+
costs.push({
|
|
10181
|
+
node: "FO",
|
|
10182
|
+
nodeType: "fan-out",
|
|
10183
|
+
costEstimate: fo.estimateCost(void 0)
|
|
10184
|
+
});
|
|
10185
|
+
}
|
|
10186
|
+
for (const fi of this.fanIns) {
|
|
10187
|
+
costs.push({
|
|
10188
|
+
node: "FI",
|
|
10189
|
+
nodeType: "fan-in",
|
|
10190
|
+
costEstimate: fi.estimateCost(void 0)
|
|
10191
|
+
});
|
|
10192
|
+
}
|
|
10193
|
+
return costs;
|
|
10194
|
+
}
|
|
10195
|
+
/**
|
|
10196
|
+
* Validate that snapshot shape matches current graph structure.
|
|
10197
|
+
*/
|
|
10198
|
+
#validateSnapshotShape(state) {
|
|
10199
|
+
assert(
|
|
10200
|
+
this.connections.length === state.connections.length,
|
|
10201
|
+
"Plan state mismatch: connections"
|
|
10202
|
+
);
|
|
10203
|
+
assert(
|
|
10204
|
+
this.joins.length === state.joins.length,
|
|
10205
|
+
"Plan state mismatch: joins"
|
|
10206
|
+
);
|
|
10207
|
+
assert(
|
|
10208
|
+
this.fanOuts.length === state.fanOuts.length,
|
|
10209
|
+
"Plan state mismatch: fanOuts"
|
|
10210
|
+
);
|
|
10211
|
+
assert(
|
|
10212
|
+
this.fanIns.length === state.fanIns.length,
|
|
10213
|
+
"Plan state mismatch: fanIns"
|
|
10214
|
+
);
|
|
10215
|
+
assert(
|
|
10216
|
+
this.connections.length === state.connectionConstraints.length,
|
|
10217
|
+
"Plan state mismatch: connectionConstraints"
|
|
10218
|
+
);
|
|
10219
|
+
}
|
|
10220
|
+
/**
|
|
10221
|
+
* Restore connection pinned flags, limits, and constraint maps.
|
|
10222
|
+
*/
|
|
10223
|
+
#restoreConnections(state) {
|
|
10224
|
+
for (let i = 0; i < this.connections.length; i++) {
|
|
10225
|
+
this.connections[i].limit = state.connections[i].limit;
|
|
10226
|
+
this.connections[i].restoreConstraints(state.connectionConstraints[i]);
|
|
10227
|
+
}
|
|
10228
|
+
}
|
|
10229
|
+
/**
|
|
10230
|
+
* Restore join types and pinned flags.
|
|
10231
|
+
*/
|
|
10232
|
+
#restoreJoins(state) {
|
|
10233
|
+
for (let i = 0; i < this.joins.length; i++) {
|
|
10234
|
+
const join = this.joins[i];
|
|
10235
|
+
const targetState = state.joins[i];
|
|
10236
|
+
join.reset();
|
|
10237
|
+
if (targetState.type === "flipped") {
|
|
10238
|
+
join.flip();
|
|
10239
|
+
}
|
|
10240
|
+
}
|
|
10241
|
+
}
|
|
10242
|
+
/**
|
|
10243
|
+
* Restore FanOut and FanIn types.
|
|
10244
|
+
*/
|
|
10245
|
+
#restoreFanNodes(state) {
|
|
10246
|
+
for (let i = 0; i < this.fanOuts.length; i++) {
|
|
10247
|
+
const fo = this.fanOuts[i];
|
|
10248
|
+
const targetType = state.fanOuts[i].type;
|
|
10249
|
+
if (targetType === "UFO" && fo.type === "FO") {
|
|
10250
|
+
fo.convertToUFO();
|
|
10251
|
+
}
|
|
10252
|
+
}
|
|
10253
|
+
for (let i = 0; i < this.fanIns.length; i++) {
|
|
10254
|
+
const fi = this.fanIns[i];
|
|
10255
|
+
const targetType = state.fanIns[i].type;
|
|
10256
|
+
if (targetType === "UFI" && fi.type === "FI") {
|
|
10257
|
+
fi.convertToUFI();
|
|
10258
|
+
}
|
|
10259
|
+
}
|
|
10260
|
+
}
|
|
10261
|
+
/**
|
|
10262
|
+
* Main planning algorithm using exhaustive join flip enumeration.
|
|
10263
|
+
*
|
|
10264
|
+
* Enumerates all possible flip patterns for flippable joins (2^n for n flippable joins).
|
|
10265
|
+
* Each pattern represents a different query execution plan. We evaluate the cost of each
|
|
10266
|
+
* plan and select the one with the lowest cost.
|
|
10267
|
+
*
|
|
10268
|
+
* Connections are used only for cost estimation - the flip patterns determine the plan.
|
|
10269
|
+
* FanOut/FanIn states (FO/UFO and FI/UFI) are automatically derived from join flip states.
|
|
10270
|
+
*
|
|
10271
|
+
* @param planDebugger - Optional debugger to receive structured events during planning
|
|
10272
|
+
*/
|
|
10273
|
+
plan(planDebugger) {
|
|
10274
|
+
const flippableJoins = this.joins.filter((j) => j.isFlippable());
|
|
10275
|
+
if (flippableJoins.length > MAX_FLIPPABLE_JOINS) {
|
|
10276
|
+
throw new Error(
|
|
10277
|
+
`Query has ${flippableJoins.length} EXISTS checks in a single RELATED call (or in the top level query), which would require ${2 ** flippableJoins.length} plan evaluations. This may be very slow. Consider simplifying the query or increasing MAX_FLIPPABLE_JOINS (currently set to ${MAX_FLIPPABLE_JOINS}).`
|
|
10278
|
+
);
|
|
10279
|
+
}
|
|
10280
|
+
const fofiCache = buildFOFICache(this);
|
|
10281
|
+
const numPatterns = 2 ** flippableJoins.length;
|
|
10282
|
+
let bestCost = Infinity;
|
|
10283
|
+
let bestPlan = void 0;
|
|
10284
|
+
let bestAttemptNumber = -1;
|
|
10285
|
+
for (let pattern = 0; pattern < numPatterns; pattern++) {
|
|
10286
|
+
this.resetPlanningState();
|
|
10287
|
+
if (planDebugger) {
|
|
10288
|
+
planDebugger.log({
|
|
10289
|
+
type: "attempt-start",
|
|
10290
|
+
attemptNumber: pattern,
|
|
10291
|
+
totalAttempts: numPatterns
|
|
10292
|
+
});
|
|
10293
|
+
}
|
|
10294
|
+
try {
|
|
10295
|
+
for (let i = 0; i < flippableJoins.length; i++) {
|
|
10296
|
+
if (pattern & 1 << i) {
|
|
10297
|
+
flippableJoins[i].flip();
|
|
10298
|
+
}
|
|
10299
|
+
}
|
|
10300
|
+
checkAndConvertFOFI(fofiCache);
|
|
10301
|
+
propagateUnlimitForFlippedJoins(this);
|
|
10302
|
+
this.propagateConstraints();
|
|
10303
|
+
if (planDebugger) {
|
|
10304
|
+
planDebugger.log({
|
|
10305
|
+
type: "constraints-propagated",
|
|
10306
|
+
attemptNumber: pattern,
|
|
10307
|
+
connectionConstraints: this.connections.map((c) => ({
|
|
10308
|
+
connection: c.name,
|
|
10309
|
+
constraints: c.getConstraintsForDebug(),
|
|
10310
|
+
constraintCosts: c.getConstraintCostsForDebug()
|
|
10311
|
+
}))
|
|
10312
|
+
});
|
|
10313
|
+
}
|
|
10314
|
+
const totalCost = this.getTotalCost();
|
|
10315
|
+
if (planDebugger) {
|
|
10316
|
+
planDebugger.log({
|
|
10317
|
+
type: "plan-complete",
|
|
10318
|
+
attemptNumber: pattern,
|
|
10319
|
+
totalCost,
|
|
10320
|
+
nodeCosts: this.#collectNodeCosts(),
|
|
10321
|
+
joinStates: this.joins.map((j) => {
|
|
10322
|
+
const info = j.getDebugInfo();
|
|
10323
|
+
return {
|
|
10324
|
+
join: info.name,
|
|
10325
|
+
type: info.type
|
|
10326
|
+
};
|
|
10327
|
+
})
|
|
10328
|
+
});
|
|
10329
|
+
}
|
|
10330
|
+
if (totalCost < bestCost) {
|
|
10331
|
+
bestCost = totalCost;
|
|
10332
|
+
bestPlan = this.capturePlanningSnapshot();
|
|
10333
|
+
bestAttemptNumber = pattern;
|
|
10334
|
+
}
|
|
10335
|
+
} catch (e) {
|
|
10336
|
+
if (planDebugger) {
|
|
10337
|
+
planDebugger.log({
|
|
10338
|
+
type: "plan-failed",
|
|
10339
|
+
attemptNumber: pattern,
|
|
10340
|
+
reason: `Flip pattern ${pattern.toString(2)} failed: ${e instanceof Error ? e.message : String(e)}`
|
|
10341
|
+
});
|
|
10342
|
+
}
|
|
10343
|
+
continue;
|
|
10344
|
+
}
|
|
10345
|
+
}
|
|
10346
|
+
if (bestPlan) {
|
|
10347
|
+
this.restorePlanningSnapshot(bestPlan);
|
|
10348
|
+
this.propagateConstraints();
|
|
10349
|
+
if (planDebugger) {
|
|
10350
|
+
planDebugger.log({
|
|
10351
|
+
type: "best-plan-selected",
|
|
10352
|
+
bestAttemptNumber,
|
|
10353
|
+
totalCost: bestCost,
|
|
10354
|
+
joinStates: this.joins.map((j) => ({
|
|
10355
|
+
join: j.getName(),
|
|
10356
|
+
type: j.type
|
|
10357
|
+
}))
|
|
10358
|
+
});
|
|
10359
|
+
}
|
|
10360
|
+
} else {
|
|
10361
|
+
throw new Error(
|
|
10362
|
+
"No valid query plan found. This should not happen - check query structure."
|
|
10363
|
+
);
|
|
10364
|
+
}
|
|
10365
|
+
}
|
|
10366
|
+
};
|
|
10367
|
+
function buildFOFICache(graph) {
|
|
10368
|
+
const cache = /* @__PURE__ */ new Map();
|
|
10369
|
+
for (const fo of graph.fanOuts) {
|
|
10370
|
+
const info = findFIAndJoins(fo);
|
|
10371
|
+
cache.set(fo, info);
|
|
10372
|
+
}
|
|
10373
|
+
return cache;
|
|
10374
|
+
}
|
|
10375
|
+
function checkAndConvertFOFI(fofiCache) {
|
|
10376
|
+
for (const [fo, info] of fofiCache) {
|
|
10377
|
+
const hasFlippedJoin = info.joinsBetween.some((j) => j.type === "flipped");
|
|
10378
|
+
if (info.fi && hasFlippedJoin) {
|
|
10379
|
+
fo.convertToUFO();
|
|
10380
|
+
info.fi.convertToUFI();
|
|
10381
|
+
}
|
|
10382
|
+
}
|
|
10383
|
+
}
|
|
10384
|
+
function findFIAndJoins(fo) {
|
|
10385
|
+
const joinsBetween = [];
|
|
10386
|
+
let fi = void 0;
|
|
10387
|
+
const queue = [...fo.outputs];
|
|
10388
|
+
const visited = /* @__PURE__ */ new Set();
|
|
10389
|
+
while (queue.length > 0) {
|
|
10390
|
+
const node = must(queue.shift());
|
|
10391
|
+
if (visited.has(node)) continue;
|
|
10392
|
+
visited.add(node);
|
|
10393
|
+
switch (node.kind) {
|
|
10394
|
+
case "join":
|
|
10395
|
+
joinsBetween.push(node);
|
|
10396
|
+
queue.push(node.output);
|
|
10397
|
+
break;
|
|
10398
|
+
case "fan-out":
|
|
10399
|
+
queue.push(...node.outputs);
|
|
10400
|
+
break;
|
|
10401
|
+
case "fan-in":
|
|
10402
|
+
fi = node;
|
|
10403
|
+
break;
|
|
10404
|
+
case "connection":
|
|
10405
|
+
break;
|
|
10406
|
+
case "terminus":
|
|
10407
|
+
break;
|
|
10408
|
+
}
|
|
10409
|
+
}
|
|
10410
|
+
return { fi, joinsBetween };
|
|
10411
|
+
}
|
|
10412
|
+
function propagateUnlimitForFlippedJoins(graph) {
|
|
10413
|
+
for (const join of graph.joins) {
|
|
10414
|
+
if (join.type === "flipped") {
|
|
10415
|
+
join.propagateUnlimit();
|
|
10416
|
+
}
|
|
10417
|
+
}
|
|
10418
|
+
}
|
|
10419
|
+
|
|
10420
|
+
// ../zql/src/planner/planner-join.ts
|
|
10421
|
+
var SEMI_JOIN_OVERHEAD_MULTIPLIER = 1.5;
|
|
10422
|
+
var PlannerJoin = class {
|
|
10423
|
+
kind = "join";
|
|
10424
|
+
#parent;
|
|
10425
|
+
#child;
|
|
10426
|
+
#parentConstraint;
|
|
10427
|
+
#childConstraint;
|
|
10428
|
+
#flippable;
|
|
10429
|
+
planId;
|
|
10430
|
+
#output;
|
|
10431
|
+
// Set once during graph construction
|
|
10432
|
+
// Reset between planning attempts
|
|
10433
|
+
#type;
|
|
10434
|
+
constructor(parent, child, parentConstraint, childConstraint, flippable, planId) {
|
|
10435
|
+
this.#type = "semi";
|
|
10436
|
+
this.#parent = parent;
|
|
10437
|
+
this.#child = child;
|
|
10438
|
+
this.#childConstraint = childConstraint;
|
|
10439
|
+
this.#parentConstraint = parentConstraint;
|
|
10440
|
+
this.#flippable = flippable;
|
|
10441
|
+
this.planId = planId;
|
|
10442
|
+
}
|
|
10443
|
+
setOutput(node) {
|
|
10444
|
+
this.#output = node;
|
|
10445
|
+
}
|
|
10446
|
+
get output() {
|
|
10447
|
+
assert(this.#output !== void 0, "Output not set");
|
|
10448
|
+
return this.#output;
|
|
10449
|
+
}
|
|
10450
|
+
closestJoinOrSource() {
|
|
10451
|
+
return "join";
|
|
10452
|
+
}
|
|
10453
|
+
flipIfNeeded(input) {
|
|
10454
|
+
if (input === this.#child) {
|
|
10455
|
+
this.flip();
|
|
10456
|
+
} else {
|
|
10457
|
+
assert(
|
|
10458
|
+
input === this.#parent,
|
|
10459
|
+
"Can only flip a join from one of its inputs"
|
|
10460
|
+
);
|
|
10461
|
+
}
|
|
10462
|
+
}
|
|
10463
|
+
flip() {
|
|
10464
|
+
assert(this.#type === "semi", "Can only flip a semi-join");
|
|
10465
|
+
if (!this.#flippable) {
|
|
10466
|
+
throw new UnflippableJoinError(
|
|
10467
|
+
"Cannot flip a non-flippable join (e.g., NOT EXISTS)"
|
|
10468
|
+
);
|
|
10469
|
+
}
|
|
10470
|
+
this.#type = "flipped";
|
|
10471
|
+
}
|
|
10472
|
+
get type() {
|
|
10473
|
+
return this.#type;
|
|
10474
|
+
}
|
|
10475
|
+
isFlippable() {
|
|
10476
|
+
return this.#flippable;
|
|
10477
|
+
}
|
|
10478
|
+
/**
|
|
10479
|
+
* Propagate unlimiting through the child subgraph when this join is flipped.
|
|
10480
|
+
* When a join is flipped, the child becomes the outer loop and should produce
|
|
10481
|
+
* all rows rather than stopping at an EXISTS limit.
|
|
10482
|
+
*
|
|
10483
|
+
* Propagation rules:
|
|
10484
|
+
* - Connection: call unlimit()
|
|
10485
|
+
* - Semi-join: continue to parent (outer loop)
|
|
10486
|
+
* - Flipped join: stop (already unlimited when it was flipped)
|
|
10487
|
+
* - Fan-out/Fan-in: propagate to all inputs
|
|
10488
|
+
*/
|
|
10489
|
+
propagateUnlimit() {
|
|
10490
|
+
assert(this.#type === "flipped", "Can only unlimit a flipped join");
|
|
10491
|
+
propagateUnlimitToNode(this.#child);
|
|
10492
|
+
}
|
|
10493
|
+
/**
|
|
10494
|
+
* Called when a parent join is flipped and this join is part of its child subgraph.
|
|
10495
|
+
* - Semi-join: continue propagation to parent (the outer loop)
|
|
10496
|
+
* - Flipped join: stop propagation (already unlimited when it was flipped)
|
|
10497
|
+
*/
|
|
10498
|
+
propagateUnlimitFromFlippedJoin() {
|
|
10499
|
+
if (this.#type === "semi") {
|
|
10500
|
+
propagateUnlimitToNode(this.#parent);
|
|
10501
|
+
}
|
|
10502
|
+
}
|
|
10503
|
+
propagateConstraints(branchPattern, constraint) {
|
|
10504
|
+
if (this.#type === "semi") {
|
|
10505
|
+
this.#child.propagateConstraints(
|
|
10506
|
+
branchPattern,
|
|
10507
|
+
this.#childConstraint,
|
|
10508
|
+
this
|
|
10509
|
+
);
|
|
10510
|
+
this.#parent.propagateConstraints(branchPattern, constraint, this);
|
|
10511
|
+
} else if (this.#type === "flipped") {
|
|
10512
|
+
this.#child.propagateConstraints(branchPattern, void 0, this);
|
|
10513
|
+
this.#parent.propagateConstraints(
|
|
10514
|
+
branchPattern,
|
|
10515
|
+
mergeConstraints(constraint, this.#parentConstraint),
|
|
10516
|
+
this
|
|
10517
|
+
);
|
|
10518
|
+
}
|
|
10519
|
+
}
|
|
10520
|
+
reset() {
|
|
10521
|
+
this.#type = "semi";
|
|
10522
|
+
}
|
|
10523
|
+
estimateCost(branchPattern) {
|
|
10524
|
+
const parentCost = this.#parent.estimateCost(branchPattern);
|
|
10525
|
+
const childCost = this.#child.estimateCost(branchPattern);
|
|
10526
|
+
let scanEst = parentCost.rows;
|
|
10527
|
+
if (this.#type === "semi" && parentCost.limit !== void 0) {
|
|
10528
|
+
if (childCost.selectivity !== 0) {
|
|
10529
|
+
scanEst = Math.min(scanEst, parentCost.limit / childCost.selectivity);
|
|
10530
|
+
}
|
|
10531
|
+
}
|
|
10532
|
+
if (this.#parent.closestJoinOrSource() === "join") {
|
|
10533
|
+
const pipelineCost = this.#type === "flipped" ? childCost.startupCost + childCost.runningCost * (parentCost.startupCost + parentCost.runningCost) : parentCost.runningCost + SEMI_JOIN_OVERHEAD_MULTIPLIER * scanEst * (childCost.startupCost + childCost.runningCost);
|
|
10534
|
+
return {
|
|
10535
|
+
rows: parentCost.rows,
|
|
10536
|
+
runningCost: pipelineCost,
|
|
10537
|
+
startupCost: parentCost.startupCost,
|
|
10538
|
+
selectivity: parentCost.selectivity,
|
|
10539
|
+
limit: parentCost.limit
|
|
10540
|
+
};
|
|
10541
|
+
}
|
|
10542
|
+
const nestedLoopCost = this.#type === "flipped" ? childCost.runningCost * (parentCost.startupCost + parentCost.runningCost) : SEMI_JOIN_OVERHEAD_MULTIPLIER * scanEst * (childCost.startupCost + childCost.runningCost);
|
|
10543
|
+
return {
|
|
10544
|
+
rows: parentCost.rows,
|
|
10545
|
+
runningCost: nestedLoopCost,
|
|
10546
|
+
startupCost: parentCost.startupCost,
|
|
10547
|
+
selectivity: parentCost.selectivity,
|
|
10548
|
+
limit: parentCost.limit
|
|
10549
|
+
};
|
|
10550
|
+
}
|
|
10551
|
+
/**
|
|
10552
|
+
* Get a human-readable name for this join for debugging.
|
|
10553
|
+
* Format: "parentName ⋈ childName"
|
|
10554
|
+
*/
|
|
10555
|
+
getName() {
|
|
10556
|
+
const parentName = getNodeName(this.#parent);
|
|
10557
|
+
const childName = getNodeName(this.#child);
|
|
10558
|
+
return `${parentName} \u22C8 ${childName}`;
|
|
10559
|
+
}
|
|
10560
|
+
/**
|
|
10561
|
+
* Get debug information about this join's state.
|
|
10562
|
+
*/
|
|
10563
|
+
getDebugInfo() {
|
|
10564
|
+
return {
|
|
10565
|
+
name: this.getName(),
|
|
10566
|
+
type: this.#type,
|
|
10567
|
+
planId: this.planId
|
|
10568
|
+
};
|
|
10569
|
+
}
|
|
10570
|
+
};
|
|
10571
|
+
var UnflippableJoinError = class extends Error {
|
|
10572
|
+
constructor(message) {
|
|
10573
|
+
super(message);
|
|
10574
|
+
this.name = "UnflippableJoinError";
|
|
10575
|
+
}
|
|
10576
|
+
};
|
|
10577
|
+
function getNodeName(node) {
|
|
10578
|
+
switch (node.kind) {
|
|
10579
|
+
case "connection":
|
|
10580
|
+
return node.name;
|
|
10581
|
+
case "join":
|
|
10582
|
+
return node.getName();
|
|
10583
|
+
case "fan-out":
|
|
10584
|
+
return "FO";
|
|
10585
|
+
case "fan-in":
|
|
10586
|
+
return "FI";
|
|
10587
|
+
case "terminus":
|
|
10588
|
+
return "terminus";
|
|
10589
|
+
}
|
|
10590
|
+
}
|
|
10591
|
+
function propagateUnlimitToNode(node) {
|
|
10592
|
+
if ("propagateUnlimitFromFlippedJoin" in node && typeof node.propagateUnlimitFromFlippedJoin === "function") {
|
|
10593
|
+
node.propagateUnlimitFromFlippedJoin();
|
|
10594
|
+
}
|
|
10595
|
+
}
|
|
10596
|
+
|
|
10597
|
+
// ../zql/src/planner/planner-terminus.ts
|
|
10598
|
+
var PlannerTerminus = class {
|
|
10599
|
+
kind = "terminus";
|
|
10600
|
+
#input;
|
|
10601
|
+
constructor(input) {
|
|
10602
|
+
this.#input = input;
|
|
10603
|
+
}
|
|
10604
|
+
get pinned() {
|
|
10605
|
+
return true;
|
|
10606
|
+
}
|
|
10607
|
+
closestJoinOrSource() {
|
|
10608
|
+
return this.#input.closestJoinOrSource();
|
|
10609
|
+
}
|
|
10610
|
+
propagateConstraints() {
|
|
10611
|
+
this.#input.propagateConstraints([], void 0, this);
|
|
10612
|
+
}
|
|
10613
|
+
estimateCost() {
|
|
10614
|
+
return this.#input.estimateCost([]);
|
|
10615
|
+
}
|
|
10616
|
+
/**
|
|
10617
|
+
* Propagate unlimiting when a parent join is flipped.
|
|
10618
|
+
* Terminus doesn't participate in unlimiting.
|
|
10619
|
+
*/
|
|
10620
|
+
propagateUnlimitFromFlippedJoin() {
|
|
10621
|
+
}
|
|
10622
|
+
};
|
|
10623
|
+
|
|
10624
|
+
// ../zql/src/planner/planner-builder.ts
|
|
10625
|
+
function wireOutput(from, to) {
|
|
10626
|
+
switch (from.kind) {
|
|
10627
|
+
case "connection":
|
|
10628
|
+
case "join":
|
|
10629
|
+
case "fan-in":
|
|
10630
|
+
from.setOutput(to);
|
|
10631
|
+
break;
|
|
10632
|
+
case "fan-out":
|
|
10633
|
+
from.addOutput(to);
|
|
10634
|
+
break;
|
|
10635
|
+
case "terminus":
|
|
10636
|
+
assert(false, "Terminus nodes cannot have outputs");
|
|
10637
|
+
}
|
|
10638
|
+
}
|
|
10639
|
+
function buildPlanGraph(ast, model, baseConstraints) {
|
|
10640
|
+
const graph = new PlannerGraph();
|
|
10641
|
+
let nextPlanId = 0;
|
|
10642
|
+
const source = graph.addSource(ast.table, model);
|
|
10643
|
+
const connection = source.connect(
|
|
10644
|
+
ast.orderBy ?? [],
|
|
10645
|
+
ast.where,
|
|
10646
|
+
baseConstraints,
|
|
10647
|
+
ast.limit
|
|
10648
|
+
);
|
|
10649
|
+
graph.connections.push(connection);
|
|
10650
|
+
let end = connection;
|
|
10651
|
+
if (ast.where) {
|
|
10652
|
+
end = processCondition(
|
|
10653
|
+
ast.where,
|
|
10654
|
+
end,
|
|
10655
|
+
graph,
|
|
10656
|
+
model,
|
|
10657
|
+
ast.table,
|
|
10658
|
+
() => nextPlanId++
|
|
10659
|
+
);
|
|
10660
|
+
}
|
|
10661
|
+
const terminus = new PlannerTerminus(end);
|
|
10662
|
+
wireOutput(end, terminus);
|
|
10663
|
+
graph.setTerminus(terminus);
|
|
10664
|
+
const subPlans = {};
|
|
10665
|
+
if (ast.related) {
|
|
10666
|
+
for (const csq of ast.related) {
|
|
10667
|
+
const alias = must(
|
|
10668
|
+
csq.subquery.alias,
|
|
10669
|
+
"Related subquery must have alias"
|
|
10670
|
+
);
|
|
10671
|
+
const childConstraints = extractConstraint(
|
|
10672
|
+
csq.correlation.childField,
|
|
10673
|
+
csq.subquery.table
|
|
10674
|
+
);
|
|
10675
|
+
subPlans[alias] = buildPlanGraph(csq.subquery, model, childConstraints);
|
|
10676
|
+
}
|
|
10677
|
+
}
|
|
10678
|
+
return { plan: graph, subPlans };
|
|
10679
|
+
}
|
|
10680
|
+
function processCondition(condition, input, graph, model, parentTable, getPlanId) {
|
|
10681
|
+
switch (condition.type) {
|
|
10682
|
+
case "simple":
|
|
10683
|
+
return input;
|
|
10684
|
+
case "and":
|
|
10685
|
+
return processAnd(condition, input, graph, model, parentTable, getPlanId);
|
|
10686
|
+
case "or":
|
|
10687
|
+
return processOr(condition, input, graph, model, parentTable, getPlanId);
|
|
10688
|
+
case "correlatedSubquery":
|
|
10689
|
+
return processCorrelatedSubquery(
|
|
10690
|
+
condition,
|
|
10691
|
+
input,
|
|
10692
|
+
graph,
|
|
10693
|
+
model,
|
|
10694
|
+
parentTable,
|
|
10695
|
+
getPlanId
|
|
10696
|
+
);
|
|
10697
|
+
}
|
|
10698
|
+
}
|
|
10699
|
+
function processAnd(condition, input, graph, model, parentTable, getPlanId) {
|
|
10700
|
+
let end = input;
|
|
10701
|
+
for (const subCondition of condition.conditions) {
|
|
10702
|
+
end = processCondition(
|
|
10703
|
+
subCondition,
|
|
10704
|
+
end,
|
|
10705
|
+
graph,
|
|
10706
|
+
model,
|
|
10707
|
+
parentTable,
|
|
10708
|
+
getPlanId
|
|
10709
|
+
);
|
|
10710
|
+
}
|
|
10711
|
+
return end;
|
|
10712
|
+
}
|
|
10713
|
+
function processOr(condition, input, graph, model, parentTable, getPlanId) {
|
|
10714
|
+
const subqueryConditions = condition.conditions.filter(
|
|
10715
|
+
(c) => c.type === "correlatedSubquery" || hasCorrelatedSubquery(c)
|
|
10716
|
+
);
|
|
10717
|
+
if (subqueryConditions.length === 0) {
|
|
10718
|
+
return input;
|
|
10719
|
+
}
|
|
10720
|
+
const fanOut = new PlannerFanOut(input);
|
|
10721
|
+
graph.fanOuts.push(fanOut);
|
|
10722
|
+
wireOutput(input, fanOut);
|
|
10723
|
+
const branches = [];
|
|
10724
|
+
for (const subCondition of subqueryConditions) {
|
|
10725
|
+
const branch = processCondition(
|
|
10726
|
+
subCondition,
|
|
10727
|
+
fanOut,
|
|
10728
|
+
graph,
|
|
10729
|
+
model,
|
|
10730
|
+
parentTable,
|
|
10731
|
+
getPlanId
|
|
10732
|
+
);
|
|
10733
|
+
branches.push(branch);
|
|
10734
|
+
fanOut.addOutput(branch);
|
|
10735
|
+
}
|
|
10736
|
+
const fanIn = new PlannerFanIn(branches);
|
|
10737
|
+
graph.fanIns.push(fanIn);
|
|
10738
|
+
for (const branch of branches) {
|
|
10739
|
+
wireOutput(branch, fanIn);
|
|
10740
|
+
}
|
|
10741
|
+
return fanIn;
|
|
10742
|
+
}
|
|
10743
|
+
function processCorrelatedSubquery(condition, input, graph, model, parentTable, getPlanId) {
|
|
10744
|
+
const { related } = condition;
|
|
10745
|
+
const childTable = related.subquery.table;
|
|
10746
|
+
const childSource = graph.hasSource(childTable) ? graph.getSource(childTable) : graph.addSource(childTable, model);
|
|
10747
|
+
const childConnection = childSource.connect(
|
|
10748
|
+
related.subquery.orderBy ?? [],
|
|
10749
|
+
related.subquery.where,
|
|
10750
|
+
void 0,
|
|
10751
|
+
// no base constraints for EXISTS/NOT EXISTS
|
|
10752
|
+
condition.op === "EXISTS" ? 1 : void 0
|
|
10753
|
+
);
|
|
10754
|
+
graph.connections.push(childConnection);
|
|
10755
|
+
let childEnd = childConnection;
|
|
10756
|
+
if (related.subquery.where) {
|
|
10757
|
+
childEnd = processCondition(
|
|
10758
|
+
related.subquery.where,
|
|
10759
|
+
childEnd,
|
|
10760
|
+
graph,
|
|
10761
|
+
model,
|
|
10762
|
+
childTable,
|
|
10763
|
+
getPlanId
|
|
10764
|
+
);
|
|
10765
|
+
}
|
|
10766
|
+
const parentConstraint = extractConstraint(
|
|
10767
|
+
related.correlation.parentField,
|
|
10768
|
+
parentTable
|
|
10769
|
+
);
|
|
10770
|
+
const childConstraint = extractConstraint(
|
|
10771
|
+
related.correlation.childField,
|
|
10772
|
+
childTable
|
|
10773
|
+
);
|
|
10774
|
+
const planId = getPlanId();
|
|
10775
|
+
condition[planIdSymbol] = planId;
|
|
10776
|
+
const join = new PlannerJoin(
|
|
10777
|
+
input,
|
|
10778
|
+
childEnd,
|
|
10779
|
+
parentConstraint,
|
|
10780
|
+
childConstraint,
|
|
10781
|
+
condition.op !== "NOT EXISTS",
|
|
10782
|
+
planId
|
|
10783
|
+
);
|
|
10784
|
+
graph.joins.push(join);
|
|
10785
|
+
wireOutput(input, join);
|
|
10786
|
+
wireOutput(childEnd, join);
|
|
10787
|
+
return join;
|
|
10788
|
+
}
|
|
10789
|
+
function hasCorrelatedSubquery(condition) {
|
|
10790
|
+
if (condition.type === "correlatedSubquery") {
|
|
10791
|
+
return true;
|
|
10792
|
+
}
|
|
10793
|
+
if (condition.type === "and" || condition.type === "or") {
|
|
10794
|
+
return condition.conditions.some(hasCorrelatedSubquery);
|
|
10795
|
+
}
|
|
10796
|
+
return false;
|
|
10797
|
+
}
|
|
10798
|
+
function extractConstraint(fields, _tableName) {
|
|
10799
|
+
return Object.fromEntries(fields.map((field) => [field, void 0]));
|
|
10800
|
+
}
|
|
10801
|
+
function planRecursively(plans, planDebugger) {
|
|
10802
|
+
for (const subPlan of Object.values(plans.subPlans)) {
|
|
10803
|
+
planRecursively(subPlan, planDebugger);
|
|
10804
|
+
}
|
|
10805
|
+
plans.plan.plan(planDebugger);
|
|
10806
|
+
}
|
|
10807
|
+
function planQuery(ast, model, planDebugger) {
|
|
10808
|
+
const plans = buildPlanGraph(ast, model);
|
|
10809
|
+
planRecursively(plans, planDebugger);
|
|
10810
|
+
return applyPlansToAST(ast, plans);
|
|
10811
|
+
}
|
|
10812
|
+
function applyToCondition(condition, flippedIds) {
|
|
10813
|
+
if (condition.type === "simple") {
|
|
10814
|
+
return condition;
|
|
10815
|
+
}
|
|
10816
|
+
if (condition.type === "correlatedSubquery") {
|
|
10817
|
+
const planId = condition[planIdSymbol];
|
|
10818
|
+
const shouldFlip = planId !== void 0 && flippedIds.has(planId);
|
|
10819
|
+
return {
|
|
10820
|
+
...condition,
|
|
10821
|
+
flip: shouldFlip ? true : condition.flip,
|
|
10822
|
+
related: {
|
|
10823
|
+
...condition.related,
|
|
10824
|
+
subquery: {
|
|
10825
|
+
...condition.related.subquery,
|
|
10826
|
+
where: condition.related.subquery.where ? applyToCondition(condition.related.subquery.where, flippedIds) : void 0
|
|
10827
|
+
}
|
|
10828
|
+
}
|
|
10829
|
+
};
|
|
10830
|
+
}
|
|
10831
|
+
return {
|
|
10832
|
+
...condition,
|
|
10833
|
+
conditions: condition.conditions.map((c) => applyToCondition(c, flippedIds))
|
|
10834
|
+
};
|
|
10835
|
+
}
|
|
10836
|
+
function applyPlansToAST(ast, plans) {
|
|
10837
|
+
const flippedIds = /* @__PURE__ */ new Set();
|
|
10838
|
+
for (const join of plans.plan.joins) {
|
|
10839
|
+
if (join.type === "flipped" && join.planId !== void 0) {
|
|
10840
|
+
flippedIds.add(join.planId);
|
|
10841
|
+
}
|
|
10842
|
+
}
|
|
10843
|
+
return {
|
|
10844
|
+
...ast,
|
|
10845
|
+
where: ast.where ? applyToCondition(ast.where, flippedIds) : void 0,
|
|
10846
|
+
related: ast.related?.map((csq) => {
|
|
10847
|
+
const alias = must(
|
|
10848
|
+
csq.subquery.alias,
|
|
10849
|
+
"Related subquery must have alias"
|
|
10850
|
+
);
|
|
10851
|
+
const subPlan = plans.subPlans[alias];
|
|
10852
|
+
return {
|
|
10853
|
+
...csq,
|
|
10854
|
+
subquery: subPlan ? applyPlansToAST(csq.subquery, subPlan) : csq.subquery
|
|
10855
|
+
};
|
|
10856
|
+
})
|
|
10857
|
+
};
|
|
10858
|
+
}
|
|
10859
|
+
|
|
10860
|
+
// ../zql/src/query/expression.ts
|
|
10861
|
+
var ExpressionBuilder = class {
|
|
10862
|
+
#exists;
|
|
10863
|
+
constructor(exists) {
|
|
10864
|
+
this.#exists = exists;
|
|
10865
|
+
this.exists = this.exists.bind(this);
|
|
10866
|
+
}
|
|
10867
|
+
get eb() {
|
|
10868
|
+
return this;
|
|
10869
|
+
}
|
|
10870
|
+
cmp(field, opOrValue, value) {
|
|
10871
|
+
return cmp(field, opOrValue, value);
|
|
10872
|
+
}
|
|
10873
|
+
cmpLit(left, op, right) {
|
|
10874
|
+
return {
|
|
10875
|
+
type: "simple",
|
|
10876
|
+
left: isParameterReference(left) ? left[toStaticParam]() : { type: "literal", value: left },
|
|
10877
|
+
right: isParameterReference(right) ? right[toStaticParam]() : { type: "literal", value: right },
|
|
10878
|
+
op
|
|
10879
|
+
};
|
|
10880
|
+
}
|
|
10881
|
+
and = and;
|
|
10882
|
+
or = or;
|
|
10883
|
+
not = not;
|
|
10884
|
+
exists = (relationship, cb, options) => this.#exists(relationship, cb, options);
|
|
10885
|
+
};
|
|
10886
|
+
function and(...conditions) {
|
|
10887
|
+
const expressions = filterTrue(filterUndefined(conditions));
|
|
10888
|
+
if (expressions.length === 1) {
|
|
10889
|
+
return expressions[0];
|
|
10890
|
+
}
|
|
10891
|
+
if (expressions.some(isAlwaysFalse)) {
|
|
10892
|
+
return FALSE;
|
|
10893
|
+
}
|
|
10894
|
+
return { type: "and", conditions: expressions };
|
|
10895
|
+
}
|
|
10896
|
+
function or(...conditions) {
|
|
10897
|
+
const expressions = filterFalse(filterUndefined(conditions));
|
|
10898
|
+
if (expressions.length === 1) {
|
|
10899
|
+
return expressions[0];
|
|
10900
|
+
}
|
|
10901
|
+
if (expressions.some(isAlwaysTrue)) {
|
|
10902
|
+
return TRUE;
|
|
10903
|
+
}
|
|
10904
|
+
return { type: "or", conditions: expressions };
|
|
10905
|
+
}
|
|
10906
|
+
function not(expression) {
|
|
10907
|
+
switch (expression.type) {
|
|
10908
|
+
case "and":
|
|
10909
|
+
return {
|
|
10910
|
+
type: "or",
|
|
10911
|
+
conditions: expression.conditions.map(not)
|
|
10912
|
+
};
|
|
10913
|
+
case "or":
|
|
10914
|
+
return {
|
|
10915
|
+
type: "and",
|
|
10916
|
+
conditions: expression.conditions.map(not)
|
|
10917
|
+
};
|
|
10918
|
+
case "correlatedSubquery":
|
|
10919
|
+
return {
|
|
10920
|
+
type: "correlatedSubquery",
|
|
10921
|
+
related: expression.related,
|
|
10922
|
+
op: negateOperator(expression.op)
|
|
10923
|
+
};
|
|
10924
|
+
case "simple":
|
|
10925
|
+
return {
|
|
10926
|
+
type: "simple",
|
|
10927
|
+
op: negateOperator(expression.op),
|
|
10928
|
+
left: expression.left,
|
|
10929
|
+
right: expression.right
|
|
10930
|
+
};
|
|
10931
|
+
}
|
|
10932
|
+
}
|
|
10933
|
+
function cmp(field, opOrValue, value) {
|
|
10934
|
+
let op;
|
|
10935
|
+
if (value === void 0) {
|
|
10936
|
+
value = opOrValue;
|
|
10937
|
+
op = "=";
|
|
10938
|
+
} else {
|
|
10939
|
+
op = opOrValue;
|
|
10940
|
+
}
|
|
10941
|
+
return {
|
|
10942
|
+
type: "simple",
|
|
10943
|
+
left: { type: "column", name: field },
|
|
10944
|
+
right: isParameterReference(value) ? value[toStaticParam]() : { type: "literal", value },
|
|
10945
|
+
op
|
|
10946
|
+
};
|
|
10947
|
+
}
|
|
10948
|
+
function isParameterReference(value) {
|
|
10949
|
+
return value !== null && typeof value === "object" && value[toStaticParam];
|
|
10950
|
+
}
|
|
10951
|
+
var TRUE = {
|
|
10952
|
+
type: "and",
|
|
10953
|
+
conditions: []
|
|
10954
|
+
};
|
|
10955
|
+
var FALSE = {
|
|
10956
|
+
type: "or",
|
|
10957
|
+
conditions: []
|
|
10958
|
+
};
|
|
10959
|
+
function isAlwaysTrue(condition) {
|
|
10960
|
+
return condition.type === "and" && condition.conditions.length === 0;
|
|
10961
|
+
}
|
|
10962
|
+
function isAlwaysFalse(condition) {
|
|
10963
|
+
return condition.type === "or" && condition.conditions.length === 0;
|
|
10964
|
+
}
|
|
10965
|
+
function simplifyCondition(c) {
|
|
10966
|
+
if (c.type === "simple" || c.type === "correlatedSubquery") {
|
|
10967
|
+
return c;
|
|
10968
|
+
}
|
|
10969
|
+
if (c.conditions.length === 1) {
|
|
10970
|
+
return simplifyCondition(c.conditions[0]);
|
|
10971
|
+
}
|
|
10972
|
+
const conditions = flatten(c.type, c.conditions.map(simplifyCondition));
|
|
10973
|
+
if (c.type === "and" && conditions.some(isAlwaysFalse)) {
|
|
10974
|
+
return FALSE;
|
|
10975
|
+
}
|
|
10976
|
+
if (c.type === "or" && conditions.some(isAlwaysTrue)) {
|
|
10977
|
+
return TRUE;
|
|
10978
|
+
}
|
|
10979
|
+
return {
|
|
10980
|
+
type: c.type,
|
|
10981
|
+
conditions
|
|
10982
|
+
};
|
|
10983
|
+
}
|
|
10984
|
+
function flatten(type, conditions) {
|
|
10985
|
+
const flattened = [];
|
|
10986
|
+
for (const c of conditions) {
|
|
10987
|
+
if (c.type === type) {
|
|
10988
|
+
flattened.push(...c.conditions);
|
|
10989
|
+
} else {
|
|
10990
|
+
flattened.push(c);
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10993
|
+
return flattened;
|
|
10994
|
+
}
|
|
10995
|
+
var negateSimpleOperatorMap = {
|
|
10996
|
+
["="]: "!=",
|
|
10997
|
+
["!="]: "=",
|
|
10998
|
+
["<"]: ">=",
|
|
10999
|
+
[">"]: "<=",
|
|
11000
|
+
[">="]: "<",
|
|
11001
|
+
["<="]: ">",
|
|
11002
|
+
["IN"]: "NOT IN",
|
|
11003
|
+
["NOT IN"]: "IN",
|
|
11004
|
+
["LIKE"]: "NOT LIKE",
|
|
11005
|
+
["NOT LIKE"]: "LIKE",
|
|
11006
|
+
["ILIKE"]: "NOT ILIKE",
|
|
11007
|
+
["NOT ILIKE"]: "ILIKE",
|
|
11008
|
+
["IS"]: "IS NOT",
|
|
11009
|
+
["IS NOT"]: "IS"
|
|
11010
|
+
};
|
|
11011
|
+
var negateOperatorMap = {
|
|
11012
|
+
...negateSimpleOperatorMap,
|
|
11013
|
+
["EXISTS"]: "NOT EXISTS",
|
|
11014
|
+
["NOT EXISTS"]: "EXISTS"
|
|
11015
|
+
};
|
|
11016
|
+
function negateOperator(op) {
|
|
11017
|
+
return must(negateOperatorMap[op]);
|
|
11018
|
+
}
|
|
11019
|
+
function filterUndefined(array10) {
|
|
11020
|
+
return array10.filter((e) => e !== void 0);
|
|
11021
|
+
}
|
|
11022
|
+
function filterTrue(conditions) {
|
|
11023
|
+
return conditions.filter((c) => !isAlwaysTrue(c));
|
|
11024
|
+
}
|
|
11025
|
+
function filterFalse(conditions) {
|
|
11026
|
+
return conditions.filter((c) => !isAlwaysFalse(c));
|
|
11027
|
+
}
|
|
11028
|
+
|
|
11029
|
+
// ../zql/src/builder/like.ts
|
|
11030
|
+
function getLikePredicate(pattern, flags) {
|
|
11031
|
+
const op = getLikeOp(String(pattern), flags);
|
|
11032
|
+
return (lhs) => {
|
|
11033
|
+
assertString(lhs);
|
|
11034
|
+
return op(String(lhs));
|
|
11035
|
+
};
|
|
11036
|
+
}
|
|
11037
|
+
function getLikeOp(pattern, flags) {
|
|
11038
|
+
if (!/_|%|\\/.test(pattern)) {
|
|
11039
|
+
if (flags === "i") {
|
|
11040
|
+
const rhsLower = pattern.toLowerCase();
|
|
11041
|
+
return (lhs) => lhs.toLowerCase() === rhsLower;
|
|
11042
|
+
}
|
|
11043
|
+
return (lhs) => lhs === pattern;
|
|
11044
|
+
}
|
|
11045
|
+
const re = patternToRegExp(pattern, flags);
|
|
11046
|
+
return (lhs) => re.test(lhs);
|
|
11047
|
+
}
|
|
11048
|
+
var specialCharsRe = /[$()*+.?[\]\\^{|}]/;
|
|
11049
|
+
function patternToRegExp(source, flags = "") {
|
|
11050
|
+
let pattern = "^";
|
|
11051
|
+
for (let i = 0; i < source.length; i++) {
|
|
11052
|
+
let c = source[i];
|
|
11053
|
+
switch (c) {
|
|
9499
11054
|
case "%":
|
|
9500
11055
|
pattern += ".*";
|
|
9501
11056
|
break;
|
|
@@ -9666,18 +11221,45 @@ function transformFilters(filters) {
|
|
|
9666
11221
|
}
|
|
9667
11222
|
|
|
9668
11223
|
// ../zql/src/builder/builder.ts
|
|
9669
|
-
function buildPipeline(ast, delegate, queryID) {
|
|
11224
|
+
function buildPipeline(ast, delegate, queryID, costModel) {
|
|
9670
11225
|
ast = delegate.mapAst ? delegate.mapAst(ast) : ast;
|
|
11226
|
+
if (costModel) {
|
|
11227
|
+
ast = planQuery(ast, costModel);
|
|
11228
|
+
}
|
|
9671
11229
|
return buildPipelineInternal(ast, delegate, queryID, "");
|
|
9672
11230
|
}
|
|
9673
11231
|
var EXISTS_LIMIT = 3;
|
|
9674
11232
|
var PERMISSIONS_EXISTS_LIMIT = 1;
|
|
11233
|
+
function assertNoNotExists(condition) {
|
|
11234
|
+
switch (condition.type) {
|
|
11235
|
+
case "simple":
|
|
11236
|
+
return;
|
|
11237
|
+
case "correlatedSubquery":
|
|
11238
|
+
if (condition.op === "NOT EXISTS") {
|
|
11239
|
+
throw new Error(
|
|
11240
|
+
"not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438"
|
|
11241
|
+
);
|
|
11242
|
+
}
|
|
11243
|
+
return;
|
|
11244
|
+
case "and":
|
|
11245
|
+
case "or":
|
|
11246
|
+
for (const c of condition.conditions) {
|
|
11247
|
+
assertNoNotExists(c);
|
|
11248
|
+
}
|
|
11249
|
+
return;
|
|
11250
|
+
default:
|
|
11251
|
+
unreachable(condition);
|
|
11252
|
+
}
|
|
11253
|
+
}
|
|
9675
11254
|
function buildPipelineInternal(ast, delegate, queryID, name, partitionKey) {
|
|
9676
11255
|
const source = delegate.getSource(ast.table);
|
|
9677
11256
|
if (!source) {
|
|
9678
11257
|
throw new Error(`Source not found: ${ast.table}`);
|
|
9679
11258
|
}
|
|
9680
11259
|
ast = uniquifyCorrelatedSubqueryConditionAliases(ast);
|
|
11260
|
+
if (!delegate.enableNotExists && ast.where) {
|
|
11261
|
+
assertNoNotExists(ast.where);
|
|
11262
|
+
}
|
|
9681
11263
|
const csqConditions = gatherCorrelatedSubqueryQueryConditions(ast.where);
|
|
9682
11264
|
const splitEditKeys = partitionKey ? new Set(partitionKey) : /* @__PURE__ */ new Set();
|
|
9683
11265
|
const aliases = /* @__PURE__ */ new Set();
|
|
@@ -10200,32 +11782,6 @@ var defaultFormat = {
|
|
|
10200
11782
|
relationships: {}
|
|
10201
11783
|
};
|
|
10202
11784
|
|
|
10203
|
-
// ../zql/src/query/assert-no-not-exists.ts
|
|
10204
|
-
function assertNoNotExists(condition) {
|
|
10205
|
-
switch (condition.type) {
|
|
10206
|
-
case "simple":
|
|
10207
|
-
return;
|
|
10208
|
-
case "correlatedSubquery":
|
|
10209
|
-
if (condition.op === "NOT EXISTS") {
|
|
10210
|
-
throw new Error(
|
|
10211
|
-
"not(exists()) is not supported on the client - see https://bugs.rocicorp.dev/issue/3438"
|
|
10212
|
-
);
|
|
10213
|
-
}
|
|
10214
|
-
if (condition.related.subquery.where) {
|
|
10215
|
-
assertNoNotExists(condition.related.subquery.where);
|
|
10216
|
-
}
|
|
10217
|
-
return;
|
|
10218
|
-
case "and":
|
|
10219
|
-
case "or":
|
|
10220
|
-
for (const c of condition.conditions) {
|
|
10221
|
-
assertNoNotExists(c);
|
|
10222
|
-
}
|
|
10223
|
-
return;
|
|
10224
|
-
default:
|
|
10225
|
-
unreachable(condition);
|
|
10226
|
-
}
|
|
10227
|
-
}
|
|
10228
|
-
|
|
10229
11785
|
// ../zql/src/query/query.ts
|
|
10230
11786
|
var delegateSymbol = Symbol("delegate");
|
|
10231
11787
|
|
|
@@ -10489,9 +12045,6 @@ var AbstractQuery = class {
|
|
|
10489
12045
|
cond = and(existingWhere, cond);
|
|
10490
12046
|
}
|
|
10491
12047
|
const where = simplifyCondition(cond);
|
|
10492
|
-
if (this.#system === "client") {
|
|
10493
|
-
assertNoNotExists(where);
|
|
10494
|
-
}
|
|
10495
12048
|
return this[newQuerySymbol](
|
|
10496
12049
|
this._delegate,
|
|
10497
12050
|
this.#schema,
|
|
@@ -11063,47 +12616,398 @@ var NativeClientLockManager = class {
|
|
|
11063
12616
|
}
|
|
11064
12617
|
}
|
|
11065
12618
|
}
|
|
11066
|
-
};
|
|
11067
|
-
var mockLockNames = /* @__PURE__ */ new Set();
|
|
11068
|
-
var mockListeners = /* @__PURE__ */ new Set();
|
|
11069
|
-
var MockClientLockManager = class {
|
|
11070
|
-
#listeners = /* @__PURE__ */ new Set();
|
|
11071
|
-
request(name, mode, fn) {
|
|
11072
|
-
if (mode === "exclusive") {
|
|
11073
|
-
mockLockNames.add(name);
|
|
11074
|
-
} else {
|
|
11075
|
-
mode;
|
|
11076
|
-
const listener = (removed) => {
|
|
11077
|
-
if (removed === name) {
|
|
11078
|
-
mockListeners.delete(listener);
|
|
11079
|
-
return fn();
|
|
11080
|
-
}
|
|
11081
|
-
};
|
|
11082
|
-
mockListeners.add(listener);
|
|
11083
|
-
this.#listeners.add(listener);
|
|
12619
|
+
};
|
|
12620
|
+
var mockLockNames = /* @__PURE__ */ new Set();
|
|
12621
|
+
var mockListeners = /* @__PURE__ */ new Set();
|
|
12622
|
+
var MockClientLockManager = class {
|
|
12623
|
+
#listeners = /* @__PURE__ */ new Set();
|
|
12624
|
+
request(name, mode, fn) {
|
|
12625
|
+
if (mode === "exclusive") {
|
|
12626
|
+
mockLockNames.add(name);
|
|
12627
|
+
} else {
|
|
12628
|
+
mode;
|
|
12629
|
+
const listener = (removed) => {
|
|
12630
|
+
if (removed === name) {
|
|
12631
|
+
mockListeners.delete(listener);
|
|
12632
|
+
return fn();
|
|
12633
|
+
}
|
|
12634
|
+
};
|
|
12635
|
+
mockListeners.add(listener);
|
|
12636
|
+
this.#listeners.add(listener);
|
|
12637
|
+
}
|
|
12638
|
+
return Promise.resolve();
|
|
12639
|
+
}
|
|
12640
|
+
release(name, fn) {
|
|
12641
|
+
mockLockNames.delete(name);
|
|
12642
|
+
for (const listener of mockListeners) {
|
|
12643
|
+
listener(name);
|
|
12644
|
+
}
|
|
12645
|
+
for (const listener of this.#listeners) {
|
|
12646
|
+
mockListeners.delete(listener);
|
|
12647
|
+
}
|
|
12648
|
+
fn();
|
|
12649
|
+
}
|
|
12650
|
+
async *queryExclusive() {
|
|
12651
|
+
yield* mockLockNames;
|
|
12652
|
+
}
|
|
12653
|
+
};
|
|
12654
|
+
|
|
12655
|
+
// ../zero-client/src/client/connection-manager.ts
|
|
12656
|
+
import { resolver as resolver9 } from "@rocicorp/resolver";
|
|
12657
|
+
|
|
12658
|
+
// ../shared/src/subscribable.ts
|
|
12659
|
+
var Subscribable = class {
|
|
12660
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
12661
|
+
/**
|
|
12662
|
+
* Subscribe to the subscribable.
|
|
12663
|
+
*
|
|
12664
|
+
* @param listener - The listener to subscribe to.
|
|
12665
|
+
* @returns A function to unsubscribe from the subscribable.
|
|
12666
|
+
*/
|
|
12667
|
+
subscribe = (listener) => {
|
|
12668
|
+
this._listeners.add(listener);
|
|
12669
|
+
return () => {
|
|
12670
|
+
this._listeners.delete(listener);
|
|
12671
|
+
};
|
|
12672
|
+
};
|
|
12673
|
+
/**
|
|
12674
|
+
* Notify all listeners.
|
|
12675
|
+
*
|
|
12676
|
+
* @param update - The update to notify listeners with.
|
|
12677
|
+
*/
|
|
12678
|
+
notify = (update) => {
|
|
12679
|
+
this._listeners.forEach((listener) => listener(update));
|
|
12680
|
+
};
|
|
12681
|
+
hasListeners = () => this._listeners.size > 0;
|
|
12682
|
+
/**
|
|
12683
|
+
* Unsubscribe all listeners.
|
|
12684
|
+
*/
|
|
12685
|
+
cleanup = () => {
|
|
12686
|
+
this._listeners.clear();
|
|
12687
|
+
};
|
|
12688
|
+
};
|
|
12689
|
+
|
|
12690
|
+
// ../zero-client/src/client/connection-manager.ts
|
|
12691
|
+
var DEFAULT_TIMEOUT_CHECK_INTERVAL_MS = 1e3;
|
|
12692
|
+
var TERMINAL_STATES = [
|
|
12693
|
+
connection_status_enum_exports.Error
|
|
12694
|
+
];
|
|
12695
|
+
var ConnectionManager = class _ConnectionManager extends Subscribable {
|
|
12696
|
+
#state;
|
|
12697
|
+
/**
|
|
12698
|
+
* The timestamp when we first started trying to connect.
|
|
12699
|
+
* This is used to track the retry window.
|
|
12700
|
+
* Reset to undefined when we successfully connect or when we transition to disconnected.
|
|
12701
|
+
*/
|
|
12702
|
+
#connectingStartedAt;
|
|
12703
|
+
/**
|
|
12704
|
+
* The amount of time we allow for continuous connecting attempts before
|
|
12705
|
+
* transitioning to disconnected state.
|
|
12706
|
+
*/
|
|
12707
|
+
#disconnectTimeoutMs;
|
|
12708
|
+
/**
|
|
12709
|
+
* Handle for the timeout interval that periodically checks whether we've
|
|
12710
|
+
* exceeded the allowed connecting window.
|
|
12711
|
+
*/
|
|
12712
|
+
#timeoutInterval;
|
|
12713
|
+
/**
|
|
12714
|
+
* Interval duration for checking whether the connecting timeout has elapsed.
|
|
12715
|
+
*/
|
|
12716
|
+
#timeoutCheckIntervalMs;
|
|
12717
|
+
/**
|
|
12718
|
+
* Resolver used to signal waiting callers when the state changes.
|
|
12719
|
+
*/
|
|
12720
|
+
#stateChangeResolver = resolver9();
|
|
12721
|
+
constructor(options) {
|
|
12722
|
+
super();
|
|
12723
|
+
const now = Date.now();
|
|
12724
|
+
this.#disconnectTimeoutMs = options.disconnectTimeoutMs;
|
|
12725
|
+
this.#timeoutCheckIntervalMs = options.timeoutCheckIntervalMs ?? DEFAULT_TIMEOUT_CHECK_INTERVAL_MS;
|
|
12726
|
+
this.#state = {
|
|
12727
|
+
name: connection_status_enum_exports.Connecting,
|
|
12728
|
+
attempt: 0,
|
|
12729
|
+
disconnectAt: now + this.#disconnectTimeoutMs
|
|
12730
|
+
};
|
|
12731
|
+
this.#connectingStartedAt = now;
|
|
12732
|
+
this.#maybeStartTimeoutInterval();
|
|
12733
|
+
}
|
|
12734
|
+
get state() {
|
|
12735
|
+
return this.#state;
|
|
12736
|
+
}
|
|
12737
|
+
/**
|
|
12738
|
+
* Returns true if the current state is equal to the given status.
|
|
12739
|
+
*/
|
|
12740
|
+
is(status) {
|
|
12741
|
+
return this.#state.name === status;
|
|
12742
|
+
}
|
|
12743
|
+
/**
|
|
12744
|
+
* Returns true if the current state is a terminal state
|
|
12745
|
+
* that can be recovered from by calling connect().
|
|
12746
|
+
*/
|
|
12747
|
+
isInTerminalState() {
|
|
12748
|
+
return _ConnectionManager.isTerminalState(this.#state);
|
|
12749
|
+
}
|
|
12750
|
+
/**
|
|
12751
|
+
* Returns true if the given status is a terminal state
|
|
12752
|
+
* that can be recovered from by calling connect().
|
|
12753
|
+
*/
|
|
12754
|
+
static isTerminalState(state) {
|
|
12755
|
+
return TERMINAL_STATES.includes(
|
|
12756
|
+
state.name
|
|
12757
|
+
);
|
|
12758
|
+
}
|
|
12759
|
+
/**
|
|
12760
|
+
* Returns true if the run loop should continue.
|
|
12761
|
+
* The run loop continues in disconnected, connecting, connected, and error states.
|
|
12762
|
+
* It stops in closed state.
|
|
12763
|
+
*/
|
|
12764
|
+
shouldContinueRunLoop() {
|
|
12765
|
+
return this.#state.name !== connection_status_enum_exports.Closed;
|
|
12766
|
+
}
|
|
12767
|
+
/**
|
|
12768
|
+
* Waits for the next state change.
|
|
12769
|
+
* @returns A promise that resolves when the next state change occurs.
|
|
12770
|
+
*/
|
|
12771
|
+
waitForStateChange() {
|
|
12772
|
+
return this.#nextStatePromise();
|
|
12773
|
+
}
|
|
12774
|
+
/**
|
|
12775
|
+
* Transition to connecting state.
|
|
12776
|
+
*
|
|
12777
|
+
* This starts the 5-minute timeout timer, but if we've entered disconnected state,
|
|
12778
|
+
* we stay there and continue retrying.
|
|
12779
|
+
*
|
|
12780
|
+
* @returns An object containing a promise that resolves on the next state change.
|
|
12781
|
+
*/
|
|
12782
|
+
connecting(reason) {
|
|
12783
|
+
if (this.#state.name === connection_status_enum_exports.Closed) {
|
|
12784
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12785
|
+
}
|
|
12786
|
+
if (this.#state.name === connection_status_enum_exports.Disconnected) {
|
|
12787
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12788
|
+
}
|
|
12789
|
+
const now = Date.now();
|
|
12790
|
+
if (this.#state.name === connection_status_enum_exports.Connecting) {
|
|
12791
|
+
this.#state = {
|
|
12792
|
+
...this.#state,
|
|
12793
|
+
attempt: this.#state.attempt + 1,
|
|
12794
|
+
reason
|
|
12795
|
+
};
|
|
12796
|
+
const nextStatePromise2 = this.#publishStateAndGetPromise();
|
|
12797
|
+
this.#maybeStartTimeoutInterval();
|
|
12798
|
+
return { nextStatePromise: nextStatePromise2 };
|
|
12799
|
+
}
|
|
12800
|
+
if (this.#connectingStartedAt === void 0) {
|
|
12801
|
+
this.#connectingStartedAt = now;
|
|
12802
|
+
}
|
|
12803
|
+
const disconnectAt = this.#connectingStartedAt + this.#disconnectTimeoutMs;
|
|
12804
|
+
this.#state = {
|
|
12805
|
+
name: connection_status_enum_exports.Connecting,
|
|
12806
|
+
attempt: 1,
|
|
12807
|
+
disconnectAt,
|
|
12808
|
+
reason
|
|
12809
|
+
};
|
|
12810
|
+
const nextStatePromise = this.#publishStateAndGetPromise();
|
|
12811
|
+
this.#maybeStartTimeoutInterval();
|
|
12812
|
+
return { nextStatePromise };
|
|
12813
|
+
}
|
|
12814
|
+
/**
|
|
12815
|
+
* Transition to connected state.
|
|
12816
|
+
* This resets the connecting timeout timer.
|
|
12817
|
+
*
|
|
12818
|
+
* @returns An object containing a promise that resolves on the next state change.
|
|
12819
|
+
*/
|
|
12820
|
+
connected() {
|
|
12821
|
+
if (this.#state.name === connection_status_enum_exports.Closed) {
|
|
12822
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12823
|
+
}
|
|
12824
|
+
if (this.#state.name === connection_status_enum_exports.Connected) {
|
|
12825
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12826
|
+
}
|
|
12827
|
+
this.#connectingStartedAt = void 0;
|
|
12828
|
+
this.#maybeStopTimeoutInterval();
|
|
12829
|
+
this.#state = {
|
|
12830
|
+
name: connection_status_enum_exports.Connected
|
|
12831
|
+
};
|
|
12832
|
+
const nextStatePromise = this.#publishStateAndGetPromise();
|
|
12833
|
+
return { nextStatePromise };
|
|
12834
|
+
}
|
|
12835
|
+
/**
|
|
12836
|
+
* Transition to disconnected state.
|
|
12837
|
+
* This is called when the 5-minute timeout expires, or when we're intentionally
|
|
12838
|
+
* disconnecting due to an error (this will eventually be a separate state, error).
|
|
12839
|
+
* The run loop will continue trying to reconnect.
|
|
12840
|
+
*
|
|
12841
|
+
* @returns An object containing a promise that resolves on the next state change.
|
|
12842
|
+
*/
|
|
12843
|
+
disconnected(reason) {
|
|
12844
|
+
if (this.#state.name === connection_status_enum_exports.Closed) {
|
|
12845
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12846
|
+
}
|
|
12847
|
+
if (this.#state.name === connection_status_enum_exports.Disconnected) {
|
|
12848
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12849
|
+
}
|
|
12850
|
+
if (this.#state.name === connection_status_enum_exports.Connected) {
|
|
12851
|
+
this.#connectingStartedAt = void 0;
|
|
12852
|
+
}
|
|
12853
|
+
this.#maybeStopTimeoutInterval();
|
|
12854
|
+
this.#state = {
|
|
12855
|
+
name: connection_status_enum_exports.Disconnected,
|
|
12856
|
+
reason
|
|
12857
|
+
};
|
|
12858
|
+
const nextStatePromise = this.#publishStateAndGetPromise();
|
|
12859
|
+
return { nextStatePromise };
|
|
12860
|
+
}
|
|
12861
|
+
/**
|
|
12862
|
+
* Transition to error state.
|
|
12863
|
+
* This pauses the run loop until connect() is called.
|
|
12864
|
+
* Resets the 5-minute retry window and attempt counter.
|
|
12865
|
+
*
|
|
12866
|
+
* @returns An object containing a promise that resolves on the next state change.
|
|
12867
|
+
*/
|
|
12868
|
+
error(reason) {
|
|
12869
|
+
if (this.#state.name === connection_status_enum_exports.Closed) {
|
|
12870
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12871
|
+
}
|
|
12872
|
+
if (this.#state.name === connection_status_enum_exports.Error) {
|
|
12873
|
+
return { nextStatePromise: this.#nextStatePromise() };
|
|
12874
|
+
}
|
|
12875
|
+
this.#connectingStartedAt = void 0;
|
|
12876
|
+
this.#maybeStopTimeoutInterval();
|
|
12877
|
+
this.#state = {
|
|
12878
|
+
name: connection_status_enum_exports.Error,
|
|
12879
|
+
reason
|
|
12880
|
+
};
|
|
12881
|
+
const nextStatePromise = this.#publishStateAndGetPromise();
|
|
12882
|
+
return { nextStatePromise };
|
|
12883
|
+
}
|
|
12884
|
+
/**
|
|
12885
|
+
* Transition to closed state.
|
|
12886
|
+
* This is terminal - no further transitions are allowed.
|
|
12887
|
+
*/
|
|
12888
|
+
closed() {
|
|
12889
|
+
if (this.#state.name === connection_status_enum_exports.Closed) {
|
|
12890
|
+
return;
|
|
12891
|
+
}
|
|
12892
|
+
this.#connectingStartedAt = void 0;
|
|
12893
|
+
this.#maybeStopTimeoutInterval();
|
|
12894
|
+
this.#state = {
|
|
12895
|
+
name: connection_status_enum_exports.Closed,
|
|
12896
|
+
reason: new ClientError({
|
|
12897
|
+
kind: client_error_kind_enum_exports.ClientClosed,
|
|
12898
|
+
message: "Zero was explicitly closed by calling zero.close()"
|
|
12899
|
+
})
|
|
12900
|
+
};
|
|
12901
|
+
this.#publishState();
|
|
12902
|
+
this.cleanup();
|
|
12903
|
+
return;
|
|
12904
|
+
}
|
|
12905
|
+
cleanup = () => {
|
|
12906
|
+
this._listeners.clear();
|
|
12907
|
+
this.#resolveNextStateWaiters();
|
|
12908
|
+
};
|
|
12909
|
+
#resolveNextStateWaiters() {
|
|
12910
|
+
this.#stateChangeResolver.resolve(this.#state);
|
|
12911
|
+
this.#stateChangeResolver = resolver9();
|
|
12912
|
+
}
|
|
12913
|
+
#publishState() {
|
|
12914
|
+
this.notify(this.#state);
|
|
12915
|
+
this.#resolveNextStateWaiters();
|
|
12916
|
+
}
|
|
12917
|
+
#nextStatePromise() {
|
|
12918
|
+
return this.#stateChangeResolver.promise;
|
|
12919
|
+
}
|
|
12920
|
+
#publishStateAndGetPromise() {
|
|
12921
|
+
this.#publishState();
|
|
12922
|
+
return this.#nextStatePromise();
|
|
12923
|
+
}
|
|
12924
|
+
/**
|
|
12925
|
+
* Check if we should transition from connecting to disconnected due to timeout.
|
|
12926
|
+
* Returns true if the transition happened.
|
|
12927
|
+
*/
|
|
12928
|
+
#checkTimeout() {
|
|
12929
|
+
if (this.#state.name !== connection_status_enum_exports.Connecting) {
|
|
12930
|
+
return false;
|
|
12931
|
+
}
|
|
12932
|
+
const now = Date.now();
|
|
12933
|
+
if (now >= this.#state.disconnectAt) {
|
|
12934
|
+
this.disconnected(
|
|
12935
|
+
new ClientError({
|
|
12936
|
+
kind: client_error_kind_enum_exports.DisconnectTimeout,
|
|
12937
|
+
message: `Zero was unable to connect for ${Math.floor(this.#disconnectTimeoutMs / 1e3)} seconds and was disconnected`
|
|
12938
|
+
})
|
|
12939
|
+
);
|
|
12940
|
+
return true;
|
|
12941
|
+
}
|
|
12942
|
+
return false;
|
|
12943
|
+
}
|
|
12944
|
+
#maybeStartTimeoutInterval() {
|
|
12945
|
+
if (this.#timeoutInterval !== void 0) {
|
|
12946
|
+
return;
|
|
12947
|
+
}
|
|
12948
|
+
this.#timeoutInterval = setInterval(() => {
|
|
12949
|
+
this.#checkTimeout();
|
|
12950
|
+
}, this.#timeoutCheckIntervalMs);
|
|
12951
|
+
}
|
|
12952
|
+
#maybeStopTimeoutInterval() {
|
|
12953
|
+
if (this.#timeoutInterval === void 0) {
|
|
12954
|
+
return;
|
|
11084
12955
|
}
|
|
11085
|
-
|
|
12956
|
+
clearInterval(this.#timeoutInterval);
|
|
12957
|
+
this.#timeoutInterval = void 0;
|
|
11086
12958
|
}
|
|
11087
|
-
|
|
11088
|
-
|
|
11089
|
-
|
|
11090
|
-
|
|
12959
|
+
};
|
|
12960
|
+
var throwIfConnectionError = (state) => {
|
|
12961
|
+
if (ConnectionManager.isTerminalState(state) || state.name === connection_status_enum_exports.Closed || (state.name === connection_status_enum_exports.Connecting || state.name === connection_status_enum_exports.Disconnected) && state.reason) {
|
|
12962
|
+
if (isClientError(state.reason) && (state.reason.kind === client_error_kind_enum_exports.ConnectTimeout || state.reason.kind === client_error_kind_enum_exports.AbruptClose || state.reason.kind === client_error_kind_enum_exports.CleanClose)) {
|
|
12963
|
+
return;
|
|
11091
12964
|
}
|
|
11092
|
-
|
|
11093
|
-
|
|
12965
|
+
throw state.reason;
|
|
12966
|
+
}
|
|
12967
|
+
};
|
|
12968
|
+
|
|
12969
|
+
// ../zero-client/src/client/connection.ts
|
|
12970
|
+
var ConnectionImpl = class {
|
|
12971
|
+
#connectionManager;
|
|
12972
|
+
#lc;
|
|
12973
|
+
#source;
|
|
12974
|
+
constructor(connectionManager, lc) {
|
|
12975
|
+
this.#connectionManager = connectionManager;
|
|
12976
|
+
this.#lc = lc;
|
|
12977
|
+
this.#source = new ConnectionSource(connectionManager);
|
|
12978
|
+
}
|
|
12979
|
+
get state() {
|
|
12980
|
+
return this.#source;
|
|
12981
|
+
}
|
|
12982
|
+
async connect() {
|
|
12983
|
+
const lc = this.#lc.withContext("connect");
|
|
12984
|
+
if (!this.#connectionManager.isInTerminalState()) {
|
|
12985
|
+
lc.debug?.(
|
|
12986
|
+
"connect() called but not in a terminal state. Current state:",
|
|
12987
|
+
this.#connectionManager.state.name
|
|
12988
|
+
);
|
|
12989
|
+
return;
|
|
11094
12990
|
}
|
|
11095
|
-
|
|
12991
|
+
lc.info?.(
|
|
12992
|
+
`Resuming connection from state: ${this.#connectionManager.state.name}`
|
|
12993
|
+
);
|
|
12994
|
+
const { nextStatePromise } = this.#connectionManager.connecting();
|
|
12995
|
+
await nextStatePromise;
|
|
11096
12996
|
}
|
|
11097
|
-
|
|
11098
|
-
|
|
12997
|
+
};
|
|
12998
|
+
var ConnectionSource = class {
|
|
12999
|
+
#connectionManager;
|
|
13000
|
+
constructor(connectionManager) {
|
|
13001
|
+
this.#connectionManager = connectionManager;
|
|
13002
|
+
}
|
|
13003
|
+
get current() {
|
|
13004
|
+
return this.#connectionManager.state;
|
|
13005
|
+
}
|
|
13006
|
+
get subscribe() {
|
|
13007
|
+
return this.#connectionManager.subscribe;
|
|
11099
13008
|
}
|
|
11100
13009
|
};
|
|
11101
13010
|
|
|
11102
|
-
// ../zero-client/src/client/connection-state-enum.ts
|
|
11103
|
-
var Disconnected = 0;
|
|
11104
|
-
var Connecting = 1;
|
|
11105
|
-
var Connected = 2;
|
|
11106
|
-
|
|
11107
13011
|
// ../zql/src/ivm/memory-storage.ts
|
|
11108
13012
|
import { compareUTF8 as compareUTF83 } from "compare-utf8";
|
|
11109
13013
|
|
|
@@ -11866,21 +13770,6 @@ var MemorySource = class _MemorySource {
|
|
|
11866
13770
|
const exists = (row) => data.has(row);
|
|
11867
13771
|
const setOverlay = (o) => this.#overlay = o;
|
|
11868
13772
|
const writeChange = (c) => this.#writeChange(c);
|
|
11869
|
-
if (change.type === "set") {
|
|
11870
|
-
const existing = data.get(change.row);
|
|
11871
|
-
if (existing !== void 0) {
|
|
11872
|
-
change = {
|
|
11873
|
-
type: "edit",
|
|
11874
|
-
row: change.row,
|
|
11875
|
-
oldRow: existing
|
|
11876
|
-
};
|
|
11877
|
-
} else {
|
|
11878
|
-
change = {
|
|
11879
|
-
type: "add",
|
|
11880
|
-
row: change.row
|
|
11881
|
-
};
|
|
11882
|
-
}
|
|
11883
|
-
}
|
|
11884
13773
|
yield* genPushAndWriteWithSplitEdit(
|
|
11885
13774
|
this.#connections,
|
|
11886
13775
|
change,
|
|
@@ -12579,16 +14468,10 @@ async function upsertImpl(tx, arg, schema, ivmBranch) {
|
|
|
12579
14468
|
schema.tables[arg.tableName].primaryKey,
|
|
12580
14469
|
arg.value
|
|
12581
14470
|
);
|
|
12582
|
-
|
|
12583
|
-
|
|
12584
|
-
|
|
12585
|
-
|
|
12586
|
-
await tx.set(key, val);
|
|
12587
|
-
if (ivmBranch) {
|
|
12588
|
-
must(ivmBranch.getSource(arg.tableName)).push({
|
|
12589
|
-
type: "set",
|
|
12590
|
-
row: arg.value
|
|
12591
|
-
});
|
|
14471
|
+
if (await tx.has(key)) {
|
|
14472
|
+
await updateImpl(tx, { ...arg, op: "update" }, schema, ivmBranch);
|
|
14473
|
+
} else {
|
|
14474
|
+
await insertImpl(tx, { ...arg, op: "insert" }, schema, ivmBranch);
|
|
12592
14475
|
}
|
|
12593
14476
|
}
|
|
12594
14477
|
async function updateImpl(tx, arg, schema, ivmBranch) {
|
|
@@ -13065,7 +14948,7 @@ function makeMessage(message, context, logLevel) {
|
|
|
13065
14948
|
}
|
|
13066
14949
|
|
|
13067
14950
|
// ../zero-client/src/client/version.ts
|
|
13068
|
-
var version2 = "0.
|
|
14951
|
+
var version2 = "0.25.0-canary.1";
|
|
13069
14952
|
|
|
13070
14953
|
// ../zero-client/src/client/log-options.ts
|
|
13071
14954
|
var LevelFilterLogSink = class {
|
|
@@ -13122,6 +15005,15 @@ function createLogOptions(options, createDatadogLogSink = (options2) => new Data
|
|
|
13122
15005
|
}
|
|
13123
15006
|
|
|
13124
15007
|
// ../zero-client/src/client/metric-name-enum.ts
|
|
15008
|
+
var metric_name_enum_exports = {};
|
|
15009
|
+
__export(metric_name_enum_exports, {
|
|
15010
|
+
LastConnectError: () => LastConnectError,
|
|
15011
|
+
LastConnectErrorV2: () => LastConnectErrorV2,
|
|
15012
|
+
NotConnected: () => NotConnected,
|
|
15013
|
+
TimeToConnectMs: () => TimeToConnectMs,
|
|
15014
|
+
TimeToConnectMsV2: () => TimeToConnectMsV2,
|
|
15015
|
+
TotalTimeToConnectMs: () => TotalTimeToConnectMs
|
|
15016
|
+
});
|
|
13125
15017
|
var TimeToConnectMs = "time_to_connect_ms";
|
|
13126
15018
|
var LastConnectError = "last_connect_error";
|
|
13127
15019
|
var TimeToConnectMsV2 = "time_to_connect_ms_v2";
|
|
@@ -13133,13 +15025,25 @@ var NotConnected = "not_connected";
|
|
|
13133
15025
|
var DID_NOT_CONNECT_VALUE = 100 * 1e3;
|
|
13134
15026
|
var REPORT_INTERVAL_MS = 5e3;
|
|
13135
15027
|
function getLastConnectErrorValue(reason) {
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
return
|
|
15028
|
+
return `${isServerError(reason) ? "server_" : "client_"}${camelToSnake(reason.kind)}`;
|
|
15029
|
+
}
|
|
15030
|
+
function camelToSnake(kind) {
|
|
15031
|
+
return kind.split(/\.?(?=[A-Z])/).join("_").toLowerCase();
|
|
13140
15032
|
}
|
|
13141
|
-
function
|
|
13142
|
-
|
|
15033
|
+
function shouldReportConnectError(reason) {
|
|
15034
|
+
if (!isClientError(reason)) {
|
|
15035
|
+
return true;
|
|
15036
|
+
}
|
|
15037
|
+
switch (reason.kind) {
|
|
15038
|
+
case client_error_kind_enum_exports.Hidden:
|
|
15039
|
+
case client_error_kind_enum_exports.ClientClosed:
|
|
15040
|
+
case client_error_kind_enum_exports.UserDisconnect:
|
|
15041
|
+
case client_error_kind_enum_exports.CleanClose:
|
|
15042
|
+
case client_error_kind_enum_exports.AbruptClose:
|
|
15043
|
+
return false;
|
|
15044
|
+
default:
|
|
15045
|
+
return true;
|
|
15046
|
+
}
|
|
13143
15047
|
}
|
|
13144
15048
|
var MetricManager = class {
|
|
13145
15049
|
#reportIntervalMs;
|
|
@@ -13180,7 +15084,7 @@ var MetricManager = class {
|
|
|
13180
15084
|
// be encapsulated with the ConnectionState. This will probably happen as part
|
|
13181
15085
|
// of https://github.com/rocicorp/reflect-server/issues/255.
|
|
13182
15086
|
timeToConnectMs = this.#register(
|
|
13183
|
-
new Gauge(TimeToConnectMs)
|
|
15087
|
+
new Gauge(metric_name_enum_exports.TimeToConnectMs)
|
|
13184
15088
|
);
|
|
13185
15089
|
// lastConnectError records the last error that occurred when connecting,
|
|
13186
15090
|
// if any. It is cleared when connecting successfully or when reported, so this
|
|
@@ -13188,28 +15092,28 @@ var MetricManager = class {
|
|
|
13188
15092
|
// we are still not connected.
|
|
13189
15093
|
lastConnectError = this.#register(
|
|
13190
15094
|
new State(
|
|
13191
|
-
LastConnectError,
|
|
15095
|
+
metric_name_enum_exports.LastConnectError,
|
|
13192
15096
|
true
|
|
13193
15097
|
// clearOnFlush
|
|
13194
15098
|
)
|
|
13195
15099
|
);
|
|
13196
15100
|
// notConnected records the reason why the client is not currently connected.
|
|
13197
15101
|
// It is cleared when the client successfully connects.
|
|
13198
|
-
#notConnected = this.#register(new State(NotConnected));
|
|
15102
|
+
#notConnected = this.#register(new State(metric_name_enum_exports.NotConnected));
|
|
13199
15103
|
// The time from the call to connect() to receiving the 'connected' ws message
|
|
13200
15104
|
// for the current connection. Cleared when the client is not connected.
|
|
13201
15105
|
// TODO: Not actually currently cleared on disconnect untill there is a
|
|
13202
15106
|
// connect error, or client reports disconnected and waiting for visible.
|
|
13203
15107
|
// Should have a value iff _notConnected has no value.
|
|
13204
15108
|
#timeToConnectMsV2 = this.#register(
|
|
13205
|
-
new Gauge(TimeToConnectMsV2)
|
|
15109
|
+
new Gauge(metric_name_enum_exports.TimeToConnectMsV2)
|
|
13206
15110
|
);
|
|
13207
15111
|
// lastConnectErrorV2 records the last error that occurred when connecting,
|
|
13208
15112
|
// if any. It is cleared when the client successfully connects or
|
|
13209
15113
|
// stops trying to connect due to being hidden.
|
|
13210
15114
|
// Should have a value iff notConnected state is NotConnectedReason.Error.
|
|
13211
15115
|
#lastConnectErrorV2 = this.#register(
|
|
13212
|
-
new State(LastConnectErrorV2)
|
|
15116
|
+
new State(metric_name_enum_exports.LastConnectErrorV2)
|
|
13213
15117
|
);
|
|
13214
15118
|
// The total time it took to connect across retries for the current
|
|
13215
15119
|
// connection. Cleared when the client is not connected.
|
|
@@ -13218,7 +15122,7 @@ var MetricManager = class {
|
|
|
13218
15122
|
// See Zero.#totalToConnectStart for details of how this total is computed.
|
|
13219
15123
|
// Should have a value iff _notConnected has no value.
|
|
13220
15124
|
#totalTimeToConnectMs = this.#register(
|
|
13221
|
-
new Gauge(TotalTimeToConnectMs)
|
|
15125
|
+
new Gauge(metric_name_enum_exports.TotalTimeToConnectMs)
|
|
13222
15126
|
);
|
|
13223
15127
|
#setNotConnectedReason(reason) {
|
|
13224
15128
|
this.#notConnected.set(reason);
|
|
@@ -13360,7 +15264,7 @@ var State = class {
|
|
|
13360
15264
|
};
|
|
13361
15265
|
|
|
13362
15266
|
// ../zero-client/src/client/mutation-tracker.ts
|
|
13363
|
-
import { resolver as
|
|
15267
|
+
import { resolver as resolver10 } from "@rocicorp/resolver";
|
|
13364
15268
|
var currentEphemeralID = 0;
|
|
13365
15269
|
function nextEphemeralID() {
|
|
13366
15270
|
return ++currentEphemeralID;
|
|
@@ -13371,10 +15275,11 @@ var MutationTracker = class {
|
|
|
13371
15275
|
#allMutationsAppliedListeners;
|
|
13372
15276
|
#lc;
|
|
13373
15277
|
#ackMutations;
|
|
15278
|
+
#onFatalError;
|
|
13374
15279
|
#clientID;
|
|
13375
15280
|
#largestOutstandingMutationID;
|
|
13376
15281
|
#currentMutationID;
|
|
13377
|
-
constructor(lc, ackMutations) {
|
|
15282
|
+
constructor(lc, ackMutations, onFatalError) {
|
|
13378
15283
|
this.#lc = lc.withContext("MutationTracker");
|
|
13379
15284
|
this.#outstandingMutations = /* @__PURE__ */ new Map();
|
|
13380
15285
|
this.#ephemeralIDsByMutationID = /* @__PURE__ */ new Map();
|
|
@@ -13382,6 +15287,7 @@ var MutationTracker = class {
|
|
|
13382
15287
|
this.#largestOutstandingMutationID = 0;
|
|
13383
15288
|
this.#currentMutationID = 0;
|
|
13384
15289
|
this.#ackMutations = ackMutations;
|
|
15290
|
+
this.#onFatalError = onFatalError;
|
|
13385
15291
|
}
|
|
13386
15292
|
setClientIDAndWatch(clientID, experimentalWatch) {
|
|
13387
15293
|
assert(this.#clientID === void 0, "clientID already set");
|
|
@@ -13398,7 +15304,7 @@ var MutationTracker = class {
|
|
|
13398
15304
|
}
|
|
13399
15305
|
trackMutation() {
|
|
13400
15306
|
const id = nextEphemeralID();
|
|
13401
|
-
const mutationResolver =
|
|
15307
|
+
const mutationResolver = resolver10();
|
|
13402
15308
|
this.#outstandingMutations.set(id, {
|
|
13403
15309
|
resolver: mutationResolver
|
|
13404
15310
|
});
|
|
@@ -13469,10 +15375,53 @@ var MutationTracker = class {
|
|
|
13469
15375
|
"Received an error response when pushing mutations",
|
|
13470
15376
|
response
|
|
13471
15377
|
);
|
|
15378
|
+
const fatalError = this.#fatalErrorFromPushError(response);
|
|
15379
|
+
if (fatalError) {
|
|
15380
|
+
this.#onFatalError(fatalError);
|
|
15381
|
+
}
|
|
13472
15382
|
} else {
|
|
13473
15383
|
this.#processPushOk(response);
|
|
13474
15384
|
}
|
|
13475
15385
|
}
|
|
15386
|
+
#fatalErrorFromPushError(error) {
|
|
15387
|
+
switch (error.error) {
|
|
15388
|
+
case "unsupportedPushVersion":
|
|
15389
|
+
return new ProtocolError({
|
|
15390
|
+
kind: error_kind_enum_exports.PushFailed,
|
|
15391
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15392
|
+
reason: error_reason_enum_exports.Internal,
|
|
15393
|
+
message: `Unsupported push version`,
|
|
15394
|
+
mutationIDs: []
|
|
15395
|
+
});
|
|
15396
|
+
case "unsupportedSchemaVersion":
|
|
15397
|
+
return new ProtocolError({
|
|
15398
|
+
kind: error_kind_enum_exports.PushFailed,
|
|
15399
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15400
|
+
reason: error_reason_enum_exports.Internal,
|
|
15401
|
+
message: `Unsupported schema version`,
|
|
15402
|
+
mutationIDs: []
|
|
15403
|
+
});
|
|
15404
|
+
case "http":
|
|
15405
|
+
return new ProtocolError({
|
|
15406
|
+
kind: error_kind_enum_exports.PushFailed,
|
|
15407
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15408
|
+
reason: error_reason_enum_exports.HTTP,
|
|
15409
|
+
status: error.status,
|
|
15410
|
+
message: `Fetch from API server returned non-OK status ${error.status}: ${error.details ?? "unknown"}`,
|
|
15411
|
+
mutationIDs: []
|
|
15412
|
+
});
|
|
15413
|
+
case "zeroPusher":
|
|
15414
|
+
return new ProtocolError({
|
|
15415
|
+
kind: error_kind_enum_exports.PushFailed,
|
|
15416
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15417
|
+
reason: error_reason_enum_exports.Internal,
|
|
15418
|
+
message: `ZeroPusher error: ${error.details ?? "unknown"}`,
|
|
15419
|
+
mutationIDs: []
|
|
15420
|
+
});
|
|
15421
|
+
default:
|
|
15422
|
+
unreachable(error);
|
|
15423
|
+
}
|
|
15424
|
+
}
|
|
13476
15425
|
/**
|
|
13477
15426
|
* DEPRECATED: to be removed when we switch to fully driving
|
|
13478
15427
|
* mutation resolution via poke.
|
|
@@ -13566,6 +15515,17 @@ var MutationTracker = class {
|
|
|
13566
15515
|
const entry = this.#outstandingMutations.get(ephemeralID);
|
|
13567
15516
|
assert(entry && entry.mutationID === mid);
|
|
13568
15517
|
this.#settleMutation(ephemeralID, entry, "reject", error);
|
|
15518
|
+
if (error.error === "oooMutation") {
|
|
15519
|
+
this.#onFatalError(
|
|
15520
|
+
new ProtocolError({
|
|
15521
|
+
kind: error_kind_enum_exports.InvalidPush,
|
|
15522
|
+
origin: error_origin_enum_exports.Server,
|
|
15523
|
+
reason: error_reason_enum_exports.Internal,
|
|
15524
|
+
message: "Server reported an out-of-order mutation",
|
|
15525
|
+
details: error.details
|
|
15526
|
+
})
|
|
15527
|
+
);
|
|
15528
|
+
}
|
|
13569
15529
|
}
|
|
13570
15530
|
#processMutationOk(clientID, mid, result) {
|
|
13571
15531
|
assert(
|
|
@@ -13615,16 +15575,13 @@ var MutationTracker = class {
|
|
|
13615
15575
|
}
|
|
13616
15576
|
};
|
|
13617
15577
|
|
|
13618
|
-
// ../zero-client/src/client/ping-result-enum.ts
|
|
13619
|
-
var TimedOut = 0;
|
|
13620
|
-
var Success = 1;
|
|
13621
|
-
|
|
13622
15578
|
// ../zero-client/src/client/query-manager.ts
|
|
13623
15579
|
var QueryManager = class {
|
|
13624
15580
|
#clientID;
|
|
13625
15581
|
#clientToServer;
|
|
13626
15582
|
#serverToClient;
|
|
13627
15583
|
#send;
|
|
15584
|
+
#onFatalError;
|
|
13628
15585
|
#queries = /* @__PURE__ */ new Map();
|
|
13629
15586
|
#recentQueriesMaxSize;
|
|
13630
15587
|
#recentQueries = /* @__PURE__ */ new Set();
|
|
@@ -13638,7 +15595,7 @@ var QueryManager = class {
|
|
|
13638
15595
|
#metrics = newMetrics();
|
|
13639
15596
|
#queryMetrics = /* @__PURE__ */ new Map();
|
|
13640
15597
|
#slowMaterializeThreshold;
|
|
13641
|
-
constructor(lc, mutationTracker, clientID, tables, send2, experimentalWatch, recentQueriesMaxSize, queryChangeThrottleMs, slowMaterializeThreshold) {
|
|
15598
|
+
constructor(lc, mutationTracker, clientID, tables, send2, experimentalWatch, recentQueriesMaxSize, queryChangeThrottleMs, slowMaterializeThreshold, onFatalError) {
|
|
13642
15599
|
this.#lc = lc.withContext("QueryManager");
|
|
13643
15600
|
this.#clientID = clientID;
|
|
13644
15601
|
this.#clientToServer = clientToServer(tables);
|
|
@@ -13648,6 +15605,7 @@ var QueryManager = class {
|
|
|
13648
15605
|
this.#mutationTracker = mutationTracker;
|
|
13649
15606
|
this.#queryChangeThrottleMs = queryChangeThrottleMs;
|
|
13650
15607
|
this.#slowMaterializeThreshold = slowMaterializeThreshold;
|
|
15608
|
+
this.#onFatalError = onFatalError;
|
|
13651
15609
|
this.#mutationTracker.onAllMutationsApplied(() => {
|
|
13652
15610
|
if (this.#pendingRemovals.length === 0) {
|
|
13653
15611
|
return;
|
|
@@ -13754,6 +15712,26 @@ var QueryManager = class {
|
|
|
13754
15712
|
if (entry) {
|
|
13755
15713
|
entry.gotCallbacks.forEach((callback) => callback(false, error));
|
|
13756
15714
|
}
|
|
15715
|
+
if (error.error !== "app") {
|
|
15716
|
+
this.#onFatalError(
|
|
15717
|
+
new ProtocolError(
|
|
15718
|
+
error.error === "http" ? {
|
|
15719
|
+
kind: error_kind_enum_exports.TransformFailed,
|
|
15720
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15721
|
+
reason: error_reason_enum_exports.HTTP,
|
|
15722
|
+
message: `HTTP ${error.status} transforming queries`,
|
|
15723
|
+
status: error.status,
|
|
15724
|
+
queryIDs: []
|
|
15725
|
+
} : {
|
|
15726
|
+
kind: error_kind_enum_exports.TransformFailed,
|
|
15727
|
+
origin: error_origin_enum_exports.ZeroCache,
|
|
15728
|
+
reason: error_reason_enum_exports.Internal,
|
|
15729
|
+
message: `Unknown error transforming queries`,
|
|
15730
|
+
queryIDs: []
|
|
15731
|
+
}
|
|
15732
|
+
)
|
|
15733
|
+
);
|
|
15734
|
+
}
|
|
13757
15735
|
}
|
|
13758
15736
|
}
|
|
13759
15737
|
addCustom(ast, { name, args }, ttl, gotCallback) {
|
|
@@ -14052,39 +16030,6 @@ function nextBackoff(lc, now) {
|
|
|
14052
16030
|
};
|
|
14053
16031
|
}
|
|
14054
16032
|
|
|
14055
|
-
// ../zero-client/src/client/server-error.ts
|
|
14056
|
-
var ServerError = class extends Error {
|
|
14057
|
-
name = "ServerError";
|
|
14058
|
-
errorBody;
|
|
14059
|
-
get kind() {
|
|
14060
|
-
return this.errorBody.kind;
|
|
14061
|
-
}
|
|
14062
|
-
constructor(errorBody) {
|
|
14063
|
-
super(errorBody.kind + ": " + errorBody.message);
|
|
14064
|
-
this.errorBody = errorBody;
|
|
14065
|
-
}
|
|
14066
|
-
};
|
|
14067
|
-
function isServerError(ex) {
|
|
14068
|
-
return ex instanceof ServerError;
|
|
14069
|
-
}
|
|
14070
|
-
function isAuthError(ex) {
|
|
14071
|
-
return isServerError(ex) && isAuthErrorKind(ex.kind);
|
|
14072
|
-
}
|
|
14073
|
-
function isAuthErrorKind(kind) {
|
|
14074
|
-
return kind === error_kind_enum_exports.AuthInvalidated || kind === error_kind_enum_exports.Unauthorized;
|
|
14075
|
-
}
|
|
14076
|
-
function isBackoffError(ex) {
|
|
14077
|
-
if (isServerError(ex)) {
|
|
14078
|
-
switch (ex.errorBody.kind) {
|
|
14079
|
-
case error_kind_enum_exports.Rebalance:
|
|
14080
|
-
case error_kind_enum_exports.Rehome:
|
|
14081
|
-
case error_kind_enum_exports.ServerOverloaded:
|
|
14082
|
-
return ex.errorBody;
|
|
14083
|
-
}
|
|
14084
|
-
}
|
|
14085
|
-
return void 0;
|
|
14086
|
-
}
|
|
14087
|
-
|
|
14088
16033
|
// ../zero-client/src/client/server-option.ts
|
|
14089
16034
|
function validateServerParam(paramName, server) {
|
|
14090
16035
|
const expectedProtocol = "http";
|
|
@@ -14508,7 +16453,6 @@ var ZeroRep = class {
|
|
|
14508
16453
|
};
|
|
14509
16454
|
|
|
14510
16455
|
// ../zero-client/src/client/zero.ts
|
|
14511
|
-
var onSetConnectionStateSymbol = Symbol();
|
|
14512
16456
|
var exposedToTestingSymbol = Symbol();
|
|
14513
16457
|
var createLogOptionsSymbol = Symbol();
|
|
14514
16458
|
var RUN_LOOP_INTERVAL_MS = 5e3;
|
|
@@ -14516,6 +16460,7 @@ var PING_INTERVAL_MS = 5e3;
|
|
|
14516
16460
|
var PING_TIMEOUT_MS = 5e3;
|
|
14517
16461
|
var PULL_TIMEOUT_MS = 5e3;
|
|
14518
16462
|
var DEFAULT_DISCONNECT_HIDDEN_DELAY_MS = 5e3;
|
|
16463
|
+
var DEFAULT_DISCONNECT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
14519
16464
|
var CONNECT_TIMEOUT_MS = 1e4;
|
|
14520
16465
|
var CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY = 6;
|
|
14521
16466
|
var NULL_LAST_MUTATION_ID_SENT = { clientID: "", id: -1 };
|
|
@@ -14602,35 +16547,22 @@ var Zero = class _Zero {
|
|
|
14602
16547
|
};
|
|
14603
16548
|
#zeroContext;
|
|
14604
16549
|
queryDelegate;
|
|
14605
|
-
#connectResolver = resolver10();
|
|
14606
16550
|
#pendingPullsByRequestID = /* @__PURE__ */ new Map();
|
|
14607
16551
|
#lastMutationIDReceived = 0;
|
|
14608
16552
|
#socket = void 0;
|
|
14609
|
-
#socketResolver =
|
|
14610
|
-
#connectionStateChangeResolver = resolver10();
|
|
16553
|
+
#socketResolver = resolver11();
|
|
14611
16554
|
/**
|
|
14612
|
-
*
|
|
14613
|
-
*
|
|
14614
|
-
*
|
|
16555
|
+
* Utility promise that resolves when the socket transitions to connected.
|
|
16556
|
+
* It rejects if we hit an error or timeout before the connected message.
|
|
16557
|
+
* Used by push/pull helpers to queue work until the connection is usable.
|
|
14615
16558
|
*/
|
|
14616
|
-
#
|
|
16559
|
+
#connectResolver = resolver11();
|
|
14617
16560
|
#closeAbortController = new AbortController();
|
|
14618
16561
|
#visibilityWatcher;
|
|
14619
|
-
|
|
14620
|
-
#
|
|
16562
|
+
#connectionManager;
|
|
16563
|
+
#connection;
|
|
14621
16564
|
#activeClientsManager;
|
|
14622
16565
|
#inspector;
|
|
14623
|
-
#setConnectionState(state) {
|
|
14624
|
-
if (state === this.#connectionState) {
|
|
14625
|
-
return;
|
|
14626
|
-
}
|
|
14627
|
-
this.#connectionState = state;
|
|
14628
|
-
this.#connectionStateChangeResolver.resolve(state);
|
|
14629
|
-
this.#connectionStateChangeResolver = resolver10();
|
|
14630
|
-
if (false) {
|
|
14631
|
-
asTestZero(this)[onSetConnectionStateSymbol]?.(state);
|
|
14632
|
-
}
|
|
14633
|
-
}
|
|
14634
16566
|
#connectStart = void 0;
|
|
14635
16567
|
// Set on connect attempt if currently undefined.
|
|
14636
16568
|
// Reset to undefined when
|
|
@@ -14664,7 +16596,10 @@ var Zero = class _Zero {
|
|
|
14664
16596
|
slowMaterializeThreshold = 5e3
|
|
14665
16597
|
} = options;
|
|
14666
16598
|
if (!userID) {
|
|
14667
|
-
throw new
|
|
16599
|
+
throw new ClientError({
|
|
16600
|
+
kind: client_error_kind_enum_exports.Internal,
|
|
16601
|
+
message: "ZeroOptions.userID must not be empty."
|
|
16602
|
+
});
|
|
14668
16603
|
}
|
|
14669
16604
|
const server = getServer(options.server);
|
|
14670
16605
|
this.#enableAnalytics = shouldEnableAnalytics(
|
|
@@ -14682,9 +16617,10 @@ var Zero = class _Zero {
|
|
|
14682
16617
|
}
|
|
14683
16618
|
}
|
|
14684
16619
|
if (hiddenTabDisconnectDelay < 0) {
|
|
14685
|
-
throw new
|
|
14686
|
-
|
|
14687
|
-
|
|
16620
|
+
throw new ClientError({
|
|
16621
|
+
kind: client_error_kind_enum_exports.Internal,
|
|
16622
|
+
message: "ZeroOptions.hiddenTabDisconnectDelay must not be negative."
|
|
16623
|
+
});
|
|
14688
16624
|
}
|
|
14689
16625
|
this.#onlineManager = new OnlineManager();
|
|
14690
16626
|
if (onOnlineChange) {
|
|
@@ -14698,9 +16634,17 @@ var Zero = class _Zero {
|
|
|
14698
16634
|
enableAnalytics: this.#enableAnalytics
|
|
14699
16635
|
});
|
|
14700
16636
|
const logOptions = this.#logOptions;
|
|
16637
|
+
this.#connectionManager = new ConnectionManager({
|
|
16638
|
+
disconnectTimeoutMs: DEFAULT_DISCONNECT_TIMEOUT_MS
|
|
16639
|
+
});
|
|
14701
16640
|
const { enableLegacyMutators = true, enableLegacyQueries = true } = schema;
|
|
14702
16641
|
const replicacheMutators = {
|
|
14703
|
-
[CRUD_MUTATION_NAME]: enableLegacyMutators ? makeCRUDMutator(schema) : () => Promise.reject(
|
|
16642
|
+
[CRUD_MUTATION_NAME]: enableLegacyMutators ? makeCRUDMutator(schema) : () => Promise.reject(
|
|
16643
|
+
new ClientError({
|
|
16644
|
+
kind: client_error_kind_enum_exports.Internal,
|
|
16645
|
+
message: "Zero CRUD mutators are not enabled."
|
|
16646
|
+
})
|
|
16647
|
+
)
|
|
14704
16648
|
};
|
|
14705
16649
|
this.#ivmMain = new IVMSourceBranch(schema.tables);
|
|
14706
16650
|
function assertUnique(key) {
|
|
@@ -14726,7 +16670,10 @@ var Zero = class _Zero {
|
|
|
14726
16670
|
const lc = new ZeroLogContext(logOptions.logLevel, {}, logSink);
|
|
14727
16671
|
this.#mutationTracker = new MutationTracker(
|
|
14728
16672
|
lc,
|
|
14729
|
-
(upTo) => this.#send(["ackMutationResponses", upTo])
|
|
16673
|
+
(upTo) => this.#send(["ackMutationResponses", upTo]),
|
|
16674
|
+
(error) => {
|
|
16675
|
+
this.#disconnect(lc, error);
|
|
16676
|
+
}
|
|
14730
16677
|
);
|
|
14731
16678
|
if (options.mutators) {
|
|
14732
16679
|
for (const [namespaceOrKey, mutatorOrMutators] of Object.entries(
|
|
@@ -14832,6 +16779,7 @@ var Zero = class _Zero {
|
|
|
14832
16779
|
this.#server = server;
|
|
14833
16780
|
this.userID = userID;
|
|
14834
16781
|
this.#lc = lc.withContext("clientID", rep.clientID);
|
|
16782
|
+
this.#connection = new ConnectionImpl(this.#connectionManager, this.#lc);
|
|
14835
16783
|
this.#mutationTracker.setClientIDAndWatch(
|
|
14836
16784
|
rep.clientID,
|
|
14837
16785
|
rep.experimentalWatch.bind(rep)
|
|
@@ -14902,7 +16850,10 @@ var Zero = class _Zero {
|
|
|
14902
16850
|
rep.experimentalWatch.bind(rep),
|
|
14903
16851
|
maxRecentQueries,
|
|
14904
16852
|
options.queryChangeThrottleMs ?? DEFAULT_QUERY_CHANGE_THROTTLE_MS,
|
|
14905
|
-
slowMaterializeThreshold
|
|
16853
|
+
slowMaterializeThreshold,
|
|
16854
|
+
(error) => {
|
|
16855
|
+
this.#disconnect(lc, error);
|
|
16856
|
+
}
|
|
14906
16857
|
);
|
|
14907
16858
|
this.#clientToServer = clientToServer(schema.tables);
|
|
14908
16859
|
this.#deleteClientsManager = new DeleteClientsManager(
|
|
@@ -14946,7 +16897,7 @@ var Zero = class _Zero {
|
|
|
14946
16897
|
logOptions: this.#logOptions,
|
|
14947
16898
|
connectStart: () => this.#connectStart,
|
|
14948
16899
|
socketResolver: () => this.#socketResolver,
|
|
14949
|
-
|
|
16900
|
+
connectionManager: () => this.#connectionManager
|
|
14950
16901
|
};
|
|
14951
16902
|
}
|
|
14952
16903
|
}
|
|
@@ -14978,7 +16929,7 @@ var Zero = class _Zero {
|
|
|
14978
16929
|
}
|
|
14979
16930
|
}
|
|
14980
16931
|
#send(msg) {
|
|
14981
|
-
if (this.#socket && this.#
|
|
16932
|
+
if (this.#socket && this.#connectionManager.is(connection_status_enum_exports.Connected)) {
|
|
14982
16933
|
send(this.#socket, msg);
|
|
14983
16934
|
}
|
|
14984
16935
|
}
|
|
@@ -15025,6 +16976,27 @@ var Zero = class _Zero {
|
|
|
15025
16976
|
get schemaVersion() {
|
|
15026
16977
|
return this.#rep.schemaVersion;
|
|
15027
16978
|
}
|
|
16979
|
+
/**
|
|
16980
|
+
* The schema passed into Zero when it was constructed.
|
|
16981
|
+
*
|
|
16982
|
+
* This can be paired with the inspector API to explore the client cache for
|
|
16983
|
+
* debugging or tooling. The inspector exposes the raw key/value map as well
|
|
16984
|
+
* as the per-table rows that back `zero.query[tableName].run()`.
|
|
16985
|
+
*
|
|
16986
|
+
* ```ts
|
|
16987
|
+
* const inspector = __zero.inspector;
|
|
16988
|
+
* const client = inspector.client;
|
|
16989
|
+
*
|
|
16990
|
+
* console.log('client map:', await client.map());
|
|
16991
|
+
*
|
|
16992
|
+
* for (const tableName of Object.keys(__zero.schema.tables)) {
|
|
16993
|
+
* console.table(await client.rows(tableName));
|
|
16994
|
+
* }
|
|
16995
|
+
* ```
|
|
16996
|
+
*/
|
|
16997
|
+
get schema() {
|
|
16998
|
+
return this.#options.schema;
|
|
16999
|
+
}
|
|
15028
17000
|
/**
|
|
15029
17001
|
* The client ID for this instance of Zero. Each instance
|
|
15030
17002
|
* gets a unique client ID.
|
|
@@ -15072,6 +17044,25 @@ var Zero = class _Zero {
|
|
|
15072
17044
|
* will throw an error.
|
|
15073
17045
|
*/
|
|
15074
17046
|
mutateBatch;
|
|
17047
|
+
/**
|
|
17048
|
+
* The connection API for managing Zero's connection lifecycle.
|
|
17049
|
+
*
|
|
17050
|
+
* Use this to monitor connection state and manually control connections.
|
|
17051
|
+
*
|
|
17052
|
+
* @example
|
|
17053
|
+
* ```ts
|
|
17054
|
+
* // Subscribe to connection state changes
|
|
17055
|
+
* z.connection.state.subscribe(state => {
|
|
17056
|
+
* console.log('Connection state:', state.name);
|
|
17057
|
+
* });
|
|
17058
|
+
*
|
|
17059
|
+
* // Manually resume connection from error state
|
|
17060
|
+
* await z.connection.connect();
|
|
17061
|
+
* ```
|
|
17062
|
+
*/
|
|
17063
|
+
get connection() {
|
|
17064
|
+
return this.#connection;
|
|
17065
|
+
}
|
|
15075
17066
|
/**
|
|
15076
17067
|
* Whether this Zero instance has been closed.
|
|
15077
17068
|
*
|
|
@@ -15079,7 +17070,7 @@ var Zero = class _Zero {
|
|
|
15079
17070
|
* longer query or mutate data with it, and its query views stop updating.
|
|
15080
17071
|
*/
|
|
15081
17072
|
get closed() {
|
|
15082
|
-
return this.#
|
|
17073
|
+
return this.#connectionManager.is(connection_status_enum_exports.Closed);
|
|
15083
17074
|
}
|
|
15084
17075
|
/**
|
|
15085
17076
|
* Closes this Zero instance.
|
|
@@ -15089,23 +17080,35 @@ var Zero = class _Zero {
|
|
|
15089
17080
|
*/
|
|
15090
17081
|
async close() {
|
|
15091
17082
|
const lc = this.#lc.withContext("close");
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
17083
|
+
try {
|
|
17084
|
+
if (this.closed) {
|
|
17085
|
+
lc.debug?.("close() called on already closed instance");
|
|
17086
|
+
return;
|
|
17087
|
+
}
|
|
17088
|
+
lc.debug?.("Closing Zero instance. Stack:", new Error().stack);
|
|
17089
|
+
this.#onlineManager.cleanup();
|
|
17090
|
+
if (!this.#connectionManager.is(connection_status_enum_exports.Disconnected)) {
|
|
17091
|
+
this.#disconnect(
|
|
17092
|
+
lc,
|
|
17093
|
+
new ClientError({
|
|
17094
|
+
kind: client_error_kind_enum_exports.ClientClosed,
|
|
17095
|
+
message: "Zero instance closed by user"
|
|
17096
|
+
}),
|
|
17097
|
+
CLOSE_CODE_NORMAL
|
|
17098
|
+
);
|
|
17099
|
+
}
|
|
17100
|
+
lc.debug?.("Aborting closeAbortController due to close()");
|
|
17101
|
+
this.#closeAbortController.abort();
|
|
17102
|
+
this.#metrics.stop();
|
|
17103
|
+
const ret = await this.#rep.close();
|
|
17104
|
+
this.#unexpose();
|
|
17105
|
+
return ret;
|
|
17106
|
+
} catch (e) {
|
|
17107
|
+
lc.error?.("Error closing Zero instance", e);
|
|
17108
|
+
throw e;
|
|
17109
|
+
} finally {
|
|
17110
|
+
this.#connectionManager.closed();
|
|
15102
17111
|
}
|
|
15103
|
-
lc.debug?.("Aborting closeAbortController due to close()");
|
|
15104
|
-
this.#closeAbortController.abort();
|
|
15105
|
-
this.#metrics.stop();
|
|
15106
|
-
const ret = await this.#rep.close();
|
|
15107
|
-
this.#unexpose();
|
|
15108
|
-
return ret;
|
|
15109
17112
|
}
|
|
15110
17113
|
#onMessage = (e) => {
|
|
15111
17114
|
const lc = this.#lc;
|
|
@@ -15114,11 +17117,6 @@ var Zero = class _Zero {
|
|
|
15114
17117
|
lc.debug?.("ignoring message because already closed");
|
|
15115
17118
|
return;
|
|
15116
17119
|
}
|
|
15117
|
-
const rejectInvalidMessage = (e2) => this.#rejectMessageError?.reject(
|
|
15118
|
-
new Error(
|
|
15119
|
-
`Invalid message received from server: ${e2 instanceof Error ? e2.message + ". " : ""}${data}`
|
|
15120
|
-
)
|
|
15121
|
-
);
|
|
15122
17120
|
let downMessage;
|
|
15123
17121
|
const { data } = e;
|
|
15124
17122
|
try {
|
|
@@ -15128,7 +17126,11 @@ var Zero = class _Zero {
|
|
|
15128
17126
|
"passthrough"
|
|
15129
17127
|
);
|
|
15130
17128
|
} catch (e2) {
|
|
15131
|
-
|
|
17129
|
+
const invalidMessageError = new ClientError({
|
|
17130
|
+
kind: client_error_kind_enum_exports.InvalidMessage,
|
|
17131
|
+
message: `Invalid message received from server: ${e2 instanceof Error ? e2.message + ". " : ""}${data}`
|
|
17132
|
+
});
|
|
17133
|
+
this.#disconnect(lc, invalidMessageError);
|
|
15132
17134
|
return;
|
|
15133
17135
|
}
|
|
15134
17136
|
this.#messageCount++;
|
|
@@ -15163,9 +17165,14 @@ var Zero = class _Zero {
|
|
|
15163
17165
|
break;
|
|
15164
17166
|
case "inspect":
|
|
15165
17167
|
break;
|
|
15166
|
-
default:
|
|
15167
|
-
|
|
15168
|
-
|
|
17168
|
+
default: {
|
|
17169
|
+
const invalidMessageError = new ClientError({
|
|
17170
|
+
kind: client_error_kind_enum_exports.InvalidMessage,
|
|
17171
|
+
message: `Invalid message received from server: ${data}`
|
|
17172
|
+
});
|
|
17173
|
+
this.#disconnect(lc, invalidMessageError);
|
|
17174
|
+
return;
|
|
17175
|
+
}
|
|
15169
17176
|
}
|
|
15170
17177
|
};
|
|
15171
17178
|
#onOpen = () => {
|
|
@@ -15193,9 +17200,17 @@ var Zero = class _Zero {
|
|
|
15193
17200
|
wasClean
|
|
15194
17201
|
});
|
|
15195
17202
|
}
|
|
15196
|
-
const
|
|
15197
|
-
|
|
15198
|
-
|
|
17203
|
+
const closeError2 = new ClientError(
|
|
17204
|
+
wasClean ? {
|
|
17205
|
+
kind: client_error_kind_enum_exports.CleanClose,
|
|
17206
|
+
message: "WebSocket connection closed cleanly"
|
|
17207
|
+
} : {
|
|
17208
|
+
kind: client_error_kind_enum_exports.AbruptClose,
|
|
17209
|
+
message: "WebSocket connection closed abruptly"
|
|
17210
|
+
}
|
|
17211
|
+
);
|
|
17212
|
+
this.#connectResolver.reject(closeError2);
|
|
17213
|
+
this.#disconnect(lc, closeError2);
|
|
15199
17214
|
};
|
|
15200
17215
|
// An error on the connection is fatal for the connection.
|
|
15201
17216
|
async #handleErrorMessage(lc, downMessage) {
|
|
@@ -15206,14 +17221,13 @@ var Zero = class _Zero {
|
|
|
15206
17221
|
return;
|
|
15207
17222
|
}
|
|
15208
17223
|
lc.info?.(`${kind}: ${message}}`);
|
|
15209
|
-
const error = new
|
|
17224
|
+
const error = new ProtocolError(downMessage[1]);
|
|
15210
17225
|
lc.error?.(`${error.kind}:
|
|
15211
17226
|
|
|
15212
17227
|
${error.errorBody.message}`, error);
|
|
15213
|
-
this.#rejectMessageError?.reject(error);
|
|
15214
17228
|
lc.debug?.("Rejecting connect resolver due to error", error);
|
|
15215
17229
|
this.#connectResolver.reject(error);
|
|
15216
|
-
this.#disconnect(lc,
|
|
17230
|
+
this.#disconnect(lc, error);
|
|
15217
17231
|
if (kind === error_kind_enum_exports.VersionNotSupported) {
|
|
15218
17232
|
this.#onUpdateNeeded({ type: kind, message });
|
|
15219
17233
|
} else if (kind === error_kind_enum_exports.SchemaVersionNotSupported) {
|
|
@@ -15311,7 +17325,7 @@ ${error.errorBody.message}`, error);
|
|
|
15311
17325
|
}
|
|
15312
17326
|
this.#initConnectionQueries = void 0;
|
|
15313
17327
|
maybeSendDeletedClients();
|
|
15314
|
-
this.#
|
|
17328
|
+
this.#connectionManager.connected();
|
|
15315
17329
|
this.#connectResolver.resolve();
|
|
15316
17330
|
}
|
|
15317
17331
|
/**
|
|
@@ -15319,8 +17333,9 @@ ${error.errorBody.message}`, error);
|
|
|
15319
17333
|
* request to the server.
|
|
15320
17334
|
*
|
|
15321
17335
|
* {@link #connect} will throw an assertion error if the
|
|
15322
|
-
* {@link #
|
|
15323
|
-
*
|
|
17336
|
+
* {@link #connectionManager} status is not {@link ConnectionState.Disconnected}
|
|
17337
|
+
* or {@link ConnectionState.Connecting}.
|
|
17338
|
+
* Callers MUST check the connection status before calling this method and log
|
|
15324
17339
|
* an error as needed.
|
|
15325
17340
|
*
|
|
15326
17341
|
* The function will resolve once the socket is connected. If you need to know
|
|
@@ -15332,11 +17347,13 @@ ${error.errorBody.message}`, error);
|
|
|
15332
17347
|
*/
|
|
15333
17348
|
async #connect(lc, additionalConnectParams) {
|
|
15334
17349
|
assert(this.#server);
|
|
15335
|
-
assert(
|
|
17350
|
+
assert(
|
|
17351
|
+
this.#connectionManager.is(connection_status_enum_exports.Disconnected) || this.#connectionManager.is(connection_status_enum_exports.Connecting)
|
|
17352
|
+
);
|
|
15336
17353
|
const wsid = nanoid();
|
|
15337
17354
|
lc = addWebSocketIDToLogContext(wsid, lc);
|
|
15338
17355
|
lc.info?.("Connecting...", { navigatorOnline: localNavigator?.onLine });
|
|
15339
|
-
this.#
|
|
17356
|
+
this.#connectionManager.connecting();
|
|
15340
17357
|
assert(this.#connectStart === void 0);
|
|
15341
17358
|
const now = Date.now();
|
|
15342
17359
|
this.#connectStart = now;
|
|
@@ -15356,10 +17373,12 @@ ${error.errorBody.message}`, error);
|
|
|
15356
17373
|
}
|
|
15357
17374
|
const timeoutID = setTimeout(() => {
|
|
15358
17375
|
lc.debug?.("Rejecting connect resolver due to timeout");
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
|
|
17376
|
+
const timeoutError = new ClientError({
|
|
17377
|
+
kind: client_error_kind_enum_exports.ConnectTimeout,
|
|
17378
|
+
message: `Connection attempt timed out after ${CONNECT_TIMEOUT_MS / 1e3} seconds`
|
|
15362
17379
|
});
|
|
17380
|
+
this.#connectResolver.reject(timeoutError);
|
|
17381
|
+
this.#disconnect(lc, timeoutError);
|
|
15363
17382
|
}, CONNECT_TIMEOUT_MS);
|
|
15364
17383
|
const abortHandler = () => {
|
|
15365
17384
|
clearTimeout(timeoutID);
|
|
@@ -15411,22 +17430,29 @@ ${error.errorBody.message}`, error);
|
|
|
15411
17430
|
}
|
|
15412
17431
|
}
|
|
15413
17432
|
#disconnect(lc, reason, closeCode) {
|
|
15414
|
-
if (
|
|
17433
|
+
if (shouldReportConnectError(reason)) {
|
|
15415
17434
|
this.#connectErrorCount++;
|
|
17435
|
+
this.#metrics.lastConnectError.set(getLastConnectErrorValue(reason));
|
|
17436
|
+
this.#metrics.timeToConnectMs.set(DID_NOT_CONNECT_VALUE);
|
|
17437
|
+
this.#metrics.setConnectError(reason);
|
|
17438
|
+
if (this.#connectErrorCount % CHECK_CONNECTIVITY_ON_ERROR_FREQUENCY === 1) {
|
|
17439
|
+
this.#checkConnectivity(`connectErrorCount=${this.#connectErrorCount}`);
|
|
17440
|
+
}
|
|
15416
17441
|
}
|
|
15417
17442
|
lc.info?.("disconnecting", {
|
|
15418
17443
|
navigatorOnline: localNavigator?.onLine,
|
|
15419
|
-
reason,
|
|
17444
|
+
reason: reason.kind,
|
|
15420
17445
|
connectStart: this.#connectStart,
|
|
15421
17446
|
totalToConnectStart: this.#totalToConnectStart,
|
|
15422
17447
|
connectedAt: this.#connectedAt,
|
|
15423
17448
|
connectionDuration: this.#connectedAt ? Date.now() - this.#connectedAt : 0,
|
|
15424
17449
|
messageCount: this.#messageCount,
|
|
15425
|
-
connectionState: this.#
|
|
17450
|
+
connectionState: this.#connectionManager.state,
|
|
15426
17451
|
connectErrorCount: this.#connectErrorCount
|
|
15427
17452
|
});
|
|
15428
|
-
|
|
15429
|
-
|
|
17453
|
+
const connectionStatus = this.#connectionManager.state.name;
|
|
17454
|
+
switch (connectionStatus) {
|
|
17455
|
+
case connection_status_enum_exports.Connected: {
|
|
15430
17456
|
if (this.#connectStart !== void 0) {
|
|
15431
17457
|
lc.error?.(
|
|
15432
17458
|
"disconnect() called while connected but connect start time is defined."
|
|
@@ -15434,30 +17460,19 @@ ${error.errorBody.message}`, error);
|
|
|
15434
17460
|
}
|
|
15435
17461
|
break;
|
|
15436
17462
|
}
|
|
15437
|
-
case
|
|
15438
|
-
|
|
15439
|
-
|
|
15440
|
-
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
`connectErrorCount=${this.#connectErrorCount}`
|
|
15444
|
-
);
|
|
15445
|
-
}
|
|
15446
|
-
if (this.#connectStart === void 0) {
|
|
15447
|
-
lc.error?.(
|
|
15448
|
-
"disconnect() called while connecting but connect start time is undefined."
|
|
15449
|
-
);
|
|
15450
|
-
}
|
|
15451
|
-
break;
|
|
15452
|
-
}
|
|
15453
|
-
case Disconnected:
|
|
15454
|
-
lc.error?.("disconnect() called while disconnected");
|
|
17463
|
+
case connection_status_enum_exports.Closed:
|
|
17464
|
+
lc.debug?.("disconnect() called while closed");
|
|
17465
|
+
return;
|
|
17466
|
+
case connection_status_enum_exports.Disconnected:
|
|
17467
|
+
case connection_status_enum_exports.Connecting:
|
|
17468
|
+
case connection_status_enum_exports.Error:
|
|
15455
17469
|
break;
|
|
17470
|
+
default:
|
|
17471
|
+
unreachable(connectionStatus);
|
|
15456
17472
|
}
|
|
15457
|
-
this.#socketResolver =
|
|
17473
|
+
this.#socketResolver = resolver11();
|
|
15458
17474
|
lc.debug?.("Creating new connect resolver");
|
|
15459
|
-
this.#connectResolver =
|
|
15460
|
-
this.#setConnectionState(Disconnected);
|
|
17475
|
+
this.#connectResolver = resolver11();
|
|
15461
17476
|
this.#messageCount = 0;
|
|
15462
17477
|
this.#connectStart = void 0;
|
|
15463
17478
|
this.#connectedAt = 0;
|
|
@@ -15468,6 +17483,23 @@ ${error.errorBody.message}`, error);
|
|
|
15468
17483
|
this.#socket = void 0;
|
|
15469
17484
|
this.#lastMutationIDSent = NULL_LAST_MUTATION_ID_SENT;
|
|
15470
17485
|
this.#pokeHandler.handleDisconnect();
|
|
17486
|
+
const transition = getErrorConnectionTransition(reason);
|
|
17487
|
+
switch (transition.status) {
|
|
17488
|
+
case connection_status_enum_exports.Error:
|
|
17489
|
+
this.#connectionManager.error(transition.reason);
|
|
17490
|
+
break;
|
|
17491
|
+
case connection_status_enum_exports.Disconnected:
|
|
17492
|
+
this.#connectionManager.disconnected(transition.reason);
|
|
17493
|
+
break;
|
|
17494
|
+
case connection_status_enum_exports.Closed:
|
|
17495
|
+
this.#connectionManager.closed();
|
|
17496
|
+
break;
|
|
17497
|
+
case NO_STATUS_TRANSITION:
|
|
17498
|
+
this.#connectionManager.connecting(transition.reason);
|
|
17499
|
+
break;
|
|
17500
|
+
default:
|
|
17501
|
+
unreachable(transition);
|
|
17502
|
+
}
|
|
15471
17503
|
}
|
|
15472
17504
|
#handlePokeStart(_lc, pokeMessage) {
|
|
15473
17505
|
this.#abortPingTimeout();
|
|
@@ -15490,12 +17522,16 @@ ${error.errorBody.message}`, error);
|
|
|
15490
17522
|
const lc = this.#lc;
|
|
15491
17523
|
lc.info?.(
|
|
15492
17524
|
"poke error, disconnecting?",
|
|
15493
|
-
this.#
|
|
17525
|
+
!this.#connectionManager.is(connection_status_enum_exports.Disconnected)
|
|
15494
17526
|
);
|
|
15495
|
-
if (this.#
|
|
15496
|
-
this.#disconnect(
|
|
15497
|
-
|
|
15498
|
-
|
|
17527
|
+
if (!this.#connectionManager.is(connection_status_enum_exports.Disconnected)) {
|
|
17528
|
+
this.#disconnect(
|
|
17529
|
+
lc,
|
|
17530
|
+
new ClientError({
|
|
17531
|
+
kind: client_error_kind_enum_exports.UnexpectedBaseCookie,
|
|
17532
|
+
message: "Server returned unexpected base cookie during sync"
|
|
17533
|
+
})
|
|
17534
|
+
);
|
|
15499
17535
|
}
|
|
15500
17536
|
}
|
|
15501
17537
|
#handlePullResponse(lc, pullResponseMessage) {
|
|
@@ -15503,12 +17539,12 @@ ${error.errorBody.message}`, error);
|
|
|
15503
17539
|
const body = pullResponseMessage[1];
|
|
15504
17540
|
lc = lc.withContext("requestID", body.requestID);
|
|
15505
17541
|
lc.debug?.("Handling pull response", body);
|
|
15506
|
-
const
|
|
15507
|
-
if (!
|
|
17542
|
+
const resolver12 = this.#pendingPullsByRequestID.get(body.requestID);
|
|
17543
|
+
if (!resolver12) {
|
|
15508
17544
|
lc.debug?.("No resolver found");
|
|
15509
17545
|
return;
|
|
15510
17546
|
}
|
|
15511
|
-
|
|
17547
|
+
resolver12.resolve(pullResponseMessage[1]);
|
|
15512
17548
|
}
|
|
15513
17549
|
async #pusher(req, requestID) {
|
|
15514
17550
|
assert(req.pushVersion === 1);
|
|
@@ -15581,6 +17617,12 @@ ${error.errorBody.message}`, error);
|
|
|
15581
17617
|
this.#lc.info?.(`Starting Zero version: ${this.version}`);
|
|
15582
17618
|
if (this.#server === null) {
|
|
15583
17619
|
this.#lc.info?.("No socket origin provided, not starting connect loop.");
|
|
17620
|
+
this.#connectionManager.error(
|
|
17621
|
+
new ClientError({
|
|
17622
|
+
kind: client_error_kind_enum_exports.NoSocketOrigin,
|
|
17623
|
+
message: "No server socket origin provided"
|
|
17624
|
+
})
|
|
17625
|
+
);
|
|
15584
17626
|
return;
|
|
15585
17627
|
}
|
|
15586
17628
|
let runLoopCounter = 0;
|
|
@@ -15595,21 +17637,29 @@ ${error.errorBody.message}`, error);
|
|
|
15595
17637
|
await this.#updateAuthToken(bareLogContext);
|
|
15596
17638
|
let needsReauth = false;
|
|
15597
17639
|
let lastReauthAttemptAt;
|
|
15598
|
-
let
|
|
15599
|
-
let backoffMs = RUN_LOOP_INTERVAL_MS;
|
|
17640
|
+
let backoffMs;
|
|
15600
17641
|
let additionalConnectParams;
|
|
15601
|
-
while (
|
|
17642
|
+
while (this.#connectionManager.shouldContinueRunLoop()) {
|
|
15602
17643
|
runLoopCounter++;
|
|
15603
17644
|
let lc = getLogContext();
|
|
15604
17645
|
backoffMs = RUN_LOOP_INTERVAL_MS;
|
|
15605
17646
|
try {
|
|
15606
|
-
|
|
15607
|
-
|
|
17647
|
+
const currentState = this.#connectionManager.state;
|
|
17648
|
+
switch (currentState.name) {
|
|
17649
|
+
case connection_status_enum_exports.Connecting:
|
|
17650
|
+
case connection_status_enum_exports.Disconnected: {
|
|
15608
17651
|
if (this.#visibilityWatcher.visibilityState === "hidden") {
|
|
15609
17652
|
this.#metrics.setDisconnectedWaitingForVisible();
|
|
15610
17653
|
this.#totalToConnectStart = void 0;
|
|
15611
17654
|
}
|
|
15612
|
-
await
|
|
17655
|
+
const visibilityResult = await promiseRace({
|
|
17656
|
+
visible: this.#visibilityWatcher.waitForVisible(),
|
|
17657
|
+
stateChange: this.#connectionManager.waitForStateChange()
|
|
17658
|
+
});
|
|
17659
|
+
if (visibilityResult.key === "stateChange") {
|
|
17660
|
+
throwIfConnectionError(visibilityResult.result);
|
|
17661
|
+
break;
|
|
17662
|
+
}
|
|
15613
17663
|
if (needsReauth) {
|
|
15614
17664
|
lastReauthAttemptAt = Date.now();
|
|
15615
17665
|
await this.#updateAuthToken(lc, "invalid-token");
|
|
@@ -15619,65 +17669,67 @@ ${error.errorBody.message}`, error);
|
|
|
15619
17669
|
}
|
|
15620
17670
|
await this.#connect(lc, additionalConnectParams);
|
|
15621
17671
|
additionalConnectParams = void 0;
|
|
15622
|
-
|
|
15623
|
-
break;
|
|
15624
|
-
}
|
|
17672
|
+
throwIfConnectionError(this.#connectionManager.state);
|
|
15625
17673
|
assert(this.#socket);
|
|
15626
17674
|
lc = getLogContext();
|
|
15627
17675
|
lc.debug?.("Connected successfully");
|
|
15628
|
-
gotError = false;
|
|
15629
17676
|
needsReauth = false;
|
|
15630
17677
|
this.#setOnline(true);
|
|
15631
17678
|
break;
|
|
15632
17679
|
}
|
|
15633
|
-
case
|
|
15634
|
-
lc.error?.("unreachable");
|
|
15635
|
-
gotError = true;
|
|
15636
|
-
break;
|
|
15637
|
-
case Connected: {
|
|
17680
|
+
case connection_status_enum_exports.Connected: {
|
|
15638
17681
|
const controller = new AbortController();
|
|
15639
17682
|
this.#abortPingTimeout = () => controller.abort();
|
|
15640
17683
|
const [pingTimeoutPromise, pingTimeoutAborted] = sleepWithAbort(
|
|
15641
17684
|
PING_INTERVAL_MS,
|
|
15642
17685
|
controller.signal
|
|
15643
17686
|
);
|
|
15644
|
-
|
|
15645
|
-
|
|
15646
|
-
|
|
15647
|
-
|
|
15648
|
-
|
|
15649
|
-
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
]);
|
|
15654
|
-
if (this.closed) {
|
|
15655
|
-
this.#rejectMessageError = void 0;
|
|
15656
|
-
break;
|
|
15657
|
-
}
|
|
15658
|
-
switch (raceResult) {
|
|
15659
|
-
case PING: {
|
|
15660
|
-
const pingResult = await this.#ping(
|
|
15661
|
-
lc,
|
|
15662
|
-
this.#rejectMessageError.promise
|
|
15663
|
-
);
|
|
15664
|
-
if (pingResult === TimedOut) {
|
|
15665
|
-
gotError = true;
|
|
15666
|
-
}
|
|
17687
|
+
const raceResult = await promiseRace({
|
|
17688
|
+
waitForPing: pingTimeoutPromise,
|
|
17689
|
+
waitForPingAborted: pingTimeoutAborted,
|
|
17690
|
+
tabHidden: this.#visibilityWatcher.waitForHidden(),
|
|
17691
|
+
stateChange: this.#connectionManager.waitForStateChange()
|
|
17692
|
+
});
|
|
17693
|
+
switch (raceResult.key) {
|
|
17694
|
+
case "waitForPing": {
|
|
17695
|
+
await this.#ping(lc);
|
|
15667
17696
|
break;
|
|
15668
17697
|
}
|
|
15669
|
-
case
|
|
15670
|
-
|
|
15671
|
-
|
|
17698
|
+
case "waitForPingAborted":
|
|
17699
|
+
break;
|
|
17700
|
+
case "tabHidden": {
|
|
17701
|
+
const hiddenError = new ClientError({
|
|
17702
|
+
kind: client_error_kind_enum_exports.Hidden,
|
|
17703
|
+
message: "Connection closed because tab was hidden"
|
|
15672
17704
|
});
|
|
17705
|
+
this.#disconnect(lc, hiddenError);
|
|
15673
17706
|
this.#setOnline(false);
|
|
15674
17707
|
break;
|
|
17708
|
+
}
|
|
17709
|
+
case "stateChange":
|
|
17710
|
+
throwIfConnectionError(raceResult.result);
|
|
17711
|
+
break;
|
|
17712
|
+
default:
|
|
17713
|
+
unreachable(raceResult);
|
|
15675
17714
|
}
|
|
15676
|
-
|
|
17715
|
+
break;
|
|
17716
|
+
}
|
|
17717
|
+
case connection_status_enum_exports.Error: {
|
|
17718
|
+
lc.info?.(
|
|
17719
|
+
`Run loop paused in error state. Call zero.connection.connect() to resume.`,
|
|
17720
|
+
currentState.reason
|
|
17721
|
+
);
|
|
17722
|
+
await this.#connectionManager.waitForStateChange();
|
|
17723
|
+
break;
|
|
15677
17724
|
}
|
|
17725
|
+
case connection_status_enum_exports.Closed:
|
|
17726
|
+
break;
|
|
17727
|
+
default:
|
|
17728
|
+
unreachable(currentState);
|
|
15678
17729
|
}
|
|
15679
17730
|
} catch (ex) {
|
|
15680
|
-
|
|
17731
|
+
const isClientClosedError = isClientError(ex) && ex.kind === client_error_kind_enum_exports.ClientClosed;
|
|
17732
|
+
if (!this.#connectionManager.is(connection_status_enum_exports.Connected) && !isClientClosedError) {
|
|
15681
17733
|
const level = isAuthError(ex) ? "warn" : "error";
|
|
15682
17734
|
const kind = isServerError(ex) ? ex.kind : "Unknown Error";
|
|
15683
17735
|
lc[level]?.("Failed to connect", ex, kind, {
|
|
@@ -15688,42 +17740,60 @@ ${error.errorBody.message}`, error);
|
|
|
15688
17740
|
lc.debug?.(
|
|
15689
17741
|
"Got an exception in the run loop",
|
|
15690
17742
|
"state:",
|
|
15691
|
-
this.#
|
|
17743
|
+
this.#connectionManager.state,
|
|
15692
17744
|
"exception:",
|
|
15693
17745
|
ex
|
|
15694
17746
|
);
|
|
15695
|
-
|
|
15696
|
-
|
|
15697
|
-
|
|
15698
|
-
|
|
15699
|
-
|
|
15700
|
-
|
|
17747
|
+
const transition = getErrorConnectionTransition(ex);
|
|
17748
|
+
switch (transition.status) {
|
|
17749
|
+
case NO_STATUS_TRANSITION: {
|
|
17750
|
+
const backoffParams = getBackoffParams(transition.reason);
|
|
17751
|
+
if (backoffParams) {
|
|
17752
|
+
if (backoffParams.minBackoffMs !== void 0) {
|
|
17753
|
+
backoffMs = Math.max(backoffMs, backoffParams.minBackoffMs);
|
|
17754
|
+
}
|
|
17755
|
+
if (backoffParams.maxBackoffMs !== void 0) {
|
|
17756
|
+
backoffMs = Math.min(backoffMs, backoffParams.maxBackoffMs);
|
|
17757
|
+
}
|
|
17758
|
+
additionalConnectParams = backoffParams.reconnectParams;
|
|
17759
|
+
}
|
|
17760
|
+
if (isAuthError(transition.reason)) {
|
|
17761
|
+
const now = Date.now();
|
|
17762
|
+
const msSinceLastReauthAttempt = lastReauthAttemptAt === void 0 ? Number.POSITIVE_INFINITY : now - lastReauthAttemptAt;
|
|
17763
|
+
needsReauth = true;
|
|
17764
|
+
if (msSinceLastReauthAttempt > RUN_LOOP_INTERVAL_MS) {
|
|
17765
|
+
continue;
|
|
17766
|
+
}
|
|
17767
|
+
}
|
|
17768
|
+
this.#setOnline(false);
|
|
17769
|
+
lc.debug?.(
|
|
17770
|
+
"Sleeping",
|
|
17771
|
+
backoffMs,
|
|
17772
|
+
"ms before reconnecting due to error, state:",
|
|
17773
|
+
this.#connectionManager.state
|
|
17774
|
+
);
|
|
17775
|
+
await sleep(backoffMs);
|
|
17776
|
+
break;
|
|
15701
17777
|
}
|
|
15702
|
-
|
|
15703
|
-
|
|
15704
|
-
|
|
15705
|
-
|
|
15706
|
-
|
|
15707
|
-
|
|
15708
|
-
|
|
15709
|
-
|
|
17778
|
+
case connection_status_enum_exports.Error: {
|
|
17779
|
+
lc.debug?.("Fatal error encountered, transitioning to error state");
|
|
17780
|
+
this.#setOnline(false);
|
|
17781
|
+
this.#connectionManager.error(transition.reason);
|
|
17782
|
+
break;
|
|
17783
|
+
}
|
|
17784
|
+
case connection_status_enum_exports.Disconnected: {
|
|
17785
|
+
this.#setOnline(false);
|
|
17786
|
+
this.#connectionManager.disconnected(transition.reason);
|
|
17787
|
+
break;
|
|
15710
17788
|
}
|
|
15711
|
-
|
|
15712
|
-
|
|
17789
|
+
case connection_status_enum_exports.Closed: {
|
|
17790
|
+
this.#setOnline(false);
|
|
17791
|
+
break;
|
|
15713
17792
|
}
|
|
15714
|
-
|
|
17793
|
+
default:
|
|
17794
|
+
unreachable(transition);
|
|
15715
17795
|
}
|
|
15716
17796
|
}
|
|
15717
|
-
if (gotError) {
|
|
15718
|
-
this.#setOnline(false);
|
|
15719
|
-
lc.debug?.(
|
|
15720
|
-
"Sleeping",
|
|
15721
|
-
backoffMs,
|
|
15722
|
-
"ms before reconnecting due to error, state:",
|
|
15723
|
-
this.#connectionState
|
|
15724
|
-
);
|
|
15725
|
-
await sleep(backoffMs);
|
|
15726
|
-
}
|
|
15727
17797
|
}
|
|
15728
17798
|
}
|
|
15729
17799
|
async #puller(req, requestID) {
|
|
@@ -15756,20 +17826,21 @@ ${error.errorBody.message}`, error);
|
|
|
15756
17826
|
}
|
|
15757
17827
|
];
|
|
15758
17828
|
send(socket, pullRequestMessage);
|
|
15759
|
-
const pullResponseResolver =
|
|
17829
|
+
const pullResponseResolver = resolver11();
|
|
15760
17830
|
this.#pendingPullsByRequestID.set(requestID, pullResponseResolver);
|
|
15761
17831
|
try {
|
|
15762
|
-
const
|
|
15763
|
-
|
|
15764
|
-
|
|
15765
|
-
|
|
15766
|
-
|
|
15767
|
-
|
|
15768
|
-
switch (raceResult) {
|
|
15769
|
-
case TIMEOUT:
|
|
17832
|
+
const raceResult = await promiseRace({
|
|
17833
|
+
timeout: sleep(PULL_TIMEOUT_MS),
|
|
17834
|
+
success: pullResponseResolver.promise
|
|
17835
|
+
});
|
|
17836
|
+
switch (raceResult.key) {
|
|
17837
|
+
case "timeout":
|
|
15770
17838
|
lc.debug?.("Mutation recovery pull timed out");
|
|
15771
|
-
throw new
|
|
15772
|
-
|
|
17839
|
+
throw new ClientError({
|
|
17840
|
+
kind: client_error_kind_enum_exports.PullTimeout,
|
|
17841
|
+
message: "Pull timed out"
|
|
17842
|
+
});
|
|
17843
|
+
case "success": {
|
|
15773
17844
|
lc.debug?.("Returning mutation recovery pull response");
|
|
15774
17845
|
const response = await pullResponseResolver.promise;
|
|
15775
17846
|
return {
|
|
@@ -15785,10 +17856,15 @@ ${error.errorBody.message}`, error);
|
|
|
15785
17856
|
};
|
|
15786
17857
|
}
|
|
15787
17858
|
default:
|
|
15788
|
-
unreachable();
|
|
17859
|
+
unreachable(raceResult);
|
|
15789
17860
|
}
|
|
15790
17861
|
} finally {
|
|
15791
|
-
pullResponseResolver.reject(
|
|
17862
|
+
pullResponseResolver.reject(
|
|
17863
|
+
new ClientError({
|
|
17864
|
+
kind: client_error_kind_enum_exports.PullTimeout,
|
|
17865
|
+
message: "Pull timed out"
|
|
17866
|
+
})
|
|
17867
|
+
);
|
|
15792
17868
|
this.#pendingPullsByRequestID.delete(requestID);
|
|
15793
17869
|
}
|
|
15794
17870
|
}
|
|
@@ -15798,6 +17874,8 @@ ${error.errorBody.message}`, error);
|
|
|
15798
17874
|
/**
|
|
15799
17875
|
* A rough heuristic for whether the client is currently online and
|
|
15800
17876
|
* authenticated.
|
|
17877
|
+
*
|
|
17878
|
+
* @deprecated Use `connection` instead, which provides more detailed connection state.
|
|
15801
17879
|
*/
|
|
15802
17880
|
get online() {
|
|
15803
17881
|
return this.#onlineManager.online;
|
|
@@ -15809,37 +17887,52 @@ ${error.errorBody.message}`, error);
|
|
|
15809
17887
|
*
|
|
15810
17888
|
* @param listener - The listener to subscribe to.
|
|
15811
17889
|
* @returns A function to unsubscribe the listener.
|
|
17890
|
+
*
|
|
17891
|
+
* @deprecated Use `connection` instead, which provides more detailed connection state.
|
|
15812
17892
|
*/
|
|
15813
17893
|
onOnline = (listener) => this.#onlineManager.subscribe(listener);
|
|
15814
17894
|
/**
|
|
15815
17895
|
* Starts a ping and waits for a pong.
|
|
15816
|
-
*
|
|
15817
|
-
* If it takes too long to get a pong we disconnect and this returns
|
|
15818
|
-
* {@linkcode PingResult.TimedOut}.
|
|
15819
17896
|
*/
|
|
15820
|
-
async #ping(lc
|
|
17897
|
+
async #ping(lc) {
|
|
15821
17898
|
lc.debug?.("pinging");
|
|
15822
|
-
const { promise, resolve } =
|
|
17899
|
+
const { promise, resolve } = resolver11();
|
|
15823
17900
|
this.#onPong = resolve;
|
|
15824
17901
|
const pingMessage = ["ping", {}];
|
|
15825
17902
|
const t0 = performance.now();
|
|
15826
17903
|
assert(this.#socket);
|
|
15827
17904
|
send(this.#socket, pingMessage);
|
|
15828
|
-
const
|
|
15829
|
-
promise,
|
|
15830
|
-
sleep(PING_TIMEOUT_MS),
|
|
15831
|
-
|
|
15832
|
-
|
|
17905
|
+
const raceResult = await promiseRace({
|
|
17906
|
+
waitForPong: promise,
|
|
17907
|
+
pingTimeout: sleep(PING_TIMEOUT_MS),
|
|
17908
|
+
stateChange: this.#connectionManager.waitForStateChange()
|
|
17909
|
+
});
|
|
15833
17910
|
const delta = performance.now() - t0;
|
|
15834
|
-
|
|
15835
|
-
|
|
15836
|
-
|
|
15837
|
-
|
|
15838
|
-
}
|
|
15839
|
-
|
|
17911
|
+
switch (raceResult.key) {
|
|
17912
|
+
case "waitForPong": {
|
|
17913
|
+
lc.debug?.("ping succeeded in", delta, "ms");
|
|
17914
|
+
return;
|
|
17915
|
+
}
|
|
17916
|
+
case "pingTimeout": {
|
|
17917
|
+
lc.info?.("ping failed in", delta, "ms - disconnecting");
|
|
17918
|
+
const pingTimeoutError = new ClientError({
|
|
17919
|
+
kind: client_error_kind_enum_exports.PingTimeout,
|
|
17920
|
+
message: "Server ping request failed"
|
|
17921
|
+
});
|
|
17922
|
+
this.#disconnect(lc, pingTimeoutError);
|
|
17923
|
+
throw pingTimeoutError;
|
|
17924
|
+
}
|
|
17925
|
+
case "stateChange": {
|
|
17926
|
+
lc.debug?.(
|
|
17927
|
+
"ping aborted due to connection state change",
|
|
17928
|
+
raceResult.result
|
|
17929
|
+
);
|
|
17930
|
+
throwIfConnectionError(raceResult.result);
|
|
17931
|
+
break;
|
|
17932
|
+
}
|
|
17933
|
+
default:
|
|
17934
|
+
unreachable(raceResult);
|
|
15840
17935
|
}
|
|
15841
|
-
lc.debug?.("ping succeeded in", delta, "ms");
|
|
15842
|
-
return Success;
|
|
15843
17936
|
}
|
|
15844
17937
|
// Sends a set of metrics to the server. Throws unless the server
|
|
15845
17938
|
// returns 200.
|
|
@@ -15998,16 +18091,6 @@ function addWebSocketIDFromSocketToLogContext({ url }, lc) {
|
|
|
15998
18091
|
function addWebSocketIDToLogContext(wsid, lc) {
|
|
15999
18092
|
return lc.withContext("wsid", wsid);
|
|
16000
18093
|
}
|
|
16001
|
-
function promiseRace(ps) {
|
|
16002
|
-
return Promise.race(ps.map((p, i) => p.then(() => i)));
|
|
16003
|
-
}
|
|
16004
|
-
var TimedOutError = class extends Error {
|
|
16005
|
-
constructor(m) {
|
|
16006
|
-
super(`${m} timed out`);
|
|
16007
|
-
}
|
|
16008
|
-
};
|
|
16009
|
-
var CloseError = class extends Error {
|
|
16010
|
-
};
|
|
16011
18094
|
function assertValidRunOptions2(_options) {
|
|
16012
18095
|
}
|
|
16013
18096
|
async function makeActiveClientsManager(clientGroupID, clientID, signal, onDelete) {
|
|
@@ -16027,12 +18110,14 @@ export {
|
|
|
16027
18110
|
dropDatabase,
|
|
16028
18111
|
dropAllDatabases,
|
|
16029
18112
|
TransactionClosedError,
|
|
18113
|
+
error_kind_enum_exports,
|
|
18114
|
+
error_origin_enum_exports,
|
|
18115
|
+
error_reason_enum_exports,
|
|
16030
18116
|
transformRequestMessageSchema,
|
|
16031
18117
|
transformResponseMessageSchema,
|
|
16032
|
-
error_kind_enum_exports,
|
|
16033
18118
|
table,
|
|
16034
|
-
|
|
16035
|
-
|
|
18119
|
+
string4 as string,
|
|
18120
|
+
number4 as number,
|
|
16036
18121
|
boolean,
|
|
16037
18122
|
json,
|
|
16038
18123
|
enumeration,
|
|
@@ -16045,7 +18130,10 @@ export {
|
|
|
16045
18130
|
newQuerySymbol,
|
|
16046
18131
|
AbstractQuery,
|
|
16047
18132
|
clientToServer,
|
|
18133
|
+
client_error_kind_enum_exports,
|
|
18134
|
+
connection_status_enum_exports,
|
|
18135
|
+
ClientError,
|
|
16048
18136
|
update_needed_reason_type_enum_exports,
|
|
16049
18137
|
Zero
|
|
16050
18138
|
};
|
|
16051
|
-
//# sourceMappingURL=chunk-
|
|
18139
|
+
//# sourceMappingURL=chunk-AIPM77UE.js.map
|