@lostgradient/weft 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -43
- package/dist/cli/conformance.js +7 -1
- package/dist/cli/generated/operation-client.generated.d.ts +55 -13
- package/dist/cli/generated/operation-client.generated.js +3 -0
- package/dist/cli/help-text.d.ts +1 -1
- package/dist/cli/help-text.js +1 -0
- package/dist/cli/operation-catalog-snapshot.d.ts +8 -0
- package/dist/cli/operation-catalog-snapshot.js +11 -0
- package/dist/cli/parse-schedule-arguments.js +3 -1
- package/dist/cli/schedule.js +2 -1
- package/dist/cli/types.d.ts +1 -0
- package/dist/cli-main.js +80 -79
- package/dist/client/handle-delegation.d.ts +7 -2
- package/dist/client/handle-delegation.js +9 -1
- package/dist/client/http-client-requests.d.ts +4 -1
- package/dist/client/http-client-requests.js +10 -0
- package/dist/client/http-client.d.ts +10 -4
- package/dist/client/http-client.js +18 -1
- package/dist/client/http-request.d.ts +11 -1
- package/dist/client/http-request.js +17 -7
- package/dist/client/index.d.ts +1 -1
- package/dist/client/interface.d.ts +100 -4
- package/dist/client/local.d.ts +7 -1
- package/dist/client/local.js +17 -2
- package/dist/client/start-body.d.ts +9 -2
- package/dist/client/start-body.js +13 -4
- package/dist/core/byte-arrays.d.ts +5 -0
- package/dist/core/byte-arrays.js +5 -0
- package/dist/core/checkpoint/lifecycle.d.ts +3 -0
- package/dist/core/checkpoint/lifecycle.js +9 -4
- package/dist/core/checkpoint/serialization.js +12 -5
- package/dist/core/codec/extension-codec.d.ts +16 -0
- package/dist/core/codec/extension-codec.js +104 -8
- package/dist/core/codec/index.d.ts +1 -0
- package/dist/core/codec/index.js +1 -0
- package/dist/core/codec/serializer-registry.d.ts +122 -0
- package/dist/core/codec/serializer-registry.js +51 -0
- package/dist/core/context/activity-retry-state.d.ts +38 -0
- package/dist/core/context/activity-retry-state.js +89 -0
- package/dist/core/context/activity-schedule-to-close.d.ts +159 -0
- package/dist/core/context/activity-schedule-to-close.js +69 -0
- package/dist/core/context/child-workflow-pipe.d.ts +5 -5
- package/dist/core/context/child-workflow-pipe.js +15 -2
- package/dist/core/context/context-presence.d.ts +19 -0
- package/dist/core/context/context-presence.js +13 -0
- package/dist/core/context/durable-operations.d.ts +25 -0
- package/dist/core/context/durable-operations.js +64 -0
- package/dist/core/context/index.d.ts +18 -5
- package/dist/core/context/index.js +17 -12
- package/dist/core/context/internals.d.ts +29 -0
- package/dist/core/context/internals.js +6 -1
- package/dist/core/context/operation-request.d.ts +35 -0
- package/dist/core/context/parallel-cache-entry.d.ts +14 -5
- package/dist/core/context/run-operation.d.ts +21 -3
- package/dist/core/context/run-operation.js +56 -93
- package/dist/core/context/session-state.js +7 -8
- package/dist/core/context/speculative-child.js +2 -0
- package/dist/core/context/types.d.ts +15 -0
- package/dist/core/context/version-patching.d.ts +8 -0
- package/dist/core/context/version-patching.js +40 -0
- package/dist/core/context/workflow-logger.d.ts +98 -0
- package/dist/core/context/workflow-logger.js +68 -0
- package/dist/core/engine/activity-heartbeat-tracking.d.ts +64 -0
- package/dist/core/engine/activity-heartbeat-tracking.js +42 -0
- package/dist/core/engine/activity-per-attempt-timeout.d.ts +41 -0
- package/dist/core/engine/activity-per-attempt-timeout.js +36 -0
- package/dist/core/engine/activity-reconciliation.d.ts +1 -0
- package/dist/core/engine/activity-reconciliation.js +12 -1
- package/dist/core/engine/activity-resolution.d.ts +23 -0
- package/dist/core/engine/activity-resolution.js +37 -0
- package/dist/core/engine/aggregate.js +66 -30
- package/dist/core/engine/async-activity-completion.d.ts +23 -6
- package/dist/core/engine/async-activity-completion.js +53 -12
- package/dist/core/engine/attributes-tags.js +9 -4
- package/dist/core/engine/bulk-operations-purge.d.ts +26 -0
- package/dist/core/engine/bulk-operations-purge.js +38 -3
- package/dist/core/engine/bulk-operations-shared.d.ts +2 -0
- package/dist/core/engine/bulk-operations-shared.js +8 -2
- package/dist/core/engine/bulk-operations.d.ts +4 -1
- package/dist/core/engine/bulk-operations.js +235 -24
- package/dist/core/engine/callback-creators-bundles.d.ts +9 -0
- package/dist/core/engine/callback-creators-bundles.js +30 -2
- package/dist/core/engine/callback-creators-core.js +6 -4
- package/dist/core/engine/callback-creators-router.js +10 -0
- package/dist/core/engine/callback-creators-schedule.d.ts +2 -2
- package/dist/core/engine/callback-creators-schedule.js +12 -8
- package/dist/core/engine/candidate-read-batching.d.ts +6 -0
- package/dist/core/engine/candidate-read-batching.js +1 -0
- package/dist/core/engine/checkpoint-io.js +61 -25
- package/dist/core/engine/checkpoint-reads.js +3 -2
- package/dist/core/engine/checkpoint-replay.d.ts +20 -0
- package/dist/core/engine/checkpoint-replay.js +242 -0
- package/dist/core/engine/checkpoint-side-effects.d.ts +23 -0
- package/dist/core/engine/checkpoint-side-effects.js +35 -0
- package/dist/core/engine/child-workflow-cancellation.d.ts +10 -0
- package/dist/core/engine/child-workflow-cancellation.js +40 -0
- package/dist/core/engine/child-workflow.js +27 -4
- package/dist/core/engine/condition-waiters.d.ts +14 -0
- package/dist/core/engine/condition-waiters.js +5 -0
- package/dist/core/engine/construction.d.ts +3 -1
- package/dist/core/engine/construction.js +30 -8
- package/dist/core/engine/coordination-branch-executors.d.ts +70 -0
- package/dist/core/engine/coordination-branch-executors.js +107 -0
- package/dist/core/engine/deferred-consume-envelope.d.ts +59 -0
- package/dist/core/engine/deferred-consume-envelope.js +14 -0
- package/dist/core/engine/disposal.js +25 -0
- package/dist/core/engine/engine-create-types.d.ts +14 -18
- package/dist/core/engine/engine-internal-types.d.ts +38 -3
- package/dist/core/engine/engine-leak-warnings.d.ts +6 -0
- package/dist/core/engine/engine-leak-warnings.js +4 -0
- package/dist/core/engine/engine-runtime-helpers.d.ts +17 -0
- package/dist/core/engine/engine-runtime-helpers.js +26 -5
- package/dist/core/engine/errors.d.ts +121 -0
- package/dist/core/engine/errors.js +45 -1
- package/dist/core/engine/event-log-compaction.d.ts +8 -0
- package/dist/core/engine/event-log-compaction.js +20 -2
- package/dist/core/engine/fenced-write.d.ts +65 -0
- package/dist/core/engine/fenced-write.js +71 -0
- package/dist/core/engine/finalizer-state.d.ts +28 -0
- package/dist/core/engine/finalizer-state.js +16 -0
- package/dist/core/engine/handle-result.js +1 -1
- package/dist/core/engine/handles.d.ts +97 -40
- package/dist/core/engine/handles.js +25 -27
- package/dist/core/engine/index.d.ts +125 -15
- package/dist/core/engine/index.js +207 -11
- package/dist/core/engine/inline-launch-queue.d.ts +14 -0
- package/dist/core/engine/inline-launch-queue.js +32 -7
- package/dist/core/engine/inline-parking.js +3 -2
- package/dist/core/engine/internals.d.ts +125 -13
- package/dist/core/engine/lease-codec.d.ts +35 -0
- package/dist/core/engine/lease-codec.js +32 -0
- package/dist/core/engine/lease-deposition.d.ts +66 -0
- package/dist/core/engine/lease-deposition.js +10 -0
- package/dist/core/engine/lease-errors.d.ts +99 -0
- package/dist/core/engine/lease-errors.js +30 -0
- package/dist/core/engine/lease-manager.d.ts +114 -0
- package/dist/core/engine/lease-manager.js +135 -0
- package/dist/core/engine/lifecycle/fork-helpers.js +1 -7
- package/dist/core/engine/lifecycle/persist.js +15 -52
- package/dist/core/engine/lifecycle/recovered-services.d.ts +8 -6
- package/dist/core/engine/lifecycle/recovered-services.js +18 -3
- package/dist/core/engine/lifecycle/resume.js +39 -11
- package/dist/core/engine/lifecycle/shared.d.ts +8 -1
- package/dist/core/engine/lifecycle/start-batch.d.ts +1 -1
- package/dist/core/engine/lifecycle/start-batch.js +2 -1
- package/dist/core/engine/lifecycle/start-commit.d.ts +56 -0
- package/dist/core/engine/lifecycle/start-commit.js +69 -0
- package/dist/core/engine/lifecycle/start-exec.d.ts +30 -2
- package/dist/core/engine/lifecycle/start-exec.js +38 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.d.ts +58 -0
- package/dist/core/engine/lifecycle/start-or-signal-create.js +95 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.d.ts +79 -0
- package/dist/core/engine/lifecycle/start-or-signal-resolution.js +60 -0
- package/dist/core/engine/lifecycle/start-or-signal.d.ts +46 -0
- package/dist/core/engine/lifecycle/start-or-signal.js +71 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.d.ts +39 -0
- package/dist/core/engine/lifecycle/start-terminal-conflict-purge.js +28 -0
- package/dist/core/engine/lifecycle/start.d.ts +6 -6
- package/dist/core/engine/lifecycle/start.js +47 -45
- package/dist/core/engine/lifecycle/transition.js +17 -5
- package/dist/core/engine/lifecycle.d.ts +3 -2
- package/dist/core/engine/lifecycle.js +9 -2
- package/dist/core/engine/list-candidate-resolution.js +2 -2
- package/dist/core/engine/listing.js +10 -6
- package/dist/core/engine/operations-activity.d.ts +4 -11
- package/dist/core/engine/operations-activity.js +22 -49
- package/dist/core/engine/operations-coordination.d.ts +10 -0
- package/dist/core/engine/operations-coordination.js +43 -8
- package/dist/core/engine/operations-router.d.ts +6 -0
- package/dist/core/engine/operations-router.js +2 -0
- package/dist/core/engine/operations-speculate.js +6 -2
- package/dist/core/engine/operations-stream.js +12 -2
- package/dist/core/engine/operations-time.d.ts +4 -2
- package/dist/core/engine/operations-time.js +14 -2
- package/dist/core/engine/operations-wait-condition.d.ts +23 -0
- package/dist/core/engine/operations-wait-condition.js +62 -0
- package/dist/core/engine/ownership-options.d.ts +23 -0
- package/dist/core/engine/ownership-options.js +26 -0
- package/dist/core/engine/payload-size-policy.d.ts +3 -0
- package/dist/core/engine/payload-size-policy.js +4 -0
- package/dist/core/engine/pending-updates.d.ts +17 -0
- package/dist/core/engine/pending-updates.js +33 -11
- package/dist/core/engine/persisted-data-version.d.ts +5 -9
- package/dist/core/engine/persisted-data-version.js +4 -5
- package/dist/core/engine/queries.js +1 -1
- package/dist/core/engine/registration.d.ts +1 -0
- package/dist/core/engine/registration.js +18 -3
- package/dist/core/engine/schedule-handle.d.ts +45 -0
- package/dist/core/engine/schedule-handle.js +26 -0
- package/dist/core/engine/schedule-jitter.d.ts +5 -0
- package/dist/core/engine/schedule-jitter.js +10 -0
- package/dist/core/engine/schedule-run.d.ts +17 -0
- package/dist/core/engine/schedule-run.js +38 -0
- package/dist/core/engine/schedule-timer.js +81 -17
- package/dist/core/engine/schedules.d.ts +8 -5
- package/dist/core/engine/schedules.js +44 -19
- package/dist/core/engine/search-attribute-records.d.ts +4 -0
- package/dist/core/engine/search-attribute-records.js +17 -0
- package/dist/core/engine/second-instance-detector.d.ts +96 -0
- package/dist/core/engine/second-instance-detector.js +108 -0
- package/dist/core/engine/signals.d.ts +38 -0
- package/dist/core/engine/signals.js +55 -19
- package/dist/core/engine/state-utilities.d.ts +49 -2
- package/dist/core/engine/state-utilities.js +114 -3
- package/dist/core/engine/storage-io.d.ts +16 -2
- package/dist/core/engine/storage-io.js +26 -5
- package/dist/core/engine/stream-chunk-loading.d.ts +2 -0
- package/dist/core/engine/stream-chunk-loading.js +24 -1
- package/dist/core/engine/sub-operation.js +22 -3
- package/dist/core/engine/termination/cleanup.d.ts +28 -1
- package/dist/core/engine/termination/cleanup.js +44 -2
- package/dist/core/engine/termination/complete.js +48 -9
- package/dist/core/engine/termination/finalizer-activity.d.ts +53 -0
- package/dist/core/engine/termination/finalizer-activity.js +30 -0
- package/dist/core/engine/termination/finalizer-claim.d.ts +110 -0
- package/dist/core/engine/termination/finalizer-claim.js +80 -0
- package/dist/core/engine/termination/finalizer.d.ts +48 -0
- package/dist/core/engine/termination/finalizer.js +159 -0
- package/dist/core/engine/termination/suspend.d.ts +70 -0
- package/dist/core/engine/termination/suspend.js +41 -0
- package/dist/core/engine/termination.d.ts +5 -2
- package/dist/core/engine/termination.js +6 -0
- package/dist/core/engine/updates.js +5 -25
- package/dist/core/engine/validation/schedule.d.ts +2 -1
- package/dist/core/engine/validation/schedule.js +51 -2
- package/dist/core/engine/validation.js +54 -3
- package/dist/core/engine/waiting-update-response.d.ts +8 -0
- package/dist/core/engine/waiting-update-response.js +22 -0
- package/dist/core/engine/workflow-concurrency.d.ts +10 -0
- package/dist/core/engine/workflow-concurrency.js +136 -0
- package/dist/core/engine/workflow-feed.d.ts +9 -8
- package/dist/core/engine/workflow-feed.js +4 -1
- package/dist/core/engine/workflow-indexes.d.ts +9 -0
- package/dist/core/engine/workflow-indexes.js +10 -0
- package/dist/core/engine/workflow-state-stream.js +33 -13
- package/dist/core/engine/workflow-visibility-queries.d.ts +2 -2
- package/dist/core/engine-helpers.js +1 -0
- package/dist/core/events/activity-events.d.ts +43 -12
- package/dist/core/events/activity-events.js +28 -0
- package/dist/core/events/attribute-events.d.ts +2 -3
- package/dist/core/events/event-map.d.ts +19 -12
- package/dist/core/events/index.d.ts +1 -0
- package/dist/core/events/index.js +1 -0
- package/dist/core/events/schedule-events.d.ts +71 -0
- package/dist/core/events/schedule-events.js +29 -0
- package/dist/core/events/signal-events.d.ts +4 -6
- package/dist/core/events/system-events.d.ts +29 -19
- package/dist/core/events/system-events.js +26 -0
- package/dist/core/events/update-events.d.ts +6 -8
- package/dist/core/events/workflow-events.d.ts +108 -20
- package/dist/core/events/workflow-events.js +35 -0
- package/dist/core/failure-categories.js +5 -17
- package/dist/core/fault-code.d.ts +9 -3
- package/dist/core/fault-code.js +1 -0
- package/dist/core/inline-execution-strategy.context-options.d.ts +69 -0
- package/dist/core/inline-execution-strategy.context-options.js +56 -0
- package/dist/core/inline-execution-strategy.d.ts +31 -36
- package/dist/core/inline-execution-strategy.js +16 -27
- package/dist/core/list-filter-validation.d.ts +1 -1
- package/dist/core/list-filter-validation.js +2 -1
- package/dist/core/payload-size.d.ts +1 -1
- package/dist/core/persisted-data-incompatible-error.d.ts +9 -7
- package/dist/core/review/events.d.ts +6 -8
- package/dist/core/scheduler/scheduler-class.d.ts +10 -1
- package/dist/core/scheduler/scheduler-class.js +38 -11
- package/dist/core/scheduler/timer-batch.js +9 -1
- package/dist/core/scheduler/timer-sources.d.ts +1 -0
- package/dist/core/scheduler/timer-sources.js +11 -5
- package/dist/core/session-state.d.ts +0 -1
- package/dist/core/session-state.js +2 -2
- package/dist/core/start-workflow-validation.d.ts +56 -0
- package/dist/core/start-workflow-validation.js +30 -1
- package/dist/core/step-context.d.ts +10 -6
- package/dist/core/step-context.js +7 -15
- package/dist/core/types/activity-verification.d.ts +67 -0
- package/dist/core/types/activity-verification.js +0 -0
- package/dist/core/types/activity.d.ts +86 -64
- package/dist/core/types/bulk.d.ts +50 -9
- package/dist/core/types/checkpoint.d.ts +44 -8
- package/dist/core/types/identity.d.ts +8 -1
- package/dist/core/types/launch-metadata.d.ts +33 -0
- package/dist/core/types/launch-metadata.js +0 -0
- package/dist/core/types/list-options.d.ts +146 -0
- package/dist/core/types/list-options.js +0 -0
- package/dist/core/types/message-handles.d.ts +25 -0
- package/dist/core/types/options.d.ts +165 -215
- package/dist/core/types/reviews.d.ts +2 -1
- package/dist/core/types/schedules.d.ts +39 -3
- package/dist/core/types/services-resolution.d.ts +47 -0
- package/dist/core/types/services-resolution.js +0 -0
- package/dist/core/types/state.d.ts +11 -11
- package/dist/core/types/workflow-builder-runtime.d.ts +12 -3
- package/dist/core/types/workflow-builder-runtime.js +11 -2
- package/dist/core/types/workflow-builder.d.ts +47 -15
- package/dist/core/types/workflow-concurrency.d.ts +39 -0
- package/dist/core/types/workflow-concurrency.js +0 -0
- package/dist/core/types/workflow-context.d.ts +157 -14
- package/dist/core/types/workflow-definition.d.ts +53 -10
- package/dist/core/types/workflow-function.d.ts +101 -9
- package/dist/core/types/workflow-log.d.ts +98 -0
- package/dist/core/types/workflow-log.js +0 -0
- package/dist/core/types/workflow-registries.d.ts +14 -3
- package/dist/core/types/workflow-registry.d.ts +3 -0
- package/dist/core/types/workflow-snapshot.d.ts +29 -0
- package/dist/core/types/workflow-snapshot.js +0 -0
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.js +7 -0
- package/dist/core/versioning.d.ts +9 -39
- package/dist/core/versioning.js +2 -12
- package/dist/core/weft-error.d.ts +44 -1
- package/dist/core/weft-error.js +19 -1
- package/dist/core/worker-execution-strategy-options.d.ts +26 -0
- package/dist/core/worker-execution-strategy.js +40 -36
- package/dist/core/worker-inbound-message.d.ts +38 -0
- package/dist/core/worker-inbound-message.js +37 -0
- package/dist/core/worker-log-abuse-counter.d.ts +175 -0
- package/dist/core/worker-log-abuse-counter.js +107 -0
- package/dist/core/worker-message-helpers.d.ts +47 -0
- package/dist/core/worker-message-helpers.js +26 -0
- package/dist/core/worker-protocol-guard.js +1 -1
- package/dist/core/worker-protocol-log.d.ts +56 -0
- package/dist/core/worker-protocol-log.js +18 -0
- package/dist/core/worker-protocol.d.ts +23 -0
- package/dist/core/worker-protocol.js +12 -2
- package/dist/core/workflow-version-tuple.d.ts +3 -9
- package/dist/core/workflow-version-tuple.js +2 -3
- package/dist/diagnostics/doctor.js +6 -3
- package/dist/diagnostics/format.js +3 -8
- package/dist/diagnostics/types.d.ts +5 -5
- package/dist/diagnostics/validate.d.ts +0 -1
- package/dist/diagnostics/version-check.d.ts +1 -1
- package/dist/diagnostics/version-check.js +10 -13
- package/dist/index.d.ts +13 -11
- package/dist/index.js +39 -4
- package/dist/json-schema.js +3 -3
- package/dist/mcp/cli.js +35 -35
- package/dist/mcp/dispatcher.js +1 -1
- package/dist/mcp/http.js +16 -6
- package/dist/mcp/list-filter.js +2 -1
- package/dist/mcp/protocol.d.ts +2 -0
- package/dist/mcp/protocol.js +1 -1
- package/dist/mcp/session.d.ts +16 -0
- package/dist/mcp/session.js +60 -6
- package/dist/mcp/tools.js +73 -6
- package/dist/observability/index.js +2 -2
- package/dist/server/asyncapi-channels.js +5 -2
- package/dist/server/attribute-filters.d.ts +8 -3
- package/dist/server/attribute-filters.js +6 -1
- package/dist/server/authentication/api-key.d.ts +2 -1
- package/dist/server/authentication/api-key.js +5 -2
- package/dist/server/authentication/constant-time-api-key.d.ts +15 -0
- package/dist/server/authentication/constant-time-api-key.js +24 -0
- package/dist/server/authentication/index.d.ts +1 -1
- package/dist/server/authentication/index.js +7 -4
- package/dist/server/authentication/rotating-api-key-store.d.ts +5 -3
- package/dist/server/authentication/rotating-api-key-store.js +19 -11
- package/dist/server/engine-event-feed-backend.d.ts +4 -5
- package/dist/server/fault-to-http.js +8 -1
- package/dist/server/fault-to-json-rpc.js +1 -0
- package/dist/server/fleet-event-feed.d.ts +31 -0
- package/dist/server/fleet-event-feed.js +157 -0
- package/dist/server/handler/index.js +1 -1
- package/dist/server/handler/response-helpers.js +2 -1
- package/dist/server/handler/route-dispatch.d.ts +6 -3
- package/dist/server/handler/route-dispatch.js +2 -2
- package/dist/server/handler.js +31 -31
- package/dist/server/index.d.ts +32 -2
- package/dist/server/index.js +35 -35
- package/dist/server/interactive-operations.js +1 -0
- package/dist/server/json-rpc-transport-helpers.d.ts +1 -0
- package/dist/server/json-rpc-transport-helpers.js +2 -1
- package/dist/server/json-rpc-websocket-runtime.d.ts +11 -2
- package/dist/server/json-rpc-websocket-runtime.js +1 -0
- package/dist/server/json-rpc-websocket-subscriptions.d.ts +10 -0
- package/dist/server/json-rpc-websocket-subscriptions.js +29 -0
- package/dist/server/json-rpc-websocket-types.d.ts +22 -0
- package/dist/server/json-rpc-websocket-types.js +0 -0
- package/dist/server/json-rpc-websocket-validation.js +20 -4
- package/dist/server/json-rpc-websocket.d.ts +2 -43
- package/dist/server/json-rpc-websocket.js +57 -74
- package/dist/server/openapi.d.ts +2 -1
- package/dist/server/openapi.js +1 -3
- package/dist/server/openrpc-document-schema.d.ts +78 -0
- package/dist/server/openrpc-document-schema.js +27 -1
- package/dist/server/openrpc-errors.d.ts +3 -0
- package/dist/server/openrpc-errors.js +2 -1
- package/dist/server/openrpc.js +32 -0
- package/dist/server/operation-catalog/index.d.ts +1 -1
- package/dist/server/operation-catalog/pipeline-helpers.js +1 -0
- package/dist/server/operation-catalog/pipeline-stages.js +26 -12
- package/dist/server/operation-catalog/pipeline.js +8 -1
- package/dist/server/operation-catalog/registry.js +13 -0
- package/dist/server/operation-catalog/types.d.ts +20 -9
- package/dist/server/operation-fault.d.ts +10 -0
- package/dist/server/operation-fault.js +2 -0
- package/dist/server/operation-registry.d.ts +12 -11
- package/dist/server/operation-registry.js +12 -3
- package/dist/server/operations/aggregate-workflows.d.ts +15 -15
- package/dist/server/operations/async-activity.d.ts +2 -2
- package/dist/server/operations/async-activity.js +12 -7
- package/dist/server/operations/bulk-cancel-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-cancel-workflows.js +2 -2
- package/dist/server/operations/bulk-delete-workflows.d.ts +1 -1
- package/dist/server/operations/bulk-delete-workflows.js +2 -2
- package/dist/server/operations/bulk-filter-helpers.d.ts +8 -6
- package/dist/server/operations/bulk-filter-helpers.js +54 -24
- package/dist/server/operations/bulk-mutate-workflow-tags.d.ts +11 -9
- package/dist/server/operations/bulk-mutate-workflow-tags.js +2 -2
- package/dist/server/operations/bulk-operation-helpers.d.ts +2 -2
- package/dist/server/operations/bulk-retry-failed-workflows.d.ts +7 -0
- package/dist/server/operations/bulk-retry-failed-workflows.js +64 -0
- package/dist/server/operations/bulk-signal-workflows.d.ts +11 -9
- package/dist/server/operations/bulk-signal-workflows.js +2 -2
- package/dist/server/operations/cancel-schedule.d.ts +1 -1
- package/dist/server/operations/create-schedule.d.ts +3 -1
- package/dist/server/operations/create-schedule.js +29 -11
- package/dist/server/operations/fleet-events-subscription.d.ts +54 -0
- package/dist/server/operations/fleet-events-subscription.js +99 -0
- package/dist/server/operations/fork-workflow.d.ts +1 -1
- package/dist/server/operations/fork-workflow.js +3 -2
- package/dist/server/operations/get-checkpoint-at.d.ts +1 -1
- package/dist/server/operations/get-registry.d.ts +1 -1
- package/dist/server/operations/get-retention-overview.d.ts +1 -1
- package/dist/server/operations/get-review.d.ts +1 -1
- package/dist/server/operations/get-schedule.d.ts +1 -1
- package/dist/server/operations/get-stream-chunks.d.ts +1 -1
- package/dist/server/operations/get-system-metrics.d.ts +2 -2
- package/dist/server/operations/get-task-diagnostics.d.ts +45 -6
- package/dist/server/operations/get-task-diagnostics.js +101 -7
- package/dist/server/operations/get-update-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/get-workflow-events.d.ts +1 -1
- package/dist/server/operations/get-workflow-result.d.ts +1 -1
- package/dist/server/operations/get-workflow-timeline.d.ts +1 -1
- package/dist/server/operations/get-workflow.d.ts +1 -1
- package/dist/server/operations/list-checkpoints.d.ts +1 -1
- package/dist/server/operations/list-reviews.d.ts +1 -1
- package/dist/server/operations/list-schedules.d.ts +1 -1
- package/dist/server/operations/list-task-queues.d.ts +2 -2
- package/dist/server/operations/list-workers.d.ts +2 -2
- package/dist/server/operations/list-workflows.d.ts +1 -1
- package/dist/server/operations/operation-helpers.d.ts +16 -1
- package/dist/server/operations/operation-helpers.js +15 -3
- package/dist/server/operations/pause-schedule.d.ts +1 -1
- package/dist/server/operations/purge-workflows.d.ts +5 -5
- package/dist/server/operations/purge-workflows.js +2 -2
- package/dist/server/operations/query-workflow.d.ts +1 -1
- package/dist/server/operations/query-workflow.js +3 -2
- package/dist/server/operations/recover-all.d.ts +1 -1
- package/dist/server/operations/replay-workflow.d.ts +1 -1
- package/dist/server/operations/resume-schedule.d.ts +1 -1
- package/dist/server/operations/resume-workflow.js +2 -2
- package/dist/server/operations/set-workflow-attributes.d.ts +1 -1
- package/dist/server/operations/set-workflow-attributes.js +6 -3
- package/dist/server/operations/signal-workflow.js +8 -3
- package/dist/server/operations/single-workflow-tag-mutation.js +13 -3
- package/dist/server/operations/start-or-signal-workflow.d.ts +44 -0
- package/dist/server/operations/start-or-signal-workflow.js +130 -0
- package/dist/server/operations/start-workflow-options.d.ts +38 -0
- package/dist/server/operations/start-workflow-options.js +63 -0
- package/dist/server/operations/start-workflow-rest-input.d.ts +14 -0
- package/dist/server/operations/start-workflow-rest-input.js +31 -0
- package/dist/server/operations/start-workflow.d.ts +1 -1
- package/dist/server/operations/start-workflow.js +15 -92
- package/dist/server/operations/storage.d.ts +6 -6
- package/dist/server/operations/storage.js +24 -14
- package/dist/server/operations/stream-workflow-sse.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.d.ts +1 -1
- package/dist/server/operations/submit-review-decision.js +6 -3
- package/dist/server/operations/suspend-workflow.d.ts +13 -0
- package/dist/server/operations/suspend-workflow.js +36 -0
- package/dist/server/operations/update-schedule.d.ts +1 -1
- package/dist/server/operations/update-schedule.js +7 -4
- package/dist/server/operations/update-workflow.d.ts +1 -1
- package/dist/server/operations/update-workflow.js +7 -3
- package/dist/server/operations/worker-drain.d.ts +8 -8
- package/dist/server/operations/worker-drain.js +11 -8
- package/dist/server/operations/workflow-events-subscription.d.ts +7 -8
- package/dist/server/operations/workflow-events-subscription.js +43 -8
- package/dist/server/rest-binding.d.ts +21 -8
- package/dist/server/rest-bindings.js +24 -0
- package/dist/server/rest-body.d.ts +10 -0
- package/dist/server/rest-body.js +80 -0
- package/dist/server/runtime/authentication-bridge.d.ts +1 -0
- package/dist/server/runtime/authentication-bridge.js +33 -6
- package/dist/server/runtime/client-visible-events.d.ts +3 -0
- package/dist/server/runtime/client-visible-events.js +65 -0
- package/dist/server/runtime/context.d.ts +7 -0
- package/dist/server/runtime/event-broadcasting.d.ts +6 -0
- package/dist/server/runtime/event-broadcasting.js +72 -38
- package/dist/server/runtime/retry.d.ts +1 -0
- package/dist/server/runtime/retry.js +14 -0
- package/dist/server/runtime/shutdown.d.ts +7 -6
- package/dist/server/runtime/shutdown.js +6 -1
- package/dist/server/runtime/task-dispatch.js +5 -3
- package/dist/server/runtime/task-polling.d.ts +16 -2
- package/dist/server/runtime/task-polling.js +80 -24
- package/dist/server/runtime/task-reconciliation.js +9 -1
- package/dist/server/runtime/task-result-resolution.d.ts +15 -0
- package/dist/server/runtime/task-result-resolution.js +81 -0
- package/dist/server/runtime/websocket-stream.d.ts +20 -1
- package/dist/server/runtime/websocket-stream.js +173 -7
- package/dist/server/runtime/websocket-upgrade.js +22 -3
- package/dist/server/runtime/websocket-worker.d.ts +1 -1
- package/dist/server/runtime/websocket-worker.js +46 -30
- package/dist/server/serve-internals.d.ts +11 -1
- package/dist/server/serve-internals.js +20 -2
- package/dist/server/task-state.d.ts +38 -0
- package/dist/server/task-state.js +28 -0
- package/dist/server/workflow-event-feed.d.ts +36 -115
- package/dist/server/workflow-event-feed.js +92 -27
- package/dist/service-worker/index.js +31 -31
- package/dist/storage/auto.js +1 -1
- package/dist/storage/bun-sql.js +24 -0
- package/dist/storage/capabilities.d.ts +10 -2
- package/dist/storage/capabilities.js +2 -2
- package/dist/storage/compressed-storage.js +1 -1
- package/dist/storage/default-scope.d.ts +7 -4
- package/dist/storage/http.js +2 -2
- package/dist/storage/index.d.ts +81 -4
- package/dist/storage/indexeddb.js +1 -1
- package/dist/storage/interface.d.ts +189 -0
- package/dist/storage/interface.js +1 -1
- package/dist/storage/key-prefixes.d.ts +1 -1
- package/dist/storage/key-prefixes.js +12 -0
- package/dist/storage/lmdb.d.ts +4 -3
- package/dist/storage/lmdb.js +1 -1
- package/dist/storage/memory.js +1 -1
- package/dist/storage/neon-batch.d.ts +30 -0
- package/dist/storage/neon-batch.js +30 -0
- package/dist/storage/neon-value-mapping.d.ts +74 -0
- package/dist/storage/neon-value-mapping.js +23 -0
- package/dist/storage/neon.d.ts +124 -0
- package/dist/storage/neon.js +15 -0
- package/dist/storage/node-sqlite-loader.d.ts +71 -0
- package/dist/storage/node-sqlite-loader.js +41 -0
- package/dist/storage/node-sqlite.d.ts +1 -19
- package/dist/storage/node-sqlite.js +61 -32
- package/dist/storage/postgres-key-value-queries.d.ts +104 -0
- package/dist/storage/postgres-key-value-queries.js +101 -0
- package/dist/storage/resolve.d.ts +2 -165
- package/dist/storage/resolve.js +1 -1
- package/dist/storage/scoped-storage.js +1 -1
- package/dist/storage/storage-configuration.d.ts +209 -0
- package/dist/storage/storage-configuration.js +0 -0
- package/dist/storage/testing.d.ts +168 -0
- package/dist/storage/testing.js +2 -0
- package/dist/storage/text-value-store.d.ts +9 -9
- package/dist/storage/turso.d.ts +8 -0
- package/dist/storage/turso.js +2 -2
- package/dist/storage/typed-storage.js +1 -1
- package/dist/storage/web-extension.js +1 -1
- package/dist/testing/index.js +35 -35
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/worker/index.js +9 -5
- package/dist/worker/long-poll.js +4 -0
- package/dist/worker/protocol-messages.d.ts +20 -0
- package/dist/worker/protocol-schemas.d.ts +32 -0
- package/dist/worker/protocol-schemas.js +8 -4
- package/dist/worker/protocol-task-result.d.ts +28 -0
- package/dist/worker/protocol-task-result.js +76 -0
- package/dist/worker/protocol.d.ts +4 -15
- package/dist/worker/protocol.js +1 -1
- package/dist/worker/registry/fair-share.d.ts +29 -0
- package/dist/worker/registry/fair-share.js +30 -0
- package/dist/worker/registry/routing.d.ts +18 -0
- package/dist/worker/registry/routing.js +14 -0
- package/dist/worker/registry/types.d.ts +7 -0
- package/dist/worker/registry.d.ts +16 -1
- package/dist/worker/registry.js +24 -36
- package/dist/workers/worker-replay-state.d.ts +32 -0
- package/dist/workers/worker-replay-state.js +35 -0
- package/dist/workers/worker-state-namespace.d.ts +21 -0
- package/dist/workers/worker-state-namespace.js +13 -0
- package/dist/workers/workflow-runner.d.ts +19 -15
- package/dist/workers/workflow-runner.js +72 -60
- package/dist/workers/workflow-worker-entry.js +5 -2
- package/package.json +21 -4
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function affectedRowCount(result) {
|
|
2
|
+
return result.rowCount ?? result.affectedRows ?? result.rows.length;
|
|
3
|
+
}
|
|
4
|
+
export function toStorageValue(raw) {
|
|
5
|
+
if (raw instanceof Uint8Array)
|
|
6
|
+
return new Uint8Array(raw);
|
|
7
|
+
return new Uint8Array(raw);
|
|
8
|
+
}
|
|
9
|
+
export function toBytea(value) {
|
|
10
|
+
return Buffer.from(value);
|
|
11
|
+
}
|
|
12
|
+
export function resolveBatchNetEffect(operations) {
|
|
13
|
+
const puts = new Map, deletes = new Set;
|
|
14
|
+
for (const operation of operations)
|
|
15
|
+
if (operation.type === "put") {
|
|
16
|
+
deletes.delete(operation.key);
|
|
17
|
+
puts.set(operation.key, operation.value);
|
|
18
|
+
} else {
|
|
19
|
+
puts.delete(operation.key);
|
|
20
|
+
deletes.add(operation.key);
|
|
21
|
+
}
|
|
22
|
+
return { puts, deletes };
|
|
23
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type DeleteRangeOptions } from './delete-range.ts';
|
|
2
|
+
import { type BatchOperation, type ConditionalBatchCondition, type ScanOptions, type Storage, type StorageCapabilities } from './interface.ts';
|
|
3
|
+
import { type NeonQueryResult } from './neon-value-mapping.ts';
|
|
4
|
+
/**
|
|
5
|
+
* A connection that can run a single interactive transaction. Obtained from
|
|
6
|
+
* {@link NeonPool.connect}; `release()` returns it to the pool. Both
|
|
7
|
+
* `batch()` and `conditionalBatch()` drive `BEGIN`/`COMMIT`/`ROLLBACK` over one
|
|
8
|
+
* of these so every statement in a transaction lands on the same connection —
|
|
9
|
+
* `pool.query()` alone may scatter statements across pooled connections, which
|
|
10
|
+
* would make a multi-statement batch non-atomic.
|
|
11
|
+
*/
|
|
12
|
+
export type NeonPoolClient = {
|
|
13
|
+
query(sql: string, parameters?: unknown[]): Promise<NeonQueryResult>;
|
|
14
|
+
release(): void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Minimal structural view of a node-postgres `Pool`. The real Neon serverless
|
|
18
|
+
* `Pool` satisfies this; the PGlite test backend is wrapped to satisfy it too.
|
|
19
|
+
* `query()` runs a single statement on a pooled connection (used for the
|
|
20
|
+
* single-statement hot paths); `connect()` pins a connection for an interactive
|
|
21
|
+
* transaction; `end()` tears the pool down.
|
|
22
|
+
*/
|
|
23
|
+
export type NeonPool = {
|
|
24
|
+
query(sql: string, parameters?: unknown[]): Promise<NeonQueryResult>;
|
|
25
|
+
connect(): Promise<NeonPoolClient>;
|
|
26
|
+
end(): Promise<void>;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Configuration for connecting to a Neon (or any Postgres) database.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { NeonStorage, type NeonStorageOptions } from '@lostgradient/weft/storage/neon';
|
|
34
|
+
*
|
|
35
|
+
* const options: NeonStorageOptions = {
|
|
36
|
+
* url: 'postgresql://user:password@ep-cool-name.us-east-2.aws.neon.tech/weft?sslmode=require',
|
|
37
|
+
* };
|
|
38
|
+
* await using storage = new NeonStorage(options);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export type NeonStorageOptions = {
|
|
42
|
+
/** Postgres connection string for the primary endpoint. */
|
|
43
|
+
url: string;
|
|
44
|
+
/**
|
|
45
|
+
* Optional pre-built pool. Pass this to reuse a pool you manage (for example a
|
|
46
|
+
* test backend such as PGlite, or a shared application pool), instead of having
|
|
47
|
+
* the adapter construct its own from `url`. When supplied, `url` is ignored and
|
|
48
|
+
* **ownership stays with the caller**: disposing the `NeonStorage` does NOT
|
|
49
|
+
* close an injected pool, so it can be shared across adapters and the caller
|
|
50
|
+
* remains responsible for ending it. A pool the adapter constructs itself (from
|
|
51
|
+
* `url`) IS closed on disposal.
|
|
52
|
+
*/
|
|
53
|
+
pool?: NeonPool;
|
|
54
|
+
/**
|
|
55
|
+
* Postgres schema to contain the kv table. Default: unqualified — the table
|
|
56
|
+
* resolves through `search_path` (in practice `public`). When set, the adapter
|
|
57
|
+
* creates the schema if absent (`CREATE SCHEMA IF NOT EXISTS`) and qualifies
|
|
58
|
+
* every statement as `"schema"."table"`. Lets Weft live in its own schema
|
|
59
|
+
* alongside the application's tables in one database — one PITR line, no Drizzle
|
|
60
|
+
* drift/drop risk. Validated as a strict Postgres identifier at construction.
|
|
61
|
+
*/
|
|
62
|
+
schema?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Table name. Default: `'kv'`. Validated as a strict Postgres identifier at
|
|
65
|
+
* construction. With neither `schema` nor `table` set, the adapter emits
|
|
66
|
+
* byte-identical SQL against the unqualified `kv` table (existing deployments
|
|
67
|
+
* are unaffected).
|
|
68
|
+
*/
|
|
69
|
+
table?: string;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Storage adapter backed by Neon serverless Postgres for durable, remote
|
|
73
|
+
* deployments. Implements the same `Storage` interface as the SQLite adapters
|
|
74
|
+
* over a single `kv(key TEXT COLLATE "C", value BYTEA)` table, so switching from
|
|
75
|
+
* a local SQLite store to Neon is a configuration change, not a code change.
|
|
76
|
+
*
|
|
77
|
+
* **Endpoint assumption.** `capabilities()` reports `readAfterWrite:
|
|
78
|
+
* 'linearizable'`, which holds for the **primary** Neon endpoint. A read-replica
|
|
79
|
+
* connection string would violate that guarantee — point this adapter at the
|
|
80
|
+
* primary.
|
|
81
|
+
*
|
|
82
|
+
* **WebSocket runtime.** The Neon serverless driver connects over WebSocket. Bun
|
|
83
|
+
* and Node 22+ provide a global `WebSocket`, so no extra wiring is needed there.
|
|
84
|
+
* On Node ≤21 the driver needs `neonConfig.webSocketConstructor` set to the `ws`
|
|
85
|
+
* package before first use; install `ws` and configure it in that runtime.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { NeonStorage } from '@lostgradient/weft/storage/neon';
|
|
90
|
+
* import { Engine } from '@lostgradient/weft';
|
|
91
|
+
*
|
|
92
|
+
* await using storage = new NeonStorage({
|
|
93
|
+
* url: process.env['NEON_DATABASE_URL']!,
|
|
94
|
+
* });
|
|
95
|
+
* await using engine = new Engine({ storage });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare class NeonStorage implements Storage {
|
|
99
|
+
#private;
|
|
100
|
+
/**
|
|
101
|
+
* @param options Connection configuration ({@link NeonStorageOptions}).
|
|
102
|
+
* @param poolFactory Internal seam for constructing the owned pool from `url`.
|
|
103
|
+
* Defaults to the real driver `Pool`; tests inject a fake (for example one
|
|
104
|
+
* whose `end()` rejects) to exercise owned-pool teardown without a network.
|
|
105
|
+
* Used only when no `pool` is supplied; an injected `pool` stays caller-owned.
|
|
106
|
+
*/
|
|
107
|
+
constructor(options: NeonStorageOptions, poolFactory?: (url: string) => NeonPool);
|
|
108
|
+
capabilities(): StorageCapabilities;
|
|
109
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
110
|
+
put(key: string, value: Uint8Array): Promise<void>;
|
|
111
|
+
delete(key: string): Promise<void>;
|
|
112
|
+
has(key: string): Promise<boolean>;
|
|
113
|
+
deletePrefix(prefix: string): Promise<number>;
|
|
114
|
+
deleteRange(prefix: string, options: DeleteRangeOptions): Promise<number>;
|
|
115
|
+
scan(prefix: string, options?: ScanOptions): AsyncIterable<[string, Uint8Array]>;
|
|
116
|
+
keys(prefix: string, options?: ScanOptions): AsyncIterable<string>;
|
|
117
|
+
count(prefix: string): Promise<number>;
|
|
118
|
+
scoped(prefix: string): Storage;
|
|
119
|
+
batch(operations: BatchOperation[]): Promise<void>;
|
|
120
|
+
conditionalBatch(conditions: ConditionalBatchCondition[], operations: BatchOperation[]): Promise<boolean>;
|
|
121
|
+
query<T>(sql: string, parameters?: unknown[]): Promise<T[]>;
|
|
122
|
+
[Symbol.dispose](): void;
|
|
123
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
124
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
var U_=Object.defineProperty;var Z_=(_)=>_;function G_(_,E){this[_]=Z_.bind(null,E)}var z_=(_,E)=>{for(var F in E)U_(_,F,{get:E[F],enumerable:!0,configurable:!0,set:G_.bind(E,F)})};var M=(_,E)=>()=>(_&&(E=_(_=0)),E);var v_=(_,E,F)=>{if(E!=null){if(typeof E!=="object"&&typeof E!=="function")throw TypeError('Object expected to be assigned to "using" declaration');let W;if(F)W=E[Symbol.asyncDispose];if(W===void 0)W=E[Symbol.dispose];if(typeof W!=="function")throw TypeError("Object not disposable");_.push([F,W,E])}else if(F)_.push([F]);return E},P_=(_,E,F)=>{let W=(Y)=>E=F?new SuppressedError(Y,E,"An error was suppressed during disposal"):(F=!0,Y),J=(Y)=>{while(Y=_.pop())try{var Q=Y[1]&&Y[1].call(Y[2]);if(Y[0])return Promise.resolve(Q).then(J,(U)=>(W(U),J()))}catch(U){W(U)}if(F)throw E};return J()};function N(_,E,F){if(!_.capabilities()[E])throw Error(`Feature "${F}" requires storage capability "${E}", but this storage backend does not provide it.`)}function M_(_){let E=_.capabilities(),F=[];if(E.persistence!=="local"&&E.persistence!=="remote")F.push(`persistence must be "local" or "remote" (got "${E.persistence}")`);if(E.readAfterWrite!=="linearizable")F.push(`readAfterWrite must be "linearizable" (got "${E.readAfterWrite}")`);if(E.scanConsistency!=="snapshot")F.push(`scanConsistency must be "snapshot" (got "${E.scanConsistency}")`);if(!E.atomicBatch)F.push("atomicBatch must be true");if(!E.conditionalBatch)F.push("conditionalBatch must be true");if(F.length>0)throw Error(`Storage is not durable enough for recovery: ${F.join("; ")}.`)}var C="default";async function q(_,E){return await _.get(E)!==null}async function*H(_,E,F){for await(let[W]of _.scan(E,F))yield W}async function h(_,E){let F=0;for await(let W of H(_,E))F++;return F}async function b(_,E){let F=[];for await(let W of H(_,E))F.push({type:"delete",key:W});if(F.length===0)return 0;return await _.batch(F),F.length}async function x(_,E,F){let W=[];for await(let J of H(_,E,F))W.push({type:"delete",key:J});if(W.length===0)return 0;return await _.batch(W),W.length}var $_;var y=M(()=>{$_=["actrec:","archive:","async-act:","attr:","audit:bulk:","blob:","budget:","budget-charged:","ev:","fleet-event-by-workflow:","fleet-event:","fleet-event-tail","idx:","lease:","liveness:","offload:","op:","review:","schedule:","schedule-due:","schedule-run:","sig:","sigres:","sigseq:","start-idem:","state:","tag:","tool-effect:","upd:","upk:","upr:","wf:","wf-cleanup:","wf-cleanup-needed:","wf-concurrency:","wf-concurrency-holder:","wf-deadline:","wf-delayed:","wf-finalizer-state:","wf-has-services:","wf-headers:","wf-idx-","wf-teardown:","wf-teardown-deadletter:","wf-teardown-needed:","wf-terminal:"]});function G(_,E){if(E>A)throw new m(_,E)}function g(_){return _.length>0?_.slice(0,-1)+String.fromCharCode(_.charCodeAt(_.length-1)+1):"\xFF"}function u_(_,E={}){if(E.gt!==void 0&&_<=E.gt)return!1;if(E.gte!==void 0&&_<E.gte)return!1;if(E.lt!==void 0&&_>=E.lt)return!1;if(E.lte!==void 0&&_>E.lte)return!1;return!0}function u(_,E){if(_===null||E===null)return _===E;if(_.byteLength!==E.byteLength)return!1;for(let F=0;F<_.byteLength;F++)if(_[F]!==E[F])return!1;return!0}async function c(_,E){if(_.has)return _.has(E);return q(_,E)}function k(_,E,F){if(_.keys)return _.keys(E,F);return H(_,E,F)}async function w(_,E){if(_.count)return _.count(E);return h(_,E)}async function f(_,E){if(_.deletePrefix)return _.deletePrefix(E);return b(_,E)}async function c_(_,E){G("batch operations",E.length),await _.batch(E)}async function d(_,E,F){if(G("conditionalBatch conditions",E.length),G("conditionalBatch operations",F.length),N(_,"conditionalBatch","storageConditionalBatch"),!_.conditionalBatch)throw Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");return _.conditionalBatch(E,F)}function X(_){return encodeURIComponent(_)}function k_(_){return decodeURIComponent(_)}function w_(_){try{return decodeURIComponent(_)}catch{return null}}var A=1e4,g_=1e4,m,Z=(_)=>String(_).padStart(16,"0"),H_="0",V_="1",I=(_,E,F,W)=>`sig:${X(_)}:${X(E)}:${W}:${X(F)}`,f_;var V=M(()=>{y();m=class m extends Error{code="StorageBatchOperationLimitExceededError";cap=A;count;target;constructor(_,E){super(`${_} count ${E} exceeds MAX_BATCH_OPERATIONS (${A}).`);this.name="StorageBatchOperationLimitExceededError",this.target=_,this.count=E}};f_={workflow:(_)=>`wf:${X(_)}`,checkpoint:(_)=>`wf:${X(_)}:ckpt`,checkpointHistory:(_,E)=>`wf:${X(_)}:ckpt:${String(E).padStart(10,"0")}`,timelinePrefix:(_)=>`wf:${X(_)}:timeline:`,timeline:(_,E)=>`wf:${X(_)}:timeline:${String(E).padStart(10,"0")}`,schedule:(_)=>`schedule:${X(_)}`,scheduleTick:(_,E)=>`schedule-due:${String(_).padStart(16,"0")}:${X(E)}`,scheduleRun:(_)=>`schedule-run:${X(_)}`,operation:(_,E,F)=>`op:${_}:${Z(E)}:${F}`,operationInflight:(_)=>`op:inflight:${_}`,operationQueued:(_)=>`op:queued:${_}`,operationResolved:(_)=>`op:resolved:${_}`,operationDeadLetterPrefix:()=>"op:dead-letter:",operationDeadLetter:(_)=>`op:dead-letter:${_}`,bulkOperationAuditPrefix:()=>"audit:bulk:",bulkOperationAudit:(_,E,F)=>`audit:bulk:${Z(_)}:${X(E)}:${X(F)}`,operationResolvedByTimePrefix:()=>"op:resolved-by-time:",operationResolvedByTime:(_,E)=>`op:resolved-by-time:${Z(_)}:${X(E)}`,asyncActivity:(_,E)=>`async-act:v1:${X(_)}:${X(E)}`,activityReconciliationPrefix:(_)=>`actrec:v1:${X(_)}:`,activityReconciliation:(_,E,F)=>`actrec:v1:${X(_)}:${X(E)}:${F}`,eventPrefix:(_)=>`ev:${X(_)}:`,event:(_,E)=>`ev:${X(_)}:${String(E).padStart(10,"0")}`,eventHead:(_)=>`ev:${X(_)}:head`,eventWatermark:(_)=>`ev:${X(_)}:watermark`,fleetEventPrefix:()=>"fleet-event:",fleetEvent:(_)=>`fleet-event:${String(_).padStart(10,"0")}`,fleetEventTail:()=>"fleet-event-tail",fleetEventByWorkflowPrefix:(_)=>`fleet-event-by-workflow:${X(_)}:`,fleetEventByWorkflow:(_,E)=>`fleet-event-by-workflow:${X(_)}:${String(E).padStart(10,"0")}`,signal:(_,E,F)=>I(_,E,F,V_),startSignal:(_,E,F)=>I(_,E,F,H_),signalSequence:(_)=>`sigseq:v1:${X(_)}`,signalAcceptedResponsePrefix:(_)=>`sigres:v1:${X(_)}:`,signalAcceptedResponse:(_,E,F)=>`sigres:v1:${X(_)}:${X(E)}:${X(F)}`,deadline:(_,E)=>`wf-deadline:${Z(_)}:${X(E)}`,terminalCleanup:(_,E)=>`wf-cleanup:${Z(_)}:${X(E)}`,teardownTimer:(_,E)=>`wf-teardown:${Z(_)}:${X(E)}`,delayedStart:(_,E)=>`wf-delayed:${Z(_)}:${X(E)}`,terminalWorkflowPrefix:()=>"wf-terminal:",terminalWorkflow:(_,E)=>`wf-terminal:${Z(_)}:${X(E)}`,attribute:(_)=>`attr:${X(_)}`,attributeIndex:(_,E,F)=>`idx:${_}:${E}:${X(F)}`,tagIndex:(_,E)=>`tag:${X(_)}:${X(E)}`,updatePrefix:(_)=>`upd:${X(_)}:`,update:(_,E)=>`upd:${X(_)}:${E}`,updateResponse:(_)=>`upr:${_}`,updateIdempotency:(_,E)=>`upk:${X(_)}:${E}`,startIdempotency:(_)=>`start-idem:${X(_)}`,startIdempotencySignalId:(_)=>`start-idem:${_}`,livenessPrefix:()=>"liveness:",liveness:(_)=>`liveness:${X(_)}`,leasePrefix:()=>"lease:",leaseEpoch:()=>"lease:epoch",leaseHolder:()=>"lease:holder",budget:(_,E,F)=>`budget:${_}:${E}:${F}`,review:(_,E)=>`review:${X(_)}:${E}`,workflowHeaders:(_)=>`wf-headers:${X(_)}`,childCancellationPrefix:(_)=>`child-cancel:${X(_)}:`,childCancellation:(_,E)=>`child-cancel:${X(_)}:${X(E)}`,terminalCleanupNeeded:(_)=>`wf-cleanup-needed:${X(_)}`,workflowConcurrency:(_,E)=>`wf-concurrency:${X(_)}:${X(E)}`,workflowConcurrencyHolder:(_)=>`wf-concurrency-holder:${X(_)}`,workflowHasServices:(_)=>`wf-has-services:${X(_)}`,finalizerState:(_)=>`wf-finalizer-state:${X(_)}`,teardownOwed:(_)=>`wf-teardown-needed:${X(_)}`,teardownDeadLetter:(_)=>`wf-teardown-deadletter:${X(_)}`,offload:(_,E)=>`offload:${X(_)}:${E}`,archive:(_,E)=>`archive:${X(_)}:${E}`,stateExecution:(_,E)=>`state:execution:${X(_)}:${X(E)}`,stateWorkflow:(_,E)=>`state:workflow-scope:${C}:${X(_)}:${X(E)}`,streamChunkPrefix:(_,E)=>`blob:${X(_)}:${E}:chunk:`,streamChunk:(_,E,F)=>`blob:${X(_)}:${E}:chunk:${String(F).padStart(10,"0")}`,streamTail:(_,E)=>`blob:${X(_)}:${E}:tail`,streamMetadata:(_,E)=>`blob:${X(_)}:${E}:meta`,budgetCharged:(_)=>`budget-charged:${_}`,toolEffect:(_,E,F)=>`tool-effect:${X(_)}:${E}:${F}`,workflowVisibilityStatus:(_,E)=>`wf-idx-status:${X(_)}:${X(E)}`,workflowVisibilityType:(_,E)=>`wf-idx-type:${X(_)}:${X(E)}`,workflowVisibilityCreated:(_,E)=>`wf-idx-created:${Z(_)}:${X(E)}`,workflowVisibilityUpdated:(_,E)=>`wf-idx-updated:${Z(_)}:${X(E)}`,workflowVisibilityDeadline:(_,E)=>`wf-idx-deadline:${Z(_)}:${X(E)}`,workflowVisibilityManifest:(_)=>`wf-idx-manifest:${X(_)}`,workflowVisibilityMetaVersion:()=>"wf-idx-meta:version",workflowVisibilityMetaBuiltAt:()=>"wf-idx-meta:built-at",workflowVisibilityMetaCursor:()=>"wf-idx-meta:cursor"}});function j_(_){if(_===void 0)return;if(typeof _!=="number"||!Number.isInteger(_)||_<0)throw Error("deleteRange limit must be a finite non-negative integer");return _===0?0:_}function j(_){let E={},F=!1;for(let J of["gt","gte","lt","lte"]){let Y=_[J];if(Y===void 0)continue;if(typeof Y!=="string")throw Error("deleteRange bounds must be strings");E[J]=Y,F=!0}if(!F)throw Error("deleteRange requires at least one of gt/gte/lt/lte; use deletePrefix to delete a whole prefix");let W=j_(_.limit);if(W!==void 0)E.limit=W;return E}async function l(_,E,F){let W=j(F);if(_.deleteRange)return _.deleteRange(E,W);return x(_,E,W)}var S=()=>{};function T(_){return _.replaceAll(/:+$/g,"")}function L_(_,E){let F=T(_),W=T(E);if(F.length===0)return W;if(W.length===0)return F;return`${F}:${W}`}function p(_,E){return new K(_,E)}var K;var a=M(()=>{S();V();K=class K{#_;#E;constructor(_,E){this.#_=_,this.#E=T(E)}#F(_){if(this.#E.length===0)return _;return _.length===0?`${this.#E}:`:`${this.#E}:${_}`}#X(_){if(this.#E.length===0)return _;return _.slice(this.#E.length+1)}#Y(_={}){let E={};if(_.limit!==void 0)E.limit=_.limit;if(_.reverse!==void 0)E.reverse=_.reverse;if(_.gt!==void 0)E.gt=this.#F(_.gt);if(_.gte!==void 0)E.gte=this.#F(_.gte);if(_.lt!==void 0)E.lt=this.#F(_.lt);if(_.lte!==void 0)E.lte=this.#F(_.lte);return E}#J(_){let E={};if(_.limit!==void 0)E.limit=_.limit;if(_.gt!==void 0)E.gt=this.#F(_.gt);if(_.gte!==void 0)E.gte=this.#F(_.gte);if(_.lt!==void 0)E.lt=this.#F(_.lt);if(_.lte!==void 0)E.lte=this.#F(_.lte);return E}capabilities(){return this.#_.capabilities()}scoped(_){return new K(this.#_,L_(this.#E,_))}async get(_){return this.#_.get(this.#F(_))}async put(_,E){await this.#_.put(this.#F(_),E)}async delete(_){await this.#_.delete(this.#F(_))}async*scan(_,E){for await(let[F,W]of this.#_.scan(this.#F(_),this.#Y(E)))yield[this.#X(F),W]}async batch(_){G("batch operations",_.length),await this.#_.batch(_.map((E)=>{if(E.type==="put")return{type:"put",key:this.#F(E.key),value:E.value};return{type:"delete",key:this.#F(E.key)}}))}async conditionalBatch(_,E){return d(this.#_,_.map((F)=>({key:this.#F(F.key),expectedValue:F.expectedValue})),E.map((F)=>{if(F.type==="put")return{type:"put",key:this.#F(F.key),value:F.value};return{type:"delete",key:this.#F(F.key)}}))}async has(_){return c(this.#_,this.#F(_))}async deletePrefix(_){return f(this.#_,this.#F(_))}async deleteRange(_,E){let F=this.#J(j(E));return l(this.#_,this.#F(_),F)}async*keys(_,E){for await(let F of k(this.#_,this.#F(_),this.#Y(E)))yield this.#X(F)}async count(_){return w(this.#_,this.#F(_))}[Symbol.dispose](){this.#_[Symbol.dispose]()}}});function C_(_){return _.trim().replace(/;+\s*$/u,"").trim()}function A_(_){return B_.test(_)}function Y_(_){let E=C_(_);if(E.length===0)throw Error("Storage query must not be empty.");if(E.includes(";"))throw Error("Storage query must contain exactly one read-only statement.");if(N_.test(E))return;if(D_.test(E)&&A_(E))return;throw Error("Storage query only supports read-only SELECT and PRAGMA statements.")}var D_,B_,N_;var J_=M(()=>{D_=/^PRAGMA\b/iu,B_=/^PRAGMA\s+(?:[A-Z_][A-Z0-9_]*\.)?[A-Z_][A-Z0-9_]*\s*$/iu,N_=/^SELECT\b/iu});S();V();import{Pool as S_}from"@neondatabase/serverless";V();function O(_){return _.rowCount??_.affectedRows??_.rows.length}function L(_){if(_ instanceof Uint8Array)return new Uint8Array(_);return new Uint8Array(_)}function D(_){return Buffer.from(_)}function z(_){let E=new Map,F=new Set;for(let W of _)if(W.type==="put")F.delete(W.key),E.set(W.key,W.value);else E.delete(W.key),F.add(W.key);return{puts:E,deletes:F}}async function s(_,E,F){if(F.length===0)return!0;let W=F.map((Q)=>Q.key),J=await _.query(E.selectValuesByKeys,[W]),Y=new Map;for(let Q of J.rows){let U=Q.value;if(U!==null&&U!==void 0)Y.set(Q.key,L(U))}for(let Q of F){let U=Y.get(Q.key)??null;if(!u(U,Q.expectedValue))return!1}return!0}async function v(_,E,F){if(F.puts.size>0){let W=[],J=[];for(let[Y,Q]of F.puts)W.push(Y),J.push(D(Q));await _.query(E.upsertValuesByKeys,[W,J])}if(F.deletes.size>0)await _.query(E.deleteValuesByKeys,[[...F.deletes]])}V();var n="kv",i=/^[a-z_][a-z0-9_]*$/i;function P(_,E){if(!i.test(_))throw Error(`NeonStorage ${E} name "${_}" is not a valid Postgres identifier. Use only letters, digits, and underscores, starting with a letter or underscore (matching ${i.source}).`)}function t(_){let{schema:E,table:F}=_;if(E===void 0&&F===void 0)return n;let W=F??n;if(P(W,"table"),E===void 0)return`"${W}"`;return P(E,"schema"),`"${E}"."${W}"`}function B(_){return[_,g(_)]}function o(_,E){let{gt:F,gte:W,lt:J,lte:Y}=E,Q=B(_),U=["key >= $1 AND key < $2"];if(F!==void 0)Q.push(F),U.push(`key > $${Q.length}`);if(W!==void 0)Q.push(W),U.push(`key >= $${Q.length}`);if(J!==void 0)Q.push(J),U.push(`key < $${Q.length}`);if(Y!==void 0)Q.push(Y),U.push(`key <= $${Q.length}`);return{conditions:U,parameters:Q}}function r(_,E={}){let{limit:F,reverse:W}=E,{conditions:J,parameters:Y}=o(_,E),Q=W?"DESC":"ASC",U="";if(F!==void 0)Y.push(F),U=` LIMIT $${Y.length}`;return{parameters:Y,whereOrderLimit:`WHERE ${J.join(" AND ")} ORDER BY key ${Q}${U}`}}function e(_){let E=`CREATE TABLE IF NOT EXISTS ${_} (
|
|
3
|
+
key TEXT COLLATE "C" PRIMARY KEY,
|
|
4
|
+
value BYTEA NOT NULL
|
|
5
|
+
)`,F=`
|
|
6
|
+
SELECT COALESCE(co.collname, 'default') AS collation
|
|
7
|
+
FROM pg_attribute a
|
|
8
|
+
LEFT JOIN pg_collation co ON co.oid = a.attcollation
|
|
9
|
+
WHERE a.attrelid = to_regclass($1) AND a.attname = 'key' AND a.attnum > 0
|
|
10
|
+
`;return{tableReference:_,createTable:E,selectKeyCollation:`
|
|
11
|
+
SELECT COALESCE(co.collname, 'default') AS collation
|
|
12
|
+
FROM pg_attribute a
|
|
13
|
+
LEFT JOIN pg_collation co ON co.oid = a.attcollation
|
|
14
|
+
WHERE a.attrelid = to_regclass($1) AND a.attname = 'key' AND a.attnum > 0
|
|
15
|
+
`,selectValueByKey:`SELECT value FROM ${_} WHERE key = $1`,upsertValueByKey:`INSERT INTO ${_} (key, value) VALUES ($1, $2) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,deleteValueByKey:`DELETE FROM ${_} WHERE key = $1`,selectKeyPresence:`SELECT 1 AS present FROM ${_} WHERE key = $1 LIMIT 1`,countKeysByPrefix:`SELECT COUNT(*) AS count FROM ${_} WHERE key >= $1 AND key < $2`,deleteKeysByPrefix:`DELETE FROM ${_} WHERE key >= $1 AND key < $2`,selectValuesByKeys:`SELECT key, value FROM ${_} WHERE key = ANY($1)`,upsertValuesByKeys:`INSERT INTO ${_} (key, value) SELECT * FROM unnest($1::text[], $2::bytea[]) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value`,deleteValuesByKeys:`DELETE FROM ${_} WHERE key = ANY($1)`,keyValueRangeSelect(W,J={}){let{parameters:Y,whereOrderLimit:Q}=r(W,J);return{parameters:Y,sql:`SELECT key, value FROM ${_} ${Q}`}},keyRangeSelect(W,J={}){let{parameters:Y,whereOrderLimit:Q}=r(W,J);return{parameters:Y,sql:`SELECT key FROM ${_} ${Q}`}},keyRangeDelete(W,J){let{conditions:Y,parameters:Q}=o(W,J),U=Y.join(" AND ");if(J.limit===void 0)return{parameters:Q,sql:`DELETE FROM ${_} WHERE ${U}`};return Q.push(J.limit),{parameters:Q,sql:`DELETE FROM ${_} WHERE key IN (SELECT key FROM ${_} WHERE ${U} ORDER BY key ASC LIMIT $${Q.length})`}}}}var __="BEGIN ISOLATION LEVEL SERIALIZABLE",E_="BEGIN ISOLATION LEVEL READ COMMITTED",F_="BEGIN READ ONLY",W_="COMMIT",R="ROLLBACK";function X_(_){return P(_,"schema"),`CREATE SCHEMA IF NOT EXISTS "${_}"`}J_();a();var T_=new Set(["40001","40P01"]),Q_=5;function K_(_){if(typeof _!=="object"||_===null||!("code"in _))return!1;let E=_.code;return typeof E==="string"&&T_.has(E)}class O_{#_;#E;#F;#X;#Y;#J;constructor(_,E=(F)=>new S_({connectionString:F})){this.#Y=_.pool===void 0,this.#_=_.pool??E(_.url),this.#F=_.schema;let F=t({schema:_.schema,table:_.table});this.#E=e(F)}capabilities(){return{persistence:"remote",readAfterWrite:"linearizable",scanConsistency:"snapshot",atomicBatch:!0,conditionalBatch:!0,boundedRangeDelete:!0}}#W(){return this.#X??=this.#Z().catch((_)=>{throw this.#X=void 0,_}),this.#X}async#Z(){if(this.#F!==void 0)await this.#_.query(X_(this.#F));await this.#_.query(this.#E.createTable),await this.#G()}async#G(){let E=(await this.#_.query(this.#E.selectKeyCollation,[this.#E.tableReference])).rows[0]?.collation;if(E==="C")return;let F=E===void 0?"no such table":typeof E==="string"?`"${E}"`:"an unexpected collation value";throw Error(`NeonStorage requires the ${this.#E.tableReference} table's "key" column to use COLLATE "C" (found ${F}). A table created without COLLATE "C" sorts keys by the database locale, which breaks Weft's lexicographic prefix scans. Use a fresh table, or recreate it as: CREATE TABLE ${this.#E.tableReference} (key TEXT COLLATE "C" PRIMARY KEY, value BYTEA NOT NULL).`)}async get(_){await this.#W();let F=(await this.#_.query(this.#E.selectValueByKey,[_])).rows[0];if(F===void 0)return null;let W=F.value;if(W===null||W===void 0)return null;return L(W)}async put(_,E){await this.#W(),await this.#_.query(this.#E.upsertValueByKey,[_,D(E)])}async delete(_){await this.#W(),await this.#_.query(this.#E.deleteValueByKey,[_])}async has(_){return await this.#W(),(await this.#_.query(this.#E.selectKeyPresence,[_])).rows.length>0}async deletePrefix(_){await this.#W();let[E,F]=B(_),W=await this.#_.query(this.#E.deleteKeysByPrefix,[E,F]);return O(W)}async deleteRange(_,E){await this.#W();let F=j(E),{parameters:W,sql:J}=this.#E.keyRangeDelete(_,F),Y=await this.#_.query(J,W);return O(Y)}async*scan(_,E={}){await this.#W();let{parameters:F,sql:W}=this.#E.keyValueRangeSelect(_,E),J=await this.#_.query(W,F);for(let Y of J.rows)yield[Y.key,L(Y.value)]}async*keys(_,E={}){await this.#W();let{parameters:F,sql:W}=this.#E.keyRangeSelect(_,E),J=await this.#_.query(W,F);for(let Y of J.rows)yield Y.key}async count(_){await this.#W();let[E,F]=B(_),W=await this.#_.query(this.#E.countKeysByPrefix,[E,F]);return Number(W.rows[0]?.count??0)}scoped(_){return p(this,_)}async#Q(_,E,F=()=>!0){let W=await this.#_.connect();try{await W.query(_);try{let J=await E(W);return await W.query(F(J)?W_:R),J}catch(J){throw await W.query(R).catch(()=>{}),J}}finally{W.release()}}async batch(_){if(G("batch operations",_.length),_.length===0)return;await this.#W(),await this.#Q(E_,async(E)=>{await v(E,this.#E,z(_))})}async conditionalBatch(_,E){G("conditionalBatch conditions",_.length),G("conditionalBatch operations",E.length),await this.#W();let F=z(E),W;for(let J=0;J<Q_;J+=1)try{return await this.#Q(__,async(Y)=>{if(!await s(Y,this.#E,_))return!1;return await v(Y,this.#E,F),!0},(Y)=>Y)}catch(Y){if(!K_(Y))throw Y;W=Y}throw Error(`conditionalBatch exhausted ${Q_} attempts after retryable transaction failures`,{cause:W})}async query(_,E){return await this.#W(),Y_(_),this.#Q(F_,async(F)=>{return(await F.query(_,E??[])).rows})}#U(){if(!this.#Y)return Promise.resolve();return this.#J??=this.#_.end(),this.#J}[Symbol.dispose](){this.#U().catch(()=>{})}async[Symbol.asyncDispose](){await this.#U()}}export{O_ as NeonStorage};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy loader for the optional `better-sqlite3` peer dependency used by
|
|
3
|
+
* {@link NodeSQLiteStorage}. Kept in its own module — and deliberately NOT in the
|
|
4
|
+
* package `exports` map — so the test-only injection seam
|
|
5
|
+
* ({@link loadBetterSqlite3ForTest}) never becomes part of the documented public
|
|
6
|
+
* surface. `node-sqlite.ts` imports `loadBetterSqlite3` (production path);
|
|
7
|
+
* `node-sqlite.test.ts` imports the test entry directly from here.
|
|
8
|
+
*
|
|
9
|
+
* @module storage/node-sqlite-loader
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Minimal `better-sqlite3` `Database` surface this adapter uses. Defined here so
|
|
13
|
+
* both the loader and the storage module compile without the package installed.
|
|
14
|
+
*/
|
|
15
|
+
export type BetterSqliteStatement = {
|
|
16
|
+
run(...parameters: unknown[]): unknown;
|
|
17
|
+
get(...parameters: unknown[]): Record<string, unknown> | undefined;
|
|
18
|
+
all(...parameters: unknown[]): Record<string, unknown>[];
|
|
19
|
+
};
|
|
20
|
+
export type BetterSqliteTransaction = (...args: unknown[]) => unknown;
|
|
21
|
+
export type BetterSqliteDatabase = {
|
|
22
|
+
pragma(source: string): unknown;
|
|
23
|
+
exec(source: string): void;
|
|
24
|
+
prepare(source: string): BetterSqliteStatement;
|
|
25
|
+
transaction(fn: (...args: unknown[]) => unknown): BetterSqliteTransaction;
|
|
26
|
+
close(): void;
|
|
27
|
+
};
|
|
28
|
+
export type BetterSqliteConstructor = new (path: string) => BetterSqliteDatabase;
|
|
29
|
+
/**
|
|
30
|
+
* Build the actionable error thrown when `better-sqlite3` cannot be loaded —
|
|
31
|
+
* either because the optional dependency is absent or its native binding fails
|
|
32
|
+
* to dlopen.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createMissingBetterSqlite3Error(cause: unknown): Error;
|
|
35
|
+
/**
|
|
36
|
+
* Whether `error` is a recognizable `better-sqlite3` load failure (missing
|
|
37
|
+
* package or native-binding dlopen failure) worth reshaping into the actionable
|
|
38
|
+
* peer-dependency error rather than re-throwing raw.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isBetterSqlite3LoadFailure(error: unknown): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve the `better-sqlite3` module via a CommonJS require. This package is
|
|
43
|
+
* ESM (`type: module`), so the global `require` is not defined — `createRequire`
|
|
44
|
+
* from `node:module` builds a CommonJS require for loading the native binding.
|
|
45
|
+
*
|
|
46
|
+
* Extracted as a standalone function so tests can inject a throwing resolver
|
|
47
|
+
* (see {@link loadBetterSqlite3ForTest}) to exercise the missing/failed-dependency
|
|
48
|
+
* paths WITHOUT `mock.module('node:module', ...)`. That mock is irreversible in
|
|
49
|
+
* Bun: it patches the CJS loader process-wide and `mock.restore()` does not undo
|
|
50
|
+
* it, which poisons `require()` for every later test in the same process
|
|
51
|
+
* (notably any WASM module that requires a core module during boot).
|
|
52
|
+
*/
|
|
53
|
+
declare function resolveBetterSqlite3Module(): {
|
|
54
|
+
default?: BetterSqliteConstructor;
|
|
55
|
+
} & BetterSqliteConstructor;
|
|
56
|
+
/** Resolver for the `better-sqlite3` module. Injectable for tests. */
|
|
57
|
+
type BetterSqlite3ModuleResolver = typeof resolveBetterSqlite3Module;
|
|
58
|
+
/**
|
|
59
|
+
* Load (and cache) the `better-sqlite3` constructor. Reshapes a recognized load
|
|
60
|
+
* failure into the actionable peer-dependency error.
|
|
61
|
+
*/
|
|
62
|
+
export declare function loadBetterSqlite3(resolveModule?: BetterSqlite3ModuleResolver): BetterSqliteConstructor;
|
|
63
|
+
/**
|
|
64
|
+
* Test-only entry that exercises {@link loadBetterSqlite3}'s module-resolution
|
|
65
|
+
* and error-shaping with an injected resolver, bypassing the cached constructor
|
|
66
|
+
* so the missing/failed-dependency paths run every call. This lets those paths be
|
|
67
|
+
* tested without mocking the global `node:module` loader. Lives in this
|
|
68
|
+
* non-exported module so it never reaches the public package surface.
|
|
69
|
+
*/
|
|
70
|
+
export declare function loadBetterSqlite3ForTest(resolveModule: BetterSqlite3ModuleResolver): BetterSqliteConstructor;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
let DatabaseConstructor;
|
|
3
|
+
export function createMissingBetterSqlite3Error(cause) {
|
|
4
|
+
return Error('NodeSQLiteStorage requires the optional peer dependency "better-sqlite3". Install it in your application with: bun add better-sqlite3 (or npm install better-sqlite3).', { cause });
|
|
5
|
+
}
|
|
6
|
+
export function isBetterSqlite3LoadFailure(error) {
|
|
7
|
+
if (!(error instanceof Error))
|
|
8
|
+
return !1;
|
|
9
|
+
const errorCode = error.code;
|
|
10
|
+
if (errorCode === "MODULE_NOT_FOUND")
|
|
11
|
+
return error.message.includes("'better-sqlite3'") || error.message.includes('"better-sqlite3"') || error.message.includes("'bindings'") || error.message.includes('"bindings"');
|
|
12
|
+
if (errorCode === "ERR_DLOPEN_FAILED")
|
|
13
|
+
return error.message.includes("better-sqlite3");
|
|
14
|
+
return !1;
|
|
15
|
+
}
|
|
16
|
+
function resolveBetterSqlite3Module() {
|
|
17
|
+
return createRequire(import.meta.url)("better-sqlite3");
|
|
18
|
+
}
|
|
19
|
+
export function loadBetterSqlite3(resolveModule = resolveBetterSqlite3Module) {
|
|
20
|
+
if (DatabaseConstructor)
|
|
21
|
+
return DatabaseConstructor;
|
|
22
|
+
let mod;
|
|
23
|
+
try {
|
|
24
|
+
mod = resolveModule();
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if (isBetterSqlite3LoadFailure(error))
|
|
27
|
+
throw createMissingBetterSqlite3Error(error);
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
DatabaseConstructor = typeof mod.default === "function" ? mod.default : mod;
|
|
31
|
+
return DatabaseConstructor;
|
|
32
|
+
}
|
|
33
|
+
export function loadBetterSqlite3ForTest(resolveModule) {
|
|
34
|
+
const previous = DatabaseConstructor;
|
|
35
|
+
DatabaseConstructor = void 0;
|
|
36
|
+
try {
|
|
37
|
+
return loadBetterSqlite3(resolveModule);
|
|
38
|
+
} finally {
|
|
39
|
+
DatabaseConstructor = previous;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -11,25 +11,7 @@
|
|
|
11
11
|
* @module storage/node-sqlite
|
|
12
12
|
*/
|
|
13
13
|
import type { BatchOperation, ConditionalBatchCondition, ScanOptions, Storage, StorageCapabilities } from './interface.ts';
|
|
14
|
-
|
|
15
|
-
* Minimal subset of the `better-sqlite3` API surface that this adapter uses.
|
|
16
|
-
* Defined here so the module compiles without the package installed — the
|
|
17
|
-
* actual dependency is resolved lazily at construction time.
|
|
18
|
-
*/
|
|
19
|
-
type BetterSqliteStatement = {
|
|
20
|
-
run(...parameters: unknown[]): unknown;
|
|
21
|
-
get(...parameters: unknown[]): Record<string, unknown> | undefined;
|
|
22
|
-
all(...parameters: unknown[]): Record<string, unknown>[];
|
|
23
|
-
};
|
|
24
|
-
type BetterSqliteTransaction = (...args: unknown[]) => unknown;
|
|
25
|
-
type BetterSqliteDatabase = {
|
|
26
|
-
pragma(source: string): unknown;
|
|
27
|
-
exec(source: string): void;
|
|
28
|
-
prepare(source: string): BetterSqliteStatement;
|
|
29
|
-
transaction(fn: (...args: unknown[]) => unknown): BetterSqliteTransaction;
|
|
30
|
-
close(): void;
|
|
31
|
-
};
|
|
32
|
-
type BetterSqliteConstructor = new (path: string) => BetterSqliteDatabase;
|
|
14
|
+
import { type BetterSqliteConstructor } from './node-sqlite-loader.ts';
|
|
33
15
|
/**
|
|
34
16
|
* Runtime-neutral alias for the Node SQLite adapter. Consumers that import
|
|
35
17
|
* from `@lostgradient/weft/storage/sqlite` get this class under Node.
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// src/storage/node-sqlite.ts
|
|
3
|
-
import { createRequire } from "module";
|
|
4
|
-
|
|
5
2
|
// src/storage/capabilities.ts
|
|
6
3
|
function requireStorageCapability(storage, capability, featureName) {
|
|
7
4
|
if (!storage.capabilities()[capability]) {
|
|
@@ -49,6 +46,24 @@ async function storageDeleteRangeCore(storage, prefix, options) {
|
|
|
49
46
|
}
|
|
50
47
|
|
|
51
48
|
// src/storage/interface.ts
|
|
49
|
+
var MAX_BATCH_OPERATIONS = 1e4;
|
|
50
|
+
class StorageBatchOperationLimitExceededError extends Error {
|
|
51
|
+
code = "StorageBatchOperationLimitExceededError";
|
|
52
|
+
cap = MAX_BATCH_OPERATIONS;
|
|
53
|
+
count;
|
|
54
|
+
target;
|
|
55
|
+
constructor(target, count) {
|
|
56
|
+
super(`${target} count ${count} exceeds MAX_BATCH_OPERATIONS (${MAX_BATCH_OPERATIONS}).`);
|
|
57
|
+
this.name = "StorageBatchOperationLimitExceededError";
|
|
58
|
+
this.target = target;
|
|
59
|
+
this.count = count;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function assertStorageBatchOperationCount(target, count) {
|
|
63
|
+
if (count > MAX_BATCH_OPERATIONS) {
|
|
64
|
+
throw new StorageBatchOperationLimitExceededError(target, count);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
52
67
|
function resolvePrefixRangeEnd(prefix) {
|
|
53
68
|
return prefix.length > 0 ? prefix.slice(0, -1) + String.fromCharCode(prefix.charCodeAt(prefix.length - 1) + 1) : "\xFF";
|
|
54
69
|
}
|
|
@@ -91,6 +106,8 @@ async function storageDeletePrefix(storage, prefix) {
|
|
|
91
106
|
return storageDeletePrefixCore(storage, prefix);
|
|
92
107
|
}
|
|
93
108
|
async function storageConditionalBatch(storage, conditions, operations) {
|
|
109
|
+
assertStorageBatchOperationCount("conditionalBatch conditions", conditions.length);
|
|
110
|
+
assertStorageBatchOperationCount("conditionalBatch operations", operations.length);
|
|
94
111
|
requireStorageCapability(storage, "conditionalBatch", "storageConditionalBatch");
|
|
95
112
|
if (!storage.conditionalBatch) {
|
|
96
113
|
throw new Error("This storage backend reports conditionalBatch capability but does not implement the conditionalBatch() method.");
|
|
@@ -98,6 +115,44 @@ async function storageConditionalBatch(storage, conditions, operations) {
|
|
|
98
115
|
return storage.conditionalBatch(conditions, operations);
|
|
99
116
|
}
|
|
100
117
|
|
|
118
|
+
// src/storage/node-sqlite-loader.ts
|
|
119
|
+
import { createRequire } from "module";
|
|
120
|
+
var DatabaseConstructor;
|
|
121
|
+
function createMissingBetterSqlite3Error(cause) {
|
|
122
|
+
return new Error('NodeSQLiteStorage requires the optional peer dependency "better-sqlite3". ' + "Install it in your application with: bun add better-sqlite3 (or npm install better-sqlite3).", { cause });
|
|
123
|
+
}
|
|
124
|
+
function isBetterSqlite3LoadFailure(error) {
|
|
125
|
+
if (!(error instanceof Error))
|
|
126
|
+
return false;
|
|
127
|
+
const errorCode = error.code;
|
|
128
|
+
if (errorCode === "MODULE_NOT_FOUND") {
|
|
129
|
+
return error.message.includes("'better-sqlite3'") || error.message.includes('"better-sqlite3"') || error.message.includes("'bindings'") || error.message.includes('"bindings"');
|
|
130
|
+
}
|
|
131
|
+
if (errorCode === "ERR_DLOPEN_FAILED") {
|
|
132
|
+
return error.message.includes("better-sqlite3");
|
|
133
|
+
}
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
function resolveBetterSqlite3Module() {
|
|
137
|
+
const requireFromHere = createRequire(import.meta.url);
|
|
138
|
+
return requireFromHere("better-sqlite3");
|
|
139
|
+
}
|
|
140
|
+
function loadBetterSqlite3(resolveModule = resolveBetterSqlite3Module) {
|
|
141
|
+
if (DatabaseConstructor)
|
|
142
|
+
return DatabaseConstructor;
|
|
143
|
+
let mod;
|
|
144
|
+
try {
|
|
145
|
+
mod = resolveModule();
|
|
146
|
+
} catch (error) {
|
|
147
|
+
if (isBetterSqlite3LoadFailure(error)) {
|
|
148
|
+
throw createMissingBetterSqlite3Error(error);
|
|
149
|
+
}
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
DatabaseConstructor = typeof mod.default === "function" ? mod.default : mod;
|
|
153
|
+
return DatabaseConstructor;
|
|
154
|
+
}
|
|
155
|
+
|
|
101
156
|
// src/storage/sqlite-key-value-queries.ts
|
|
102
157
|
var SQLITE_CREATE_KEY_VALUE_TABLE = `CREATE TABLE IF NOT EXISTS kv (
|
|
103
158
|
key TEXT PRIMARY KEY,
|
|
@@ -178,35 +233,6 @@ function buildSqliteKeyRangeSelect(prefix, options = {}) {
|
|
|
178
233
|
}
|
|
179
234
|
|
|
180
235
|
// src/storage/node-sqlite.ts
|
|
181
|
-
var DatabaseConstructor;
|
|
182
|
-
function createMissingBetterSqlite3Error(cause) {
|
|
183
|
-
return new Error('NodeSQLiteStorage requires the optional peer dependency "better-sqlite3". ' + "Install it in your application with: bun add better-sqlite3 (or npm install better-sqlite3).", { cause });
|
|
184
|
-
}
|
|
185
|
-
function isBetterSqlite3LoadFailure(error) {
|
|
186
|
-
if (!(error instanceof Error))
|
|
187
|
-
return false;
|
|
188
|
-
const errorCode = error.code;
|
|
189
|
-
if (errorCode === "MODULE_NOT_FOUND") {
|
|
190
|
-
return error.message.includes("'better-sqlite3'") || error.message.includes('"better-sqlite3"') || error.message.includes("'bindings'") || error.message.includes('"bindings"');
|
|
191
|
-
}
|
|
192
|
-
if (errorCode === "ERR_DLOPEN_FAILED") {
|
|
193
|
-
return error.message.includes("better-sqlite3");
|
|
194
|
-
}
|
|
195
|
-
return false;
|
|
196
|
-
}
|
|
197
|
-
function loadBetterSqlite3() {
|
|
198
|
-
if (DatabaseConstructor)
|
|
199
|
-
return DatabaseConstructor;
|
|
200
|
-
const requireFromHere = createRequire(import.meta.url);
|
|
201
|
-
let mod;
|
|
202
|
-
try {
|
|
203
|
-
mod = requireFromHere("better-sqlite3");
|
|
204
|
-
} catch (error) {
|
|
205
|
-
throw createMissingBetterSqlite3Error(error);
|
|
206
|
-
}
|
|
207
|
-
DatabaseConstructor = typeof mod.default === "function" ? mod.default : mod;
|
|
208
|
-
return DatabaseConstructor;
|
|
209
|
-
}
|
|
210
236
|
class NodeSQLiteStorage {
|
|
211
237
|
#database;
|
|
212
238
|
#persistence;
|
|
@@ -286,11 +312,14 @@ class NodeSQLiteStorage {
|
|
|
286
312
|
}
|
|
287
313
|
}
|
|
288
314
|
async batch(operations) {
|
|
315
|
+
assertStorageBatchOperationCount("batch operations", operations.length);
|
|
289
316
|
if (operations.length === 0)
|
|
290
317
|
return;
|
|
291
318
|
this.#batchTransaction(operations);
|
|
292
319
|
}
|
|
293
320
|
async conditionalBatch(conditions, operations) {
|
|
321
|
+
assertStorageBatchOperationCount("conditionalBatch conditions", conditions.length);
|
|
322
|
+
assertStorageBatchOperationCount("conditionalBatch operations", operations.length);
|
|
294
323
|
const conditionalTransaction = this.#database.transaction((...arguments_) => {
|
|
295
324
|
const pendingConditions = arguments_[0];
|
|
296
325
|
const pendingOperations = arguments_[1];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { NormalizedDeleteRangeOptions } from './delete-range.ts';
|
|
2
|
+
import { type ScanOptions } from './interface.ts';
|
|
3
|
+
/**
|
|
4
|
+
* The Postgres counterpart of `sqlite-key-value-queries.ts`. The schema is the
|
|
5
|
+
* same single `kv(key, value)` table, but two Postgres specifics differ from the
|
|
6
|
+
* SQLite builders and force a separate module:
|
|
7
|
+
*
|
|
8
|
+
* - **Numbered placeholders.** Postgres binds parameters as `$1`, `$2`, … in
|
|
9
|
+
* statement order, not the positional `?` SQLite uses. A builder that appends
|
|
10
|
+
* bounds dynamically must therefore track the next placeholder index.
|
|
11
|
+
* - **`COLLATE "C"` on the key.** Postgres `TEXT` sorts by the database locale,
|
|
12
|
+
* which reorders punctuation and would silently corrupt every prefix-range
|
|
13
|
+
* scan and `ORDER BY key` the engine relies on. Pinning the primary-key column
|
|
14
|
+
* to the `C` collation restores byte-wise (codepoint) ordering, matching
|
|
15
|
+
* SQLite's default `BINARY` collation and the engine's key-layout assumptions.
|
|
16
|
+
*
|
|
17
|
+
* Every query is parameterized by a **table reference** so the adapter can point
|
|
18
|
+
* at a configured `"schema"."table"` instead of the default unqualified `kv`
|
|
19
|
+
* (see {@link buildPostgresKeyValueQueries}). The reference is interpolated once
|
|
20
|
+
* at construction, not per query.
|
|
21
|
+
*
|
|
22
|
+
* @module storage/postgres-key-value-queries
|
|
23
|
+
*/
|
|
24
|
+
/** The default unqualified table reference (resolves through `search_path`). */
|
|
25
|
+
export declare const DEFAULT_POSTGRES_TABLE_REFERENCE = "kv";
|
|
26
|
+
/**
|
|
27
|
+
* Validate a Postgres identifier (schema or table name) against a strict
|
|
28
|
+
* `[a-z_][a-z0-9_]*` pattern. Identifiers cannot be bound as `$n` parameters, so
|
|
29
|
+
* they must be interpolated into the SQL text — this validation, run once at
|
|
30
|
+
* construction, is the injection guard that makes interpolation safe. The strict
|
|
31
|
+
* pattern excludes the `"` quote character, so no quote-doubling is required.
|
|
32
|
+
*/
|
|
33
|
+
export declare function assertPostgresIdentifier(value: string, role: 'schema' | 'table'): void;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve the SQL table reference from optional schema/table names. With neither
|
|
36
|
+
* set, returns the bare unqualified `kv` so existing deployments emit
|
|
37
|
+
* byte-identical SQL (the default search-path-resolved table). With either set,
|
|
38
|
+
* returns a fully quoted `"schema"."table"` reference; both names are validated
|
|
39
|
+
* as strict identifiers first so the interpolation is injection-safe.
|
|
40
|
+
*/
|
|
41
|
+
export declare function resolvePostgresTableReference(options: {
|
|
42
|
+
schema?: string | undefined;
|
|
43
|
+
table?: string | undefined;
|
|
44
|
+
}): string;
|
|
45
|
+
export type PostgresKeyRangeQueryParameter = string | number;
|
|
46
|
+
/** A fully-built SQL statement and its bound parameters (SELECT or DELETE). */
|
|
47
|
+
export type PostgresBuiltQuery = {
|
|
48
|
+
parameters: PostgresKeyRangeQueryParameter[];
|
|
49
|
+
sql: string;
|
|
50
|
+
};
|
|
51
|
+
export declare function buildPostgresPrefixRangeParameters(prefix: string): [string, string];
|
|
52
|
+
/**
|
|
53
|
+
* The complete set of SQL statements an adapter instance runs, all bound to one
|
|
54
|
+
* `tableReference`. Built once per {@link NeonStorage} via
|
|
55
|
+
* {@link buildPostgresKeyValueQueries}; the range builders close over the
|
|
56
|
+
* reference so callers never re-pass it.
|
|
57
|
+
*/
|
|
58
|
+
export type PostgresKeyValueQueries = {
|
|
59
|
+
readonly tableReference: string;
|
|
60
|
+
readonly createTable: string;
|
|
61
|
+
readonly selectKeyCollation: string;
|
|
62
|
+
readonly selectValueByKey: string;
|
|
63
|
+
readonly upsertValueByKey: string;
|
|
64
|
+
readonly deleteValueByKey: string;
|
|
65
|
+
readonly selectKeyPresence: string;
|
|
66
|
+
readonly countKeysByPrefix: string;
|
|
67
|
+
readonly deleteKeysByPrefix: string;
|
|
68
|
+
/** One-statement condition read for `conditionalBatch`: `key = ANY($1)`. */
|
|
69
|
+
readonly selectValuesByKeys: string;
|
|
70
|
+
/** One-statement multi-row upsert for `batch`: `unnest($1::text[], $2::bytea[])`. */
|
|
71
|
+
readonly upsertValuesByKeys: string;
|
|
72
|
+
/** One-statement delete for `batch`: `key = ANY($1)`. */
|
|
73
|
+
readonly deleteValuesByKeys: string;
|
|
74
|
+
keyValueRangeSelect(prefix: string, options?: ScanOptions): PostgresBuiltQuery;
|
|
75
|
+
keyRangeSelect(prefix: string, options?: ScanOptions): PostgresBuiltQuery;
|
|
76
|
+
keyRangeDelete(prefix: string, options: NormalizedDeleteRangeOptions): PostgresBuiltQuery;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Build the full query set for a `kv`-shaped table at `tableReference` (either
|
|
80
|
+
* the bare unqualified `kv` or a quoted `"schema"."table"`). The reference is
|
|
81
|
+
* already validated/quoted by {@link resolvePostgresTableReference}; this only
|
|
82
|
+
* interpolates it into statement text.
|
|
83
|
+
*
|
|
84
|
+
* The collation check uses `to_regclass($1)` with the resolved reference so it
|
|
85
|
+
* is scoped to the configured table — a `kv` table elsewhere on the search path
|
|
86
|
+
* can never be inspected by mistake.
|
|
87
|
+
*/
|
|
88
|
+
export declare function buildPostgresKeyValueQueries(tableReference: string): PostgresKeyValueQueries;
|
|
89
|
+
/** Begin a transaction at SERIALIZABLE isolation (conditionalBatch's CAS path). */
|
|
90
|
+
export declare const PG_BEGIN_SERIALIZABLE = "BEGIN ISOLATION LEVEL SERIALIZABLE";
|
|
91
|
+
/** Begin a transaction at READ COMMITTED isolation (the atomic batch() path). */
|
|
92
|
+
export declare const PG_BEGIN_READ_COMMITTED = "BEGIN ISOLATION LEVEL READ COMMITTED";
|
|
93
|
+
/**
|
|
94
|
+
* Begin a READ ONLY transaction for the `query()` passthrough. Postgres enforces
|
|
95
|
+
* this at the database level — a writing statement (including a data-modifying
|
|
96
|
+
* CTE that a textual SELECT check would miss) errors instead of mutating.
|
|
97
|
+
*/
|
|
98
|
+
export declare const PG_BEGIN_READ_ONLY = "BEGIN READ ONLY";
|
|
99
|
+
/** Commit the current transaction. */
|
|
100
|
+
export declare const PG_COMMIT = "COMMIT";
|
|
101
|
+
/** Roll back the current transaction. */
|
|
102
|
+
export declare const PG_ROLLBACK = "ROLLBACK";
|
|
103
|
+
/** Create the configured schema if it is absent (only when a schema is set). */
|
|
104
|
+
export declare function buildPostgresCreateSchema(schema: string): string;
|