@workflow/core 5.0.0-beta.3 → 5.0.0-beta.31
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/dist/attribute-changes.d.ts +7 -0
- package/dist/attribute-changes.d.ts.map +1 -0
- package/dist/attribute-changes.js +25 -0
- package/dist/capabilities.d.ts +22 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +41 -4
- package/dist/capture-stack.d.ts +16 -0
- package/dist/capture-stack.d.ts.map +1 -0
- package/dist/capture-stack.js +21 -0
- package/dist/class-serialization.d.ts +32 -0
- package/dist/class-serialization.d.ts.map +1 -1
- package/dist/class-serialization.js +37 -1
- package/dist/classify-error.d.ts +26 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +103 -6
- package/dist/context-errors.d.ts +27 -0
- package/dist/context-errors.d.ts.map +1 -0
- package/dist/context-errors.js +101 -0
- package/dist/context-violation-error.d.ts +97 -0
- package/dist/context-violation-error.d.ts.map +1 -0
- package/dist/context-violation-error.js +147 -0
- package/dist/create-hook.d.ts +42 -3
- package/dist/create-hook.d.ts.map +1 -1
- package/dist/create-hook.js +4 -3
- package/dist/define-hook.d.ts.map +1 -1
- package/dist/define-hook.js +20 -5
- package/dist/describe-error.d.ts +70 -0
- package/dist/describe-error.d.ts.map +1 -0
- package/dist/describe-error.js +165 -0
- package/dist/encryption.d.ts +22 -1
- package/dist/encryption.d.ts.map +1 -1
- package/dist/encryption.js +72 -27
- package/dist/events-consumer.d.ts +25 -1
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +95 -16
- package/dist/flushable-stream.d.ts +10 -10
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +26 -15
- package/dist/global.d.ts +35 -1
- package/dist/global.d.ts.map +1 -1
- package/dist/global.js +21 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/log-format.d.ts +25 -0
- package/dist/log-format.d.ts.map +1 -0
- package/dist/log-format.js +250 -0
- package/dist/logger.d.ts +29 -30
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +82 -32
- package/dist/private.d.ts +107 -2
- package/dist/private.d.ts.map +1 -1
- package/dist/private.js +80 -3
- package/dist/runtime/constants.d.ts +189 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +310 -15
- package/dist/runtime/get-port-lazy.d.ts +25 -0
- package/dist/runtime/get-port-lazy.d.ts.map +1 -0
- package/dist/runtime/get-port-lazy.js +92 -0
- package/dist/runtime/get-world-lazy.d.ts +23 -0
- package/dist/runtime/get-world-lazy.d.ts.map +1 -0
- package/dist/runtime/get-world-lazy.js +46 -0
- package/dist/runtime/helpers.d.ts +57 -6
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +169 -32
- package/dist/runtime/replay-budget.d.ts +98 -0
- package/dist/runtime/replay-budget.d.ts.map +1 -0
- package/dist/runtime/replay-budget.js +192 -0
- package/dist/runtime/resume-hook.d.ts.map +1 -1
- package/dist/runtime/resume-hook.js +39 -23
- package/dist/runtime/run-id-time.d.ts +10 -0
- package/dist/runtime/run-id-time.d.ts.map +1 -0
- package/dist/runtime/run-id-time.js +31 -0
- package/dist/runtime/run.d.ts +6 -2
- package/dist/runtime/run.d.ts.map +1 -1
- package/dist/runtime/run.js +52 -10
- package/dist/runtime/runs.d.ts +36 -2
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +18 -7
- package/dist/runtime/start.d.ts +58 -1
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +160 -46
- package/dist/runtime/step-executor.d.ts +131 -0
- package/dist/runtime/step-executor.d.ts.map +1 -0
- package/dist/runtime/step-executor.js +818 -0
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +718 -557
- package/dist/runtime/step-latency.d.ts +131 -0
- package/dist/runtime/step-latency.d.ts.map +1 -0
- package/dist/runtime/step-latency.js +155 -0
- package/dist/runtime/step-ownership.d.ts +72 -0
- package/dist/runtime/step-ownership.d.ts.map +1 -0
- package/dist/runtime/step-ownership.js +114 -0
- package/dist/runtime/step-single-flight.d.ts +12 -0
- package/dist/runtime/step-single-flight.d.ts.map +1 -0
- package/dist/runtime/step-single-flight.js +69 -0
- package/dist/runtime/suspension-handler.d.ts +81 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +355 -137
- package/dist/runtime/wait-continuation.d.ts +84 -0
- package/dist/runtime/wait-continuation.d.ts.map +1 -0
- package/dist/runtime/wait-continuation.js +105 -0
- package/dist/runtime/wait-until.d.ts +18 -0
- package/dist/runtime/wait-until.d.ts.map +1 -0
- package/dist/runtime/wait-until.js +42 -0
- package/dist/runtime/world-compatibility.d.ts +5 -0
- package/dist/runtime/world-compatibility.d.ts.map +1 -0
- package/dist/runtime/world-compatibility.js +12 -0
- package/dist/runtime/world-init.d.ts +50 -0
- package/dist/runtime/world-init.d.ts.map +1 -0
- package/dist/runtime/world-init.js +50 -0
- package/dist/runtime/world-target.d.ts +11 -0
- package/dist/runtime/world-target.d.ts.map +1 -0
- package/dist/runtime/world-target.js +15 -0
- package/dist/runtime/world.d.ts +21 -9
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +58 -83
- package/dist/runtime.d.ts +15 -10
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1757 -326
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +1 -1
- package/dist/serialization/client.d.ts +17 -0
- package/dist/serialization/client.d.ts.map +1 -0
- package/dist/serialization/client.js +48 -0
- package/dist/serialization/codec-devalue.d.ts +14 -0
- package/dist/serialization/codec-devalue.d.ts.map +1 -0
- package/dist/serialization/codec-devalue.js +98 -0
- package/dist/serialization/codec.d.ts +106 -0
- package/dist/serialization/codec.d.ts.map +1 -0
- package/dist/serialization/codec.js +17 -0
- package/dist/serialization/compression.d.ts +104 -0
- package/dist/serialization/compression.d.ts.map +1 -0
- package/dist/serialization/compression.js +260 -0
- package/dist/serialization/encryption.d.ts +33 -0
- package/dist/serialization/encryption.d.ts.map +1 -0
- package/dist/serialization/encryption.js +70 -0
- package/dist/serialization/errors.d.ts +34 -0
- package/dist/serialization/errors.d.ts.map +1 -0
- package/dist/serialization/errors.js +59 -0
- package/dist/serialization/format.d.ts +60 -0
- package/dist/serialization/format.d.ts.map +1 -0
- package/dist/serialization/format.js +97 -0
- package/dist/serialization/index.d.ts +19 -0
- package/dist/serialization/index.d.ts.map +1 -0
- package/dist/serialization/index.js +22 -0
- package/dist/serialization/reducers/class.d.ts +11 -0
- package/dist/serialization/reducers/class.d.ts.map +1 -0
- package/dist/serialization/reducers/class.js +68 -0
- package/dist/serialization/reducers/common.d.ts +16 -0
- package/dist/serialization/reducers/common.d.ts.map +1 -0
- package/dist/serialization/reducers/common.js +417 -0
- package/dist/serialization/reducers/step-function.d.ts +35 -0
- package/dist/serialization/reducers/step-function.d.ts.map +1 -0
- package/dist/serialization/reducers/step-function.js +88 -0
- package/dist/serialization/step.d.ts +17 -0
- package/dist/serialization/step.d.ts.map +1 -0
- package/dist/serialization/step.js +48 -0
- package/dist/serialization/types.d.ts +253 -0
- package/dist/serialization/types.d.ts.map +1 -0
- package/dist/serialization/types.js +25 -0
- package/dist/serialization/workflow.d.ts +29 -0
- package/dist/serialization/workflow.d.ts.map +1 -0
- package/dist/serialization/workflow.js +54 -0
- package/dist/serialization-format.d.ts +16 -0
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +213 -50
- package/dist/serialization.d.ts +322 -214
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +1575 -664
- package/dist/set-attributes.d.ts +18 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +61 -0
- package/dist/sleep.d.ts.map +1 -1
- package/dist/sleep.js +3 -2
- package/dist/source-map.d.ts +5 -0
- package/dist/source-map.d.ts.map +1 -1
- package/dist/source-map.js +102 -10
- package/dist/step/context-storage.d.ts +53 -0
- package/dist/step/context-storage.d.ts.map +1 -1
- package/dist/step/context-storage.js +1 -1
- package/dist/step/get-closure-vars.d.ts.map +1 -1
- package/dist/step/get-closure-vars.js +3 -2
- package/dist/step/get-step-metadata.d.ts.map +1 -1
- package/dist/step/get-step-metadata.js +3 -2
- package/dist/step/get-workflow-metadata.d.ts.map +1 -1
- package/dist/step/get-workflow-metadata.js +3 -2
- package/dist/step/writable-stream.d.ts.map +1 -1
- package/dist/step/writable-stream.js +58 -6
- package/dist/step-hydration-cache.d.ts +148 -0
- package/dist/step-hydration-cache.d.ts.map +1 -0
- package/dist/step-hydration-cache.js +171 -0
- package/dist/step.d.ts.map +1 -1
- package/dist/step.js +144 -25
- package/dist/symbols.d.ts +28 -0
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +29 -1
- package/dist/telemetry/semantic-conventions.d.ts +98 -2
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +66 -1
- package/dist/telemetry.d.ts +68 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +106 -4
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +23 -1
- package/dist/util.d.ts +16 -6
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +25 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +2 -2
- package/dist/vm/index.d.ts.map +1 -1
- package/dist/vm/index.js +3 -2
- package/dist/vm/script-cache.d.ts +28 -0
- package/dist/vm/script-cache.d.ts.map +1 -0
- package/dist/vm/script-cache.js +140 -0
- package/dist/workflow/abort-controller.d.ts +65 -0
- package/dist/workflow/abort-controller.d.ts.map +1 -0
- package/dist/workflow/abort-controller.js +277 -0
- package/dist/workflow/attribute-dispatcher.d.ts +6 -0
- package/dist/workflow/attribute-dispatcher.d.ts.map +1 -0
- package/dist/workflow/attribute-dispatcher.js +48 -0
- package/dist/workflow/create-hook.d.ts.map +1 -1
- package/dist/workflow/create-hook.js +25 -3
- package/dist/workflow/define-hook.d.ts +1 -1
- package/dist/workflow/define-hook.d.ts.map +1 -1
- package/dist/workflow/define-hook.js +8 -4
- package/dist/workflow/get-workflow-metadata.d.ts.map +1 -1
- package/dist/workflow/get-workflow-metadata.js +14 -3
- package/dist/workflow/hook.d.ts.map +1 -1
- package/dist/workflow/hook.js +207 -33
- package/dist/workflow/index.d.ts +1 -0
- package/dist/workflow/index.d.ts.map +1 -1
- package/dist/workflow/index.js +5 -3
- package/dist/workflow/set-attributes.d.ts +77 -0
- package/dist/workflow/set-attributes.d.ts.map +1 -0
- package/dist/workflow/set-attributes.js +65 -0
- package/dist/workflow/sleep.d.ts.map +1 -1
- package/dist/workflow/sleep.js +45 -8
- package/dist/workflow/world-init-stub.d.ts +15 -0
- package/dist/workflow/world-init-stub.d.ts.map +1 -0
- package/dist/workflow/world-init-stub.js +15 -0
- package/dist/workflow.d.ts +17 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +190 -56
- package/docs/api-reference/create-hook.mdx +38 -0
- package/docs/api-reference/create-webhook.mdx +1 -0
- package/docs/api-reference/fetch.mdx +5 -0
- package/docs/api-reference/index.mdx +3 -0
- package/docs/api-reference/set-attributes.mdx +65 -0
- package/docs/foundations/cancellation.mdx +459 -0
- package/docs/foundations/errors-and-retries.mdx +7 -3
- package/docs/foundations/hooks.mdx +29 -0
- package/docs/foundations/idempotency.mdx +236 -11
- package/docs/foundations/index.mdx +1 -23
- package/docs/foundations/meta.json +3 -1
- package/docs/foundations/serialization.mdx +77 -41
- package/docs/foundations/starting-workflows.mdx +5 -1
- package/docs/foundations/streaming.mdx +14 -23
- package/docs/foundations/versioning.mdx +263 -0
- package/docs/how-it-works/cancellation.mdx +287 -0
- package/docs/how-it-works/code-transform.mdx +2 -2
- package/docs/how-it-works/encryption.mdx +2 -2
- package/docs/how-it-works/event-sourcing.mdx +2 -2
- package/docs/how-it-works/meta.json +2 -1
- package/package.json +32 -11
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wait-continuation dispatch: delay + idempotency-key selection.
|
|
3
|
+
*
|
|
4
|
+
* When V2 suspension processing observes a pending wait, it enqueues a
|
|
5
|
+
* delayed "continuation" message that fires once the wait elapses and
|
|
6
|
+
* drives the next replay (which completes the wait via the "complete
|
|
7
|
+
* elapsed waits" pass). This module decides the message's `delaySeconds`
|
|
8
|
+
* and `idempotencyKey`.
|
|
9
|
+
*
|
|
10
|
+
* The continuation is keyed on the wait's correlationId: while a wait is
|
|
11
|
+
* pending, every replay pass over the run re-observes it (e.g., once per
|
|
12
|
+
* step completion in `Promise.all([steps..., sleep()])`), and without
|
|
13
|
+
* dedupe each pass would enqueue another delayed continuation — each one
|
|
14
|
+
* a spurious full replay when the wait elapses, and each a fresh message
|
|
15
|
+
* that resets the delivery-attempt runaway guard. A key is attached in
|
|
16
|
+
* all cases: some worlds (e.g. world-postgres) serialize key-less
|
|
17
|
+
* workflow messages per run, which would park the continuation behind
|
|
18
|
+
* the handler's own inline step execution and defeat the race semantics
|
|
19
|
+
* the continuation exists to provide.
|
|
20
|
+
*
|
|
21
|
+
* The bare correlationId cannot be the key in every case, though: world
|
|
22
|
+
* dedupe windows outlive the first delivery (VQS keeps idempotency
|
|
23
|
+
* records until message-retention TTL; world-postgres keeps a
|
|
24
|
+
* completed-keys cache), so once a key has been used, a later enqueue
|
|
25
|
+
* under the same key is silently dropped. Any situation where a
|
|
26
|
+
* continuation is delivered while its wait is still pending therefore
|
|
27
|
+
* needs a fresh key for the re-enqueue, or the wait's timer is lost and
|
|
28
|
+
* the run stalls until unrelated traffic happens to wake it. Two such
|
|
29
|
+
* situations exist, each with its own key variation:
|
|
30
|
+
*
|
|
31
|
+
* - Waits longer than the maximum queue delay are chained: the delay is
|
|
32
|
+
* clamped to `WAIT_CONTINUATION_MAX_DELAY_SECONDS` (23h — VQS messages
|
|
33
|
+
* have a 24h retention limit, and one hour of buffer matches
|
|
34
|
+
* world-vercel's own clamp for delayed re-enqueues), so the
|
|
35
|
+
* continuation intentionally fires early, re-observes the wait, and
|
|
36
|
+
* must enqueue the next hop. The key is suffixed with the hop index
|
|
37
|
+
* (`ceil(timeoutSeconds / maxDelay)`): stable for every re-observation
|
|
38
|
+
* within the same hop window (so passes dedupe), decremented at each
|
|
39
|
+
* hop delivery (so the chain always advances). Worlds without a delay
|
|
40
|
+
* limit (world-postgres, world-local) simply take the same ≤23h hops.
|
|
41
|
+
*
|
|
42
|
+
* - Near-elapsed waits (≤2s remaining) get a second-bucketed suffix. A
|
|
43
|
+
* continuation delivered marginally early (clock skew between the
|
|
44
|
+
* enqueuing and handling hosts; the ceil() on the delay can leave a ~0
|
|
45
|
+
* margin) re-observes the wait as pending with ~1s remaining and must
|
|
46
|
+
* be able to enqueue a fresh short-delay retry. The bucket suffix
|
|
47
|
+
* keeps that retry enqueueable (its ≥1s delay guarantees a later
|
|
48
|
+
* bucket) while still collapsing same-instant duplicates.
|
|
49
|
+
*
|
|
50
|
+
* Mid-range waits (more than the near-elapsed threshold, at most one
|
|
51
|
+
* hop) use the bare correlationId: every re-observation targets the same
|
|
52
|
+
* deadline, so deduping to the first message is semantically lossless.
|
|
53
|
+
* Host clock skew beyond the near-elapsed threshold could in principle
|
|
54
|
+
* deliver such a continuation early enough to re-observe its wait and
|
|
55
|
+
* lose the re-enqueue to the burnt key; the threshold is the skew
|
|
56
|
+
* tolerance we accept for the benefit of exactly-one continuation per
|
|
57
|
+
* wait.
|
|
58
|
+
*/
|
|
59
|
+
/**
|
|
60
|
+
* Maximum `delaySeconds` for a single wait-continuation message. Waits
|
|
61
|
+
* longer than this are chained across multiple hops. 23 hours leaves a 1h
|
|
62
|
+
* buffer under Vercel Queues' default 24h message TTL and mirrors
|
|
63
|
+
* world-vercel's `MAX_DELAY_SECONDS`.
|
|
64
|
+
*/
|
|
65
|
+
export declare const WAIT_CONTINUATION_MAX_DELAY_SECONDS = 82800;
|
|
66
|
+
/**
|
|
67
|
+
* Waits with at most this many seconds remaining use a second-bucketed
|
|
68
|
+
* idempotency key so an early-delivered continuation can re-enqueue its
|
|
69
|
+
* short-delay retry. This is also the host clock-skew tolerance for
|
|
70
|
+
* mid-range waits keyed on the bare correlationId.
|
|
71
|
+
*/
|
|
72
|
+
export declare const NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS = 2;
|
|
73
|
+
export interface WaitContinuationDispatch {
|
|
74
|
+
delaySeconds: number;
|
|
75
|
+
idempotencyKey: string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Computes the queue delay and idempotency key for a wait-continuation
|
|
79
|
+
* message. `timeoutSeconds` is the time until the wait's `resumeAt`
|
|
80
|
+
* (floored at 1s by the suspension handler); `waitCorrelationId`
|
|
81
|
+
* identifies the wait so repeated suspension passes dedupe.
|
|
82
|
+
*/
|
|
83
|
+
export declare function getWaitContinuationDispatch(timeoutSeconds: number, waitCorrelationId: string, now?: number): WaitContinuationDispatch;
|
|
84
|
+
//# sourceMappingURL=wait-continuation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-continuation.d.ts","sourceRoot":"","sources":["../../src/runtime/wait-continuation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAIH;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,QAAS,CAAC;AAE1D;;;;;GAKG;AACH,eAAO,MAAM,mCAAmC,IAAI,CAAC;AAiBrD,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,MAAM,EACzB,GAAG,GAAE,MAAmB,GACvB,wBAAwB,CAyB1B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wait-continuation dispatch: delay + idempotency-key selection.
|
|
3
|
+
*
|
|
4
|
+
* When V2 suspension processing observes a pending wait, it enqueues a
|
|
5
|
+
* delayed "continuation" message that fires once the wait elapses and
|
|
6
|
+
* drives the next replay (which completes the wait via the "complete
|
|
7
|
+
* elapsed waits" pass). This module decides the message's `delaySeconds`
|
|
8
|
+
* and `idempotencyKey`.
|
|
9
|
+
*
|
|
10
|
+
* The continuation is keyed on the wait's correlationId: while a wait is
|
|
11
|
+
* pending, every replay pass over the run re-observes it (e.g., once per
|
|
12
|
+
* step completion in `Promise.all([steps..., sleep()])`), and without
|
|
13
|
+
* dedupe each pass would enqueue another delayed continuation — each one
|
|
14
|
+
* a spurious full replay when the wait elapses, and each a fresh message
|
|
15
|
+
* that resets the delivery-attempt runaway guard. A key is attached in
|
|
16
|
+
* all cases: some worlds (e.g. world-postgres) serialize key-less
|
|
17
|
+
* workflow messages per run, which would park the continuation behind
|
|
18
|
+
* the handler's own inline step execution and defeat the race semantics
|
|
19
|
+
* the continuation exists to provide.
|
|
20
|
+
*
|
|
21
|
+
* The bare correlationId cannot be the key in every case, though: world
|
|
22
|
+
* dedupe windows outlive the first delivery (VQS keeps idempotency
|
|
23
|
+
* records until message-retention TTL; world-postgres keeps a
|
|
24
|
+
* completed-keys cache), so once a key has been used, a later enqueue
|
|
25
|
+
* under the same key is silently dropped. Any situation where a
|
|
26
|
+
* continuation is delivered while its wait is still pending therefore
|
|
27
|
+
* needs a fresh key for the re-enqueue, or the wait's timer is lost and
|
|
28
|
+
* the run stalls until unrelated traffic happens to wake it. Two such
|
|
29
|
+
* situations exist, each with its own key variation:
|
|
30
|
+
*
|
|
31
|
+
* - Waits longer than the maximum queue delay are chained: the delay is
|
|
32
|
+
* clamped to `WAIT_CONTINUATION_MAX_DELAY_SECONDS` (23h — VQS messages
|
|
33
|
+
* have a 24h retention limit, and one hour of buffer matches
|
|
34
|
+
* world-vercel's own clamp for delayed re-enqueues), so the
|
|
35
|
+
* continuation intentionally fires early, re-observes the wait, and
|
|
36
|
+
* must enqueue the next hop. The key is suffixed with the hop index
|
|
37
|
+
* (`ceil(timeoutSeconds / maxDelay)`): stable for every re-observation
|
|
38
|
+
* within the same hop window (so passes dedupe), decremented at each
|
|
39
|
+
* hop delivery (so the chain always advances). Worlds without a delay
|
|
40
|
+
* limit (world-postgres, world-local) simply take the same ≤23h hops.
|
|
41
|
+
*
|
|
42
|
+
* - Near-elapsed waits (≤2s remaining) get a second-bucketed suffix. A
|
|
43
|
+
* continuation delivered marginally early (clock skew between the
|
|
44
|
+
* enqueuing and handling hosts; the ceil() on the delay can leave a ~0
|
|
45
|
+
* margin) re-observes the wait as pending with ~1s remaining and must
|
|
46
|
+
* be able to enqueue a fresh short-delay retry. The bucket suffix
|
|
47
|
+
* keeps that retry enqueueable (its ≥1s delay guarantees a later
|
|
48
|
+
* bucket) while still collapsing same-instant duplicates.
|
|
49
|
+
*
|
|
50
|
+
* Mid-range waits (more than the near-elapsed threshold, at most one
|
|
51
|
+
* hop) use the bare correlationId: every re-observation targets the same
|
|
52
|
+
* deadline, so deduping to the first message is semantically lossless.
|
|
53
|
+
* Host clock skew beyond the near-elapsed threshold could in principle
|
|
54
|
+
* deliver such a continuation early enough to re-observe its wait and
|
|
55
|
+
* lose the re-enqueue to the burnt key; the threshold is the skew
|
|
56
|
+
* tolerance we accept for the benefit of exactly-one continuation per
|
|
57
|
+
* wait.
|
|
58
|
+
*/
|
|
59
|
+
import { envNumber } from '@workflow/world';
|
|
60
|
+
/**
|
|
61
|
+
* Maximum `delaySeconds` for a single wait-continuation message. Waits
|
|
62
|
+
* longer than this are chained across multiple hops. 23 hours leaves a 1h
|
|
63
|
+
* buffer under Vercel Queues' default 24h message TTL and mirrors
|
|
64
|
+
* world-vercel's `MAX_DELAY_SECONDS`.
|
|
65
|
+
*/
|
|
66
|
+
export const WAIT_CONTINUATION_MAX_DELAY_SECONDS = 82_800;
|
|
67
|
+
/**
|
|
68
|
+
* Waits with at most this many seconds remaining use a second-bucketed
|
|
69
|
+
* idempotency key so an early-delivered continuation can re-enqueue its
|
|
70
|
+
* short-delay retry. This is also the host clock-skew tolerance for
|
|
71
|
+
* mid-range waits keyed on the bare correlationId.
|
|
72
|
+
*/
|
|
73
|
+
export const NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS = 2;
|
|
74
|
+
/** Effective max continuation delay. Override: `WORKFLOW_WAIT_CONTINUATION_MAX_DELAY_SECONDS`. */
|
|
75
|
+
const getWaitContinuationMaxDelaySeconds = () => envNumber('WORKFLOW_WAIT_CONTINUATION_MAX_DELAY_SECONDS', WAIT_CONTINUATION_MAX_DELAY_SECONDS, { integer: true, min: 1 });
|
|
76
|
+
/** Effective near-elapsed threshold. Override: `WORKFLOW_NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS`. */
|
|
77
|
+
const getNearElapsedWaitThresholdSeconds = () => envNumber('WORKFLOW_NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS', NEAR_ELAPSED_WAIT_THRESHOLD_SECONDS);
|
|
78
|
+
/**
|
|
79
|
+
* Computes the queue delay and idempotency key for a wait-continuation
|
|
80
|
+
* message. `timeoutSeconds` is the time until the wait's `resumeAt`
|
|
81
|
+
* (floored at 1s by the suspension handler); `waitCorrelationId`
|
|
82
|
+
* identifies the wait so repeated suspension passes dedupe.
|
|
83
|
+
*/
|
|
84
|
+
export function getWaitContinuationDispatch(timeoutSeconds, waitCorrelationId, now = Date.now()) {
|
|
85
|
+
const maxDelaySeconds = getWaitContinuationMaxDelaySeconds();
|
|
86
|
+
// The near-elapsed branch returns the full remaining time as the delay, so
|
|
87
|
+
// its threshold can never exceed the max delay — otherwise a wait between the
|
|
88
|
+
// max and the threshold would be dispatched with a delay above the max. Cap
|
|
89
|
+
// the threshold at the max so every branch yields a delay within it. (With
|
|
90
|
+
// defaults — threshold 2s, max 82_800s — this is a no-op; it only bites when
|
|
91
|
+
// the max is tuned down below the threshold for testing.)
|
|
92
|
+
const nearElapsedThreshold = Math.min(getNearElapsedWaitThresholdSeconds(), maxDelaySeconds);
|
|
93
|
+
if (timeoutSeconds <= nearElapsedThreshold) {
|
|
94
|
+
return {
|
|
95
|
+
delaySeconds: timeoutSeconds,
|
|
96
|
+
idempotencyKey: `${waitCorrelationId}:${Math.floor(now / 1000)}`,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const hop = Math.ceil(timeoutSeconds / maxDelaySeconds);
|
|
100
|
+
return {
|
|
101
|
+
delaySeconds: Math.min(timeoutSeconds, maxDelaySeconds),
|
|
102
|
+
idempotencyKey: hop === 1 ? waitCorrelationId : `${waitCorrelationId}:hop-${hop}`,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FpdC1jb250aW51YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS93YWl0LWNvbnRpbnVhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeURHO0FBRUgsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTVDOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUNBQW1DLEdBQUcsTUFBTSxDQUFDO0FBRTFEOzs7OztHQUtHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUNBQW1DLEdBQUcsQ0FBQyxDQUFDO0FBRXJELGtHQUFrRztBQUNsRyxNQUFNLGtDQUFrQyxHQUFHLEdBQVcsRUFBRSxDQUN0RCxTQUFTLENBQ1AsOENBQThDLEVBQzlDLG1DQUFtQyxFQUNuQyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUMxQixDQUFDO0FBRUosa0dBQWtHO0FBQ2xHLE1BQU0sa0NBQWtDLEdBQUcsR0FBVyxFQUFFLENBQ3RELFNBQVMsQ0FDUCw4Q0FBOEMsRUFDOUMsbUNBQW1DLENBQ3BDLENBQUM7QUFPSjs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSwyQkFBMkIsQ0FDekMsY0FBc0IsRUFDdEIsaUJBQXlCLEVBQ3pCLE1BQWMsSUFBSSxDQUFDLEdBQUcsRUFBRTtJQUV4QixNQUFNLGVBQWUsR0FBRyxrQ0FBa0MsRUFBRSxDQUFDO0lBQzdELDJFQUEyRTtJQUMzRSw4RUFBOEU7SUFDOUUsNEVBQTRFO0lBQzVFLDJFQUEyRTtJQUMzRSw2RUFBNkU7SUFDN0UsMERBQTBEO0lBQzFELE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FDbkMsa0NBQWtDLEVBQUUsRUFDcEMsZUFBZSxDQUNoQixDQUFDO0lBQ0YsSUFBSSxjQUFjLElBQUksb0JBQW9CLEVBQUUsQ0FBQztRQUMzQyxPQUFPO1lBQ0wsWUFBWSxFQUFFLGNBQWM7WUFDNUIsY0FBYyxFQUFFLEdBQUcsaUJBQWlCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEVBQUU7U0FDakUsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxlQUFlLENBQUMsQ0FBQztJQUN4RCxPQUFPO1FBQ0wsWUFBWSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLGVBQWUsQ0FBQztRQUN2RCxjQUFjLEVBQ1osR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLEdBQUcsaUJBQWlCLFFBQVEsR0FBRyxFQUFFO0tBQ3BFLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXYWl0LWNvbnRpbnVhdGlvbiBkaXNwYXRjaDogZGVsYXkgKyBpZGVtcG90ZW5jeS1rZXkgc2VsZWN0aW9uLlxuICpcbiAqIFdoZW4gVjIgc3VzcGVuc2lvbiBwcm9jZXNzaW5nIG9ic2VydmVzIGEgcGVuZGluZyB3YWl0LCBpdCBlbnF1ZXVlcyBhXG4gKiBkZWxheWVkIFwiY29udGludWF0aW9uXCIgbWVzc2FnZSB0aGF0IGZpcmVzIG9uY2UgdGhlIHdhaXQgZWxhcHNlcyBhbmRcbiAqIGRyaXZlcyB0aGUgbmV4dCByZXBsYXkgKHdoaWNoIGNvbXBsZXRlcyB0aGUgd2FpdCB2aWEgdGhlIFwiY29tcGxldGVcbiAqIGVsYXBzZWQgd2FpdHNcIiBwYXNzKS4gVGhpcyBtb2R1bGUgZGVjaWRlcyB0aGUgbWVzc2FnZSdzIGBkZWxheVNlY29uZHNgXG4gKiBhbmQgYGlkZW1wb3RlbmN5S2V5YC5cbiAqXG4gKiBUaGUgY29udGludWF0aW9uIGlzIGtleWVkIG9uIHRoZSB3YWl0J3MgY29ycmVsYXRpb25JZDogd2hpbGUgYSB3YWl0IGlzXG4gKiBwZW5kaW5nLCBldmVyeSByZXBsYXkgcGFzcyBvdmVyIHRoZSBydW4gcmUtb2JzZXJ2ZXMgaXQgKGUuZy4sIG9uY2UgcGVyXG4gKiBzdGVwIGNvbXBsZXRpb24gaW4gYFByb21pc2UuYWxsKFtzdGVwcy4uLiwgc2xlZXAoKV0pYCksIGFuZCB3aXRob3V0XG4gKiBkZWR1cGUgZWFjaCBwYXNzIHdvdWxkIGVucXVldWUgYW5vdGhlciBkZWxheWVkIGNvbnRpbnVhdGlvbiDigJQgZWFjaCBvbmVcbiAqIGEgc3B1cmlvdXMgZnVsbCByZXBsYXkgd2hlbiB0aGUgd2FpdCBlbGFwc2VzLCBhbmQgZWFjaCBhIGZyZXNoIG1lc3NhZ2VcbiAqIHRoYXQgcmVzZXRzIHRoZSBkZWxpdmVyeS1hdHRlbXB0IHJ1bmF3YXkgZ3VhcmQuIEEga2V5IGlzIGF0dGFjaGVkIGluXG4gKiBhbGwgY2FzZXM6IHNvbWUgd29ybGRzIChlLmcuIHdvcmxkLXBvc3RncmVzKSBzZXJpYWxpemUga2V5LWxlc3NcbiAqIHdvcmtmbG93IG1lc3NhZ2VzIHBlciBydW4sIHdoaWNoIHdvdWxkIHBhcmsgdGhlIGNvbnRpbnVhdGlvbiBiZWhpbmRcbiAqIHRoZSBoYW5kbGVyJ3Mgb3duIGlubGluZSBzdGVwIGV4ZWN1dGlvbiBhbmQgZGVmZWF0IHRoZSByYWNlIHNlbWFudGljc1xuICogdGhlIGNvbnRpbnVhdGlvbiBleGlzdHMgdG8gcHJvdmlkZS5cbiAqXG4gKiBUaGUgYmFyZSBjb3JyZWxhdGlvbklkIGNhbm5vdCBiZSB0aGUga2V5IGluIGV2ZXJ5IGNhc2UsIHRob3VnaDogd29ybGRcbiAqIGRlZHVwZSB3aW5kb3dzIG91dGxpdmUgdGhlIGZpcnN0IGRlbGl2ZXJ5IChWUVMga2VlcHMgaWRlbXBvdGVuY3lcbiAqIHJlY29yZHMgdW50aWwgbWVzc2FnZS1yZXRlbnRpb24gVFRMOyB3b3JsZC1wb3N0Z3JlcyBrZWVwcyBhXG4gKiBjb21wbGV0ZWQta2V5cyBjYWNoZSksIHNvIG9uY2UgYSBrZXkgaGFzIGJlZW4gdXNlZCwgYSBsYXRlciBlbnF1ZXVlXG4gKiB1bmRlciB0aGUgc2FtZSBrZXkgaXMgc2lsZW50bHkgZHJvcHBlZC4gQW55IHNpdHVhdGlvbiB3aGVyZSBhXG4gKiBjb250aW51YXRpb24gaXMgZGVsaXZlcmVkIHdoaWxlIGl0cyB3YWl0IGlzIHN0aWxsIHBlbmRpbmcgdGhlcmVmb3JlXG4gKiBuZWVkcyBhIGZyZXNoIGtleSBmb3IgdGhlIHJlLWVucXVldWUsIG9yIHRoZSB3YWl0J3MgdGltZXIgaXMgbG9zdCBhbmRcbiAqIHRoZSBydW4gc3RhbGxzIHVudGlsIHVucmVsYXRlZCB0cmFmZmljIGhhcHBlbnMgdG8gd2FrZSBpdC4gVHdvIHN1Y2hcbiAqIHNpdHVhdGlvbnMgZXhpc3QsIGVhY2ggd2l0aCBpdHMgb3duIGtleSB2YXJpYXRpb246XG4gKlxuICogLSBXYWl0cyBsb25nZXIgdGhhbiB0aGUgbWF4aW11bSBxdWV1ZSBkZWxheSBhcmUgY2hhaW5lZDogdGhlIGRlbGF5IGlzXG4gKiAgIGNsYW1wZWQgdG8gYFdBSVRfQ09OVElOVUFUSU9OX01BWF9ERUxBWV9TRUNPTkRTYCAoMjNoIOKAlCBWUVMgbWVzc2FnZXNcbiAqICAgaGF2ZSBhIDI0aCByZXRlbnRpb24gbGltaXQsIGFuZCBvbmUgaG91ciBvZiBidWZmZXIgbWF0Y2hlc1xuICogICB3b3JsZC12ZXJjZWwncyBvd24gY2xhbXAgZm9yIGRlbGF5ZWQgcmUtZW5xdWV1ZXMpLCBzbyB0aGVcbiAqICAgY29udGludWF0aW9uIGludGVudGlvbmFsbHkgZmlyZXMgZWFybHksIHJlLW9ic2VydmVzIHRoZSB3YWl0LCBhbmRcbiAqICAgbXVzdCBlbnF1ZXVlIHRoZSBuZXh0IGhvcC4gVGhlIGtleSBpcyBzdWZmaXhlZCB3aXRoIHRoZSBob3AgaW5kZXhcbiAqICAgKGBjZWlsKHRpbWVvdXRTZWNvbmRzIC8gbWF4RGVsYXkpYCk6IHN0YWJsZSBmb3IgZXZlcnkgcmUtb2JzZXJ2YXRpb25cbiAqICAgd2l0aGluIHRoZSBzYW1lIGhvcCB3aW5kb3cgKHNvIHBhc3NlcyBkZWR1cGUpLCBkZWNyZW1lbnRlZCBhdCBlYWNoXG4gKiAgIGhvcCBkZWxpdmVyeSAoc28gdGhlIGNoYWluIGFsd2F5cyBhZHZhbmNlcykuIFdvcmxkcyB3aXRob3V0IGEgZGVsYXlcbiAqICAgbGltaXQgKHdvcmxkLXBvc3RncmVzLCB3b3JsZC1sb2NhbCkgc2ltcGx5IHRha2UgdGhlIHNhbWUg4omkMjNoIGhvcHMuXG4gKlxuICogLSBOZWFyLWVsYXBzZWQgd2FpdHMgKOKJpDJzIHJlbWFpbmluZykgZ2V0IGEgc2Vjb25kLWJ1Y2tldGVkIHN1ZmZpeC4gQVxuICogICBjb250aW51YXRpb24gZGVsaXZlcmVkIG1hcmdpbmFsbHkgZWFybHkgKGNsb2NrIHNrZXcgYmV0d2VlbiB0aGVcbiAqICAgZW5xdWV1aW5nIGFuZCBoYW5kbGluZyBob3N0czsgdGhlIGNlaWwoKSBvbiB0aGUgZGVsYXkgY2FuIGxlYXZlIGEgfjBcbiAqICAgbWFyZ2luKSByZS1vYnNlcnZlcyB0aGUgd2FpdCBhcyBwZW5kaW5nIHdpdGggfjFzIHJlbWFpbmluZyBhbmQgbXVzdFxuICogICBiZSBhYmxlIHRvIGVucXVldWUgYSBmcmVzaCBzaG9ydC1kZWxheSByZXRyeS4gVGhlIGJ1Y2tldCBzdWZmaXhcbiAqICAga2VlcHMgdGhhdCByZXRyeSBlbnF1ZXVlYWJsZSAoaXRzIOKJpTFzIGRlbGF5IGd1YXJhbnRlZXMgYSBsYXRlclxuICogICBidWNrZXQpIHdoaWxlIHN0aWxsIGNvbGxhcHNpbmcgc2FtZS1pbnN0YW50IGR1cGxpY2F0ZXMuXG4gKlxuICogTWlkLXJhbmdlIHdhaXRzIChtb3JlIHRoYW4gdGhlIG5lYXItZWxhcHNlZCB0aHJlc2hvbGQsIGF0IG1vc3Qgb25lXG4gKiBob3ApIHVzZSB0aGUgYmFyZSBjb3JyZWxhdGlvbklkOiBldmVyeSByZS1vYnNlcnZhdGlvbiB0YXJnZXRzIHRoZSBzYW1lXG4gKiBkZWFkbGluZSwgc28gZGVkdXBpbmcgdG8gdGhlIGZpcnN0IG1lc3NhZ2UgaXMgc2VtYW50aWNhbGx5IGxvc3NsZXNzLlxuICogSG9zdCBjbG9jayBza2V3IGJleW9uZCB0aGUgbmVhci1lbGFwc2VkIHRocmVzaG9sZCBjb3VsZCBpbiBwcmluY2lwbGVcbiAqIGRlbGl2ZXIgc3VjaCBhIGNvbnRpbnVhdGlvbiBlYXJseSBlbm91Z2ggdG8gcmUtb2JzZXJ2ZSBpdHMgd2FpdCBhbmRcbiAqIGxvc2UgdGhlIHJlLWVucXVldWUgdG8gdGhlIGJ1cm50IGtleTsgdGhlIHRocmVzaG9sZCBpcyB0aGUgc2tld1xuICogdG9sZXJhbmNlIHdlIGFjY2VwdCBmb3IgdGhlIGJlbmVmaXQgb2YgZXhhY3RseS1vbmUgY29udGludWF0aW9uIHBlclxuICogd2FpdC5cbiAqL1xuXG5pbXBvcnQgeyBlbnZOdW1iZXIgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuXG4vKipcbiAqIE1heGltdW0gYGRlbGF5U2Vjb25kc2AgZm9yIGEgc2luZ2xlIHdhaXQtY29udGludWF0aW9uIG1lc3NhZ2UuIFdhaXRzXG4gKiBsb25nZXIgdGhhbiB0aGlzIGFyZSBjaGFpbmVkIGFjcm9zcyBtdWx0aXBsZSBob3BzLiAyMyBob3VycyBsZWF2ZXMgYSAxaFxuICogYnVmZmVyIHVuZGVyIFZlcmNlbCBRdWV1ZXMnIGRlZmF1bHQgMjRoIG1lc3NhZ2UgVFRMIGFuZCBtaXJyb3JzXG4gKiB3b3JsZC12ZXJjZWwncyBgTUFYX0RFTEFZX1NFQ09ORFNgLlxuICovXG5leHBvcnQgY29uc3QgV0FJVF9DT05USU5VQVRJT05fTUFYX0RFTEFZX1NFQ09ORFMgPSA4Ml84MDA7XG5cbi8qKlxuICogV2FpdHMgd2l0aCBhdCBtb3N0IHRoaXMgbWFueSBzZWNvbmRzIHJlbWFpbmluZyB1c2UgYSBzZWNvbmQtYnVja2V0ZWRcbiAqIGlkZW1wb3RlbmN5IGtleSBzbyBhbiBlYXJseS1kZWxpdmVyZWQgY29udGludWF0aW9uIGNhbiByZS1lbnF1ZXVlIGl0c1xuICogc2hvcnQtZGVsYXkgcmV0cnkuIFRoaXMgaXMgYWxzbyB0aGUgaG9zdCBjbG9jay1za2V3IHRvbGVyYW5jZSBmb3JcbiAqIG1pZC1yYW5nZSB3YWl0cyBrZXllZCBvbiB0aGUgYmFyZSBjb3JyZWxhdGlvbklkLlxuICovXG5leHBvcnQgY29uc3QgTkVBUl9FTEFQU0VEX1dBSVRfVEhSRVNIT0xEX1NFQ09ORFMgPSAyO1xuXG4vKiogRWZmZWN0aXZlIG1heCBjb250aW51YXRpb24gZGVsYXkuIE92ZXJyaWRlOiBgV09SS0ZMT1dfV0FJVF9DT05USU5VQVRJT05fTUFYX0RFTEFZX1NFQ09ORFNgLiAqL1xuY29uc3QgZ2V0V2FpdENvbnRpbnVhdGlvbk1heERlbGF5U2Vjb25kcyA9ICgpOiBudW1iZXIgPT5cbiAgZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19XQUlUX0NPTlRJTlVBVElPTl9NQVhfREVMQVlfU0VDT05EUycsXG4gICAgV0FJVF9DT05USU5VQVRJT05fTUFYX0RFTEFZX1NFQ09ORFMsXG4gICAgeyBpbnRlZ2VyOiB0cnVlLCBtaW46IDEgfVxuICApO1xuXG4vKiogRWZmZWN0aXZlIG5lYXItZWxhcHNlZCB0aHJlc2hvbGQuIE92ZXJyaWRlOiBgV09SS0ZMT1dfTkVBUl9FTEFQU0VEX1dBSVRfVEhSRVNIT0xEX1NFQ09ORFNgLiAqL1xuY29uc3QgZ2V0TmVhckVsYXBzZWRXYWl0VGhyZXNob2xkU2Vjb25kcyA9ICgpOiBudW1iZXIgPT5cbiAgZW52TnVtYmVyKFxuICAgICdXT1JLRkxPV19ORUFSX0VMQVBTRURfV0FJVF9USFJFU0hPTERfU0VDT05EUycsXG4gICAgTkVBUl9FTEFQU0VEX1dBSVRfVEhSRVNIT0xEX1NFQ09ORFNcbiAgKTtcblxuZXhwb3J0IGludGVyZmFjZSBXYWl0Q29udGludWF0aW9uRGlzcGF0Y2gge1xuICBkZWxheVNlY29uZHM6IG51bWJlcjtcbiAgaWRlbXBvdGVuY3lLZXk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb21wdXRlcyB0aGUgcXVldWUgZGVsYXkgYW5kIGlkZW1wb3RlbmN5IGtleSBmb3IgYSB3YWl0LWNvbnRpbnVhdGlvblxuICogbWVzc2FnZS4gYHRpbWVvdXRTZWNvbmRzYCBpcyB0aGUgdGltZSB1bnRpbCB0aGUgd2FpdCdzIGByZXN1bWVBdGBcbiAqIChmbG9vcmVkIGF0IDFzIGJ5IHRoZSBzdXNwZW5zaW9uIGhhbmRsZXIpOyBgd2FpdENvcnJlbGF0aW9uSWRgXG4gKiBpZGVudGlmaWVzIHRoZSB3YWl0IHNvIHJlcGVhdGVkIHN1c3BlbnNpb24gcGFzc2VzIGRlZHVwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFdhaXRDb250aW51YXRpb25EaXNwYXRjaChcbiAgdGltZW91dFNlY29uZHM6IG51bWJlcixcbiAgd2FpdENvcnJlbGF0aW9uSWQ6IHN0cmluZyxcbiAgbm93OiBudW1iZXIgPSBEYXRlLm5vdygpXG4pOiBXYWl0Q29udGludWF0aW9uRGlzcGF0Y2gge1xuICBjb25zdCBtYXhEZWxheVNlY29uZHMgPSBnZXRXYWl0Q29udGludWF0aW9uTWF4RGVsYXlTZWNvbmRzKCk7XG4gIC8vIFRoZSBuZWFyLWVsYXBzZWQgYnJhbmNoIHJldHVybnMgdGhlIGZ1bGwgcmVtYWluaW5nIHRpbWUgYXMgdGhlIGRlbGF5LCBzb1xuICAvLyBpdHMgdGhyZXNob2xkIGNhbiBuZXZlciBleGNlZWQgdGhlIG1heCBkZWxheSDigJQgb3RoZXJ3aXNlIGEgd2FpdCBiZXR3ZWVuIHRoZVxuICAvLyBtYXggYW5kIHRoZSB0aHJlc2hvbGQgd291bGQgYmUgZGlzcGF0Y2hlZCB3aXRoIGEgZGVsYXkgYWJvdmUgdGhlIG1heC4gQ2FwXG4gIC8vIHRoZSB0aHJlc2hvbGQgYXQgdGhlIG1heCBzbyBldmVyeSBicmFuY2ggeWllbGRzIGEgZGVsYXkgd2l0aGluIGl0LiAoV2l0aFxuICAvLyBkZWZhdWx0cyDigJQgdGhyZXNob2xkIDJzLCBtYXggODJfODAwcyDigJQgdGhpcyBpcyBhIG5vLW9wOyBpdCBvbmx5IGJpdGVzIHdoZW5cbiAgLy8gdGhlIG1heCBpcyB0dW5lZCBkb3duIGJlbG93IHRoZSB0aHJlc2hvbGQgZm9yIHRlc3RpbmcuKVxuICBjb25zdCBuZWFyRWxhcHNlZFRocmVzaG9sZCA9IE1hdGgubWluKFxuICAgIGdldE5lYXJFbGFwc2VkV2FpdFRocmVzaG9sZFNlY29uZHMoKSxcbiAgICBtYXhEZWxheVNlY29uZHNcbiAgKTtcbiAgaWYgKHRpbWVvdXRTZWNvbmRzIDw9IG5lYXJFbGFwc2VkVGhyZXNob2xkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRlbGF5U2Vjb25kczogdGltZW91dFNlY29uZHMsXG4gICAgICBpZGVtcG90ZW5jeUtleTogYCR7d2FpdENvcnJlbGF0aW9uSWR9OiR7TWF0aC5mbG9vcihub3cgLyAxMDAwKX1gLFxuICAgIH07XG4gIH1cblxuICBjb25zdCBob3AgPSBNYXRoLmNlaWwodGltZW91dFNlY29uZHMgLyBtYXhEZWxheVNlY29uZHMpO1xuICByZXR1cm4ge1xuICAgIGRlbGF5U2Vjb25kczogTWF0aC5taW4odGltZW91dFNlY29uZHMsIG1heERlbGF5U2Vjb25kcyksXG4gICAgaWRlbXBvdGVuY3lLZXk6XG4gICAgICBob3AgPT09IDEgPyB3YWl0Q29ycmVsYXRpb25JZCA6IGAke3dhaXRDb3JyZWxhdGlvbklkfTpob3AtJHtob3B9YCxcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function waitUntil(promise: Promise<unknown>): void;
|
|
2
|
+
/**
|
|
3
|
+
* Schedule a background promise via `waitUntil`, guaranteeing that the
|
|
4
|
+
* promise handed to `waitUntil` can never reject. Nothing consumes a
|
|
5
|
+
* `waitUntil` promise, so a rejection surfaces as an `unhandledRejection`
|
|
6
|
+
* and can crash the process — even when the same underlying error is
|
|
7
|
+
* correctly handled by an awaited copy elsewhere.
|
|
8
|
+
*
|
|
9
|
+
* Expected client-disconnect errors (`AbortError` / `ResponseAborted`)
|
|
10
|
+
* are ignored. Any other error is passed to `onError` and swallowed.
|
|
11
|
+
*/
|
|
12
|
+
export declare function safeWaitUntil(promise: Promise<unknown>, onError: (err: unknown) => void): void;
|
|
13
|
+
/**
|
|
14
|
+
* A small wrapper around `waitUntil` that also returns
|
|
15
|
+
* the result of the awaited promise.
|
|
16
|
+
*/
|
|
17
|
+
export declare function waitedUntil<T>(fn: () => Promise<T>): Promise<T>;
|
|
18
|
+
//# sourceMappingURL=wait-until.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wait-until.d.ts","sourceRoot":"","sources":["../../src/runtime/wait-until.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAIzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAC9B,IAAI,CAcN;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAUrE"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export function waitUntil(promise) {
|
|
2
|
+
void import('@vercel/functions').then(({ waitUntil }) => {
|
|
3
|
+
waitUntil(promise);
|
|
4
|
+
});
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Schedule a background promise via `waitUntil`, guaranteeing that the
|
|
8
|
+
* promise handed to `waitUntil` can never reject. Nothing consumes a
|
|
9
|
+
* `waitUntil` promise, so a rejection surfaces as an `unhandledRejection`
|
|
10
|
+
* and can crash the process — even when the same underlying error is
|
|
11
|
+
* correctly handled by an awaited copy elsewhere.
|
|
12
|
+
*
|
|
13
|
+
* Expected client-disconnect errors (`AbortError` / `ResponseAborted`)
|
|
14
|
+
* are ignored. Any other error is passed to `onError` and swallowed.
|
|
15
|
+
*/
|
|
16
|
+
export function safeWaitUntil(promise, onError) {
|
|
17
|
+
waitUntil(promise.catch((err) => {
|
|
18
|
+
const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
|
|
19
|
+
if (!isAbortError) {
|
|
20
|
+
try {
|
|
21
|
+
onError(err);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Never let onError break the no-reject guarantee.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A small wrapper around `waitUntil` that also returns
|
|
31
|
+
* the result of the awaited promise.
|
|
32
|
+
*/
|
|
33
|
+
export async function waitedUntil(fn) {
|
|
34
|
+
const result = fn();
|
|
35
|
+
waitUntil(result.catch(() => {
|
|
36
|
+
// Ignore error from the promise being rejected.
|
|
37
|
+
// It's expected that the invoker of `waitedUntil`
|
|
38
|
+
// will handle the error.
|
|
39
|
+
}));
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2FpdC11bnRpbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL3dhaXQtdW50aWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxVQUFVLFNBQVMsQ0FBQyxPQUF5QjtJQUNqRCxLQUFLLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRTtRQUN0RCxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDckIsQ0FBQyxDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsT0FBeUIsRUFDekIsT0FBK0I7SUFFL0IsU0FBUyxDQUNQLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtRQUNwQixNQUFNLFlBQVksR0FDaEIsR0FBRyxFQUFFLElBQUksS0FBSyxZQUFZLElBQUksR0FBRyxFQUFFLElBQUksS0FBSyxpQkFBaUIsQ0FBQztRQUNoRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDbEIsSUFBSSxDQUFDO2dCQUNILE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNmLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsbURBQW1EO1lBQ3JELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVcsQ0FBSSxFQUFvQjtJQUN2RCxNQUFNLE1BQU0sR0FBRyxFQUFFLEVBQUUsQ0FBQztJQUNwQixTQUFTLENBQ1AsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7UUFDaEIsZ0RBQWdEO1FBQ2hELGtEQUFrRDtRQUNsRCx5QkFBeUI7SUFDM0IsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUNGLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gd2FpdFVudGlsKHByb21pc2U6IFByb21pc2U8dW5rbm93bj4pOiB2b2lkIHtcbiAgdm9pZCBpbXBvcnQoJ0B2ZXJjZWwvZnVuY3Rpb25zJykudGhlbigoeyB3YWl0VW50aWwgfSkgPT4ge1xuICAgIHdhaXRVbnRpbChwcm9taXNlKTtcbiAgfSk7XG59XG5cbi8qKlxuICogU2NoZWR1bGUgYSBiYWNrZ3JvdW5kIHByb21pc2UgdmlhIGB3YWl0VW50aWxgLCBndWFyYW50ZWVpbmcgdGhhdCB0aGVcbiAqIHByb21pc2UgaGFuZGVkIHRvIGB3YWl0VW50aWxgIGNhbiBuZXZlciByZWplY3QuIE5vdGhpbmcgY29uc3VtZXMgYVxuICogYHdhaXRVbnRpbGAgcHJvbWlzZSwgc28gYSByZWplY3Rpb24gc3VyZmFjZXMgYXMgYW4gYHVuaGFuZGxlZFJlamVjdGlvbmBcbiAqIGFuZCBjYW4gY3Jhc2ggdGhlIHByb2Nlc3Mg4oCUIGV2ZW4gd2hlbiB0aGUgc2FtZSB1bmRlcmx5aW5nIGVycm9yIGlzXG4gKiBjb3JyZWN0bHkgaGFuZGxlZCBieSBhbiBhd2FpdGVkIGNvcHkgZWxzZXdoZXJlLlxuICpcbiAqIEV4cGVjdGVkIGNsaWVudC1kaXNjb25uZWN0IGVycm9ycyAoYEFib3J0RXJyb3JgIC8gYFJlc3BvbnNlQWJvcnRlZGApXG4gKiBhcmUgaWdub3JlZC4gQW55IG90aGVyIGVycm9yIGlzIHBhc3NlZCB0byBgb25FcnJvcmAgYW5kIHN3YWxsb3dlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNhZmVXYWl0VW50aWwoXG4gIHByb21pc2U6IFByb21pc2U8dW5rbm93bj4sXG4gIG9uRXJyb3I6IChlcnI6IHVua25vd24pID0+IHZvaWRcbik6IHZvaWQge1xuICB3YWl0VW50aWwoXG4gICAgcHJvbWlzZS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBjb25zdCBpc0Fib3J0RXJyb3IgPVxuICAgICAgICBlcnI/Lm5hbWUgPT09ICdBYm9ydEVycm9yJyB8fCBlcnI/Lm5hbWUgPT09ICdSZXNwb25zZUFib3J0ZWQnO1xuICAgICAgaWYgKCFpc0Fib3J0RXJyb3IpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBvbkVycm9yKGVycik7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIE5ldmVyIGxldCBvbkVycm9yIGJyZWFrIHRoZSBuby1yZWplY3QgZ3VhcmFudGVlLlxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSlcbiAgKTtcbn1cblxuLyoqXG4gKiBBIHNtYWxsIHdyYXBwZXIgYXJvdW5kIGB3YWl0VW50aWxgIHRoYXQgYWxzbyByZXR1cm5zXG4gKiB0aGUgcmVzdWx0IG9mIHRoZSBhd2FpdGVkIHByb21pc2UuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3YWl0ZWRVbnRpbDxUPihmbjogKCkgPT4gUHJvbWlzZTxUPik6IFByb21pc2U8VD4ge1xuICBjb25zdCByZXN1bHQgPSBmbigpO1xuICB3YWl0VW50aWwoXG4gICAgcmVzdWx0LmNhdGNoKCgpID0+IHtcbiAgICAgIC8vIElnbm9yZSBlcnJvciBmcm9tIHRoZSBwcm9taXNlIGJlaW5nIHJlamVjdGVkLlxuICAgICAgLy8gSXQncyBleHBlY3RlZCB0aGF0IHRoZSBpbnZva2VyIG9mIGB3YWl0ZWRVbnRpbGBcbiAgICAgIC8vIHdpbGwgaGFuZGxlIHRoZSBlcnJvci5cbiAgICB9KVxuICApO1xuICByZXR1cm4gcmVzdWx0O1xufVxuIl19
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { World } from '@workflow/world';
|
|
2
|
+
type WorldSpecVersionMetadata = Pick<World, 'specVersion'>;
|
|
3
|
+
export declare function assertWorldSupportsRuntimeProtocol(world: WorldSpecVersionMetadata): void;
|
|
4
|
+
export {};
|
|
5
|
+
//# sourceMappingURL=world-compatibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-compatibility.d.ts","sourceRoot":"","sources":["../../src/runtime/world-compatibility.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAG7C,KAAK,wBAAwB,GAAG,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;AAE3D,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,wBAAwB,GAC9B,IAAI,CAWN"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { WorkflowRuntimeError } from '@workflow/errors';
|
|
2
|
+
import { SPEC_VERSION_CURRENT } from '@workflow/world';
|
|
3
|
+
export function assertWorldSupportsRuntimeProtocol(world) {
|
|
4
|
+
if (world.specVersion === SPEC_VERSION_CURRENT) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
const supportedVersion = world.specVersion ?? 'none';
|
|
8
|
+
throw new WorkflowRuntimeError(`This Workflow runtime requires a World with matching spec version ${SPEC_VERSION_CURRENT}, ` +
|
|
9
|
+
`but the configured World declares spec version ${supportedVersion}. ` +
|
|
10
|
+
'Install a World package version compatible with the current Workflow runtime.');
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGQtY29tcGF0aWJpbGl0eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL3dvcmxkLWNvbXBhdGliaWxpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFFeEQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFJdkQsTUFBTSxVQUFVLGtDQUFrQyxDQUNoRCxLQUErQjtJQUUvQixJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssb0JBQW9CLEVBQUUsQ0FBQztRQUMvQyxPQUFPO0lBQ1QsQ0FBQztJQUVELE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLFdBQVcsSUFBSSxNQUFNLENBQUM7SUFDckQsTUFBTSxJQUFJLG9CQUFvQixDQUM1QixxRUFBcUUsb0JBQW9CLElBQUk7UUFDM0Ysa0RBQWtELGdCQUFnQixJQUFJO1FBQ3RFLCtFQUErRSxDQUNsRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFdvcmtmbG93UnVudGltZUVycm9yIH0gZnJvbSAnQHdvcmtmbG93L2Vycm9ycyc7XG5pbXBvcnQgdHlwZSB7IFdvcmxkIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcbmltcG9ydCB7IFNQRUNfVkVSU0lPTl9DVVJSRU5UIH0gZnJvbSAnQHdvcmtmbG93L3dvcmxkJztcblxudHlwZSBXb3JsZFNwZWNWZXJzaW9uTWV0YWRhdGEgPSBQaWNrPFdvcmxkLCAnc3BlY1ZlcnNpb24nPjtcblxuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFdvcmxkU3VwcG9ydHNSdW50aW1lUHJvdG9jb2woXG4gIHdvcmxkOiBXb3JsZFNwZWNWZXJzaW9uTWV0YWRhdGFcbik6IHZvaWQge1xuICBpZiAod29ybGQuc3BlY1ZlcnNpb24gPT09IFNQRUNfVkVSU0lPTl9DVVJSRU5UKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3Qgc3VwcG9ydGVkVmVyc2lvbiA9IHdvcmxkLnNwZWNWZXJzaW9uID8/ICdub25lJztcbiAgdGhyb3cgbmV3IFdvcmtmbG93UnVudGltZUVycm9yKFxuICAgIGBUaGlzIFdvcmtmbG93IHJ1bnRpbWUgcmVxdWlyZXMgYSBXb3JsZCB3aXRoIG1hdGNoaW5nIHNwZWMgdmVyc2lvbiAke1NQRUNfVkVSU0lPTl9DVVJSRU5UfSwgYCArXG4gICAgICBgYnV0IHRoZSBjb25maWd1cmVkIFdvcmxkIGRlY2xhcmVzIHNwZWMgdmVyc2lvbiAke3N1cHBvcnRlZFZlcnNpb259LiBgICtcbiAgICAgICdJbnN0YWxsIGEgV29ybGQgcGFja2FnZSB2ZXJzaW9uIGNvbXBhdGlibGUgd2l0aCB0aGUgY3VycmVudCBXb3JrZmxvdyBydW50aW1lLidcbiAgKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-only side-effect module that ensures `world.ts` is loaded so its
|
|
3
|
+
* module-load side effect — `globalThis[GetWorldFnKey] ??= getWorld` —
|
|
4
|
+
* fires in host bundles.
|
|
5
|
+
*
|
|
6
|
+
* # Why this exists
|
|
7
|
+
*
|
|
8
|
+
* `getWorldLazy()` in `./get-world-lazy.ts` checks the globalThis cache
|
|
9
|
+
* populated by `world.ts`'s module-load side effect. When a server route
|
|
10
|
+
* only consumes a helper that goes through `getWorldLazy` — for example
|
|
11
|
+
* `start` from `workflow/api`, or `defineHook().resume()` from `workflow`
|
|
12
|
+
* — webpack/turbopack can tree-shake the named import `{ getWorld }` out
|
|
13
|
+
* of `runtime.ts`, taking `world.ts`'s module evaluation with it. The
|
|
14
|
+
* globalThis registration never fires.
|
|
15
|
+
*
|
|
16
|
+
* Importing this module for its side effect from the host-side `workflow`
|
|
17
|
+
* and `workflow/api` entries guarantees `world.ts` enters the bundle, the
|
|
18
|
+
* global is registered at module load, and `getWorldLazy()` short-circuits
|
|
19
|
+
* to the registered function on the first call.
|
|
20
|
+
*
|
|
21
|
+
* # Why a separate module instead of importing `./world.js` directly
|
|
22
|
+
*
|
|
23
|
+
* `world.ts` is internal to `@workflow/core` and not part of the public
|
|
24
|
+
* exports surface. Adding a dedicated public init entry (this file)
|
|
25
|
+
* keeps the side-effect intent obvious to anyone reading
|
|
26
|
+
* `packages/workflow/src/api.ts`, and lets the `workflow` export
|
|
27
|
+
* condition route to a stub for VM/step bundles (see below).
|
|
28
|
+
*
|
|
29
|
+
* # Why this doesn't break VM/step bundles
|
|
30
|
+
*
|
|
31
|
+
* The `@workflow/core/runtime/world-init` export resolves via the
|
|
32
|
+
* `workflow` condition to `./dist/workflow/world-init-stub.js`, an empty
|
|
33
|
+
* module. Esbuild runs the workflow VM and step bundlers with the
|
|
34
|
+
* `workflow` condition active, so they pick up the stub and never reach
|
|
35
|
+
* `world.ts`. Host bundlers (webpack, turbopack, Node.js) use the
|
|
36
|
+
* `default` (or `node`) condition and pick up this file, loading
|
|
37
|
+
* `world.ts` as intended. The split keeps the configured world package
|
|
38
|
+
* and other server-only deps out of the workflow sandbox bundle.
|
|
39
|
+
*
|
|
40
|
+
* # Maintenance notes
|
|
41
|
+
*
|
|
42
|
+
* If you add another `getWorldLazy()` consumer that's reachable from a
|
|
43
|
+
* host route without going through `workflow` or `workflow/api`, make
|
|
44
|
+
* sure that entry also imports this module — or that it transitively
|
|
45
|
+
* reaches `world.ts` via a non-tree-shakeable path. Adding a regression
|
|
46
|
+
* test in `world-init.test.ts` is preferred to relying on careful manual
|
|
47
|
+
* tracing.
|
|
48
|
+
*/
|
|
49
|
+
import './world.js';
|
|
50
|
+
//# sourceMappingURL=world-init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-init.d.ts","sourceRoot":"","sources":["../../src/runtime/world-init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,OAAO,YAAY,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-only side-effect module that ensures `world.ts` is loaded so its
|
|
3
|
+
* module-load side effect — `globalThis[GetWorldFnKey] ??= getWorld` —
|
|
4
|
+
* fires in host bundles.
|
|
5
|
+
*
|
|
6
|
+
* # Why this exists
|
|
7
|
+
*
|
|
8
|
+
* `getWorldLazy()` in `./get-world-lazy.ts` checks the globalThis cache
|
|
9
|
+
* populated by `world.ts`'s module-load side effect. When a server route
|
|
10
|
+
* only consumes a helper that goes through `getWorldLazy` — for example
|
|
11
|
+
* `start` from `workflow/api`, or `defineHook().resume()` from `workflow`
|
|
12
|
+
* — webpack/turbopack can tree-shake the named import `{ getWorld }` out
|
|
13
|
+
* of `runtime.ts`, taking `world.ts`'s module evaluation with it. The
|
|
14
|
+
* globalThis registration never fires.
|
|
15
|
+
*
|
|
16
|
+
* Importing this module for its side effect from the host-side `workflow`
|
|
17
|
+
* and `workflow/api` entries guarantees `world.ts` enters the bundle, the
|
|
18
|
+
* global is registered at module load, and `getWorldLazy()` short-circuits
|
|
19
|
+
* to the registered function on the first call.
|
|
20
|
+
*
|
|
21
|
+
* # Why a separate module instead of importing `./world.js` directly
|
|
22
|
+
*
|
|
23
|
+
* `world.ts` is internal to `@workflow/core` and not part of the public
|
|
24
|
+
* exports surface. Adding a dedicated public init entry (this file)
|
|
25
|
+
* keeps the side-effect intent obvious to anyone reading
|
|
26
|
+
* `packages/workflow/src/api.ts`, and lets the `workflow` export
|
|
27
|
+
* condition route to a stub for VM/step bundles (see below).
|
|
28
|
+
*
|
|
29
|
+
* # Why this doesn't break VM/step bundles
|
|
30
|
+
*
|
|
31
|
+
* The `@workflow/core/runtime/world-init` export resolves via the
|
|
32
|
+
* `workflow` condition to `./dist/workflow/world-init-stub.js`, an empty
|
|
33
|
+
* module. Esbuild runs the workflow VM and step bundlers with the
|
|
34
|
+
* `workflow` condition active, so they pick up the stub and never reach
|
|
35
|
+
* `world.ts`. Host bundlers (webpack, turbopack, Node.js) use the
|
|
36
|
+
* `default` (or `node`) condition and pick up this file, loading
|
|
37
|
+
* `world.ts` as intended. The split keeps the configured world package
|
|
38
|
+
* and other server-only deps out of the workflow sandbox bundle.
|
|
39
|
+
*
|
|
40
|
+
* # Maintenance notes
|
|
41
|
+
*
|
|
42
|
+
* If you add another `getWorldLazy()` consumer that's reachable from a
|
|
43
|
+
* host route without going through `workflow` or `workflow/api`, make
|
|
44
|
+
* sure that entry also imports this module — or that it transitively
|
|
45
|
+
* reaches `world.ts` via a non-tree-shakeable path. Adding a regression
|
|
46
|
+
* test in `world-init.test.ts` is preferred to relying on careful manual
|
|
47
|
+
* tracing.
|
|
48
|
+
*/
|
|
49
|
+
import './world.js';
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGQtaW5pdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL3dvcmxkLWluaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0NHO0FBQ0gsT0FBTyxZQUFZLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFNlcnZlci1vbmx5IHNpZGUtZWZmZWN0IG1vZHVsZSB0aGF0IGVuc3VyZXMgYHdvcmxkLnRzYCBpcyBsb2FkZWQgc28gaXRzXG4gKiBtb2R1bGUtbG9hZCBzaWRlIGVmZmVjdCDigJQgYGdsb2JhbFRoaXNbR2V0V29ybGRGbktleV0gPz89IGdldFdvcmxkYCDigJRcbiAqIGZpcmVzIGluIGhvc3QgYnVuZGxlcy5cbiAqXG4gKiAjIFdoeSB0aGlzIGV4aXN0c1xuICpcbiAqIGBnZXRXb3JsZExhenkoKWAgaW4gYC4vZ2V0LXdvcmxkLWxhenkudHNgIGNoZWNrcyB0aGUgZ2xvYmFsVGhpcyBjYWNoZVxuICogcG9wdWxhdGVkIGJ5IGB3b3JsZC50c2AncyBtb2R1bGUtbG9hZCBzaWRlIGVmZmVjdC4gV2hlbiBhIHNlcnZlciByb3V0ZVxuICogb25seSBjb25zdW1lcyBhIGhlbHBlciB0aGF0IGdvZXMgdGhyb3VnaCBgZ2V0V29ybGRMYXp5YCDigJQgZm9yIGV4YW1wbGVcbiAqIGBzdGFydGAgZnJvbSBgd29ya2Zsb3cvYXBpYCwgb3IgYGRlZmluZUhvb2soKS5yZXN1bWUoKWAgZnJvbSBgd29ya2Zsb3dgXG4gKiDigJQgd2VicGFjay90dXJib3BhY2sgY2FuIHRyZWUtc2hha2UgdGhlIG5hbWVkIGltcG9ydCBgeyBnZXRXb3JsZCB9YCBvdXRcbiAqIG9mIGBydW50aW1lLnRzYCwgdGFraW5nIGB3b3JsZC50c2AncyBtb2R1bGUgZXZhbHVhdGlvbiB3aXRoIGl0LiBUaGVcbiAqIGdsb2JhbFRoaXMgcmVnaXN0cmF0aW9uIG5ldmVyIGZpcmVzLlxuICpcbiAqIEltcG9ydGluZyB0aGlzIG1vZHVsZSBmb3IgaXRzIHNpZGUgZWZmZWN0IGZyb20gdGhlIGhvc3Qtc2lkZSBgd29ya2Zsb3dgXG4gKiBhbmQgYHdvcmtmbG93L2FwaWAgZW50cmllcyBndWFyYW50ZWVzIGB3b3JsZC50c2AgZW50ZXJzIHRoZSBidW5kbGUsIHRoZVxuICogZ2xvYmFsIGlzIHJlZ2lzdGVyZWQgYXQgbW9kdWxlIGxvYWQsIGFuZCBgZ2V0V29ybGRMYXp5KClgIHNob3J0LWNpcmN1aXRzXG4gKiB0byB0aGUgcmVnaXN0ZXJlZCBmdW5jdGlvbiBvbiB0aGUgZmlyc3QgY2FsbC5cbiAqXG4gKiAjIFdoeSBhIHNlcGFyYXRlIG1vZHVsZSBpbnN0ZWFkIG9mIGltcG9ydGluZyBgLi93b3JsZC5qc2AgZGlyZWN0bHlcbiAqXG4gKiBgd29ybGQudHNgIGlzIGludGVybmFsIHRvIGBAd29ya2Zsb3cvY29yZWAgYW5kIG5vdCBwYXJ0IG9mIHRoZSBwdWJsaWNcbiAqIGV4cG9ydHMgc3VyZmFjZS4gQWRkaW5nIGEgZGVkaWNhdGVkIHB1YmxpYyBpbml0IGVudHJ5ICh0aGlzIGZpbGUpXG4gKiBrZWVwcyB0aGUgc2lkZS1lZmZlY3QgaW50ZW50IG9idmlvdXMgdG8gYW55b25lIHJlYWRpbmdcbiAqIGBwYWNrYWdlcy93b3JrZmxvdy9zcmMvYXBpLnRzYCwgYW5kIGxldHMgdGhlIGB3b3JrZmxvd2AgZXhwb3J0XG4gKiBjb25kaXRpb24gcm91dGUgdG8gYSBzdHViIGZvciBWTS9zdGVwIGJ1bmRsZXMgKHNlZSBiZWxvdykuXG4gKlxuICogIyBXaHkgdGhpcyBkb2Vzbid0IGJyZWFrIFZNL3N0ZXAgYnVuZGxlc1xuICpcbiAqIFRoZSBgQHdvcmtmbG93L2NvcmUvcnVudGltZS93b3JsZC1pbml0YCBleHBvcnQgcmVzb2x2ZXMgdmlhIHRoZVxuICogYHdvcmtmbG93YCBjb25kaXRpb24gdG8gYC4vZGlzdC93b3JrZmxvdy93b3JsZC1pbml0LXN0dWIuanNgLCBhbiBlbXB0eVxuICogbW9kdWxlLiBFc2J1aWxkIHJ1bnMgdGhlIHdvcmtmbG93IFZNIGFuZCBzdGVwIGJ1bmRsZXJzIHdpdGggdGhlXG4gKiBgd29ya2Zsb3dgIGNvbmRpdGlvbiBhY3RpdmUsIHNvIHRoZXkgcGljayB1cCB0aGUgc3R1YiBhbmQgbmV2ZXIgcmVhY2hcbiAqIGB3b3JsZC50c2AuIEhvc3QgYnVuZGxlcnMgKHdlYnBhY2ssIHR1cmJvcGFjaywgTm9kZS5qcykgdXNlIHRoZVxuICogYGRlZmF1bHRgIChvciBgbm9kZWApIGNvbmRpdGlvbiBhbmQgcGljayB1cCB0aGlzIGZpbGUsIGxvYWRpbmdcbiAqIGB3b3JsZC50c2AgYXMgaW50ZW5kZWQuIFRoZSBzcGxpdCBrZWVwcyB0aGUgY29uZmlndXJlZCB3b3JsZCBwYWNrYWdlXG4gKiBhbmQgb3RoZXIgc2VydmVyLW9ubHkgZGVwcyBvdXQgb2YgdGhlIHdvcmtmbG93IHNhbmRib3ggYnVuZGxlLlxuICpcbiAqICMgTWFpbnRlbmFuY2Ugbm90ZXNcbiAqXG4gKiBJZiB5b3UgYWRkIGFub3RoZXIgYGdldFdvcmxkTGF6eSgpYCBjb25zdW1lciB0aGF0J3MgcmVhY2hhYmxlIGZyb20gYVxuICogaG9zdCByb3V0ZSB3aXRob3V0IGdvaW5nIHRocm91Z2ggYHdvcmtmbG93YCBvciBgd29ya2Zsb3cvYXBpYCwgbWFrZVxuICogc3VyZSB0aGF0IGVudHJ5IGFsc28gaW1wb3J0cyB0aGlzIG1vZHVsZSDigJQgb3IgdGhhdCBpdCB0cmFuc2l0aXZlbHlcbiAqIHJlYWNoZXMgYHdvcmxkLnRzYCB2aWEgYSBub24tdHJlZS1zaGFrZWFibGUgcGF0aC4gQWRkaW5nIGEgcmVncmVzc2lvblxuICogdGVzdCBpbiBgd29ybGQtaW5pdC50ZXN0LnRzYCBpcyBwcmVmZXJyZWQgdG8gcmVseWluZyBvbiBjYXJlZnVsIG1hbnVhbFxuICogdHJhY2luZy5cbiAqL1xuaW1wb3J0ICcuL3dvcmxkLmpzJztcbiJdfQ==
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { World } from '@workflow/world';
|
|
2
|
+
/**
|
|
3
|
+
* Unaliased target stub.
|
|
4
|
+
*
|
|
5
|
+
* Framework integrations alias this module to the configured world package at
|
|
6
|
+
* build time, including the default local world. Reaching this file means that
|
|
7
|
+
* static injection did not happen, so fail loudly instead of importing a
|
|
8
|
+
* fallback world that bundlers could retain alongside the configured one.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createWorld(): World | Promise<World>;
|
|
11
|
+
//# sourceMappingURL=world-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-target.d.ts","sourceRoot":"","sources":["../../src/runtime/world-target.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAQ7C;;;;;;;GAOG;AACH,wBAAgB,WAAW,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAEpD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function throwMissingStaticInjection() {
|
|
2
|
+
throw new Error('Workflow target world was not statically injected. Configure a Workflow builder/framework plugin so @workflow/core/runtime/world-target is aliased to the selected world package.');
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Unaliased target stub.
|
|
6
|
+
*
|
|
7
|
+
* Framework integrations alias this module to the configured world package at
|
|
8
|
+
* build time, including the default local world. Reaching this file means that
|
|
9
|
+
* static injection did not happen, so fail loudly instead of importing a
|
|
10
|
+
* fallback world that bundlers could retain alongside the configured one.
|
|
11
|
+
*/
|
|
12
|
+
export function createWorld() {
|
|
13
|
+
throwMissingStaticInjection();
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ybGQtdGFyZ2V0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvd29ybGQtdGFyZ2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLFNBQVMsMkJBQTJCO0lBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQ2IsbUxBQW1MLENBQ3BMLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7R0FPRztBQUNILE1BQU0sVUFBVSxXQUFXO0lBQ3pCLDJCQUEyQixFQUFFLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgV29ybGQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuXG5mdW5jdGlvbiB0aHJvd01pc3NpbmdTdGF0aWNJbmplY3Rpb24oKTogbmV2ZXIge1xuICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgJ1dvcmtmbG93IHRhcmdldCB3b3JsZCB3YXMgbm90IHN0YXRpY2FsbHkgaW5qZWN0ZWQuIENvbmZpZ3VyZSBhIFdvcmtmbG93IGJ1aWxkZXIvZnJhbWV3b3JrIHBsdWdpbiBzbyBAd29ya2Zsb3cvY29yZS9ydW50aW1lL3dvcmxkLXRhcmdldCBpcyBhbGlhc2VkIHRvIHRoZSBzZWxlY3RlZCB3b3JsZCBwYWNrYWdlLidcbiAgKTtcbn1cblxuLyoqXG4gKiBVbmFsaWFzZWQgdGFyZ2V0IHN0dWIuXG4gKlxuICogRnJhbWV3b3JrIGludGVncmF0aW9ucyBhbGlhcyB0aGlzIG1vZHVsZSB0byB0aGUgY29uZmlndXJlZCB3b3JsZCBwYWNrYWdlIGF0XG4gKiBidWlsZCB0aW1lLCBpbmNsdWRpbmcgdGhlIGRlZmF1bHQgbG9jYWwgd29ybGQuIFJlYWNoaW5nIHRoaXMgZmlsZSBtZWFucyB0aGF0XG4gKiBzdGF0aWMgaW5qZWN0aW9uIGRpZCBub3QgaGFwcGVuLCBzbyBmYWlsIGxvdWRseSBpbnN0ZWFkIG9mIGltcG9ydGluZyBhXG4gKiBmYWxsYmFjayB3b3JsZCB0aGF0IGJ1bmRsZXJzIGNvdWxkIHJldGFpbiBhbG9uZ3NpZGUgdGhlIGNvbmZpZ3VyZWQgb25lLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV29ybGQoKTogV29ybGQgfCBQcm9taXNlPFdvcmxkPiB7XG4gIHRocm93TWlzc2luZ1N0YXRpY0luamVjdGlvbigpO1xufVxuIl19
|
package/dist/runtime/world.d.ts
CHANGED
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import type { World } from '@workflow/world';
|
|
2
|
+
export type WorldFactoryModule = {
|
|
3
|
+
createWorld?: () => World | Promise<World>;
|
|
4
|
+
/** @deprecated World packages should export `createWorld()` instead. */
|
|
5
|
+
createLocalWorld?: () => World | Promise<World>;
|
|
6
|
+
/** @deprecated World packages should export `createWorld()` instead. */
|
|
7
|
+
createVercelWorld?: () => World | Promise<World>;
|
|
8
|
+
default?: (() => World | Promise<World>) | World;
|
|
9
|
+
};
|
|
2
10
|
/**
|
|
3
|
-
* Create a
|
|
4
|
-
*
|
|
11
|
+
* Create a World instance from a world factory module. Shared by
|
|
12
|
+
* `createWorld()` (for the statically injected target world module) and
|
|
13
|
+
* tooling that loads a world module dynamically (e.g. the Nitro dev
|
|
14
|
+
* handler and `@workflow/world-testing`). Legacy world-specific factory
|
|
15
|
+
* names are still accepted for compatibility, but world packages should
|
|
16
|
+
* export `createWorld()`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createWorldFromModule(mod: WorldFactoryModule): World | Promise<World>;
|
|
19
|
+
/**
|
|
20
|
+
* Create a new world instance from the statically imported target world module.
|
|
5
21
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* authentication via OIDC tokens and project context via system env vars
|
|
10
|
-
* (VERCEL_DEPLOYMENT_ID, VERCEL_PROJECT_ID). Tooling that needs these env
|
|
11
|
-
* vars should call createVercelWorld() directly with an explicit config and
|
|
12
|
-
* use setWorld() to inject the instance.
|
|
22
|
+
* Framework integrations alias `@workflow/core/runtime/world-target` to the
|
|
23
|
+
* concrete world package at build time, so bundlers see a static import path
|
|
24
|
+
* instead of tracing a runtime-built require/import expression.
|
|
13
25
|
*/
|
|
14
26
|
export declare const createWorld: () => Promise<World>;
|
|
15
27
|
export type WorldHandlers = Pick<World, 'createQueueHandler' | 'specVersion'>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../../src/runtime/world.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAiB7C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,CAAC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC3C,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAChD,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,KAAK,CAAC;CAClD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,kBAAkB,GACtB,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAoBxB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,WAAW,QAAa,OAAO,CAAC,KAAK,CAkBjD,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,EAAE,oBAAoB,GAAG,aAAa,CAAC,CAAC;AAE9E;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,aAAa,CAoB9D,CAAC;AAEF,eAAO,MAAM,QAAQ,QAAa,OAAO,CAAC,KAAK,CAgB9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,KAAK,GAAG,SAAS,KAAG,IAKnD,CAAC"}
|