@workflow/core 5.0.0-beta.2 → 5.0.0-beta.21
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 +11 -3
- package/dist/classify-error.d.ts.map +1 -1
- package/dist/classify-error.js +59 -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 +40 -1
- 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 +24 -0
- package/dist/events-consumer.d.ts.map +1 -1
- package/dist/events-consumer.js +79 -16
- package/dist/flushable-stream.d.ts +10 -10
- package/dist/flushable-stream.d.ts.map +1 -1
- package/dist/flushable-stream.js +18 -13
- package/dist/global.d.ts +15 -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 +28 -30
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +77 -31
- 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 +121 -0
- package/dist/runtime/constants.d.ts.map +1 -1
- package/dist/runtime/constants.js +206 -8
- 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 +32 -0
- package/dist/runtime/get-world-lazy.d.ts.map +1 -0
- package/dist/runtime/get-world-lazy.js +56 -0
- package/dist/runtime/helpers.d.ts +50 -7
- package/dist/runtime/helpers.d.ts.map +1 -1
- package/dist/runtime/helpers.js +149 -31
- 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 +191 -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.map +1 -1
- package/dist/runtime/run.js +44 -9
- package/dist/runtime/runs.d.ts.map +1 -1
- package/dist/runtime/runs.js +4 -1
- package/dist/runtime/start.d.ts +30 -1
- package/dist/runtime/start.d.ts.map +1 -1
- package/dist/runtime/start.js +138 -20
- package/dist/runtime/step-executor.d.ts +108 -0
- package/dist/runtime/step-executor.d.ts.map +1 -0
- package/dist/runtime/step-executor.js +715 -0
- package/dist/runtime/step-handler.d.ts.map +1 -1
- package/dist/runtime/step-handler.js +715 -556
- package/dist/runtime/suspension-handler.d.ts +74 -7
- package/dist/runtime/suspension-handler.d.ts.map +1 -1
- package/dist/runtime/suspension-handler.js +308 -116
- 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 +92 -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-init.d.ts +75 -0
- package/dist/runtime/world-init.d.ts.map +1 -0
- package/dist/runtime/world-init.js +75 -0
- package/dist/runtime/world.d.ts.map +1 -1
- package/dist/runtime/world.js +47 -18
- package/dist/runtime.d.ts +11 -8
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1395 -319
- 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 +15 -0
- package/dist/serialization-format.d.ts.map +1 -1
- package/dist/serialization-format.js +209 -11
- package/dist/serialization.d.ts +313 -214
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +1430 -658
- package/dist/set-attributes.d.ts +13 -0
- package/dist/set-attributes.d.ts.map +1 -0
- package/dist/set-attributes.js +42 -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 +43 -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 +49 -5
- 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 +115 -21
- 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 +30 -2
- package/dist/telemetry/semantic-conventions.d.ts.map +1 -1
- package/dist/telemetry/semantic-conventions.js +21 -1
- package/dist/telemetry.d.ts +60 -0
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/telemetry.js +82 -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 +23 -2
- 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 +73 -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 +10 -1
- package/dist/workflow.d.ts.map +1 -1
- package/dist/workflow.js +168 -49
- package/docs/api-reference/create-hook.mdx +38 -0
- package/docs/api-reference/create-webhook.mdx +1 -0
- package/docs/api-reference/experimental-set-attributes.mdx +65 -0
- package/docs/api-reference/fetch.mdx +5 -0
- package/docs/api-reference/index.mdx +3 -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 +3 -3
- package/docs/foundations/meta.json +3 -2
- package/docs/foundations/serialization.mdx +78 -42
- package/docs/foundations/starting-workflows.mdx +6 -2
- 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 +22 -10
- package/docs/foundations/common-patterns.mdx +0 -265
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { runtimeLogger } from '../logger.js';
|
|
1
2
|
// Maximum number of queue delivery attempts before the handler gives up and
|
|
2
3
|
// gracefully fails the run/step. This must be bounded under the VQS message
|
|
3
4
|
// max visibility window (24 hours) so that our handler-side failure path
|
|
@@ -11,17 +12,214 @@
|
|
|
11
12
|
// At 48 attempts the total elapsed time is approximately 20 hours, which is
|
|
12
13
|
// safely under the 24-hour message visibility limit.
|
|
13
14
|
export const MAX_QUEUE_DELIVERIES = 48;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Default maximum time allowed for the *replay* portion of a single workflow
|
|
17
|
+
* handler invocation (in ms). This budget only covers deterministic-replay
|
|
18
|
+
* and workflow-VM execution between step boundaries — inline step bodies
|
|
19
|
+
* (`"use step"` functions invoked via `executeStep`) do NOT count against
|
|
20
|
+
* it. Step bodies are bounded separately by the platform's function
|
|
21
|
+
* `maxDuration` (e.g. 800s on Vercel Pro Fluid) and `NO_INLINE_REPLAY_AFTER_MS`.
|
|
22
|
+
*
|
|
23
|
+
* If the non-step ("replay") time within a single invocation exceeds this
|
|
24
|
+
* budget, the handler exits so the queue can retry. After
|
|
25
|
+
* `REPLAY_TIMEOUT_MAX_RETRIES` exhausted attempts the run is failed with
|
|
26
|
+
* `RUN_ERROR_CODES.REPLAY_TIMEOUT`.
|
|
27
|
+
*
|
|
28
|
+
* Note that on Vercel Hobby (standard functions), the platform `maxDuration`
|
|
29
|
+
* is 60s — well below this budget, so the platform SIGTERM will fire first
|
|
30
|
+
* and the queue will re-deliver until the visibility window expires. With
|
|
31
|
+
* Fluid Compute on Hobby the per-function ceiling rises to 300s, still
|
|
32
|
+
* under the default budget.
|
|
33
|
+
*
|
|
34
|
+
* Override via the `WORKFLOW_REPLAY_TIMEOUT_MS` env var (clamped to
|
|
35
|
+
* `MIN_REPLAY_TIMEOUT_MS`..`MAX_REPLAY_TIMEOUT_MS`).
|
|
36
|
+
*/
|
|
21
37
|
export const REPLAY_TIMEOUT_MS = 240_000;
|
|
38
|
+
/** Lower bound for the replay-timeout env var override. */
|
|
39
|
+
export const MIN_REPLAY_TIMEOUT_MS = 30_000;
|
|
40
|
+
/**
|
|
41
|
+
* Upper bound for the replay-timeout env var override. 780s leaves ≥20s of
|
|
42
|
+
* headroom under Vercel Pro Fluid's 800s function ceiling so the handler
|
|
43
|
+
* can write `run_failed` before SIGTERM.
|
|
44
|
+
*/
|
|
45
|
+
export const MAX_REPLAY_TIMEOUT_MS = 780_000;
|
|
46
|
+
// Track which raw env var values we've already warned about so the warning
|
|
47
|
+
// log only fires once per process (the function may be called many times).
|
|
48
|
+
const warnedReplayTimeoutValues = new Set();
|
|
49
|
+
function warnOnce(raw, message, data) {
|
|
50
|
+
if (warnedReplayTimeoutValues.has(raw))
|
|
51
|
+
return;
|
|
52
|
+
warnedReplayTimeoutValues.add(raw);
|
|
53
|
+
runtimeLogger.warn(message, data);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Resolve the effective replay-timeout budget for the current process.
|
|
57
|
+
*
|
|
58
|
+
* Reads `process.env.WORKFLOW_REPLAY_TIMEOUT_MS` lazily so tests and
|
|
59
|
+
* deployments can override per invocation. Invalid / out-of-range values
|
|
60
|
+
* fall back to a safe value (no throw — the env var is an escape hatch,
|
|
61
|
+
* not a hard requirement) and emit a one-time warning so misconfiguration
|
|
62
|
+
* is observable.
|
|
63
|
+
*/
|
|
64
|
+
export function getReplayTimeoutMs() {
|
|
65
|
+
const raw = process.env.WORKFLOW_REPLAY_TIMEOUT_MS;
|
|
66
|
+
if (!raw)
|
|
67
|
+
return REPLAY_TIMEOUT_MS;
|
|
68
|
+
const parsed = Number(raw);
|
|
69
|
+
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
70
|
+
warnOnce(raw, 'Ignoring WORKFLOW_REPLAY_TIMEOUT_MS: not a positive finite number; using default', { raw, defaultMs: REPLAY_TIMEOUT_MS });
|
|
71
|
+
return REPLAY_TIMEOUT_MS;
|
|
72
|
+
}
|
|
73
|
+
if (parsed < MIN_REPLAY_TIMEOUT_MS) {
|
|
74
|
+
warnOnce(raw, 'WORKFLOW_REPLAY_TIMEOUT_MS below minimum; clamped', {
|
|
75
|
+
raw,
|
|
76
|
+
clampedMs: MIN_REPLAY_TIMEOUT_MS,
|
|
77
|
+
minMs: MIN_REPLAY_TIMEOUT_MS,
|
|
78
|
+
});
|
|
79
|
+
return MIN_REPLAY_TIMEOUT_MS;
|
|
80
|
+
}
|
|
81
|
+
if (parsed > MAX_REPLAY_TIMEOUT_MS) {
|
|
82
|
+
warnOnce(raw, 'WORKFLOW_REPLAY_TIMEOUT_MS above maximum; clamped', {
|
|
83
|
+
raw,
|
|
84
|
+
clampedMs: MAX_REPLAY_TIMEOUT_MS,
|
|
85
|
+
maxMs: MAX_REPLAY_TIMEOUT_MS,
|
|
86
|
+
});
|
|
87
|
+
return MAX_REPLAY_TIMEOUT_MS;
|
|
88
|
+
}
|
|
89
|
+
return parsed;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Reset the warn-once cache. Test-only — exported so unit tests can
|
|
93
|
+
* exercise the warn path repeatedly without sharing state.
|
|
94
|
+
*
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
export function _resetReplayTimeoutWarnCacheForTests() {
|
|
98
|
+
warnedReplayTimeoutValues.clear();
|
|
99
|
+
}
|
|
22
100
|
// Number of queue delivery attempts to allow before permanently failing a run
|
|
23
101
|
// due to a replay timeout. On attempts 1 through this value, the timeout
|
|
24
102
|
// handler exits without writing run_failed so the queue retries the message.
|
|
25
103
|
// On the next attempt the run is marked as failed.
|
|
26
104
|
export const REPLAY_TIMEOUT_MAX_RETRIES = 3;
|
|
27
|
-
|
|
105
|
+
/**
|
|
106
|
+
* Default maximum number of steps the owned-inline path runs inline (in
|
|
107
|
+
* parallel) per suspension. The rest are queued to background handlers. Each
|
|
108
|
+
* inline step is created lazily — its `step_created` is folded into the
|
|
109
|
+
* `step_started` that `executeStep` sends — so inlining N steps saves N queue
|
|
110
|
+
* round-trips for a `Promise.all`-style fan-out. `1` reproduces the
|
|
111
|
+
* single-inline-step behavior exactly (useful kill-switch).
|
|
112
|
+
*
|
|
113
|
+
* Override via `WORKFLOW_MAX_INLINE_STEPS` (clamped to
|
|
114
|
+
* `MIN_MAX_INLINE_STEPS`..`MAX_MAX_INLINE_STEPS`).
|
|
115
|
+
*/
|
|
116
|
+
export const MAX_INLINE_STEPS = 3;
|
|
117
|
+
/** Lower bound for the inline-steps env override (1 = single inline step). */
|
|
118
|
+
export const MIN_MAX_INLINE_STEPS = 1;
|
|
119
|
+
/**
|
|
120
|
+
* Upper bound for the inline-steps env override. Inline bodies run in parallel
|
|
121
|
+
* within one function invocation, so this caps memory/CPU fan-out per handler.
|
|
122
|
+
*/
|
|
123
|
+
export const MAX_MAX_INLINE_STEPS = 16;
|
|
124
|
+
// Warn-once cache for WORKFLOW_MAX_INLINE_STEPS, keyed by raw env value.
|
|
125
|
+
const warnedMaxInlineStepsValues = new Set();
|
|
126
|
+
/**
|
|
127
|
+
* Resolve the effective max number of inline steps for the current process.
|
|
128
|
+
*
|
|
129
|
+
* Reads `process.env.WORKFLOW_MAX_INLINE_STEPS` lazily so tests and
|
|
130
|
+
* deployments can override per invocation. Invalid / out-of-range values fall
|
|
131
|
+
* back to a safe value (no throw — the env var is an escape hatch) and emit a
|
|
132
|
+
* one-time warning so misconfiguration is observable.
|
|
133
|
+
*/
|
|
134
|
+
export function getMaxInlineSteps() {
|
|
135
|
+
const raw = process.env.WORKFLOW_MAX_INLINE_STEPS;
|
|
136
|
+
if (!raw)
|
|
137
|
+
return MAX_INLINE_STEPS;
|
|
138
|
+
const parsed = Number(raw);
|
|
139
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
140
|
+
if (!warnedMaxInlineStepsValues.has(raw)) {
|
|
141
|
+
warnedMaxInlineStepsValues.add(raw);
|
|
142
|
+
runtimeLogger.warn('Ignoring WORKFLOW_MAX_INLINE_STEPS: not a positive integer; using default', { raw, defaultValue: MAX_INLINE_STEPS });
|
|
143
|
+
}
|
|
144
|
+
return MAX_INLINE_STEPS;
|
|
145
|
+
}
|
|
146
|
+
if (parsed < MIN_MAX_INLINE_STEPS)
|
|
147
|
+
return MIN_MAX_INLINE_STEPS;
|
|
148
|
+
if (parsed > MAX_MAX_INLINE_STEPS) {
|
|
149
|
+
if (!warnedMaxInlineStepsValues.has(raw)) {
|
|
150
|
+
warnedMaxInlineStepsValues.add(raw);
|
|
151
|
+
runtimeLogger.warn('WORKFLOW_MAX_INLINE_STEPS above maximum; clamped', {
|
|
152
|
+
raw,
|
|
153
|
+
clampedValue: MAX_MAX_INLINE_STEPS,
|
|
154
|
+
maxValue: MAX_MAX_INLINE_STEPS,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return MAX_MAX_INLINE_STEPS;
|
|
158
|
+
}
|
|
159
|
+
return parsed;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Whether optimistic inline step start is enabled. When on, the owned-inline
|
|
163
|
+
* path begins running a brand-new step's body *before* its lazy `step_started`
|
|
164
|
+
* network call resolves (the input is already known locally), awaiting the
|
|
165
|
+
* `step_started` only before the terminal write.
|
|
166
|
+
*
|
|
167
|
+
* This can run a step body more than once when handlers race for the same
|
|
168
|
+
* step's create-claim — both run the body before one wins. That is unsafe for
|
|
169
|
+
* steps with non-idempotent side effects; in particular, two concurrent runs
|
|
170
|
+
* of a step that writes to the workflow stream (e.g. an AI agent streaming
|
|
171
|
+
* tokens) can interleave and corrupt the stream data. So the optimization is
|
|
172
|
+
* **off by default** and must be explicitly opted into per deployment.
|
|
173
|
+
*
|
|
174
|
+
* Reads `process.env.WORKFLOW_OPTIMISTIC_INLINE_START` lazily. Default OFF;
|
|
175
|
+
* enabled only by an explicit `'1'` / `'true'`.
|
|
176
|
+
*/
|
|
177
|
+
export function isOptimisticInlineStartEnabled() {
|
|
178
|
+
const raw = process.env.WORKFLOW_OPTIMISTIC_INLINE_START;
|
|
179
|
+
if (raw === undefined || raw === '')
|
|
180
|
+
return false;
|
|
181
|
+
return raw === '1' || raw.toLowerCase() === 'true';
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Whether an operator has **explicitly disabled** optimistic inline start via
|
|
185
|
+
* `WORKFLOW_OPTIMISTIC_INLINE_START=0` / `=false`. Distinct from "unset": unset
|
|
186
|
+
* leaves the optimization off by default but lets turbo force it on; an explicit
|
|
187
|
+
* `0`/`false` is an operator opt-out that turbo must honor (turbo's forced
|
|
188
|
+
* optimistic start still runs a step body before `step_started`/`run_started` is
|
|
189
|
+
* confirmed, the property such an operator is opting out of), so
|
|
190
|
+
* `forceOptimisticStart` defers to this. Reads the env var lazily.
|
|
191
|
+
*/
|
|
192
|
+
export function isOptimisticInlineStartExplicitlyDisabled() {
|
|
193
|
+
const raw = process.env.WORKFLOW_OPTIMISTIC_INLINE_START;
|
|
194
|
+
if (raw === undefined || raw === '')
|
|
195
|
+
return false;
|
|
196
|
+
return raw === '0' || raw.toLowerCase() === 'false';
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Whether "turbo mode" is enabled. Turbo mode fast-paths the *first delivery of
|
|
200
|
+
* the first invocation* of a run (detected by the entrypoint via `runInput`
|
|
201
|
+
* presence + `metadata.attempt === 1`): it backgrounds the `run_started` event
|
|
202
|
+
* creation, skips the initial event-log load (nothing has been written yet),
|
|
203
|
+
* and forces optimistic inline step start for that invocation — independent of
|
|
204
|
+
* `WORKFLOW_OPTIMISTIC_INLINE_START`.
|
|
205
|
+
*
|
|
206
|
+
* Forcing optimistic start is safe here because the first delivery has no
|
|
207
|
+
* concurrent peer handler to race the step create-claim, so a step body runs
|
|
208
|
+
* exactly once. That single-handler guarantee ends as soon as the run creates a
|
|
209
|
+
* hook or wait (which introduce resume/parallel invocations), so the runtime
|
|
210
|
+
* exits turbo at that point.
|
|
211
|
+
*
|
|
212
|
+
* Reads `process.env.WORKFLOW_TURBO` lazily. Default **ON**; disabled only by an
|
|
213
|
+
* explicit `'0'` / `'false'` (case-insensitive).
|
|
214
|
+
*/
|
|
215
|
+
export function isTurboEnabled() {
|
|
216
|
+
const raw = process.env.WORKFLOW_TURBO;
|
|
217
|
+
if (raw === undefined || raw === '')
|
|
218
|
+
return true;
|
|
219
|
+
return !(raw === '0' || raw.toLowerCase() === 'false');
|
|
220
|
+
}
|
|
221
|
+
// A replay-consumer mismatch can be caused by a transient divergent replay
|
|
222
|
+
// rather than an invalid persisted history. Queue bounded recovery replays
|
|
223
|
+
// before recording terminal corruption for a run that cannot replay.
|
|
224
|
+
export const REPLAY_DIVERGENCE_MAX_RETRIES = 3;
|
|
225
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3J1bnRpbWUvY29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFN0MsNEVBQTRFO0FBQzVFLDRFQUE0RTtBQUM1RSx5RUFBeUU7QUFDekUsb0RBQW9EO0FBQ3BELEVBQUU7QUFDRixrREFBa0Q7QUFDbEQsMkVBQTJFO0FBQzNFLCtEQUErRDtBQUMvRCx3RUFBd0U7QUFDeEUsRUFBRTtBQUNGLDRFQUE0RTtBQUM1RSxxREFBcUQ7QUFDckQsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsRUFBRSxDQUFDO0FBRXZDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFDSCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxPQUFPLENBQUM7QUFFekMsMkRBQTJEO0FBQzNELE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLE1BQU0sQ0FBQztBQUU1Qzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsT0FBTyxDQUFDO0FBRTdDLDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0UsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO0FBRXBELFNBQVMsUUFBUSxDQUNmLEdBQVcsRUFDWCxPQUFlLEVBQ2YsSUFBNkI7SUFFN0IsSUFBSSx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDO1FBQUUsT0FBTztJQUMvQyx5QkFBeUIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDbkMsYUFBYSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFDcEMsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQjtJQUNoQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixD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QTJFO0FBQzNFLHFFQUFxRTtBQUNyRSxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBydW50aW1lTG9nZ2VyIH0gZnJvbSAnLi4vbG9nZ2VyLmpzJztcblxuLy8gTWF4aW11bSBudW1iZXIgb2YgcXVldWUgZGVsaXZlcnkgYXR0ZW1wdHMgYmVmb3JlIHRoZSBoYW5kbGVyIGdpdmVzIHVwIGFuZFxuLy8gZ3JhY2VmdWxseSBmYWlscyB0aGUgcnVuL3N0ZXAuIFRoaXMgbXVzdCBiZSBib3VuZGVkIHVuZGVyIHRoZSBWUVMgbWVzc2FnZVxuLy8gbWF4IHZpc2liaWxpdHkgd2luZG93ICgyNCBob3Vycykgc28gdGhhdCBvdXIgaGFuZGxlci1zaWRlIGZhaWx1cmUgcGF0aFxuLy8gcmVsaWFibHkgZXhlY3V0ZXMgYmVmb3JlIFZRUyBleHBpcmVzIHRoZSBtZXNzYWdlLlxuLy9cbi8vIFZRUyByZXRyeSBzY2hlZHVsZSAod2l0aCByZXRyeUFmdGVyU2Vjb25kczogNSk6XG4vLyAgIEF0dGVtcHRzIDHigJMzMjogIGxpbmVhciBiYWNrb2ZmIGF0IDVzIGVhY2ggIOKGkiAzMiDDlyA1cyA9IDE2MHMgKH4yLjcgbWluKVxuLy8gICBBdHRlbXB0cyAzMys6ICAgZXhwb25lbnRpYWwgYmFja29mZjogNjBzIMOXIDJeKGF0dGVtcHQtMzIpLFxuLy8gICAgICAgICAgICAgICAgICAgY2FwcGVkIGF0IDcsMjAwcyAoMmgpLCBmbG9vcmVkIGF0IHJldHJ5QWZ0ZXJTZWNvbmRzXG4vL1xuLy8gQXQgNDggYXR0ZW1wdHMgdGhlIHRvdGFsIGVsYXBzZWQgdGltZSBpcyBhcHByb3hpbWF0ZWx5IDIwIGhvdXJzLCB3aGljaCBpc1xuLy8gc2FmZWx5IHVuZGVyIHRoZSAyNC1ob3VyIG1lc3NhZ2UgdmlzaWJpbGl0eSBsaW1pdC5cbmV4cG9ydCBjb25zdCBNQVhfUVVFVUVfREVMSVZFUklFUyA9IDQ4O1xuXG4vKipcbiAqIERlZmF1bHQgbWF4aW11bSB0aW1lIGFsbG93ZWQgZm9yIHRoZSAqcmVwbGF5KiBwb3J0aW9uIG9mIGEgc2luZ2xlIHdvcmtmbG93XG4gKiBoYW5kbGVyIGludm9jYXRpb24gKGluIG1zKS4gVGhpcyBidWRnZXQgb25seSBjb3ZlcnMgZGV0ZXJtaW5pc3RpYy1yZXBsYXlcbiAqIGFuZCB3b3JrZmxvdy1WTSBleGVjdXRpb24gYmV0d2VlbiBzdGVwIGJvdW5kYXJpZXMg4oCUIGlubGluZSBzdGVwIGJvZGllc1xuICogKGBcInVzZSBzdGVwXCJgIGZ1bmN0aW9ucyBpbnZva2VkIHZpYSBgZXhlY3V0ZVN0ZXBgKSBkbyBOT1QgY291bnQgYWdhaW5zdFxuICogaXQuIFN0ZXAgYm9kaWVzIGFyZSBib3VuZGVkIHNlcGFyYXRlbHkgYnkgdGhlIHBsYXRmb3JtJ3MgZnVuY3Rpb25cbiAqIGBtYXhEdXJhdGlvbmAgKGUuZy4gODAwcyBvbiBWZXJjZWwgUHJvIEZsdWlkKSBhbmQgYE5PX0lOTElORV9SRVBMQVlfQUZURVJfTVNgLlxuICpcbiAqIElmIHRoZSBub24tc3RlcCAoXCJyZXBsYXlcIikgdGltZSB3aXRoaW4gYSBzaW5nbGUgaW52b2NhdGlvbiBleGNlZWRzIHRoaXNcbiAqIGJ1ZGdldCwgdGhlIGhhbmRsZXIgZXhpdHMgc28gdGhlIHF1ZXVlIGNhbiByZXRyeS4gQWZ0ZXJcbiAqIGBSRVBMQVlfVElNRU9VVF9NQVhfUkVUUklFU2AgZXhoYXVzdGVkIGF0dGVtcHRzIHRoZSBydW4gaXMgZmFpbGVkIHdpdGhcbiAqIGBSVU5fRVJST1JfQ09ERVMuUkVQTEFZX1RJTUVPVVRgLlxuICpcbiAqIE5vdGUgdGhhdCBvbiBWZXJjZWwgSG9iYnkgKHN0YW5kYXJkIGZ1bmN0aW9ucyksIHRoZSBwbGF0Zm9ybSBgbWF4RHVyYXRpb25gXG4gKiBpcyA2MHMg4oCUIHdlbGwgYmVsb3cgdGhpcyBidWRnZXQsIHNvIHRoZSBwbGF0Zm9ybSBTSUdURVJNIHdpbGwgZmlyZSBmaXJzdFxuICogYW5kIHRoZSBxdWV1ZSB3aWxsIHJlLWRlbGl2ZXIgdW50aWwgdGhlIHZpc2liaWxpdHkgd2luZG93IGV4cGlyZXMuIFdpdGhcbiAqIEZsdWlkIENvbXB1dGUgb24gSG9iYnkgdGhlIHBlci1mdW5jdGlvbiBjZWlsaW5nIHJpc2VzIHRvIDMwMHMsIHN0aWxsXG4gKiB1bmRlciB0aGUgZGVmYXVsdCBidWRnZXQuXG4gKlxuICogT3ZlcnJpZGUgdmlhIHRoZSBgV09SS0ZMT1dfUkVQTEFZX1RJTUVPVVRfTVNgIGVudiB2YXIgKGNsYW1wZWQgdG9cbiAqIGBNSU5fUkVQTEFZX1RJTUVPVVRfTVNgLi5gTUFYX1JFUExBWV9USU1FT1VUX01TYCkuXG4gKi9cbmV4cG9ydCBjb25zdCBSRVBMQVlfVElNRU9VVF9NUyA9IDI0MF8wMDA7XG5cbi8qKiBMb3dlciBib3VuZCBmb3IgdGhlIHJlcGxheS10aW1lb3V0IGVudiB2YXIgb3ZlcnJpZGUuICovXG5leHBvcnQgY29uc3QgTUlOX1JFUExBWV9USU1FT1VUX01TID0gMzBfMDAwO1xuXG4vKipcbiAqIFVwcGVyIGJvdW5kIGZvciB0aGUgcmVwbGF5LXRpbWVvdXQgZW52IHZhciBvdmVycmlkZS4gNzgwcyBsZWF2ZXMg4omlMjBzIG9mXG4gKiBoZWFkcm9vbSB1bmRlciBWZXJjZWwgUHJvIEZsdWlkJ3MgODAwcyBmdW5jdGlvbiBjZWlsaW5nIHNvIHRoZSBoYW5kbGVyXG4gKiBjYW4gd3JpdGUgYHJ1bl9mYWlsZWRgIGJlZm9yZSBTSUdURVJNLlxuICovXG5leHBvcnQgY29uc3QgTUFYX1JFUExBWV9USU1FT1VUX01TID0gNzgwXzAwMDtcblxuLy8gVHJhY2sgd2hpY2ggcmF3IGVudiB2YXIgdmFsdWVzIHdlJ3ZlIGFscmVhZHkgd2FybmVkIGFib3V0IHNvIHRoZSB3YXJuaW5nXG4vLyBsb2cgb25seSBmaXJlcyBvbmNlIHBlciBwcm9jZXNzICh0aGUgZnVuY3Rpb24gbWF5IGJlIGNhbGxlZCBtYW55IHRpbWVzKS5cbmNvbnN0IHdhcm5lZFJlcGxheVRpbWVvdXRWYWx1ZXMgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuZnVuY3Rpb24gd2Fybk9uY2UoXG4gIHJhdzogc3RyaW5nLFxuICBtZXNzYWdlOiBzdHJpbmcsXG4gIGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+XG4pOiB2b2lkIHtcbiAgaWYgKHdhcm5lZFJlcGxheVRpbWVvdXRWYWx1ZXMuaGFzKHJhdykpIHJldHVybjtcbiAgd2FybmVkUmVwbGF5VGltZW91dFZhbHVlcy5hZGQocmF3KTtcbiAgcnVudGltZUxvZ2dlci53YXJuKG1lc3NhZ2UsIGRhdGEpO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSByZXBsYXktdGltZW91dCBidWRnZXQgZm9yIHRoZSBjdXJyZW50IHByb2Nlc3MuXG4gKlxuICogUmVhZHMgYHByb2Nlc3MuZW52LldPUktGTE9XX1JFUExBWV9USU1FT1VUX01TYCBsYXppbHkgc28gdGVzdHMgYW5kXG4gKiBkZXBsb3ltZW50cyBjYW4gb3ZlcnJpZGUgcGVyIGludm9jYXRpb24uIEludmFsaWQgLyBvdXQtb2YtcmFuZ2UgdmFsdWVzXG4gKiBmYWxsIGJhY2sgdG8gYSBzYWZlIHZhbHVlIChubyB0aHJvdyDigJQgdGhlIGVudiB2YXIgaXMgYW4gZXNjYXBlIGhhdGNoLFxuICogbm90IGEgaGFyZCByZXF1aXJlbWVudCkgYW5kIGVtaXQgYSBvbmUtdGltZSB3YXJuaW5nIHNvIG1pc2NvbmZpZ3VyYXRpb25cbiAqIGlzIG9ic2VydmFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRSZXBsYXlUaW1lb3V0TXMoKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gcHJvY2Vzcy5lbnYuV09SS0ZMT1dfUkVQTEFZX1RJTUVPVVRfTVM7XG4gIGlmICghcmF3KSByZXR1cm4gUkVQTEFZX1RJTUVPVVRfTVM7XG4gIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyYXcpO1xuICBpZiAoIU51bWJlci5pc0Zpbml0ZShwYXJzZWQpIHx8IHBhcnNlZCA8PSAwKSB7XG4gICAgd2Fybk9uY2UoXG4gICAgICByYXcsXG4gICAgICAnSWdub3JpbmcgV09SS0ZMT1dfUkVQTEFZX1RJTUVPVVRfTVM6IG5vdCBhIHBvc2l0aXZlIGZpbml0ZSBudW1iZXI7IHVzaW5nIGRlZmF1bHQnLFxuICAgICAgeyByYXcsIGRlZmF1bHRNczogUkVQTEFZX1RJTUVPVVRfTVMgfVxuICAgICk7XG4gICAgcmV0dXJuIFJFUExBWV9USU1FT1VUX01TO1xuICB9XG4gIGlmIChwYXJzZWQgPCBNSU5fUkVQTEFZX1RJTUVPVVRfTVMpIHtcbiAgICB3YXJuT25jZShyYXcsICdXT1JLRkxPV19SRVBMQVlfVElNRU9VVF9NUyBiZWxvdyBtaW5pbXVtOyBjbGFtcGVkJywge1xuICAgICAgcmF3LFxuICAgICAgY2xhbXBlZE1zOiBNSU5fUkVQTEFZX1RJTUVPVVRfTVMsXG4gICAgICBtaW5NczogTUlOX1JFUExBWV9USU1FT1VUX01TLFxuICAgIH0pO1xuICAgIHJldHVybiBNSU5fUkVQTEFZX1RJTUVPVVRfTVM7XG4gIH1cbiAgaWYgKHBhcnNlZCA+IE1BWF9SRVBMQVlfVElNRU9VVF9NUykge1xuICAgIHdhcm5PbmNlKHJhdywgJ1dPUktGTE9XX1JFUExBWV9USU1FT1VUX01TIGFib3ZlIG1heGltdW07IGNsYW1wZWQnLCB7XG4gICAgICByYXcsXG4gICAgICBjbGFtcGVkTXM6IE1BWF9SRVBMQVlfVElNRU9VVF9NUyxcbiAgICAgIG1heE1zOiBNQVhfUkVQTEFZX1RJTUVPVVRfTVMsXG4gICAgfSk7XG4gICAgcmV0dXJuIE1BWF9SRVBMQVlfVElNRU9VVF9NUztcbiAgfVxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIFJlc2V0IHRoZSB3YXJuLW9uY2UgY2FjaGUuIFRlc3Qtb25seSDigJQgZXhwb3J0ZWQgc28gdW5pdCB0ZXN0cyBjYW5cbiAqIGV4ZXJjaXNlIHRoZSB3YXJuIHBhdGggcmVwZWF0ZWRseSB3aXRob3V0IHNoYXJpbmcgc3RhdGUuXG4gKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBfcmVzZXRSZXBsYXlUaW1lb3V0V2FybkNhY2hlRm9yVGVzdHMoKTogdm9pZCB7XG4gIHdhcm5lZFJlcGxheVRpbWVvdXRWYWx1ZXMuY2xlYXIoKTtcbn1cblxuLy8gTnVtYmVyIG9mIHF1ZXVlIGRlbGl2ZXJ5IGF0dGVtcHRzIHRvIGFsbG93IGJlZm9yZSBwZXJtYW5lbnRseSBmYWlsaW5nIGEgcnVuXG4vLyBkdWUgdG8gYSByZXBsYXkgdGltZW91dC4gT24gYXR0ZW1wdHMgMSB0aHJvdWdoIHRoaXMgdmFsdWUsIHRoZSB0aW1lb3V0XG4vLyBoYW5kbGVyIGV4aXRzIHdpdGhvdXQgd3JpdGluZyBydW5fZmFpbGVkIHNvIHRoZSBxdWV1ZSByZXRyaWVzIHRoZSBtZXNzYWdlLlxuLy8gT24gdGhlIG5leHQgYXR0ZW1wdCB0aGUgcnVuIGlzIG1hcmtlZCBhcyBmYWlsZWQuXG5leHBvcnQgY29uc3QgUkVQTEFZX1RJTUVPVVRfTUFYX1JFVFJJRVMgPSAzO1xuXG4vKipcbiAqIERlZmF1bHQgbWF4aW11bSBudW1iZXIgb2Ygc3RlcHMgdGhlIG93bmVkLWlubGluZSBwYXRoIHJ1bnMgaW5saW5lIChpblxuICogcGFyYWxsZWwpIHBlciBzdXNwZW5zaW9uLiBUaGUgcmVzdCBhcmUgcXVldWVkIHRvIGJhY2tncm91bmQgaGFuZGxlcnMuIEVhY2hcbiAqIGlubGluZSBzdGVwIGlzIGNyZWF0ZWQgbGF6aWx5IOKAlCBpdHMgYHN0ZXBfY3JlYXRlZGAgaXMgZm9sZGVkIGludG8gdGhlXG4gKiBgc3RlcF9zdGFydGVkYCB0aGF0IGBleGVjdXRlU3RlcGAgc2VuZHMg4oCUIHNvIGlubGluaW5nIE4gc3RlcHMgc2F2ZXMgTiBxdWV1ZVxuICogcm91bmQtdHJpcHMgZm9yIGEgYFByb21pc2UuYWxsYC1zdHlsZSBmYW4tb3V0LiBgMWAgcmVwcm9kdWNlcyB0aGVcbiAqIHNpbmdsZS1pbmxpbmUtc3RlcCBiZWhhdmlvciBleGFjdGx5ICh1c2VmdWwga2lsbC1zd2l0Y2gpLlxuICpcbiAqIE92ZXJyaWRlIHZpYSBgV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQU2AgKGNsYW1wZWQgdG9cbiAqIGBNSU5fTUFYX0lOTElORV9TVEVQU2AuLmBNQVhfTUFYX0lOTElORV9TVEVQU2ApLlxuICovXG5leHBvcnQgY29uc3QgTUFYX0lOTElORV9TVEVQUyA9IDM7XG5cbi8qKiBMb3dlciBib3VuZCBmb3IgdGhlIGlubGluZS1zdGVwcyBlbnYgb3ZlcnJpZGUgKDEgPSBzaW5nbGUgaW5saW5lIHN0ZXApLiAqL1xuZXhwb3J0IGNvbnN0IE1JTl9NQVhfSU5MSU5FX1NURVBTID0gMTtcblxuLyoqXG4gKiBVcHBlciBib3VuZCBmb3IgdGhlIGlubGluZS1zdGVwcyBlbnYgb3ZlcnJpZGUuIElubGluZSBib2RpZXMgcnVuIGluIHBhcmFsbGVsXG4gKiB3aXRoaW4gb25lIGZ1bmN0aW9uIGludm9jYXRpb24sIHNvIHRoaXMgY2FwcyBtZW1vcnkvQ1BVIGZhbi1vdXQgcGVyIGhhbmRsZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBNQVhfTUFYX0lOTElORV9TVEVQUyA9IDE2O1xuXG4vLyBXYXJuLW9uY2UgY2FjaGUgZm9yIFdPUktGTE9XX01BWF9JTkxJTkVfU1RFUFMsIGtleWVkIGJ5IHJhdyBlbnYgdmFsdWUuXG5jb25zdCB3YXJuZWRNYXhJbmxpbmVTdGVwc1ZhbHVlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSBtYXggbnVtYmVyIG9mIGlubGluZSBzdGVwcyBmb3IgdGhlIGN1cnJlbnQgcHJvY2Vzcy5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQU2AgbGF6aWx5IHNvIHRlc3RzIGFuZFxuICogZGVwbG95bWVudHMgY2FuIG92ZXJyaWRlIHBlciBpbnZvY2F0aW9uLiBJbnZhbGlkIC8gb3V0LW9mLXJhbmdlIHZhbHVlcyBmYWxsXG4gKiBiYWNrIHRvIGEgc2FmZSB2YWx1ZSAobm8gdGhyb3cg4oCUIHRoZSBlbnYgdmFyIGlzIGFuIGVzY2FwZSBoYXRjaCkgYW5kIGVtaXQgYVxuICogb25lLXRpbWUgd2FybmluZyBzbyBtaXNjb25maWd1cmF0aW9uIGlzIG9ic2VydmFibGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRNYXhJbmxpbmVTdGVwcygpOiBudW1iZXIge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTO1xuICBpZiAoIXJhdykgcmV0dXJuIE1BWF9JTkxJTkVfU1RFUFM7XG4gIGNvbnN0IHBhcnNlZCA9IE51bWJlcihyYXcpO1xuICBpZiAoIU51bWJlci5pc0ludGVnZXIocGFyc2VkKSB8fCBwYXJzZWQgPD0gMCkge1xuICAgIGlmICghd2FybmVkTWF4SW5saW5lU3RlcHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZE1heElubGluZVN0ZXBzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKFxuICAgICAgICAnSWdub3JpbmcgV09SS0ZMT1dfTUFYX0lOTElORV9TVEVQUzogbm90IGEgcG9zaXRpdmUgaW50ZWdlcjsgdXNpbmcgZGVmYXVsdCcsXG4gICAgICAgIHsgcmF3LCBkZWZhdWx0VmFsdWU6IE1BWF9JTkxJTkVfU1RFUFMgfVxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIE1BWF9JTkxJTkVfU1RFUFM7XG4gIH1cbiAgaWYgKHBhcnNlZCA8IE1JTl9NQVhfSU5MSU5FX1NURVBTKSByZXR1cm4gTUlOX01BWF9JTkxJTkVfU1RFUFM7XG4gIGlmIChwYXJzZWQgPiBNQVhfTUFYX0lOTElORV9TVEVQUykge1xuICAgIGlmICghd2FybmVkTWF4SW5saW5lU3RlcHNWYWx1ZXMuaGFzKHJhdykpIHtcbiAgICAgIHdhcm5lZE1heElubGluZVN0ZXBzVmFsdWVzLmFkZChyYXcpO1xuICAgICAgcnVudGltZUxvZ2dlci53YXJuKCdXT1JLRkxPV19NQVhfSU5MSU5FX1NURVBTIGFib3ZlIG1heGltdW07IGNsYW1wZWQnLCB7XG4gICAgICAgIHJhdyxcbiAgICAgICAgY2xhbXBlZFZhbHVlOiBNQVhfTUFYX0lOTElORV9TVEVQUyxcbiAgICAgICAgbWF4VmFsdWU6IE1BWF9NQVhfSU5MSU5FX1NURVBTLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBNQVhfTUFYX0lOTElORV9TVEVQUztcbiAgfVxuICByZXR1cm4gcGFyc2VkO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgb3B0aW1pc3RpYyBpbmxpbmUgc3RlcCBzdGFydCBpcyBlbmFibGVkLiBXaGVuIG9uLCB0aGUgb3duZWQtaW5saW5lXG4gKiBwYXRoIGJlZ2lucyBydW5uaW5nIGEgYnJhbmQtbmV3IHN0ZXAncyBib2R5ICpiZWZvcmUqIGl0cyBsYXp5IGBzdGVwX3N0YXJ0ZWRgXG4gKiBuZXR3b3JrIGNhbGwgcmVzb2x2ZXMgKHRoZSBpbnB1dCBpcyBhbHJlYWR5IGtub3duIGxvY2FsbHkpLCBhd2FpdGluZyB0aGVcbiAqIGBzdGVwX3N0YXJ0ZWRgIG9ubHkgYmVmb3JlIHRoZSB0ZXJtaW5hbCB3cml0ZS5cbiAqXG4gKiBUaGlzIGNhbiBydW4gYSBzdGVwIGJvZHkgbW9yZSB0aGFuIG9uY2Ugd2hlbiBoYW5kbGVycyByYWNlIGZvciB0aGUgc2FtZVxuICogc3RlcCdzIGNyZWF0ZS1jbGFpbSDigJQgYm90aCBydW4gdGhlIGJvZHkgYmVmb3JlIG9uZSB3aW5zLiBUaGF0IGlzIHVuc2FmZSBmb3JcbiAqIHN0ZXBzIHdpdGggbm9uLWlkZW1wb3RlbnQgc2lkZSBlZmZlY3RzOyBpbiBwYXJ0aWN1bGFyLCB0d28gY29uY3VycmVudCBydW5zXG4gKiBvZiBhIHN0ZXAgdGhhdCB3cml0ZXMgdG8gdGhlIHdvcmtmbG93IHN0cmVhbSAoZS5nLiBhbiBBSSBhZ2VudCBzdHJlYW1pbmdcbiAqIHRva2VucykgY2FuIGludGVybGVhdmUgYW5kIGNvcnJ1cHQgdGhlIHN0cmVhbSBkYXRhLiBTbyB0aGUgb3B0aW1pemF0aW9uIGlzXG4gKiAqKm9mZiBieSBkZWZhdWx0KiogYW5kIG11c3QgYmUgZXhwbGljaXRseSBvcHRlZCBpbnRvIHBlciBkZXBsb3ltZW50LlxuICpcbiAqIFJlYWRzIGBwcm9jZXNzLmVudi5XT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVGAgbGF6aWx5LiBEZWZhdWx0IE9GRjtcbiAqIGVuYWJsZWQgb25seSBieSBhbiBleHBsaWNpdCBgJzEnYCAvIGAndHJ1ZSdgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcHRpbWlzdGljSW5saW5lU3RhcnRFbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19PUFRJTUlTVElDX0lOTElORV9TVEFSVDtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHJhdyA9PT0gJzEnIHx8IHJhdy50b0xvd2VyQ2FzZSgpID09PSAndHJ1ZSc7XG59XG5cbi8qKlxuICogV2hldGhlciBhbiBvcGVyYXRvciBoYXMgKipleHBsaWNpdGx5IGRpc2FibGVkKiogb3B0aW1pc3RpYyBpbmxpbmUgc3RhcnQgdmlhXG4gKiBgV09SS0ZMT1dfT1BUSU1JU1RJQ19JTkxJTkVfU1RBUlQ9MGAgLyBgPWZhbHNlYC4gRGlzdGluY3QgZnJvbSBcInVuc2V0XCI6IHVuc2V0XG4gKiBsZWF2ZXMgdGhlIG9wdGltaXphdGlvbiBvZmYgYnkgZGVmYXVsdCBidXQgbGV0cyB0dXJibyBmb3JjZSBpdCBvbjsgYW4gZXhwbGljaXRcbiAqIGAwYC9gZmFsc2VgIGlzIGFuIG9wZXJhdG9yIG9wdC1vdXQgdGhhdCB0dXJibyBtdXN0IGhvbm9yICh0dXJibydzIGZvcmNlZFxuICogb3B0aW1pc3RpYyBzdGFydCBzdGlsbCBydW5zIGEgc3RlcCBib2R5IGJlZm9yZSBgc3RlcF9zdGFydGVkYC9gcnVuX3N0YXJ0ZWRgIGlzXG4gKiBjb25maXJtZWQsIHRoZSBwcm9wZXJ0eSBzdWNoIGFuIG9wZXJhdG9yIGlzIG9wdGluZyBvdXQgb2YpLCBzb1xuICogYGZvcmNlT3B0aW1pc3RpY1N0YXJ0YCBkZWZlcnMgdG8gdGhpcy4gUmVhZHMgdGhlIGVudiB2YXIgbGF6aWx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNPcHRpbWlzdGljSW5saW5lU3RhcnRFeHBsaWNpdGx5RGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LldPUktGTE9XX09QVElNSVNUSUNfSU5MSU5FX1NUQVJUO1xuICBpZiAocmF3ID09PSB1bmRlZmluZWQgfHwgcmF3ID09PSAnJykgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gcmF3ID09PSAnMCcgfHwgcmF3LnRvTG93ZXJDYXNlKCkgPT09ICdmYWxzZSc7XG59XG5cbi8qKlxuICogV2hldGhlciBcInR1cmJvIG1vZGVcIiBpcyBlbmFibGVkLiBUdXJibyBtb2RlIGZhc3QtcGF0aHMgdGhlICpmaXJzdCBkZWxpdmVyeSBvZlxuICogdGhlIGZpcnN0IGludm9jYXRpb24qIG9mIGEgcnVuIChkZXRlY3RlZCBieSB0aGUgZW50cnlwb2ludCB2aWEgYHJ1bklucHV0YFxuICogcHJlc2VuY2UgKyBgbWV0YWRhdGEuYXR0ZW1wdCA9PT0gMWApOiBpdCBiYWNrZ3JvdW5kcyB0aGUgYHJ1bl9zdGFydGVkYCBldmVudFxuICogY3JlYXRpb24sIHNraXBzIHRoZSBpbml0aWFsIGV2ZW50LWxvZyBsb2FkIChub3RoaW5nIGhhcyBiZWVuIHdyaXR0ZW4geWV0KSxcbiAqIGFuZCBmb3JjZXMgb3B0aW1pc3RpYyBpbmxpbmUgc3RlcCBzdGFydCBmb3IgdGhhdCBpbnZvY2F0aW9uIOKAlCBpbmRlcGVuZGVudCBvZlxuICogYFdPUktGTE9XX09QVElNSVNUSUNfSU5MSU5FX1NUQVJUYC5cbiAqXG4gKiBGb3JjaW5nIG9wdGltaXN0aWMgc3RhcnQgaXMgc2FmZSBoZXJlIGJlY2F1c2UgdGhlIGZpcnN0IGRlbGl2ZXJ5IGhhcyBub1xuICogY29uY3VycmVudCBwZWVyIGhhbmRsZXIgdG8gcmFjZSB0aGUgc3RlcCBjcmVhdGUtY2xhaW0sIHNvIGEgc3RlcCBib2R5IHJ1bnNcbiAqIGV4YWN0bHkgb25jZS4gVGhhdCBzaW5nbGUtaGFuZGxlciBndWFyYW50ZWUgZW5kcyBhcyBzb29uIGFzIHRoZSBydW4gY3JlYXRlcyBhXG4gKiBob29rIG9yIHdhaXQgKHdoaWNoIGludHJvZHVjZSByZXN1bWUvcGFyYWxsZWwgaW52b2NhdGlvbnMpLCBzbyB0aGUgcnVudGltZVxuICogZXhpdHMgdHVyYm8gYXQgdGhhdCBwb2ludC5cbiAqXG4gKiBSZWFkcyBgcHJvY2Vzcy5lbnYuV09SS0ZMT1dfVFVSQk9gIGxhemlseS4gRGVmYXVsdCAqKk9OKio7IGRpc2FibGVkIG9ubHkgYnkgYW5cbiAqIGV4cGxpY2l0IGAnMCdgIC8gYCdmYWxzZSdgIChjYXNlLWluc2Vuc2l0aXZlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVHVyYm9FbmFibGVkKCk6IGJvb2xlYW4ge1xuICBjb25zdCByYXcgPSBwcm9jZXNzLmVudi5XT1JLRkxPV19UVVJCTztcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdyA9PT0gJycpIHJldHVybiB0cnVlO1xuICByZXR1cm4gIShyYXcgPT09ICcwJyB8fCByYXcudG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJyk7XG59XG5cbi8vIEEgcmVwbGF5LWNvbnN1bWVyIG1pc21hdGNoIGNhbiBiZSBjYXVzZWQgYnkgYSB0cmFuc2llbnQgZGl2ZXJnZW50IHJlcGxheVxuLy8gcmF0aGVyIHRoYW4gYW4gaW52YWxpZCBwZXJzaXN0ZWQgaGlzdG9yeS4gUXVldWUgYm91bmRlZCByZWNvdmVyeSByZXBsYXlzXG4vLyBiZWZvcmUgcmVjb3JkaW5nIHRlcm1pbmFsIGNvcnJ1cHRpb24gZm9yIGEgcnVuIHRoYXQgY2Fubm90IHJlcGxheS5cbmV4cG9ydCBjb25zdCBSRVBMQVlfRElWRVJHRU5DRV9NQVhfUkVUUklFUyA9IDM7XG4iXX0=
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy loader for getPort that prevents bundlers (Turbopack, esbuild)
|
|
3
|
+
* from statically tracing @workflow/utils/get-port and its filesystem
|
|
4
|
+
* operations (readdir, readFile, readlink) into the flow route bundle.
|
|
5
|
+
*
|
|
6
|
+
* Uses createRequire with a dynamically constructed specifier so the
|
|
7
|
+
* dependency is invisible to bundler static analysis.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getPortLazy(): Promise<number | undefined>;
|
|
10
|
+
/**
|
|
11
|
+
* Resets the per-process port cache. Intended for tests; not used on the hot
|
|
12
|
+
* path. Callers must let any in-flight lookup settle (await the pending
|
|
13
|
+
* `getPortLazy()` call) before resetting: clearing `_inFlight` here does not
|
|
14
|
+
* cancel an already-scheduled resolution, so a late `.then` could otherwise
|
|
15
|
+
* repopulate `_cachedPort` after the reset and bleed into the next test.
|
|
16
|
+
*/
|
|
17
|
+
export declare function resetPortCacheForTesting(): void;
|
|
18
|
+
/**
|
|
19
|
+
* Installs a fake port resolver and clears the cache. Test-only seam: the real
|
|
20
|
+
* resolver is loaded via `createRequire` with a runtime-built specifier (to
|
|
21
|
+
* hide it from bundlers), which also defeats module mocking, so injection is
|
|
22
|
+
* the only deterministic way to exercise the caching contract.
|
|
23
|
+
*/
|
|
24
|
+
export declare function setPortResolverForTesting(fn: () => Promise<number | undefined>): void;
|
|
25
|
+
//# sourceMappingURL=get-port-lazy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-port-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/get-port-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,wBAAsB,WAAW,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4C/D;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAI/C;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GACpC,IAAI,CAIN"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy loader for getPort that prevents bundlers (Turbopack, esbuild)
|
|
3
|
+
* from statically tracing @workflow/utils/get-port and its filesystem
|
|
4
|
+
* operations (readdir, readFile, readlink) into the flow route bundle.
|
|
5
|
+
*
|
|
6
|
+
* Uses createRequire with a dynamically constructed specifier so the
|
|
7
|
+
* dependency is invisible to bundler static analysis.
|
|
8
|
+
*/
|
|
9
|
+
import { createRequire } from 'node:module';
|
|
10
|
+
import { pathToFileURL } from 'node:url';
|
|
11
|
+
let _getPort;
|
|
12
|
+
// Per-process cache of the resolved port. The workflow dev server listens on a
|
|
13
|
+
// stable port for the lifetime of the process, but `getPort()` rediscovers it
|
|
14
|
+
// on every call by querying the OS for the process's listening sockets — on
|
|
15
|
+
// macOS that shells out to `lsof` (~60ms), which the runtime pays on EVERY
|
|
16
|
+
// workflow replay (the non-Vercel branch of `runWorkflow`). Since the port does
|
|
17
|
+
// not change within a process, resolve it once and reuse it. `_inFlight`
|
|
18
|
+
// dedupes concurrent first calls so discovery never runs more than once.
|
|
19
|
+
//
|
|
20
|
+
// The first concrete port is pinned for the lifetime of the process — there is
|
|
21
|
+
// no per-call re-resolution. This is safe because the runtime only runs inside
|
|
22
|
+
// the already-listening dev-server process, and `getPort()` -> `getAllPorts()`
|
|
23
|
+
// returns a deterministic order, so repeated calls would resolve the same port
|
|
24
|
+
// anyway.
|
|
25
|
+
let _cachedPort;
|
|
26
|
+
let _inFlight;
|
|
27
|
+
export async function getPortLazy() {
|
|
28
|
+
// Fast path: already resolved a concrete port for this process.
|
|
29
|
+
if (_cachedPort !== undefined) {
|
|
30
|
+
return _cachedPort;
|
|
31
|
+
}
|
|
32
|
+
// A discovery is already running — share it rather than starting a second.
|
|
33
|
+
if (_inFlight) {
|
|
34
|
+
return _inFlight;
|
|
35
|
+
}
|
|
36
|
+
if (!_getPort) {
|
|
37
|
+
try {
|
|
38
|
+
// Construct specifier at runtime to defeat bundler static analysis.
|
|
39
|
+
const spec = ['@workflow/utils', 'get-port'].join('/');
|
|
40
|
+
// Use process.cwd()-based createRequire for CJS/ESM compatibility.
|
|
41
|
+
// import.meta.url is unavailable in CJS re-bundled outputs.
|
|
42
|
+
const _require = createRequire(pathToFileURL(process.cwd() + '/package.json').href);
|
|
43
|
+
const mod = _require(spec);
|
|
44
|
+
_getPort = mod.getPort;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Module not available (e.g., in a browser or minimal bundle)
|
|
48
|
+
_getPort = async () => undefined;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// `_getPort` is always assigned by the block above; the fallback keeps the
|
|
52
|
+
// type non-nullable without a non-null assertion.
|
|
53
|
+
const resolver = _getPort ?? (async () => undefined);
|
|
54
|
+
_inFlight = resolver()
|
|
55
|
+
.then((port) => {
|
|
56
|
+
// Only cache a concrete port. A transient `undefined` (e.g. the server is
|
|
57
|
+
// not listening yet on the very first replay) must not poison the cache —
|
|
58
|
+
// leaving it unset lets the next call retry discovery.
|
|
59
|
+
if (typeof port === 'number') {
|
|
60
|
+
_cachedPort = port;
|
|
61
|
+
}
|
|
62
|
+
return port;
|
|
63
|
+
})
|
|
64
|
+
.finally(() => {
|
|
65
|
+
_inFlight = undefined;
|
|
66
|
+
});
|
|
67
|
+
return _inFlight;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Resets the per-process port cache. Intended for tests; not used on the hot
|
|
71
|
+
* path. Callers must let any in-flight lookup settle (await the pending
|
|
72
|
+
* `getPortLazy()` call) before resetting: clearing `_inFlight` here does not
|
|
73
|
+
* cancel an already-scheduled resolution, so a late `.then` could otherwise
|
|
74
|
+
* repopulate `_cachedPort` after the reset and bleed into the next test.
|
|
75
|
+
*/
|
|
76
|
+
export function resetPortCacheForTesting() {
|
|
77
|
+
_getPort = undefined;
|
|
78
|
+
_cachedPort = undefined;
|
|
79
|
+
_inFlight = undefined;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Installs a fake port resolver and clears the cache. Test-only seam: the real
|
|
83
|
+
* resolver is loaded via `createRequire` with a runtime-built specifier (to
|
|
84
|
+
* hide it from bundlers), which also defeats module mocking, so injection is
|
|
85
|
+
* the only deterministic way to exercise the caching contract.
|
|
86
|
+
*/
|
|
87
|
+
export function setPortResolverForTesting(fn) {
|
|
88
|
+
_getPort = fn;
|
|
89
|
+
_cachedPort = undefined;
|
|
90
|
+
_inFlight = undefined;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXBvcnQtbGF6eS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2dldC1wb3J0LWxhenkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDNUMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUV6QyxJQUFJLFFBQXlELENBQUM7QUFFOUQsK0VBQStFO0FBQy9FLDhFQUE4RTtBQUM5RSw0RUFBNEU7QUFDNUUsMkVBQTJFO0FBQzNFLGdGQUFnRjtBQUNoRix5RUFBeUU7QUFDekUseUVBQXlFO0FBQ3pFLEVBQUU7QUFDRiwrRUFBK0U7QUFDL0UsK0VBQStFO0FBQy9FLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsVUFBVTtBQUNWLElBQUksV0FBK0IsQ0FBQztBQUNwQyxJQUFJLFNBQWtELENBQUM7QUFFdkQsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXO0lBQy9CLGdFQUFnRTtJQUNoRSxJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUM5QixPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBQ0QsMkVBQTJFO0lBQzNFLElBQUksU0FBUyxFQUFFLENBQUM7UUFDZCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ2QsSUFBSSxDQUFDO1lBQ0gsb0VBQW9FO1lBQ3BFLE1BQU0sSUFBSSxHQUFHLENBQUMsaUJBQWlCLEVBQUUsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZELG1FQUFtRTtZQUNuRSw0REFBNEQ7WUFDNUQsTUFBTSxRQUFRLEdBQUcsYUFBYSxDQUM1QixhQUFhLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxHQUFHLGVBQWUsQ0FBQyxDQUFDLElBQUksQ0FDcEQsQ0FBQztZQUNGLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixRQUFRLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQztRQUN6QixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsOERBQThEO1lBQzlELFFBQVEsR0FBRyxLQUFLLElBQUksRUFBRSxDQUFDLFNBQVMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSxrREFBa0Q7SUFDbEQsTUFBTSxRQUFRLEdBQUcsUUFBUSxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNyRCxTQUFTLEdBQUcsUUFBUSxFQUFFO1NBQ25CLElBQUksQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQ2IsMEVBQTBFO1FBQzFFLDBFQUEwRTtRQUMxRSx1REFBdUQ7UUFDdkQsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM3QixXQUFXLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUMsQ0FBQztTQUNELE9BQU8sQ0FBQyxHQUFHLEVBQUU7UUFDWixTQUFTLEdBQUcsU0FBUyxDQUFDO0lBQ3hCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSx3QkFBd0I7SUFDdEMsUUFBUSxHQUFHLFNBQVMsQ0FBQztJQUNyQixXQUFXLEdBQUcsU0FBUyxDQUFDO0lBQ3hCLFNBQVMsR0FBRyxTQUFTLENBQUM7QUFDeEIsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLHlCQUF5QixDQUN2QyxFQUFxQztJQUVyQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0lBQ2QsV0FBVyxHQUFHLFNBQVMsQ0FBQztJQUN4QixTQUFTLEdBQUcsU0FBUyxDQUFDO0FBQ3hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExhenkgbG9hZGVyIGZvciBnZXRQb3J0IHRoYXQgcHJldmVudHMgYnVuZGxlcnMgKFR1cmJvcGFjaywgZXNidWlsZClcbiAqIGZyb20gc3RhdGljYWxseSB0cmFjaW5nIEB3b3JrZmxvdy91dGlscy9nZXQtcG9ydCBhbmQgaXRzIGZpbGVzeXN0ZW1cbiAqIG9wZXJhdGlvbnMgKHJlYWRkaXIsIHJlYWRGaWxlLCByZWFkbGluaykgaW50byB0aGUgZmxvdyByb3V0ZSBidW5kbGUuXG4gKlxuICogVXNlcyBjcmVhdGVSZXF1aXJlIHdpdGggYSBkeW5hbWljYWxseSBjb25zdHJ1Y3RlZCBzcGVjaWZpZXIgc28gdGhlXG4gKiBkZXBlbmRlbmN5IGlzIGludmlzaWJsZSB0byBidW5kbGVyIHN0YXRpYyBhbmFseXNpcy5cbiAqL1xuXG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSAnbm9kZTptb2R1bGUnO1xuaW1wb3J0IHsgcGF0aFRvRmlsZVVSTCB9IGZyb20gJ25vZGU6dXJsJztcblxubGV0IF9nZXRQb3J0OiAoKCkgPT4gUHJvbWlzZTxudW1iZXIgfCB1bmRlZmluZWQ+KSB8IHVuZGVmaW5lZDtcblxuLy8gUGVyLXByb2Nlc3MgY2FjaGUgb2YgdGhlIHJlc29sdmVkIHBvcnQuIFRoZSB3b3JrZmxvdyBkZXYgc2VydmVyIGxpc3RlbnMgb24gYVxuLy8gc3RhYmxlIHBvcnQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcHJvY2VzcywgYnV0IGBnZXRQb3J0KClgIHJlZGlzY292ZXJzIGl0XG4vLyBvbiBldmVyeSBjYWxsIGJ5IHF1ZXJ5aW5nIHRoZSBPUyBmb3IgdGhlIHByb2Nlc3MncyBsaXN0ZW5pbmcgc29ja2V0cyDigJQgb25cbi8vIG1hY09TIHRoYXQgc2hlbGxzIG91dCB0byBgbHNvZmAgKH42MG1zKSwgd2hpY2ggdGhlIHJ1bnRpbWUgcGF5cyBvbiBFVkVSWVxuLy8gd29ya2Zsb3cgcmVwbGF5ICh0aGUgbm9uLVZlcmNlbCBicmFuY2ggb2YgYHJ1bldvcmtmbG93YCkuIFNpbmNlIHRoZSBwb3J0IGRvZXNcbi8vIG5vdCBjaGFuZ2Ugd2l0aGluIGEgcHJvY2VzcywgcmVzb2x2ZSBpdCBvbmNlIGFuZCByZXVzZSBpdC4gYF9pbkZsaWdodGBcbi8vIGRlZHVwZXMgY29uY3VycmVudCBmaXJzdCBjYWxscyBzbyBkaXNjb3ZlcnkgbmV2ZXIgcnVucyBtb3JlIHRoYW4gb25jZS5cbi8vXG4vLyBUaGUgZmlyc3QgY29uY3JldGUgcG9ydCBpcyBwaW5uZWQgZm9yIHRoZSBsaWZldGltZSBvZiB0aGUgcHJvY2VzcyDigJQgdGhlcmUgaXNcbi8vIG5vIHBlci1jYWxsIHJlLXJlc29sdXRpb24uIFRoaXMgaXMgc2FmZSBiZWNhdXNlIHRoZSBydW50aW1lIG9ubHkgcnVucyBpbnNpZGVcbi8vIHRoZSBhbHJlYWR5LWxpc3RlbmluZyBkZXYtc2VydmVyIHByb2Nlc3MsIGFuZCBgZ2V0UG9ydCgpYCAtPiBgZ2V0QWxsUG9ydHMoKWBcbi8vIHJldHVybnMgYSBkZXRlcm1pbmlzdGljIG9yZGVyLCBzbyByZXBlYXRlZCBjYWxscyB3b3VsZCByZXNvbHZlIHRoZSBzYW1lIHBvcnRcbi8vIGFueXdheS5cbmxldCBfY2FjaGVkUG9ydDogbnVtYmVyIHwgdW5kZWZpbmVkO1xubGV0IF9pbkZsaWdodDogUHJvbWlzZTxudW1iZXIgfCB1bmRlZmluZWQ+IHwgdW5kZWZpbmVkO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0UG9ydExhenkoKTogUHJvbWlzZTxudW1iZXIgfCB1bmRlZmluZWQ+IHtcbiAgLy8gRmFzdCBwYXRoOiBhbHJlYWR5IHJlc29sdmVkIGEgY29uY3JldGUgcG9ydCBmb3IgdGhpcyBwcm9jZXNzLlxuICBpZiAoX2NhY2hlZFBvcnQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBfY2FjaGVkUG9ydDtcbiAgfVxuICAvLyBBIGRpc2NvdmVyeSBpcyBhbHJlYWR5IHJ1bm5pbmcg4oCUIHNoYXJlIGl0IHJhdGhlciB0aGFuIHN0YXJ0aW5nIGEgc2Vjb25kLlxuICBpZiAoX2luRmxpZ2h0KSB7XG4gICAgcmV0dXJuIF9pbkZsaWdodDtcbiAgfVxuXG4gIGlmICghX2dldFBvcnQpIHtcbiAgICB0cnkge1xuICAgICAgLy8gQ29uc3RydWN0IHNwZWNpZmllciBhdCBydW50aW1lIHRvIGRlZmVhdCBidW5kbGVyIHN0YXRpYyBhbmFseXNpcy5cbiAgICAgIGNvbnN0IHNwZWMgPSBbJ0B3b3JrZmxvdy91dGlscycsICdnZXQtcG9ydCddLmpvaW4oJy8nKTtcbiAgICAgIC8vIFVzZSBwcm9jZXNzLmN3ZCgpLWJhc2VkIGNyZWF0ZVJlcXVpcmUgZm9yIENKUy9FU00gY29tcGF0aWJpbGl0eS5cbiAgICAgIC8vIGltcG9ydC5tZXRhLnVybCBpcyB1bmF2YWlsYWJsZSBpbiBDSlMgcmUtYnVuZGxlZCBvdXRwdXRzLlxuICAgICAgY29uc3QgX3JlcXVpcmUgPSBjcmVhdGVSZXF1aXJlKFxuICAgICAgICBwYXRoVG9GaWxlVVJMKHByb2Nlc3MuY3dkKCkgKyAnL3BhY2thZ2UuanNvbicpLmhyZWZcbiAgICAgICk7XG4gICAgICBjb25zdCBtb2QgPSBfcmVxdWlyZShzcGVjKTtcbiAgICAgIF9nZXRQb3J0ID0gbW9kLmdldFBvcnQ7XG4gICAgfSBjYXRjaCB7XG4gICAgICAvLyBNb2R1bGUgbm90IGF2YWlsYWJsZSAoZS5nLiwgaW4gYSBicm93c2VyIG9yIG1pbmltYWwgYnVuZGxlKVxuICAgICAgX2dldFBvcnQgPSBhc3luYyAoKSA9PiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgLy8gYF9nZXRQb3J0YCBpcyBhbHdheXMgYXNzaWduZWQgYnkgdGhlIGJsb2NrIGFib3ZlOyB0aGUgZmFsbGJhY2sga2VlcHMgdGhlXG4gIC8vIHR5cGUgbm9uLW51bGxhYmxlIHdpdGhvdXQgYSBub24tbnVsbCBhc3NlcnRpb24uXG4gIGNvbnN0IHJlc29sdmVyID0gX2dldFBvcnQgPz8gKGFzeW5jICgpID0+IHVuZGVmaW5lZCk7XG4gIF9pbkZsaWdodCA9IHJlc29sdmVyKClcbiAgICAudGhlbigocG9ydCkgPT4ge1xuICAgICAgLy8gT25seSBjYWNoZSBhIGNvbmNyZXRlIHBvcnQuIEEgdHJhbnNpZW50IGB1bmRlZmluZWRgIChlLmcuIHRoZSBzZXJ2ZXIgaXNcbiAgICAgIC8vIG5vdCBsaXN0ZW5pbmcgeWV0IG9uIHRoZSB2ZXJ5IGZpcnN0IHJlcGxheSkgbXVzdCBub3QgcG9pc29uIHRoZSBjYWNoZSDigJRcbiAgICAgIC8vIGxlYXZpbmcgaXQgdW5zZXQgbGV0cyB0aGUgbmV4dCBjYWxsIHJldHJ5IGRpc2NvdmVyeS5cbiAgICAgIGlmICh0eXBlb2YgcG9ydCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgX2NhY2hlZFBvcnQgPSBwb3J0O1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBvcnQ7XG4gICAgfSlcbiAgICAuZmluYWxseSgoKSA9PiB7XG4gICAgICBfaW5GbGlnaHQgPSB1bmRlZmluZWQ7XG4gICAgfSk7XG4gIHJldHVybiBfaW5GbGlnaHQ7XG59XG5cbi8qKlxuICogUmVzZXRzIHRoZSBwZXItcHJvY2VzcyBwb3J0IGNhY2hlLiBJbnRlbmRlZCBmb3IgdGVzdHM7IG5vdCB1c2VkIG9uIHRoZSBob3RcbiAqIHBhdGguIENhbGxlcnMgbXVzdCBsZXQgYW55IGluLWZsaWdodCBsb29rdXAgc2V0dGxlIChhd2FpdCB0aGUgcGVuZGluZ1xuICogYGdldFBvcnRMYXp5KClgIGNhbGwpIGJlZm9yZSByZXNldHRpbmc6IGNsZWFyaW5nIGBfaW5GbGlnaHRgIGhlcmUgZG9lcyBub3RcbiAqIGNhbmNlbCBhbiBhbHJlYWR5LXNjaGVkdWxlZCByZXNvbHV0aW9uLCBzbyBhIGxhdGUgYC50aGVuYCBjb3VsZCBvdGhlcndpc2VcbiAqIHJlcG9wdWxhdGUgYF9jYWNoZWRQb3J0YCBhZnRlciB0aGUgcmVzZXQgYW5kIGJsZWVkIGludG8gdGhlIG5leHQgdGVzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0UG9ydENhY2hlRm9yVGVzdGluZygpOiB2b2lkIHtcbiAgX2dldFBvcnQgPSB1bmRlZmluZWQ7XG4gIF9jYWNoZWRQb3J0ID0gdW5kZWZpbmVkO1xuICBfaW5GbGlnaHQgPSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogSW5zdGFsbHMgYSBmYWtlIHBvcnQgcmVzb2x2ZXIgYW5kIGNsZWFycyB0aGUgY2FjaGUuIFRlc3Qtb25seSBzZWFtOiB0aGUgcmVhbFxuICogcmVzb2x2ZXIgaXMgbG9hZGVkIHZpYSBgY3JlYXRlUmVxdWlyZWAgd2l0aCBhIHJ1bnRpbWUtYnVpbHQgc3BlY2lmaWVyICh0b1xuICogaGlkZSBpdCBmcm9tIGJ1bmRsZXJzKSwgd2hpY2ggYWxzbyBkZWZlYXRzIG1vZHVsZSBtb2NraW5nLCBzbyBpbmplY3Rpb24gaXNcbiAqIHRoZSBvbmx5IGRldGVybWluaXN0aWMgd2F5IHRvIGV4ZXJjaXNlIHRoZSBjYWNoaW5nIGNvbnRyYWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0UG9ydFJlc29sdmVyRm9yVGVzdGluZyhcbiAgZm46ICgpID0+IFByb21pc2U8bnVtYmVyIHwgdW5kZWZpbmVkPlxuKTogdm9pZCB7XG4gIF9nZXRQb3J0ID0gZm47XG4gIF9jYWNoZWRQb3J0ID0gdW5kZWZpbmVkO1xuICBfaW5GbGlnaHQgPSB1bmRlZmluZWQ7XG59XG4iXX0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy accessor for the World singleton via globalThis symbols.
|
|
3
|
+
*
|
|
4
|
+
* This module exists to break the static import chain from step-side
|
|
5
|
+
* modules (serialization, run, helpers, start) to world.ts. Without it,
|
|
6
|
+
* esbuild bundles world.ts (and its transitive deps: world-local,
|
|
7
|
+
* world-vercel, process.cwd(), etc.) into the step registrations bundle,
|
|
8
|
+
* which triggers Turbopack NFT tracing errors in the V2 combined flow route.
|
|
9
|
+
*
|
|
10
|
+
* Resolution order, in priority:
|
|
11
|
+
*
|
|
12
|
+
* 1. `globalThis[WorldCacheKey]` — populated by a successful prior
|
|
13
|
+
* `getWorld()` call. This is the steady-state hot path.
|
|
14
|
+
* 2. `globalThis[GetWorldFnKey]` — populated by the module-load side
|
|
15
|
+
* effect at the bottom of `./world.ts`. Fires on every server bundle
|
|
16
|
+
* that reaches this file via `workflow/api` (which imports
|
|
17
|
+
* `./world-init.ts` for its side effect; see that file for the full
|
|
18
|
+
* rationale). This is the cold-start path for routes that consume
|
|
19
|
+
* `start` without any prior workflow run.
|
|
20
|
+
* 3. Dynamic `import('./world.js')` — last-resort fallback for
|
|
21
|
+
* environments where neither (1) nor (2) is available (CJS test
|
|
22
|
+
* runners, scripts that import deeply into `@workflow/core` without
|
|
23
|
+
* going through `workflow/api`, future bundlers we haven't validated).
|
|
24
|
+
* The specifier is built at runtime so esbuild can't trace it into
|
|
25
|
+
* step bundles. Note: this branch is unreliable in webpack-bundled
|
|
26
|
+
* routes because webpack inlines this module into the route file and
|
|
27
|
+
* the relative path resolves against the bundle location — paths (1)
|
|
28
|
+
* and (2) cover those cases instead.
|
|
29
|
+
*/
|
|
30
|
+
import type { World } from '@workflow/world';
|
|
31
|
+
export declare function getWorldLazy(): Promise<World>;
|
|
32
|
+
//# sourceMappingURL=get-world-lazy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-world-lazy.d.ts","sourceRoot":"","sources":["../../src/runtime/get-world-lazy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAM7C,wBAAsB,YAAY,IAAI,OAAO,CAAC,KAAK,CAAC,CAoBnD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lazy accessor for the World singleton via globalThis symbols.
|
|
3
|
+
*
|
|
4
|
+
* This module exists to break the static import chain from step-side
|
|
5
|
+
* modules (serialization, run, helpers, start) to world.ts. Without it,
|
|
6
|
+
* esbuild bundles world.ts (and its transitive deps: world-local,
|
|
7
|
+
* world-vercel, process.cwd(), etc.) into the step registrations bundle,
|
|
8
|
+
* which triggers Turbopack NFT tracing errors in the V2 combined flow route.
|
|
9
|
+
*
|
|
10
|
+
* Resolution order, in priority:
|
|
11
|
+
*
|
|
12
|
+
* 1. `globalThis[WorldCacheKey]` — populated by a successful prior
|
|
13
|
+
* `getWorld()` call. This is the steady-state hot path.
|
|
14
|
+
* 2. `globalThis[GetWorldFnKey]` — populated by the module-load side
|
|
15
|
+
* effect at the bottom of `./world.ts`. Fires on every server bundle
|
|
16
|
+
* that reaches this file via `workflow/api` (which imports
|
|
17
|
+
* `./world-init.ts` for its side effect; see that file for the full
|
|
18
|
+
* rationale). This is the cold-start path for routes that consume
|
|
19
|
+
* `start` without any prior workflow run.
|
|
20
|
+
* 3. Dynamic `import('./world.js')` — last-resort fallback for
|
|
21
|
+
* environments where neither (1) nor (2) is available (CJS test
|
|
22
|
+
* runners, scripts that import deeply into `@workflow/core` without
|
|
23
|
+
* going through `workflow/api`, future bundlers we haven't validated).
|
|
24
|
+
* The specifier is built at runtime so esbuild can't trace it into
|
|
25
|
+
* step bundles. Note: this branch is unreliable in webpack-bundled
|
|
26
|
+
* routes because webpack inlines this module into the route file and
|
|
27
|
+
* the relative path resolves against the bundle location — paths (1)
|
|
28
|
+
* and (2) cover those cases instead.
|
|
29
|
+
*/
|
|
30
|
+
const WorldCacheKey = Symbol.for('@workflow/world//cache');
|
|
31
|
+
const WorldCachePromiseKey = Symbol.for('@workflow/world//cachePromise');
|
|
32
|
+
const GetWorldFnKey = Symbol.for('@workflow/world//getWorldFn');
|
|
33
|
+
export async function getWorldLazy() {
|
|
34
|
+
const g = globalThis;
|
|
35
|
+
if (g[WorldCacheKey])
|
|
36
|
+
return g[WorldCacheKey];
|
|
37
|
+
if (g[WorldCachePromiseKey]) {
|
|
38
|
+
g[WorldCacheKey] = await g[WorldCachePromiseKey];
|
|
39
|
+
return g[WorldCacheKey];
|
|
40
|
+
}
|
|
41
|
+
// If world.ts is statically present in this bundle, it has registered
|
|
42
|
+
// getWorld on globalThis at module load. Prefer that over the dynamic
|
|
43
|
+
// import fallback, which doesn't survive Next.js inlining get-world-lazy
|
|
44
|
+
// into a route bundle (the relative './world.js' resolves against the
|
|
45
|
+
// bundled location, where no sibling world.js exists).
|
|
46
|
+
const getWorldFn = g[GetWorldFnKey];
|
|
47
|
+
if (getWorldFn)
|
|
48
|
+
return getWorldFn();
|
|
49
|
+
// Last resort: dynamic import for environments where world.ts wasn't
|
|
50
|
+
// bundled but is reachable as a sibling module on disk. The specifier is
|
|
51
|
+
// built at runtime so esbuild can't trace it into the step bundle.
|
|
52
|
+
const worldPath = ['./world', 'js'].join('.');
|
|
53
|
+
const { getWorld } = await import(worldPath);
|
|
54
|
+
return getWorld();
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LXdvcmxkLWxhenkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9nZXQtd29ybGQtbGF6eS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTRCRztBQUlILE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsQ0FBQztBQUMzRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsK0JBQStCLENBQUMsQ0FBQztBQUN6RSxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFFaEUsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZO0lBQ2hDLE1BQU0sQ0FBQyxHQUFHLFVBQWlCLENBQUM7SUFDNUIsSUFBSSxDQUFDLENBQUMsYUFBYSxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDOUMsSUFBSSxDQUFDLENBQUMsb0JBQW9CLENBQUMsRUFBRSxDQUFDO1FBQzVCLENBQUMsQ0FBQyxhQUFhLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQ2pELE9BQU8sQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQzFCLENBQUM7SUFDRCxzRUFBc0U7SUFDdEUsc0VBQXNFO0lBQ3RFLHlFQUF5RTtJQUN6RSxzRUFBc0U7SUFDdEUsdURBQXVEO0lBQ3ZELE1BQU0sVUFBVSxHQUFHLENBQUMsQ0FBQyxhQUFhLENBQXVDLENBQUM7SUFDMUUsSUFBSSxVQUFVO1FBQUUsT0FBTyxVQUFVLEVBQUUsQ0FBQztJQUNwQyxxRUFBcUU7SUFDckUseUVBQXlFO0lBQ3pFLG1FQUFtRTtJQUNuRSxNQUFNLFNBQVMsR0FBRyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDOUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLE9BQU8sUUFBUSxFQUFFLENBQUM7QUFDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGF6eSBhY2Nlc3NvciBmb3IgdGhlIFdvcmxkIHNpbmdsZXRvbiB2aWEgZ2xvYmFsVGhpcyBzeW1ib2xzLlxuICpcbiAqIFRoaXMgbW9kdWxlIGV4aXN0cyB0byBicmVhayB0aGUgc3RhdGljIGltcG9ydCBjaGFpbiBmcm9tIHN0ZXAtc2lkZVxuICogbW9kdWxlcyAoc2VyaWFsaXphdGlvbiwgcnVuLCBoZWxwZXJzLCBzdGFydCkgdG8gd29ybGQudHMuIFdpdGhvdXQgaXQsXG4gKiBlc2J1aWxkIGJ1bmRsZXMgd29ybGQudHMgKGFuZCBpdHMgdHJhbnNpdGl2ZSBkZXBzOiB3b3JsZC1sb2NhbCxcbiAqIHdvcmxkLXZlcmNlbCwgcHJvY2Vzcy5jd2QoKSwgZXRjLikgaW50byB0aGUgc3RlcCByZWdpc3RyYXRpb25zIGJ1bmRsZSxcbiAqIHdoaWNoIHRyaWdnZXJzIFR1cmJvcGFjayBORlQgdHJhY2luZyBlcnJvcnMgaW4gdGhlIFYyIGNvbWJpbmVkIGZsb3cgcm91dGUuXG4gKlxuICogUmVzb2x1dGlvbiBvcmRlciwgaW4gcHJpb3JpdHk6XG4gKlxuICogMS4gYGdsb2JhbFRoaXNbV29ybGRDYWNoZUtleV1gIOKAlCBwb3B1bGF0ZWQgYnkgYSBzdWNjZXNzZnVsIHByaW9yXG4gKiAgICBgZ2V0V29ybGQoKWAgY2FsbC4gVGhpcyBpcyB0aGUgc3RlYWR5LXN0YXRlIGhvdCBwYXRoLlxuICogMi4gYGdsb2JhbFRoaXNbR2V0V29ybGRGbktleV1gIOKAlCBwb3B1bGF0ZWQgYnkgdGhlIG1vZHVsZS1sb2FkIHNpZGVcbiAqICAgIGVmZmVjdCBhdCB0aGUgYm90dG9tIG9mIGAuL3dvcmxkLnRzYC4gRmlyZXMgb24gZXZlcnkgc2VydmVyIGJ1bmRsZVxuICogICAgdGhhdCByZWFjaGVzIHRoaXMgZmlsZSB2aWEgYHdvcmtmbG93L2FwaWAgKHdoaWNoIGltcG9ydHNcbiAqICAgIGAuL3dvcmxkLWluaXQudHNgIGZvciBpdHMgc2lkZSBlZmZlY3Q7IHNlZSB0aGF0IGZpbGUgZm9yIHRoZSBmdWxsXG4gKiAgICByYXRpb25hbGUpLiBUaGlzIGlzIHRoZSBjb2xkLXN0YXJ0IHBhdGggZm9yIHJvdXRlcyB0aGF0IGNvbnN1bWVcbiAqICAgIGBzdGFydGAgd2l0aG91dCBhbnkgcHJpb3Igd29ya2Zsb3cgcnVuLlxuICogMy4gRHluYW1pYyBgaW1wb3J0KCcuL3dvcmxkLmpzJylgIOKAlCBsYXN0LXJlc29ydCBmYWxsYmFjayBmb3JcbiAqICAgIGVudmlyb25tZW50cyB3aGVyZSBuZWl0aGVyICgxKSBub3IgKDIpIGlzIGF2YWlsYWJsZSAoQ0pTIHRlc3RcbiAqICAgIHJ1bm5lcnMsIHNjcmlwdHMgdGhhdCBpbXBvcnQgZGVlcGx5IGludG8gYEB3b3JrZmxvdy9jb3JlYCB3aXRob3V0XG4gKiAgICBnb2luZyB0aHJvdWdoIGB3b3JrZmxvdy9hcGlgLCBmdXR1cmUgYnVuZGxlcnMgd2UgaGF2ZW4ndCB2YWxpZGF0ZWQpLlxuICogICAgVGhlIHNwZWNpZmllciBpcyBidWlsdCBhdCBydW50aW1lIHNvIGVzYnVpbGQgY2FuJ3QgdHJhY2UgaXQgaW50b1xuICogICAgc3RlcCBidW5kbGVzLiBOb3RlOiB0aGlzIGJyYW5jaCBpcyB1bnJlbGlhYmxlIGluIHdlYnBhY2stYnVuZGxlZFxuICogICAgcm91dGVzIGJlY2F1c2Ugd2VicGFjayBpbmxpbmVzIHRoaXMgbW9kdWxlIGludG8gdGhlIHJvdXRlIGZpbGUgYW5kXG4gKiAgICB0aGUgcmVsYXRpdmUgcGF0aCByZXNvbHZlcyBhZ2FpbnN0IHRoZSBidW5kbGUgbG9jYXRpb24g4oCUIHBhdGhzICgxKVxuICogICAgYW5kICgyKSBjb3ZlciB0aG9zZSBjYXNlcyBpbnN0ZWFkLlxuICovXG5cbmltcG9ydCB0eXBlIHsgV29ybGQgfSBmcm9tICdAd29ya2Zsb3cvd29ybGQnO1xuXG5jb25zdCBXb3JsZENhY2hlS2V5ID0gU3ltYm9sLmZvcignQHdvcmtmbG93L3dvcmxkLy9jYWNoZScpO1xuY29uc3QgV29ybGRDYWNoZVByb21pc2VLZXkgPSBTeW1ib2wuZm9yKCdAd29ya2Zsb3cvd29ybGQvL2NhY2hlUHJvbWlzZScpO1xuY29uc3QgR2V0V29ybGRGbktleSA9IFN5bWJvbC5mb3IoJ0B3b3JrZmxvdy93b3JsZC8vZ2V0V29ybGRGbicpO1xuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0V29ybGRMYXp5KCk6IFByb21pc2U8V29ybGQ+IHtcbiAgY29uc3QgZyA9IGdsb2JhbFRoaXMgYXMgYW55O1xuICBpZiAoZ1tXb3JsZENhY2hlS2V5XSkgcmV0dXJuIGdbV29ybGRDYWNoZUtleV07XG4gIGlmIChnW1dvcmxkQ2FjaGVQcm9taXNlS2V5XSkge1xuICAgIGdbV29ybGRDYWNoZUtleV0gPSBhd2FpdCBnW1dvcmxkQ2FjaGVQcm9taXNlS2V5XTtcbiAgICByZXR1cm4gZ1tXb3JsZENhY2hlS2V5XTtcbiAgfVxuICAvLyBJZiB3b3JsZC50cyBpcyBzdGF0aWNhbGx5IHByZXNlbnQgaW4gdGhpcyBidW5kbGUsIGl0IGhhcyByZWdpc3RlcmVkXG4gIC8vIGdldFdvcmxkIG9uIGdsb2JhbFRoaXMgYXQgbW9kdWxlIGxvYWQuIFByZWZlciB0aGF0IG92ZXIgdGhlIGR5bmFtaWNcbiAgLy8gaW1wb3J0IGZhbGxiYWNrLCB3aGljaCBkb2Vzbid0IHN1cnZpdmUgTmV4dC5qcyBpbmxpbmluZyBnZXQtd29ybGQtbGF6eVxuICAvLyBpbnRvIGEgcm91dGUgYnVuZGxlICh0aGUgcmVsYXRpdmUgJy4vd29ybGQuanMnIHJlc29sdmVzIGFnYWluc3QgdGhlXG4gIC8vIGJ1bmRsZWQgbG9jYXRpb24sIHdoZXJlIG5vIHNpYmxpbmcgd29ybGQuanMgZXhpc3RzKS5cbiAgY29uc3QgZ2V0V29ybGRGbiA9IGdbR2V0V29ybGRGbktleV0gYXMgKCgpID0+IFByb21pc2U8V29ybGQ+KSB8IHVuZGVmaW5lZDtcbiAgaWYgKGdldFdvcmxkRm4pIHJldHVybiBnZXRXb3JsZEZuKCk7XG4gIC8vIExhc3QgcmVzb3J0OiBkeW5hbWljIGltcG9ydCBmb3IgZW52aXJvbm1lbnRzIHdoZXJlIHdvcmxkLnRzIHdhc24ndFxuICAvLyBidW5kbGVkIGJ1dCBpcyByZWFjaGFibGUgYXMgYSBzaWJsaW5nIG1vZHVsZSBvbiBkaXNrLiBUaGUgc3BlY2lmaWVyIGlzXG4gIC8vIGJ1aWx0IGF0IHJ1bnRpbWUgc28gZXNidWlsZCBjYW4ndCB0cmFjZSBpdCBpbnRvIHRoZSBzdGVwIGJ1bmRsZS5cbiAgY29uc3Qgd29ybGRQYXRoID0gWycuL3dvcmxkJywgJ2pzJ10uam9pbignLicpO1xuICBjb25zdCB7IGdldFdvcmxkIH0gPSBhd2FpdCBpbXBvcnQod29ybGRQYXRoKTtcbiAgcmV0dXJuIGdldFdvcmxkKCk7XG59XG4iXX0=
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { Event, HealthCheckPayload, ValidQueueName, World } from '@workflow/world';
|
|
1
|
+
import type { Event, HealthCheckPayload, ValidQueueName, WorkflowRun, World } from '@workflow/world';
|
|
2
|
+
import { type CryptoKey } from '../encryption.js';
|
|
2
3
|
/**
|
|
3
4
|
* Validates a workflow name and returns the corresponding queue name.
|
|
4
5
|
* Ensures the workflow name only contains safe characters before
|
|
5
6
|
* interpolating it into the queue name string.
|
|
6
7
|
*/
|
|
7
|
-
export declare function getWorkflowQueueName(workflowName: string): ValidQueueName;
|
|
8
|
+
export declare function getWorkflowQueueName(workflowName: string, namespace?: string): ValidQueueName;
|
|
8
9
|
/**
|
|
9
10
|
* Result of a health check operation.
|
|
10
11
|
*/
|
|
@@ -16,6 +17,14 @@ export interface HealthCheckResult {
|
|
|
16
17
|
latencyMs?: number;
|
|
17
18
|
/** Spec version of the responding deployment */
|
|
18
19
|
specVersion?: number;
|
|
20
|
+
/**
|
|
21
|
+
* `@workflow/core` version of the responding deployment, used for
|
|
22
|
+
* capability detection (see `getRunCapabilities`). Omitted when the
|
|
23
|
+
* responding deployment did not provide the field as a string —
|
|
24
|
+
* for example, an older `@workflow/core` that predates this field,
|
|
25
|
+
* or a non-JSON plain-text health response.
|
|
26
|
+
*/
|
|
27
|
+
workflowCoreVersion?: string;
|
|
19
28
|
}
|
|
20
29
|
/**
|
|
21
30
|
* Checks if the given message is a health check payload.
|
|
@@ -37,13 +46,24 @@ export interface HealthCheckOptions {
|
|
|
37
46
|
/** Deployment ID to send the health check to. Falls back to process.env.VERCEL_DEPLOYMENT_ID. */
|
|
38
47
|
deploymentId?: string;
|
|
39
48
|
}
|
|
40
|
-
export declare function healthCheck(world: World, endpoint: HealthCheckEndpoint, options?: HealthCheckOptions
|
|
49
|
+
export declare function healthCheck(world: World, endpoint: HealthCheckEndpoint, options?: HealthCheckOptions & {
|
|
50
|
+
namespace?: string;
|
|
51
|
+
}): Promise<HealthCheckResult>;
|
|
41
52
|
/**
|
|
42
|
-
* Loads
|
|
43
|
-
*
|
|
44
|
-
*
|
|
53
|
+
* Loads workflow run events by iterating through all pages of paginated
|
|
54
|
+
* results. Events are returned in chronological (ascending) order for
|
|
55
|
+
* deterministic workflow replay.
|
|
56
|
+
*
|
|
57
|
+
* @param runId - The workflow run ID.
|
|
58
|
+
* @param afterCursor - If provided, only events after this cursor are
|
|
59
|
+
* returned (incremental load). If omitted, all events are returned.
|
|
60
|
+
* The returned cursor can be passed back in on a subsequent call for
|
|
61
|
+
* incremental loading.
|
|
45
62
|
*/
|
|
46
|
-
export declare function
|
|
63
|
+
export declare function loadWorkflowRunEvents(runId: string, afterCursor?: string): Promise<{
|
|
64
|
+
events: Event[];
|
|
65
|
+
cursor: string | null;
|
|
66
|
+
}>;
|
|
47
67
|
/**
|
|
48
68
|
* Wraps a request/response handler and adds a health check "mode"
|
|
49
69
|
* based on the presence of a `__health` query parameter.
|
|
@@ -61,4 +81,27 @@ export declare function getQueueOverhead(message: {
|
|
|
61
81
|
}): {
|
|
62
82
|
[k: string]: number;
|
|
63
83
|
} | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Returns a memoized accessor for the per-run AES-256 encryption key.
|
|
86
|
+
*
|
|
87
|
+
* The first call resolves the key via `world.getEncryptionKeyForRun` (which
|
|
88
|
+
* may do HKDF derivation locally on Vercel, or a network fetch from
|
|
89
|
+
* external contexts) and imports it as a `CryptoKey`; subsequent calls
|
|
90
|
+
* await the same cached promise. If the world doesn't support encryption
|
|
91
|
+
* or the run has no key configured, the cached value is `undefined`.
|
|
92
|
+
*
|
|
93
|
+
* Used by step / workflow handlers to defer the (potentially expensive)
|
|
94
|
+
* key fetch until the first code path that actually needs it — typically
|
|
95
|
+
* input hydration on the success path, or error dehydration on a failure
|
|
96
|
+
* path. Both paths can race-call the accessor without triggering duplicate
|
|
97
|
+
* fetches.
|
|
98
|
+
*
|
|
99
|
+
* Errors thrown by `getEncryptionKeyForRun` propagate to every caller
|
|
100
|
+
* (the cached promise rejects). This is intentional: when encryption is
|
|
101
|
+
* configured, we never want to silently fall back to plaintext
|
|
102
|
+
* serialization. A propagated error in an event-emission path leaves the
|
|
103
|
+
* outer try/catch to log and surface the issue; the queue's redelivery
|
|
104
|
+
* semantics will retry the key fetch on the next attempt.
|
|
105
|
+
*/
|
|
106
|
+
export declare function memoizeEncryptionKey(world: World, runOrId: WorkflowRun | string): () => Promise<CryptoKey | undefined>;
|
|
64
107
|
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/runtime/helpers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/runtime/helpers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,KAAK,EACN,MAAM,iBAAiB,CAAC;AAUzB,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,kBAAkB,CAAC;AAiB7D;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,SAAS,CAAC,EAAE,MAAM,GACjB,cAAc,CAWhB;AAWD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,GACf,kBAAkB,GAAG,SAAS,CAMhC;AAYD;;;;;;GAMG;AACH,wBAAsB,wBAAwB,CAC5C,WAAW,EAAE,kBAAkB,EAC/B,QAAQ,EAAE,UAAU,GAAG,MAAM,EAC7B,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED,MAAM,MAAM,mBAAmB,GAAG,UAAU,GAAG,MAAM,CAAC;AAEtD,MAAM,WAAW,kBAAkB;IACjC,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AA6GD,wBAAsB,WAAW,CAC/B,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,CAAC,EAAE,kBAAkB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD,OAAO,CAAC,iBAAiB,CAAC,CAyE5B;AAwED;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC;IAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAwGrD;AAYD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,EAC5C,gBAAgB,CAAC,EAAE,MAAM,GACxB,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA8BrC;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,KAAK,EACZ,GAAG,IAAI,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,KAAK,CAAC,iBA0BxC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IAAE,WAAW,CAAC,EAAE,IAAI,CAAA;CAAE;;cAS/D;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,WAAW,GAAG,MAAM,GAC5B,MAAM,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAiBtC"}
|