awaitly 1.34.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{duration.d.ts → di-BDlT7InM.d.cts} +15 -1
- package/dist/{duration.d.cts → di-BbFFfO8y.d.ts} +15 -1
- package/dist/errors-DtXvrCiO.d.cts +708 -0
- package/dist/errors-DtXvrCiO.d.ts +708 -0
- package/dist/index.cjs +4594 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1970 -141
- package/dist/index.d.ts +1970 -141
- package/dist/index.js +4398 -1
- package/dist/index.js.map +1 -1
- package/dist/result.cjs +641 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +35 -5
- package/dist/result.d.ts +35 -5
- package/dist/result.js +561 -1
- package/dist/result.js.map +1 -1
- package/dist/testing.cjs +4202 -8
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +2 -6
- package/dist/testing.d.ts +2 -6
- package/dist/testing.js +4154 -8
- package/dist/testing.js.map +1 -1
- package/dist/{run-entry-D2MmJFj9.d.cts → types-B8NfNRGX.d.ts} +1152 -1499
- package/dist/{run-entry-Dduz-is2.d.ts → types-BZ2f4MRR.d.cts} +1152 -1499
- package/dist/workflow.cjs +7096 -6
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3346 -22
- package/dist/workflow.d.ts +3346 -22
- package/dist/workflow.js +6929 -6
- package/dist/workflow.js.map +1 -1
- package/package.json +13 -178
- package/dist/adapters.cjs +0 -7
- package/dist/adapters.cjs.map +0 -1
- package/dist/adapters.d.cts +0 -179
- package/dist/adapters.d.ts +0 -179
- package/dist/adapters.js +0 -7
- package/dist/adapters.js.map +0 -1
- package/dist/batch.cjs +0 -7
- package/dist/batch.cjs.map +0 -1
- package/dist/batch.d.cts +0 -200
- package/dist/batch.d.ts +0 -200
- package/dist/batch.js +0 -7
- package/dist/batch.js.map +0 -1
- package/dist/bind-deps.cjs +0 -2
- package/dist/bind-deps.cjs.map +0 -1
- package/dist/bind-deps.d.cts +0 -28
- package/dist/bind-deps.d.ts +0 -28
- package/dist/bind-deps.js +0 -2
- package/dist/bind-deps.js.map +0 -1
- package/dist/cache.cjs +0 -2
- package/dist/cache.cjs.map +0 -1
- package/dist/cache.d.cts +0 -269
- package/dist/cache.d.ts +0 -269
- package/dist/cache.js +0 -2
- package/dist/cache.js.map +0 -1
- package/dist/circuit-breaker.cjs +0 -7
- package/dist/circuit-breaker.cjs.map +0 -1
- package/dist/circuit-breaker.d.cts +0 -211
- package/dist/circuit-breaker.d.ts +0 -211
- package/dist/circuit-breaker.js +0 -7
- package/dist/circuit-breaker.js.map +0 -1
- package/dist/conditional.cjs +0 -2
- package/dist/conditional.cjs.map +0 -1
- package/dist/conditional.d.cts +0 -252
- package/dist/conditional.d.ts +0 -252
- package/dist/conditional.js +0 -2
- package/dist/conditional.js.map +0 -1
- package/dist/core.cjs +0 -7
- package/dist/core.cjs.map +0 -1
- package/dist/core.d.cts +0 -5
- package/dist/core.d.ts +0 -5
- package/dist/core.js +0 -7
- package/dist/core.js.map +0 -1
- package/dist/di-COl5oFnR.d.cts +0 -15
- package/dist/di-CyDj_JyZ.d.ts +0 -15
- package/dist/diagnostics.cjs +0 -8
- package/dist/diagnostics.cjs.map +0 -1
- package/dist/diagnostics.d.cts +0 -68
- package/dist/diagnostics.d.ts +0 -68
- package/dist/diagnostics.js +0 -8
- package/dist/diagnostics.js.map +0 -1
- package/dist/durable.cjs +0 -11
- package/dist/durable.cjs.map +0 -1
- package/dist/durable.d.cts +0 -9
- package/dist/durable.d.ts +0 -9
- package/dist/durable.js +0 -11
- package/dist/durable.js.map +0 -1
- package/dist/duration.cjs +0 -2
- package/dist/duration.cjs.map +0 -1
- package/dist/duration.js +0 -2
- package/dist/duration.js.map +0 -1
- package/dist/engine.cjs +0 -11
- package/dist/engine.cjs.map +0 -1
- package/dist/engine.d.cts +0 -115
- package/dist/engine.d.ts +0 -115
- package/dist/engine.js +0 -11
- package/dist/engine.js.map +0 -1
- package/dist/errors.cjs +0 -2
- package/dist/errors.cjs.map +0 -1
- package/dist/errors.d.cts +0 -361
- package/dist/errors.d.ts +0 -361
- package/dist/errors.js +0 -2
- package/dist/errors.js.map +0 -1
- package/dist/fetch.cjs +0 -7
- package/dist/fetch.cjs.map +0 -1
- package/dist/fetch.d.cts +0 -86
- package/dist/fetch.d.ts +0 -86
- package/dist/fetch.js +0 -7
- package/dist/fetch.js.map +0 -1
- package/dist/flow.cjs +0 -7
- package/dist/flow.cjs.map +0 -1
- package/dist/flow.d.cts +0 -163
- package/dist/flow.d.ts +0 -163
- package/dist/flow.js +0 -7
- package/dist/flow.js.map +0 -1
- package/dist/functional.cjs +0 -2
- package/dist/functional.cjs.map +0 -1
- package/dist/functional.d.cts +0 -444
- package/dist/functional.d.ts +0 -444
- package/dist/functional.js +0 -2
- package/dist/functional.js.map +0 -1
- package/dist/guards-BodHXLzX.d.cts +0 -72
- package/dist/guards-CeWoQ8fn.d.ts +0 -72
- package/dist/hitl-BPE_1UiM.d.cts +0 -468
- package/dist/hitl-byp570uC.d.ts +0 -468
- package/dist/hitl.cjs +0 -7
- package/dist/hitl.cjs.map +0 -1
- package/dist/hitl.d.cts +0 -442
- package/dist/hitl.d.ts +0 -442
- package/dist/hitl.js +0 -7
- package/dist/hitl.js.map +0 -1
- package/dist/index-BYT3amEz.d.ts +0 -417
- package/dist/index-C_ak66jy.d.cts +0 -417
- package/dist/match-entry-DjI2bLpD.d.cts +0 -209
- package/dist/match-entry-DjI2bLpD.d.ts +0 -209
- package/dist/match.cjs +0 -2
- package/dist/match.cjs.map +0 -1
- package/dist/match.d.cts +0 -1
- package/dist/match.d.ts +0 -1
- package/dist/match.js +0 -2
- package/dist/match.js.map +0 -1
- package/dist/otel.cjs +0 -2
- package/dist/otel.cjs.map +0 -1
- package/dist/otel.d.cts +0 -188
- package/dist/otel.d.ts +0 -188
- package/dist/otel.js +0 -2
- package/dist/otel.js.map +0 -1
- package/dist/persistence-entry-DOMx3woy.d.ts +0 -822
- package/dist/persistence-entry-ymCA4iDu.d.cts +0 -822
- package/dist/persistence.cjs +0 -2
- package/dist/persistence.cjs.map +0 -1
- package/dist/persistence.d.cts +0 -7
- package/dist/persistence.d.ts +0 -7
- package/dist/persistence.js +0 -2
- package/dist/persistence.js.map +0 -1
- package/dist/policies.cjs +0 -2
- package/dist/policies.cjs.map +0 -1
- package/dist/policies.d.cts +0 -379
- package/dist/policies.d.ts +0 -379
- package/dist/policies.js +0 -2
- package/dist/policies.js.map +0 -1
- package/dist/ratelimit.cjs +0 -7
- package/dist/ratelimit.cjs.map +0 -1
- package/dist/ratelimit.d.cts +0 -458
- package/dist/ratelimit.d.ts +0 -458
- package/dist/ratelimit.js +0 -7
- package/dist/ratelimit.js.map +0 -1
- package/dist/reliability.cjs +0 -11
- package/dist/reliability.cjs.map +0 -1
- package/dist/reliability.d.cts +0 -11
- package/dist/reliability.d.ts +0 -11
- package/dist/reliability.js +0 -11
- package/dist/reliability.js.map +0 -1
- package/dist/resolver.cjs +0 -7
- package/dist/resolver.cjs.map +0 -1
- package/dist/resolver.d.cts +0 -68
- package/dist/resolver.d.ts +0 -68
- package/dist/resolver.js +0 -7
- package/dist/resolver.js.map +0 -1
- package/dist/resource.cjs +0 -7
- package/dist/resource.cjs.map +0 -1
- package/dist/resource.d.cts +0 -174
- package/dist/resource.d.ts +0 -174
- package/dist/resource.js +0 -7
- package/dist/resource.js.map +0 -1
- package/dist/result/retry.cjs +0 -2
- package/dist/result/retry.cjs.map +0 -1
- package/dist/result/retry.d.cts +0 -70
- package/dist/result/retry.d.ts +0 -70
- package/dist/result/retry.js +0 -2
- package/dist/result/retry.js.map +0 -1
- package/dist/retry.cjs +0 -2
- package/dist/retry.cjs.map +0 -1
- package/dist/retry.d.cts +0 -388
- package/dist/retry.d.ts +0 -388
- package/dist/retry.js +0 -2
- package/dist/retry.js.map +0 -1
- package/dist/run.cjs +0 -7
- package/dist/run.cjs.map +0 -1
- package/dist/run.d.cts +0 -4
- package/dist/run.d.ts +0 -4
- package/dist/run.js +0 -7
- package/dist/run.js.map +0 -1
- package/dist/saga.cjs +0 -11
- package/dist/saga.cjs.map +0 -1
- package/dist/saga.d.cts +0 -164
- package/dist/saga.d.ts +0 -164
- package/dist/saga.js +0 -11
- package/dist/saga.js.map +0 -1
- package/dist/singleflight.cjs +0 -2
- package/dist/singleflight.cjs.map +0 -1
- package/dist/singleflight.d.cts +0 -145
- package/dist/singleflight.d.ts +0 -145
- package/dist/singleflight.js +0 -2
- package/dist/singleflight.js.map +0 -1
- package/dist/slugs.cjs +0 -2
- package/dist/slugs.cjs.map +0 -1
- package/dist/slugs.d.cts +0 -67
- package/dist/slugs.d.ts +0 -67
- package/dist/slugs.js +0 -2
- package/dist/slugs.js.map +0 -1
- package/dist/streaming.cjs +0 -9
- package/dist/streaming.cjs.map +0 -1
- package/dist/streaming.d.cts +0 -596
- package/dist/streaming.d.ts +0 -596
- package/dist/streaming.js +0 -9
- package/dist/streaming.js.map +0 -1
- package/dist/tagged-error.cjs +0 -2
- package/dist/tagged-error.cjs.map +0 -1
- package/dist/tagged-error.d.cts +0 -275
- package/dist/tagged-error.d.ts +0 -275
- package/dist/tagged-error.js +0 -2
- package/dist/tagged-error.js.map +0 -1
- package/dist/types-DQmzO9f4.d.ts +0 -323
- package/dist/types-qBUOYi-4.d.cts +0 -323
- package/dist/webhook.cjs +0 -7
- package/dist/webhook.cjs.map +0 -1
- package/dist/webhook.d.cts +0 -499
- package/dist/webhook.d.ts +0 -499
- package/dist/webhook.js +0 -7
- package/dist/webhook.js.map +0 -1
|
@@ -1,9 +1,49 @@
|
|
|
1
|
-
import { UnexpectedError } from './errors.
|
|
1
|
+
import { U as UnexpectedError } from './errors-DtXvrCiO.js';
|
|
2
|
+
import { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* Bound steps for the deps-first forms: run(deps, fn) and workflow({ steps }).
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
+
* Each dep key becomes a step function with the dep's own arguments that
|
|
8
|
+
* unwraps the ok value and early-exits on err. Kept out of core/index.ts
|
|
9
|
+
* so the core stays focused on the run/step engine.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
type AnyFunction$1 = (...args: never[]) => unknown;
|
|
13
|
+
/**
|
|
14
|
+
* Success value of a dependency's return type. Result-returning deps
|
|
15
|
+
* contribute their `ok` value; plain (non-Result) deps pass through as-is.
|
|
16
|
+
* Shared with the policy wrappers, which normalize the same way.
|
|
17
|
+
*/
|
|
18
|
+
type DepValueOfReturn<R> = [Extract<Awaited<R>, {
|
|
19
|
+
ok: true;
|
|
20
|
+
}>] extends [never] ? Awaited<R> : Extract<Awaited<R>, {
|
|
21
|
+
ok: true;
|
|
22
|
+
}> extends {
|
|
23
|
+
value: infer V;
|
|
24
|
+
} ? V : never;
|
|
25
|
+
/**
|
|
26
|
+
* The steps object passed to `run(deps, fn)`: each dep key becomes a step
|
|
27
|
+
* function with the same arguments that resolves to the unwrapped value
|
|
28
|
+
* (early-exiting the run on error).
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const result = await run({ getUser, getOrder }, async (s) => {
|
|
33
|
+
* const user = await s.getUser(userId); // User — unwrapped
|
|
34
|
+
* const order = await s.getOrder(user.id); // Order
|
|
35
|
+
* return { user, order };
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
type BoundSteps<Deps extends Record<string, AnyFunction$1>> = {
|
|
40
|
+
[K in keyof Deps]: (...args: Parameters<Deps[K]>) => Promise<DepValueOfReturn<ReturnType<Deps[K]>>>;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Core module (internal): Result primitives and the run() function.
|
|
45
|
+
*
|
|
46
|
+
* Surfaced through the root `awaitly` entry (formerly `awaitly/core`).
|
|
7
47
|
* Use this module for minimal bundle size when you don't need the full workflow capabilities
|
|
8
48
|
* (like retries, timeout, or state persistence) provided by `createWorkflow`.
|
|
9
49
|
*
|
|
@@ -27,7 +67,7 @@ type DurationInput = string | DurationObject;
|
|
|
27
67
|
*
|
|
28
68
|
* @example
|
|
29
69
|
* ```typescript
|
|
30
|
-
* const success =
|
|
70
|
+
* const success = ok(42);
|
|
31
71
|
* // Type shown: Ok<number>
|
|
32
72
|
* ```
|
|
33
73
|
*/
|
|
@@ -45,7 +85,7 @@ type Ok<T> = {
|
|
|
45
85
|
*
|
|
46
86
|
* @example
|
|
47
87
|
* ```typescript
|
|
48
|
-
* const failure =
|
|
88
|
+
* const failure = err({ type: "NOT_FOUND", message: "User not found" });
|
|
49
89
|
* // Type shown: Err<{ type: string; message: string }>
|
|
50
90
|
* ```
|
|
51
91
|
*/
|
|
@@ -69,191 +109,18 @@ type Result<T, E = unknown, C = unknown> = Ok<T> | Err<E, C>;
|
|
|
69
109
|
* Use this for asynchronous operations that might fail.
|
|
70
110
|
*/
|
|
71
111
|
type AsyncResult<T, E = unknown, C = unknown> = Promise<Result<T, E, C>>;
|
|
72
|
-
/** Discriminant for PromiseRejectedError type - use in switch statements */
|
|
73
|
-
declare const PROMISE_REJECTED: "PROMISE_REJECTED";
|
|
74
|
-
/**
|
|
75
|
-
* Named error constant for unexpected/unhandled errors.
|
|
76
|
-
* Used by the analyzer when a step doesn't declare errors.
|
|
77
|
-
*/
|
|
78
|
-
declare const AWAITLY_UNEXPECTED: "AWAITLY_UNEXPECTED";
|
|
79
|
-
/**
|
|
80
|
-
* Named error constant for cancelled operations.
|
|
81
|
-
*/
|
|
82
|
-
declare const AWAITLY_CANCELLED: "AWAITLY_CANCELLED";
|
|
83
|
-
/**
|
|
84
|
-
* Named error constant for timed-out operations.
|
|
85
|
-
*/
|
|
86
|
-
declare const AWAITLY_TIMEOUT: "AWAITLY_TIMEOUT";
|
|
87
|
-
/**
|
|
88
|
-
* Helper to create a tuple of string literal tags with preserved literal types.
|
|
89
|
-
* Use this when you need to store error tags in a variable while keeping
|
|
90
|
-
* TypeScript's literal type inference (avoiding widening to string[]).
|
|
91
|
-
*
|
|
92
|
-
* @param t - The string literal tags
|
|
93
|
-
* @returns The same array with preserved literal types
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```typescript
|
|
97
|
-
* // Without tags() - type widens to string[]
|
|
98
|
-
* const errs = ['CART_NOT_FOUND', 'CART_EMPTY']; // string[]
|
|
99
|
-
*
|
|
100
|
-
* // With tags() - literal types preserved
|
|
101
|
-
* const errs = tags('CART_NOT_FOUND', 'CART_EMPTY'); // ['CART_NOT_FOUND', 'CART_EMPTY']
|
|
102
|
-
*
|
|
103
|
-
* await step('getCart', () => getCart(id), {
|
|
104
|
-
* errors: errs, // Analyzer can extract literal types
|
|
105
|
-
* out: 'cart',
|
|
106
|
-
* });
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
declare const tags: <const T extends readonly string[]>(...t: T) => T;
|
|
110
|
-
|
|
111
|
-
type PromiseRejectedError = {
|
|
112
|
-
type: typeof PROMISE_REJECTED;
|
|
113
|
-
cause: unknown;
|
|
114
|
-
};
|
|
115
|
-
/** Cause type for promise rejections in async batch helpers */
|
|
116
|
-
type PromiseRejectionCause = {
|
|
117
|
-
type: "PROMISE_REJECTION";
|
|
118
|
-
reason: unknown;
|
|
119
|
-
};
|
|
120
|
-
type EmptyInputError = {
|
|
121
|
-
type: "EMPTY_INPUT";
|
|
122
|
-
message: string;
|
|
123
|
-
};
|
|
124
112
|
type MaybeAsyncResult<T, E, C = unknown> = Result<T, E, C> | Promise<Result<T, E, C>>;
|
|
125
|
-
/**
|
|
126
|
-
* Creates a successful Result.
|
|
127
|
-
* Use this when an operation completes successfully.
|
|
128
|
-
*
|
|
129
|
-
* @remarks When to use: Wrap a successful value in a Result for consistent return types.
|
|
130
|
-
*
|
|
131
|
-
* @param value - The success value to wrap
|
|
132
|
-
* @returns An Ok object with `{ ok: true, value }`
|
|
133
|
-
*
|
|
134
|
-
* @example
|
|
135
|
-
* ```typescript
|
|
136
|
-
* const success = Awaitly.ok(42);
|
|
137
|
-
* // Type: Ok<number>
|
|
138
|
-
*
|
|
139
|
-
* function divide(a: number, b: number): Result<number, string> {
|
|
140
|
-
* if (b === 0) return Awaitly.err("Division by zero");
|
|
141
|
-
* return Awaitly.ok(a / b);
|
|
142
|
-
* }
|
|
143
|
-
* ```
|
|
144
|
-
*/
|
|
145
|
-
declare function ok<T>(value: T): Ok<T>;
|
|
146
|
-
/**
|
|
147
|
-
* Creates a failed Result.
|
|
148
|
-
* Use this when an operation fails.
|
|
149
|
-
*
|
|
150
|
-
* @remarks When to use: Return a typed failure without throwing so callers can handle it explicitly.
|
|
151
|
-
*
|
|
152
|
-
* @param error - The error value describing what went wrong (e.g., error code, object)
|
|
153
|
-
* @returns An Err object with `{ ok: false, error }`
|
|
154
|
-
*
|
|
155
|
-
* @example
|
|
156
|
-
* ```typescript
|
|
157
|
-
* // Simple error
|
|
158
|
-
* const r1 = Awaitly.err("NOT_FOUND");
|
|
159
|
-
* // Type: Err<"NOT_FOUND">
|
|
160
|
-
*
|
|
161
|
-
* // Error with context (include in error object)
|
|
162
|
-
* const r2 = Awaitly.err({ type: "PROCESSING_FAILED", cause: originalError });
|
|
163
|
-
* // Type: Err<{ type: string; cause: Error }>
|
|
164
|
-
* ```
|
|
165
|
-
*/
|
|
166
|
-
declare function err<E, C = unknown>(error: E, options?: {
|
|
167
|
-
cause?: C;
|
|
168
|
-
}): Err<E, C>;
|
|
169
|
-
/**
|
|
170
|
-
* Checks if a Result is successful.
|
|
171
|
-
* Use this to narrow the type of a Result to the success case.
|
|
172
|
-
*
|
|
173
|
-
* @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.
|
|
174
|
-
*
|
|
175
|
-
* @param r - The Result to check
|
|
176
|
-
* @returns `true` if successful, allowing access to `r.value`
|
|
177
|
-
*
|
|
178
|
-
* @example
|
|
179
|
-
* ```typescript
|
|
180
|
-
* const r = someOperation();
|
|
181
|
-
* if (isOk(r)) {
|
|
182
|
-
* // Use r.value (Type is T)
|
|
183
|
-
* processValue(r.value);
|
|
184
|
-
* } else {
|
|
185
|
-
* // Handle r.error (Type is E)
|
|
186
|
-
* handleError(r.error);
|
|
187
|
-
* }
|
|
188
|
-
* ```
|
|
189
|
-
*/
|
|
190
|
-
declare const isOk: <T, E, C>(r: Result<T, E, C>) => r is Ok<T>;
|
|
191
|
-
/**
|
|
192
|
-
* Checks if a Result is a failure.
|
|
193
|
-
* Use this to narrow the type of a Result to the error case.
|
|
194
|
-
*
|
|
195
|
-
* @remarks When to use: Prefer functional-style checks or array filtering over `result.ok`.
|
|
196
|
-
*
|
|
197
|
-
* @param r - The Result to check
|
|
198
|
-
* @returns `true` if failed, allowing access to `r.error` and `r.cause`
|
|
199
|
-
*
|
|
200
|
-
* @example
|
|
201
|
-
* ```typescript
|
|
202
|
-
* if (isErr(r)) {
|
|
203
|
-
* // Handle error case early
|
|
204
|
-
* return;
|
|
205
|
-
* }
|
|
206
|
-
* // Proceed with success case
|
|
207
|
-
* ```
|
|
208
|
-
*/
|
|
209
|
-
declare const isErr: <T, E, C>(r: Result<T, E, C>) => r is Err<E, C>;
|
|
210
|
-
/**
|
|
211
|
-
* Checks if an error is an UnexpectedError.
|
|
212
|
-
* Used internally by the framework but exported for advanced custom handling.
|
|
213
|
-
* Indicates an error that wasn't typed/expected in the `run` signature.
|
|
214
|
-
*
|
|
215
|
-
* @remarks When to use: Distinguish unexpected failures from your typed error union.
|
|
216
|
-
*/
|
|
217
|
-
declare const isUnexpectedError: (e: unknown) => e is UnexpectedError;
|
|
218
|
-
/**
|
|
219
|
-
* Type for exhaustive error handlers mapping string literal errors and UnexpectedError.
|
|
220
|
-
* Each key in E gets a handler, plus UnexpectedError is required.
|
|
221
|
-
*/
|
|
222
|
-
type MatchErrorHandlers<E extends string, R> = {
|
|
223
|
-
[K in Exclude<E, "UnexpectedError">]: (error: K) => R;
|
|
224
|
-
} & {
|
|
225
|
-
UnexpectedError: (error: UnexpectedError) => R;
|
|
226
|
-
};
|
|
227
|
-
/**
|
|
228
|
-
* Exhaustive pattern matching for error types.
|
|
229
|
-
* Handles both string literal errors and UnexpectedError, ensuring all cases are covered.
|
|
230
|
-
*
|
|
231
|
-
* @param error - The error to match (string literal or UnexpectedError)
|
|
232
|
-
* @param handlers - Object with a handler for each error case plus UnexpectedError
|
|
233
|
-
* @returns The result of the matched handler
|
|
234
|
-
*
|
|
235
|
-
* @example
|
|
236
|
-
* ```typescript
|
|
237
|
-
* type FetchError = "NOT_FOUND" | "FETCH_ERROR";
|
|
238
|
-
* const result: Result<User, FetchError | UnexpectedError> = await fetchUser();
|
|
239
|
-
*
|
|
240
|
-
* if (!result.ok) {
|
|
241
|
-
* return matchError(result.error, {
|
|
242
|
-
* NOT_FOUND: () => 404,
|
|
243
|
-
* FETCH_ERROR: () => 500,
|
|
244
|
-
* UnexpectedError: (e) => { throw e.cause; }
|
|
245
|
-
* });
|
|
246
|
-
* }
|
|
247
|
-
* ```
|
|
248
|
-
*/
|
|
249
|
-
declare function matchError<E extends string, R>(handlers: MatchErrorHandlers<E, R>): (error: E | UnexpectedError) => R;
|
|
250
|
-
declare function matchError<E extends string, R>(error: E | UnexpectedError, handlers: MatchErrorHandlers<E, R>): R;
|
|
251
113
|
type AnyFunction = (...args: never[]) => unknown;
|
|
252
114
|
/**
|
|
253
115
|
* Helper to extract the error type from Result or AsyncResult return values.
|
|
254
116
|
* Works even when a function is declared to return a union of both forms.
|
|
117
|
+
* Plain (non-Result) return types contribute `never` — without the [never]
|
|
118
|
+
* guard they would infer `unknown` and poison error unions built from
|
|
119
|
+
* mixed deps.
|
|
255
120
|
*/
|
|
256
|
-
type ErrorOfReturn<R> = Extract<Awaited<R>, {
|
|
121
|
+
type ErrorOfReturn<R> = [Extract<Awaited<R>, {
|
|
122
|
+
ok: false;
|
|
123
|
+
}>] extends [never] ? never : Extract<Awaited<R>, {
|
|
257
124
|
ok: false;
|
|
258
125
|
}> extends {
|
|
259
126
|
error: infer E;
|
|
@@ -262,12 +129,6 @@ type ErrorOfReturn<R> = Extract<Awaited<R>, {
|
|
|
262
129
|
* Extract error type from a single function's return type
|
|
263
130
|
*/
|
|
264
131
|
type ErrorOf<T extends AnyFunction> = ErrorOfReturn<ReturnType<T>>;
|
|
265
|
-
/**
|
|
266
|
-
* Extract union of error types from multiple functions (tuple form)
|
|
267
|
-
*/
|
|
268
|
-
type Errors<T extends AnyFunction[]> = {
|
|
269
|
-
[K in keyof T]: ErrorOf<T[K]>;
|
|
270
|
-
}[number];
|
|
271
132
|
/**
|
|
272
133
|
* Extract union of error types from a deps object.
|
|
273
134
|
*
|
|
@@ -281,27 +142,6 @@ type Errors<T extends AnyFunction[]> = {
|
|
|
281
142
|
type ErrorsOf<Deps extends Record<string, AnyFunction>> = {
|
|
282
143
|
[K in keyof Deps]: ErrorOf<Deps[K]>;
|
|
283
144
|
}[keyof Deps];
|
|
284
|
-
/**
|
|
285
|
-
* Extract value type from Result
|
|
286
|
-
*/
|
|
287
|
-
type ExtractValue<T> = T extends {
|
|
288
|
-
ok: true;
|
|
289
|
-
value: infer U;
|
|
290
|
-
} ? U : never;
|
|
291
|
-
/**
|
|
292
|
-
* Extract error type from Result
|
|
293
|
-
*/
|
|
294
|
-
type ExtractError<T> = T extends {
|
|
295
|
-
ok: false;
|
|
296
|
-
error: infer E;
|
|
297
|
-
} ? E : never;
|
|
298
|
-
/**
|
|
299
|
-
* Extract cause type from Result
|
|
300
|
-
*/
|
|
301
|
-
type ExtractCause<T> = T extends {
|
|
302
|
-
ok: false;
|
|
303
|
-
cause?: infer C;
|
|
304
|
-
} ? C : never;
|
|
305
145
|
/**
|
|
306
146
|
* Helper to extract the cause type from Result or AsyncResult return values.
|
|
307
147
|
* Works even when a function is declared to return a union of both forms.
|
|
@@ -574,14 +414,6 @@ interface StepErrorDiagnostics {
|
|
|
574
414
|
cumulativeDurationMs?: number;
|
|
575
415
|
origin: 'result' | 'throw' | 'timeout';
|
|
576
416
|
}
|
|
577
|
-
/** Extract canonical error tag. Priority: _tag > tag > code > Error.name > "unknown".
|
|
578
|
-
* Tags are case-sensitive, whitespace-trimmed, otherwise raw.
|
|
579
|
-
* Note: Error.name is fallback-grade (often too coarse like "Error", "TypeError"). */
|
|
580
|
-
declare function extractErrorTag(error: unknown): string;
|
|
581
|
-
/** Look up ErrorClassification from errorMeta for a given tag. */
|
|
582
|
-
declare function lookupErrorClassification(tag: string, errorMeta?: Record<string, ErrorClassification>): ErrorClassification | undefined;
|
|
583
|
-
/** Extract StepMetadata from StepOptions (returns undefined when empty). */
|
|
584
|
-
declare function extractStepMetadata(options: StepOptions): StepMetadata | undefined;
|
|
585
417
|
/**
|
|
586
418
|
* Backoff strategy for retry operations.
|
|
587
419
|
*/
|
|
@@ -1659,6 +1491,18 @@ type WorkflowEvent<E, C = unknown> = {
|
|
|
1659
1491
|
ts: number;
|
|
1660
1492
|
metadata?: StepMetadata;
|
|
1661
1493
|
context?: C;
|
|
1494
|
+
} | {
|
|
1495
|
+
type: "decision";
|
|
1496
|
+
workflowId: string;
|
|
1497
|
+
workflowName?: string;
|
|
1498
|
+
decisionId: string;
|
|
1499
|
+
label?: string;
|
|
1500
|
+
branch: string;
|
|
1501
|
+
value: unknown;
|
|
1502
|
+
phase?: "start" | "end";
|
|
1503
|
+
durationMs?: number;
|
|
1504
|
+
ts: number;
|
|
1505
|
+
context?: C;
|
|
1662
1506
|
} | {
|
|
1663
1507
|
type: "scope_start";
|
|
1664
1508
|
workflowId: string;
|
|
@@ -1831,6 +1675,23 @@ type WorkflowEvent<E, C = unknown> = {
|
|
|
1831
1675
|
lastStepKey?: string;
|
|
1832
1676
|
context?: C;
|
|
1833
1677
|
};
|
|
1678
|
+
/**
|
|
1679
|
+
* A declared workflow graph for strict runtime validation.
|
|
1680
|
+
*
|
|
1681
|
+
* Pass either a list of step/decision ids or a WorkflowDiagramDSL-shaped
|
|
1682
|
+
* object (`{ states: [{ id }] }`, as produced by awaitly-analyze).
|
|
1683
|
+
* When provided, any runtime step or decision id not present in the graph
|
|
1684
|
+
* fails the workflow immediately — so the static diagram is guaranteed to
|
|
1685
|
+
* match what actually runs. Ids containing `{...}` placeholders
|
|
1686
|
+
* (e.g. "item-{i}") match any value in that position.
|
|
1687
|
+
*/
|
|
1688
|
+
type DeclaredGraph = readonly string[] | {
|
|
1689
|
+
readonly states: ReadonlyArray<{
|
|
1690
|
+
readonly id: string;
|
|
1691
|
+
/** Authored id when the unique diagram id needed a collision suffix. */
|
|
1692
|
+
readonly semanticId?: string;
|
|
1693
|
+
}>;
|
|
1694
|
+
};
|
|
1834
1695
|
type RunOptionsWithCatch<E, C = void> = {
|
|
1835
1696
|
/**
|
|
1836
1697
|
* Handler for expected errors.
|
|
@@ -1866,6 +1727,11 @@ type RunOptionsWithCatch<E, C = void> = {
|
|
|
1866
1727
|
* Useful for passing request IDs, user IDs, or loggers.
|
|
1867
1728
|
*/
|
|
1868
1729
|
context?: C;
|
|
1730
|
+
/**
|
|
1731
|
+
* Declared workflow graph for strict runtime validation.
|
|
1732
|
+
* Undeclared step/decision ids fail the workflow immediately.
|
|
1733
|
+
*/
|
|
1734
|
+
graph?: DeclaredGraph;
|
|
1869
1735
|
/**
|
|
1870
1736
|
* @internal External signal for workflow-level cancellation.
|
|
1871
1737
|
* Used by createWorkflow() to pass the workflow signal to steps.
|
|
@@ -1893,6 +1759,11 @@ type RunOptionsWithoutCatch<E, C = void> = {
|
|
|
1893
1759
|
*/
|
|
1894
1760
|
workflowName?: string;
|
|
1895
1761
|
context?: C;
|
|
1762
|
+
/**
|
|
1763
|
+
* Declared workflow graph for strict runtime validation.
|
|
1764
|
+
* Undeclared step/decision ids fail the workflow immediately.
|
|
1765
|
+
*/
|
|
1766
|
+
graph?: DeclaredGraph;
|
|
1896
1767
|
/**
|
|
1897
1768
|
* @internal External signal for workflow-level cancellation.
|
|
1898
1769
|
* Used by createWorkflow() to pass the workflow signal to steps.
|
|
@@ -1967,7 +1838,7 @@ declare function isEarlyExit<E>(e: unknown): e is EarlyExit<E>;
|
|
|
1967
1838
|
/**
|
|
1968
1839
|
* run() with catchUnexpected: closed union Result<T, E>.
|
|
1969
1840
|
*/
|
|
1970
|
-
declare function
|
|
1841
|
+
declare function runFn<T, E, C = void>(fn: (context: {
|
|
1971
1842
|
step: RunStep<E>;
|
|
1972
1843
|
}) => Promise<T> | T, options: RunOptionsWithCatch<E, C>): AsyncResult<T, E, unknown>;
|
|
1973
1844
|
/**
|
|
@@ -1976,7 +1847,7 @@ declare function run<T, E, C = void>(fn: (context: {
|
|
|
1976
1847
|
* uncaught exceptions are possible. Step errors pass through as-is.
|
|
1977
1848
|
* When E is never (default), step is RunStep<unknown> so any operation is allowed.
|
|
1978
1849
|
*/
|
|
1979
|
-
declare function
|
|
1850
|
+
declare function runFn<T, E = never, C = void>(fn: (context: {
|
|
1980
1851
|
step: [E] extends [never] ? RunStep<unknown> : RunStep<E>;
|
|
1981
1852
|
}) => Promise<T> | T, options?: {
|
|
1982
1853
|
onError?: (error: E | UnexpectedError, stepName?: string, ctx?: C) => void;
|
|
@@ -1984,11 +1855,55 @@ declare function run<T, E = never, C = void>(fn: (context: {
|
|
|
1984
1855
|
workflowId?: string;
|
|
1985
1856
|
workflowName?: string;
|
|
1986
1857
|
context?: C;
|
|
1858
|
+
graph?: DeclaredGraph;
|
|
1987
1859
|
/** @internal External signal for workflow-level cancellation. */
|
|
1988
1860
|
_workflowSignal?: AbortSignal;
|
|
1989
1861
|
}): AsyncResult<T, E | UnexpectedError, unknown>;
|
|
1990
|
-
|
|
1991
|
-
|
|
1862
|
+
/**
|
|
1863
|
+
* run() with dependencies: auto-bound steps and automatic error inference.
|
|
1864
|
+
*
|
|
1865
|
+
* Pass your functions as the first argument; the callback receives a steps
|
|
1866
|
+
* object mirroring them. Calling `s.getUser(id)` behaves exactly like
|
|
1867
|
+
* `step('getUser', () => getUser(id))` — unwraps ok, early-exits on err —
|
|
1868
|
+
* and the result's error union is inferred from the deps. No type
|
|
1869
|
+
* parameters, no string IDs, no thunks.
|
|
1870
|
+
*
|
|
1871
|
+
* Plain (non-Result) functions are valid deps: their values pass through
|
|
1872
|
+
* and their throws become UnexpectedError, so existing code works unchanged
|
|
1873
|
+
* and can adopt typed errors incrementally.
|
|
1874
|
+
*
|
|
1875
|
+
* @example
|
|
1876
|
+
* ```typescript
|
|
1877
|
+
* const result = await run({ getOrder, getUser, charge }, async (s) => {
|
|
1878
|
+
* const order = await s.getOrder(orderId);
|
|
1879
|
+
* const user = await s.getUser(order.userId);
|
|
1880
|
+
* return s.charge(order.total);
|
|
1881
|
+
* });
|
|
1882
|
+
* // result.error: OrderNotFound | UserNotFound | ChargeDeclined | UnexpectedError
|
|
1883
|
+
* ```
|
|
1884
|
+
*/
|
|
1885
|
+
declare function runFn<const Deps extends Record<string, AnyFunction>, T, C = void>(deps: Deps, fn: (steps: BoundSteps<Deps>, context: {
|
|
1886
|
+
step: [ErrorsOf<Deps>] extends [never] ? RunStep<unknown> : RunStep<ErrorsOf<Deps>>;
|
|
1887
|
+
}) => Promise<T> | T, options?: {
|
|
1888
|
+
onError?: (error: ErrorsOf<Deps> | UnexpectedError, stepName?: string, ctx?: C) => void;
|
|
1889
|
+
onEvent?: (event: WorkflowEvent<ErrorsOf<Deps> | UnexpectedError, C>, ctx: C) => void;
|
|
1890
|
+
workflowId?: string;
|
|
1891
|
+
workflowName?: string;
|
|
1892
|
+
context?: C;
|
|
1893
|
+
graph?: DeclaredGraph;
|
|
1894
|
+
/** @internal External signal for workflow-level cancellation. */
|
|
1895
|
+
_workflowSignal?: AbortSignal;
|
|
1896
|
+
}): AsyncResult<T, ErrorsOf<Deps> | UnexpectedError, unknown>;
|
|
1897
|
+
/**
|
|
1898
|
+
* The public run(): the engine with `.strict` attached.
|
|
1899
|
+
*
|
|
1900
|
+
* Assembled with a PURE-annotated Object.assign instead of a top-level
|
|
1901
|
+
* `run.strict = ...` mutation — a top-level property assignment is a side
|
|
1902
|
+
* effect that pins run (and the whole step engine) into every consumer
|
|
1903
|
+
* bundle even when only Result primitives are imported.
|
|
1904
|
+
*/
|
|
1905
|
+
declare const run: typeof runFn & {
|
|
1906
|
+
strict: <T, E, C = void>(fn: (context: {
|
|
1992
1907
|
step: RunStep<E>;
|
|
1993
1908
|
}) => Promise<T> | T, options: {
|
|
1994
1909
|
onError?: (error: E, stepName?: string, ctx?: C) => void;
|
|
@@ -2005,1427 +1920,1165 @@ declare namespace run {
|
|
|
2005
1920
|
/** @internal External signal for workflow-level cancellation. */
|
|
2006
1921
|
_workflowSignal?: AbortSignal;
|
|
2007
1922
|
}) => AsyncResult<T, E, unknown>;
|
|
2008
|
-
}
|
|
1923
|
+
};
|
|
1924
|
+
|
|
2009
1925
|
/**
|
|
2010
|
-
*
|
|
1926
|
+
* awaitly/streaming - Types
|
|
2011
1927
|
*
|
|
2012
|
-
*
|
|
2013
|
-
*
|
|
1928
|
+
* Core types for Result-aware streaming in workflows.
|
|
1929
|
+
* All stream operations return Result types, enabling typed error handling
|
|
1930
|
+
* throughout the streaming pipeline.
|
|
1931
|
+
*/
|
|
1932
|
+
|
|
1933
|
+
/** Discriminant for stream write errors */
|
|
1934
|
+
declare const STREAM_WRITE_ERROR: "STREAM_WRITE_ERROR";
|
|
1935
|
+
/** Discriminant for stream read errors */
|
|
1936
|
+
declare const STREAM_READ_ERROR: "STREAM_READ_ERROR";
|
|
1937
|
+
/** Discriminant for stream close errors */
|
|
1938
|
+
declare const STREAM_CLOSE_ERROR: "STREAM_CLOSE_ERROR";
|
|
1939
|
+
/** Discriminant for stream store errors */
|
|
1940
|
+
declare const STREAM_STORE_ERROR: "STREAM_STORE_ERROR";
|
|
1941
|
+
/** Discriminant for stream ended marker */
|
|
1942
|
+
declare const STREAM_ENDED: "STREAM_ENDED";
|
|
1943
|
+
/** Discriminant for stream backpressure errors */
|
|
1944
|
+
declare const STREAM_BACKPRESSURE_ERROR: "STREAM_BACKPRESSURE_ERROR";
|
|
1945
|
+
/**
|
|
1946
|
+
* Error returned when a write operation fails.
|
|
1947
|
+
*/
|
|
1948
|
+
type StreamWriteError = {
|
|
1949
|
+
type: typeof STREAM_WRITE_ERROR;
|
|
1950
|
+
reason: "closed" | "aborted" | "store_error";
|
|
1951
|
+
message: string;
|
|
1952
|
+
cause?: unknown;
|
|
1953
|
+
};
|
|
1954
|
+
/**
|
|
1955
|
+
* Error returned when a read operation fails.
|
|
1956
|
+
*/
|
|
1957
|
+
type StreamReadError = {
|
|
1958
|
+
type: typeof STREAM_READ_ERROR;
|
|
1959
|
+
reason: "closed" | "store_error";
|
|
1960
|
+
message: string;
|
|
1961
|
+
cause?: unknown;
|
|
1962
|
+
};
|
|
1963
|
+
/**
|
|
1964
|
+
* Error returned when closing a stream fails.
|
|
1965
|
+
*/
|
|
1966
|
+
type StreamCloseError = {
|
|
1967
|
+
type: typeof STREAM_CLOSE_ERROR;
|
|
1968
|
+
reason: "already_closed" | "store_error";
|
|
1969
|
+
message: string;
|
|
1970
|
+
cause?: unknown;
|
|
1971
|
+
};
|
|
1972
|
+
/**
|
|
1973
|
+
* Error returned from StreamStore operations.
|
|
1974
|
+
*/
|
|
1975
|
+
type StreamStoreError = {
|
|
1976
|
+
type: typeof STREAM_STORE_ERROR;
|
|
1977
|
+
reason: "read_error" | "write_error" | "metadata_error" | "close_error";
|
|
1978
|
+
message: string;
|
|
1979
|
+
cause?: unknown;
|
|
1980
|
+
};
|
|
1981
|
+
/**
|
|
1982
|
+
* Marker indicating stream has ended (not an error, but a terminal state).
|
|
1983
|
+
* Used as the "error" type when stream is exhausted.
|
|
1984
|
+
*/
|
|
1985
|
+
type StreamEndedMarker = {
|
|
1986
|
+
type: typeof STREAM_ENDED;
|
|
1987
|
+
finalPosition: number;
|
|
1988
|
+
};
|
|
1989
|
+
/**
|
|
1990
|
+
* Backpressure error when writer is paused.
|
|
1991
|
+
*/
|
|
1992
|
+
type StreamBackpressureError = {
|
|
1993
|
+
type: typeof STREAM_BACKPRESSURE_ERROR;
|
|
1994
|
+
bufferedCount: number;
|
|
1995
|
+
highWaterMark: number;
|
|
1996
|
+
};
|
|
1997
|
+
/**
|
|
1998
|
+
* Union of all stream errors.
|
|
1999
|
+
*/
|
|
2000
|
+
type StreamError = StreamWriteError | StreamReadError | StreamCloseError | StreamStoreError | StreamBackpressureError;
|
|
2001
|
+
/**
|
|
2002
|
+
* A single item in the stream with metadata.
|
|
2014
2003
|
*/
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2004
|
+
interface StreamItem<T> {
|
|
2005
|
+
/** The value stored in this stream item */
|
|
2006
|
+
value: T;
|
|
2007
|
+
/** Position in the stream (0-indexed) */
|
|
2008
|
+
position: number;
|
|
2009
|
+
/** Timestamp when item was written */
|
|
2010
|
+
ts: number;
|
|
2019
2011
|
}
|
|
2020
2012
|
/**
|
|
2021
|
-
*
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
*
|
|
2043
|
-
* @returns The success value if the Result is successful
|
|
2044
|
-
* @throws {UnwrapError} If the Result is an error (includes the error and cause)
|
|
2045
|
-
*
|
|
2046
|
-
* @example
|
|
2047
|
-
* ```typescript
|
|
2048
|
-
* // Safe usage after checking
|
|
2049
|
-
* const result = someOperation();
|
|
2050
|
-
* if (isOk(result)) {
|
|
2051
|
-
* const value = unwrap(result); // Safe - we know it's ok
|
|
2052
|
-
* }
|
|
2053
|
-
*
|
|
2054
|
-
* // Unsafe usage (not recommended)
|
|
2055
|
-
* const value = unwrap(someOperation()); // May throw!
|
|
2056
|
-
* ```
|
|
2013
|
+
* Metadata about a stream.
|
|
2014
|
+
*/
|
|
2015
|
+
interface StreamMetadata {
|
|
2016
|
+
/** Unique identifier for the stream (workflowId + namespace) */
|
|
2017
|
+
id: string;
|
|
2018
|
+
/** Namespace within the workflow */
|
|
2019
|
+
namespace: string;
|
|
2020
|
+
/** Workflow ID that owns this stream */
|
|
2021
|
+
workflowId: string;
|
|
2022
|
+
/** Number of items in the stream */
|
|
2023
|
+
length: number;
|
|
2024
|
+
/** Whether the stream has been closed */
|
|
2025
|
+
closed: boolean;
|
|
2026
|
+
/** Timestamp when stream was created */
|
|
2027
|
+
createdAt: number;
|
|
2028
|
+
/** Timestamp when stream was last written to */
|
|
2029
|
+
lastWriteAt?: number;
|
|
2030
|
+
/** Timestamp when stream was closed */
|
|
2031
|
+
closedAt?: number;
|
|
2032
|
+
}
|
|
2033
|
+
/**
|
|
2034
|
+
* Options for creating a writable stream.
|
|
2057
2035
|
*/
|
|
2058
|
-
|
|
2036
|
+
interface StreamOptions {
|
|
2037
|
+
/** Named streams (default: 'default') */
|
|
2038
|
+
namespace?: string;
|
|
2039
|
+
/** Backpressure threshold (default: 16) */
|
|
2040
|
+
highWaterMark?: number;
|
|
2041
|
+
}
|
|
2059
2042
|
/**
|
|
2060
|
-
*
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
*
|
|
2070
|
-
|
|
2071
|
-
|
|
2043
|
+
* Options for creating a readable stream.
|
|
2044
|
+
*/
|
|
2045
|
+
interface StreamReadOptions {
|
|
2046
|
+
/** Named streams (default: 'default') */
|
|
2047
|
+
namespace?: string;
|
|
2048
|
+
/** Resume from position (0-indexed) */
|
|
2049
|
+
startIndex?: number;
|
|
2050
|
+
}
|
|
2051
|
+
/**
|
|
2052
|
+
* Options for streamForEach operation.
|
|
2053
|
+
*/
|
|
2054
|
+
interface StreamForEachOptions {
|
|
2055
|
+
/** Name for the operation (used in events) */
|
|
2056
|
+
name?: string;
|
|
2057
|
+
/** Checkpoint after every N items (default: 1 = checkpoint each item) */
|
|
2058
|
+
checkpointInterval?: number;
|
|
2059
|
+
/** Maximum concurrent processors (default: 1 = sequential) */
|
|
2060
|
+
concurrency?: number;
|
|
2061
|
+
}
|
|
2062
|
+
/**
|
|
2063
|
+
* Result from streamForEach operation.
|
|
2064
|
+
*/
|
|
2065
|
+
interface StreamForEachResult<R> {
|
|
2066
|
+
/** Results from each processed item */
|
|
2067
|
+
results: R[];
|
|
2068
|
+
/** Total items processed */
|
|
2069
|
+
processedCount: number;
|
|
2070
|
+
/** Position of last processed item */
|
|
2071
|
+
lastPosition: number;
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Writable stream interface - never throws, returns Results.
|
|
2072
2075
|
*
|
|
2073
|
-
*
|
|
2074
|
-
*
|
|
2075
|
-
* - **Type-safe**: TypeScript knows you'll always get a `T`
|
|
2076
|
+
* Use within a step to write values to a stream that can be consumed
|
|
2077
|
+
* by readers (e.g., HTTP response streaming, AI token streaming).
|
|
2076
2078
|
*
|
|
2077
|
-
* @
|
|
2078
|
-
* @param defaultValue - The value to return if the Result is an error
|
|
2079
|
-
* @returns The success value if successful, otherwise the default value
|
|
2079
|
+
* @template T - Type of values written to the stream
|
|
2080
2080
|
*
|
|
2081
2081
|
* @example
|
|
2082
2082
|
* ```typescript
|
|
2083
|
-
*
|
|
2084
|
-
* const user = unwrapOr(fetchUser(id), { id: 'anonymous', name: 'Guest' });
|
|
2083
|
+
* const writer = step.getWritable<string>({ namespace: 'ai-response' });
|
|
2085
2084
|
*
|
|
2086
|
-
*
|
|
2087
|
-
*
|
|
2085
|
+
* await step(() => generateAI({
|
|
2086
|
+
* prompt: 'Hello',
|
|
2087
|
+
* onToken: async (token) => { await writer.write(token); }
|
|
2088
|
+
* }), { key: 'generate' });
|
|
2088
2089
|
*
|
|
2089
|
-
*
|
|
2090
|
-
* const config = unwrapOr(loadConfig(), getDefaultConfig());
|
|
2090
|
+
* await writer.close();
|
|
2091
2091
|
* ```
|
|
2092
2092
|
*/
|
|
2093
|
-
|
|
2093
|
+
interface StreamWriter<T> {
|
|
2094
|
+
/**
|
|
2095
|
+
* Write a value to the stream.
|
|
2096
|
+
* Returns an error if the stream is closed, aborted, or store fails.
|
|
2097
|
+
*/
|
|
2098
|
+
write(value: T): AsyncResult<void, StreamWriteError>;
|
|
2099
|
+
/**
|
|
2100
|
+
* Close the stream normally.
|
|
2101
|
+
* Signals to readers that no more data will be written.
|
|
2102
|
+
*/
|
|
2103
|
+
close(): AsyncResult<void, StreamCloseError>;
|
|
2104
|
+
/**
|
|
2105
|
+
* Abort the stream with a reason.
|
|
2106
|
+
* Use for error conditions that should terminate the stream.
|
|
2107
|
+
*/
|
|
2108
|
+
abort(reason: unknown): void;
|
|
2109
|
+
/** Whether the stream is still writable */
|
|
2110
|
+
readonly writable: boolean;
|
|
2111
|
+
/** Current write position (number of items written) */
|
|
2112
|
+
readonly position: number;
|
|
2113
|
+
/** Stream namespace */
|
|
2114
|
+
readonly namespace: string;
|
|
2115
|
+
}
|
|
2094
2116
|
/**
|
|
2095
|
-
*
|
|
2096
|
-
*
|
|
2097
|
-
* @remarks When to use: Compute a fallback from the error (logging, metrics, or derived defaults).
|
|
2098
|
-
*
|
|
2099
|
-
* ## When to Use
|
|
2117
|
+
* Readable stream interface - returns STREAM_ENDED marker when complete.
|
|
2100
2118
|
*
|
|
2101
|
-
* Use
|
|
2102
|
-
*
|
|
2103
|
-
* - You need to log or handle the error before providing a default
|
|
2104
|
-
* - The default depends on the error type or cause
|
|
2105
|
-
* - You want to transform the error into a success value
|
|
2119
|
+
* Use to consume values from a stream, with support for resuming from
|
|
2120
|
+
* a specific position.
|
|
2106
2121
|
*
|
|
2107
|
-
*
|
|
2108
|
-
*
|
|
2109
|
-
* - **Lazy**: Default is only computed if needed (better performance)
|
|
2110
|
-
* - **Error-aware**: You can inspect the error before providing default
|
|
2111
|
-
* - **Flexible**: Default can depend on error type or cause
|
|
2112
|
-
*
|
|
2113
|
-
* @param r - The Result to unwrap
|
|
2114
|
-
* @param fn - Function that receives the error and optional cause, returns the default value
|
|
2115
|
-
* @returns The success value if successful, otherwise the result of calling `fn(error, cause)`
|
|
2122
|
+
* @template T - Type of values read from the stream
|
|
2116
2123
|
*
|
|
2117
2124
|
* @example
|
|
2118
2125
|
* ```typescript
|
|
2119
|
-
*
|
|
2120
|
-
* const port = unwrapOrElse(parsePort(env.PORT), (error) => {
|
|
2121
|
-
* if (error === 'INVALID_FORMAT') return 3000;
|
|
2122
|
-
* if (error === 'OUT_OF_RANGE') return 8080;
|
|
2123
|
-
* return 4000; // default
|
|
2124
|
-
* });
|
|
2126
|
+
* const reader = getStreamReader<string>(runId, { namespace: 'ai-response' });
|
|
2125
2127
|
*
|
|
2126
|
-
*
|
|
2127
|
-
*
|
|
2128
|
-
*
|
|
2129
|
-
*
|
|
2130
|
-
* }
|
|
2128
|
+
* let result = await reader.read();
|
|
2129
|
+
* while (result.ok) {
|
|
2130
|
+
* response.write(result.value);
|
|
2131
|
+
* result = await reader.read();
|
|
2132
|
+
* }
|
|
2131
2133
|
*
|
|
2132
|
-
*
|
|
2133
|
-
*
|
|
2134
|
-
*
|
|
2135
|
-
* });
|
|
2134
|
+
* if (result.error.type === 'STREAM_ENDED') {
|
|
2135
|
+
* console.log('Stream complete at position', result.error.finalPosition);
|
|
2136
|
+
* }
|
|
2136
2137
|
* ```
|
|
2137
2138
|
*/
|
|
2138
|
-
|
|
2139
|
+
interface StreamReader<T> {
|
|
2140
|
+
/**
|
|
2141
|
+
* Read the next value from the stream.
|
|
2142
|
+
* Returns StreamEndedMarker when stream is exhausted.
|
|
2143
|
+
*/
|
|
2144
|
+
read(): AsyncResult<T, StreamReadError | StreamEndedMarker>;
|
|
2145
|
+
/**
|
|
2146
|
+
* Close the reader (stop consuming).
|
|
2147
|
+
* Does not affect the underlying stream.
|
|
2148
|
+
*/
|
|
2149
|
+
close(): void;
|
|
2150
|
+
/** Whether there may be more data to read */
|
|
2151
|
+
readonly readable: boolean;
|
|
2152
|
+
/** Current read position */
|
|
2153
|
+
readonly position: number;
|
|
2154
|
+
/** Stream namespace */
|
|
2155
|
+
readonly namespace: string;
|
|
2156
|
+
}
|
|
2157
|
+
/** Unsubscribe function returned by subscribe */
|
|
2158
|
+
type Unsubscribe = () => void;
|
|
2139
2159
|
/**
|
|
2140
|
-
*
|
|
2160
|
+
* Storage backend for stream data.
|
|
2161
|
+
* Follows the same patterns as persistence.ts adapters.
|
|
2141
2162
|
*
|
|
2142
|
-
*
|
|
2163
|
+
* @example In-memory store
|
|
2164
|
+
* ```typescript
|
|
2165
|
+
* const store = createMemoryStreamStore();
|
|
2166
|
+
* ```
|
|
2143
2167
|
*
|
|
2144
|
-
* @
|
|
2145
|
-
*
|
|
2146
|
-
*
|
|
2168
|
+
* @example File-based store
|
|
2169
|
+
* ```typescript
|
|
2170
|
+
* const store = createFileStreamStore({ directory: './streams', fs });
|
|
2171
|
+
* ```
|
|
2147
2172
|
*/
|
|
2148
|
-
|
|
2173
|
+
interface StreamStore {
|
|
2174
|
+
/**
|
|
2175
|
+
* Append an item to the stream.
|
|
2176
|
+
*/
|
|
2177
|
+
append<T>(workflowId: string, namespace: string, item: StreamItem<T>): AsyncResult<void, StreamStoreError>;
|
|
2178
|
+
/**
|
|
2179
|
+
* Read items from the stream starting at an index.
|
|
2180
|
+
* @param startIndex - Position to start reading from (0-indexed)
|
|
2181
|
+
* @param limit - Maximum number of items to read (default: all remaining)
|
|
2182
|
+
*/
|
|
2183
|
+
read<T>(workflowId: string, namespace: string, startIndex: number, limit?: number): AsyncResult<StreamItem<T>[], StreamStoreError>;
|
|
2184
|
+
/**
|
|
2185
|
+
* Get metadata about a stream.
|
|
2186
|
+
* Returns undefined if stream doesn't exist.
|
|
2187
|
+
*/
|
|
2188
|
+
getMetadata(workflowId: string, namespace: string): AsyncResult<StreamMetadata | undefined, StreamStoreError>;
|
|
2189
|
+
/**
|
|
2190
|
+
* Mark stream as closed.
|
|
2191
|
+
*/
|
|
2192
|
+
closeStream(workflowId: string, namespace: string): AsyncResult<void, StreamStoreError>;
|
|
2193
|
+
/**
|
|
2194
|
+
* Subscribe to new items in a stream.
|
|
2195
|
+
* Callback is invoked for each new item written.
|
|
2196
|
+
* Returns unsubscribe function.
|
|
2197
|
+
*/
|
|
2198
|
+
subscribe<T>(workflowId: string, namespace: string, callback: (item: StreamItem<T>) => void): Unsubscribe;
|
|
2199
|
+
}
|
|
2149
2200
|
/**
|
|
2150
|
-
*
|
|
2151
|
-
*
|
|
2152
|
-
* The returned promise **resolves with T** on success and **rejects with UnwrapError** on failure.
|
|
2153
|
-
* UnwrapError extends Error and carries the original `error` and `cause` from the Err.
|
|
2154
|
-
*
|
|
2155
|
-
* @param ar - A Promise or thenable that resolves to a Result
|
|
2156
|
-
* @returns A Promise that resolves with the success value or rejects with UnwrapError
|
|
2201
|
+
* Check if an error is a StreamEndedMarker.
|
|
2157
2202
|
*/
|
|
2158
|
-
declare
|
|
2203
|
+
declare function isStreamEnded(error: unknown): error is StreamEndedMarker;
|
|
2159
2204
|
/**
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2162
|
-
* @param r - The Result to unwrap
|
|
2163
|
-
* @returns The success value if successful, otherwise null
|
|
2205
|
+
* Check if an error is a StreamWriteError.
|
|
2164
2206
|
*/
|
|
2165
|
-
declare
|
|
2207
|
+
declare function isStreamWriteError(error: unknown): error is StreamWriteError;
|
|
2166
2208
|
/**
|
|
2167
|
-
*
|
|
2168
|
-
*
|
|
2169
|
-
* @param r - The Result to unwrap
|
|
2170
|
-
* @returns The success value if successful, otherwise undefined
|
|
2209
|
+
* Check if an error is a StreamReadError.
|
|
2171
2210
|
*/
|
|
2172
|
-
declare
|
|
2211
|
+
declare function isStreamReadError(error: unknown): error is StreamReadError;
|
|
2173
2212
|
/**
|
|
2174
|
-
*
|
|
2175
|
-
*
|
|
2176
|
-
* @remarks When to use: Wrap sync code that might throw so exceptions become Err values.
|
|
2177
|
-
*
|
|
2178
|
-
* ## When to Use
|
|
2179
|
-
*
|
|
2180
|
-
* Use `from()` when:
|
|
2181
|
-
* - You have a synchronous function that throws exceptions
|
|
2182
|
-
* - You want to convert exceptions to typed errors
|
|
2183
|
-
* - You're integrating with libraries that throw (e.g., JSON.parse, fs.readFileSync)
|
|
2184
|
-
* - You need to handle errors without try/catch blocks
|
|
2185
|
-
*
|
|
2186
|
-
* ## Why Use This
|
|
2187
|
-
*
|
|
2188
|
-
* - **Type-safe errors**: Convert thrown exceptions to typed Result errors
|
|
2189
|
-
* - **No try/catch**: Cleaner code without nested try/catch blocks
|
|
2190
|
-
* - **Composable**: Results can be chained with `andThen`, `map`, etc.
|
|
2191
|
-
* - **Explicit errors**: Forces you to handle errors explicitly
|
|
2192
|
-
*
|
|
2193
|
-
* @param fn - The synchronous function to execute (may throw)
|
|
2194
|
-
* @returns A Result with the function's return value or the thrown error
|
|
2195
|
-
*
|
|
2196
|
-
* @example
|
|
2197
|
-
* ```typescript
|
|
2198
|
-
* // Wrap JSON.parse
|
|
2199
|
-
* const parsed = from(() => JSON.parse('{"key": "value"}'));
|
|
2200
|
-
* // parsed: { ok: true, value: { key: "value" } }
|
|
2201
|
-
*
|
|
2202
|
-
* const error = from(() => JSON.parse('invalid'));
|
|
2203
|
-
* // error: { ok: false, error: SyntaxError }
|
|
2204
|
-
* ```
|
|
2213
|
+
* Check if an error is a StreamStoreError.
|
|
2205
2214
|
*/
|
|
2206
|
-
declare function
|
|
2215
|
+
declare function isStreamStoreError(error: unknown): error is StreamStoreError;
|
|
2207
2216
|
/**
|
|
2208
|
-
*
|
|
2209
|
-
*
|
|
2210
|
-
* Use this overload when you want to map thrown exceptions to your typed error union.
|
|
2211
|
-
*
|
|
2212
|
-
* @param fn - The synchronous function to execute (may throw)
|
|
2213
|
-
* @param onError - Function to map the thrown exception to a typed error
|
|
2214
|
-
* @returns A Result with the function's return value or the mapped error
|
|
2215
|
-
*
|
|
2216
|
-
* @example
|
|
2217
|
-
* ```typescript
|
|
2218
|
-
* // Map exceptions to typed errors
|
|
2219
|
-
* const parsed = from(
|
|
2220
|
-
* () => JSON.parse(input),
|
|
2221
|
-
* (cause) => ({ type: 'PARSE_ERROR' as const, cause })
|
|
2222
|
-
* );
|
|
2223
|
-
* // parsed.error: { type: 'PARSE_ERROR', cause: SyntaxError }
|
|
2224
|
-
*
|
|
2225
|
-
* // Map to simple error codes
|
|
2226
|
-
* const value = from(
|
|
2227
|
-
* () => riskyOperation(),
|
|
2228
|
-
* () => 'OPERATION_FAILED' as const
|
|
2229
|
-
* );
|
|
2230
|
-
* ```
|
|
2217
|
+
* Check if an error is a StreamBackpressureError.
|
|
2231
2218
|
*/
|
|
2232
|
-
declare function
|
|
2219
|
+
declare function isStreamBackpressureError(error: unknown): error is StreamBackpressureError;
|
|
2233
2220
|
/**
|
|
2234
|
-
*
|
|
2235
|
-
*
|
|
2236
|
-
* @remarks When to use: Wrap a Promise and keep the raw rejection as Err; use tryAsync to map errors.
|
|
2237
|
-
*
|
|
2238
|
-
* ## When to Use
|
|
2239
|
-
*
|
|
2240
|
-
* Use `fromPromise()` when:
|
|
2241
|
-
* - You have an existing Promise that might reject
|
|
2242
|
-
* - You want to convert Promise rejections to typed errors
|
|
2243
|
-
* - You're working with libraries that return Promises (fetch, database clients)
|
|
2244
|
-
* - You need to handle rejections without .catch() chains
|
|
2245
|
-
*
|
|
2246
|
-
* ## Why Use This
|
|
2247
|
-
*
|
|
2248
|
-
* - **Type-safe errors**: Convert Promise rejections to typed Result errors
|
|
2249
|
-
* - **Composable**: Results can be chained with `andThen`, `map`, etc.
|
|
2250
|
-
* - **Explicit handling**: Forces you to handle errors explicitly
|
|
2251
|
-
* - **No .catch() chains**: Cleaner than Promise.catch() patterns
|
|
2252
|
-
*
|
|
2253
|
-
* @param promise - The Promise to await (may reject)
|
|
2254
|
-
* @returns A Promise resolving to a Result with the resolved value or rejection reason
|
|
2255
|
-
*
|
|
2256
|
-
* @example
|
|
2257
|
-
* ```typescript
|
|
2258
|
-
* // Wrap fetch
|
|
2259
|
-
* const result = await fromPromise(
|
|
2260
|
-
* fetch('/api').then(r => r.json())
|
|
2261
|
-
* );
|
|
2262
|
-
* // result.ok: true if fetch succeeded, false if rejected
|
|
2263
|
-
* ```
|
|
2221
|
+
* Create a StreamWriteError.
|
|
2264
2222
|
*/
|
|
2265
|
-
declare function
|
|
2223
|
+
declare function streamWriteError(reason: StreamWriteError["reason"], message: string, cause?: unknown): StreamWriteError;
|
|
2266
2224
|
/**
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
2269
|
-
* Use this overload when you want to map Promise rejections to your typed error union.
|
|
2270
|
-
*
|
|
2271
|
-
* @param promise - The Promise to await (may reject)
|
|
2272
|
-
* @param onError - Function to map the rejection reason to a typed error
|
|
2273
|
-
* @returns A Promise resolving to a Result with the resolved value or mapped error
|
|
2274
|
-
*
|
|
2275
|
-
* @example
|
|
2276
|
-
* ```typescript
|
|
2277
|
-
* // Map fetch errors to typed errors
|
|
2278
|
-
* const result = await fromPromise(
|
|
2279
|
-
* fetch('/api').then(r => {
|
|
2280
|
-
* if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
2281
|
-
* return r.json();
|
|
2282
|
-
* }),
|
|
2283
|
-
* () => 'FETCH_FAILED' as const
|
|
2284
|
-
* );
|
|
2285
|
-
* // result.error: 'FETCH_FAILED' if fetch failed
|
|
2286
|
-
*
|
|
2287
|
-
* // Map with error details
|
|
2288
|
-
* const data = await fromPromise(
|
|
2289
|
-
* db.query(sql),
|
|
2290
|
-
* (cause) => ({ type: 'DB_ERROR' as const, message: String(cause) })
|
|
2291
|
-
* );
|
|
2292
|
-
* ```
|
|
2225
|
+
* Create a StreamReadError.
|
|
2293
2226
|
*/
|
|
2294
|
-
declare function
|
|
2227
|
+
declare function streamReadError(reason: StreamReadError["reason"], message: string, cause?: unknown): StreamReadError;
|
|
2295
2228
|
/**
|
|
2296
|
-
*
|
|
2297
|
-
*
|
|
2298
|
-
* @remarks When to use: Wrap async work and map thrown/rejected values into your typed error union.
|
|
2299
|
-
*
|
|
2300
|
-
* ## When to Use
|
|
2301
|
-
*
|
|
2302
|
-
* Use `tryAsync()` when:
|
|
2303
|
-
* - You have an async function that might throw or reject
|
|
2304
|
-
* - You want to convert both exceptions and rejections to typed errors
|
|
2305
|
-
* - You're creating new async functions (use `fromPromise` for existing Promises)
|
|
2306
|
-
* - You need to handle errors without try/catch or .catch()
|
|
2307
|
-
*
|
|
2308
|
-
* ## Why Use This Instead of `fromPromise`
|
|
2309
|
-
*
|
|
2310
|
-
* - **Function form**: Takes a function, not a Promise (lazy evaluation)
|
|
2311
|
-
* - **Catches both**: Handles both thrown exceptions and Promise rejections
|
|
2312
|
-
* - **Cleaner syntax**: No need to wrap in Promise manually
|
|
2313
|
-
*
|
|
2314
|
-
* @param fn - The async function to execute (may throw or reject)
|
|
2315
|
-
* @returns A Promise resolving to a Result with the function's return value or error
|
|
2316
|
-
*
|
|
2317
|
-
* @example
|
|
2318
|
-
* ```typescript
|
|
2319
|
-
* // Wrap async function
|
|
2320
|
-
* const result = await tryAsync(async () => {
|
|
2321
|
-
* const data = await fetchData();
|
|
2322
|
-
* return processData(data);
|
|
2323
|
-
* });
|
|
2324
|
-
* ```
|
|
2229
|
+
* Create a StreamCloseError.
|
|
2325
2230
|
*/
|
|
2326
|
-
declare function
|
|
2231
|
+
declare function streamCloseError(reason: StreamCloseError["reason"], message: string, cause?: unknown): StreamCloseError;
|
|
2327
2232
|
/**
|
|
2328
|
-
*
|
|
2329
|
-
*
|
|
2330
|
-
* Use this overload when you want to map errors to your typed error union.
|
|
2331
|
-
*
|
|
2332
|
-
* @param fn - The async function to execute (may throw or reject)
|
|
2333
|
-
* @param onError - Function to map the error (exception or rejection) to a typed error
|
|
2334
|
-
* @returns A Promise resolving to a Result with the function's return value or mapped error
|
|
2335
|
-
*
|
|
2336
|
-
* @example
|
|
2337
|
-
* ```typescript
|
|
2338
|
-
* // Map errors to typed errors
|
|
2339
|
-
* const result = await tryAsync(
|
|
2340
|
-
* async () => await fetchData(),
|
|
2341
|
-
* () => 'FETCH_ERROR' as const
|
|
2342
|
-
* );
|
|
2343
|
-
*
|
|
2344
|
-
* // Map with error details
|
|
2345
|
-
* const data = await tryAsync(
|
|
2346
|
-
* async () => await processFile(path),
|
|
2347
|
-
* (cause) => ({ type: 'PROCESSING_ERROR' as const, cause })
|
|
2348
|
-
* );
|
|
2349
|
-
* ```
|
|
2233
|
+
* Create a StreamStoreError.
|
|
2350
2234
|
*/
|
|
2351
|
-
declare function
|
|
2235
|
+
declare function streamStoreError(reason: StreamStoreError["reason"], message: string, cause?: unknown): StreamStoreError;
|
|
2352
2236
|
/**
|
|
2353
|
-
*
|
|
2354
|
-
*
|
|
2355
|
-
* @remarks When to use: Turn null/undefined into a typed error before continuing.
|
|
2356
|
-
*
|
|
2357
|
-
* ## When to Use
|
|
2358
|
-
*
|
|
2359
|
-
* Use `fromNullable()` when:
|
|
2360
|
-
* - You have a value that might be `null` or `undefined`
|
|
2361
|
-
* - You want to treat null/undefined as an error case
|
|
2362
|
-
* - You're working with APIs that return nullable values (DOM APIs, optional properties)
|
|
2363
|
-
* - You want to avoid null checks scattered throughout your code
|
|
2364
|
-
*
|
|
2365
|
-
* ## Why Use This
|
|
2366
|
-
*
|
|
2367
|
-
* - **Type-safe**: Converts nullable types to non-nullable Results
|
|
2368
|
-
* - **Explicit errors**: Forces you to handle null/undefined cases
|
|
2369
|
-
* - **Composable**: Results can be chained with `andThen`, `map`, etc.
|
|
2370
|
-
* - **No null checks**: Eliminates need for `if (value == null)` checks
|
|
2371
|
-
*
|
|
2372
|
-
* @param value - The value that may be null or undefined
|
|
2373
|
-
* @param onNull - Function that returns an error when value is null/undefined
|
|
2374
|
-
* @returns A Result with the value if not null/undefined, otherwise the error from `onNull`
|
|
2375
|
-
*
|
|
2376
|
-
* @example
|
|
2377
|
-
* ```typescript
|
|
2378
|
-
* // Convert DOM element lookup
|
|
2379
|
-
* const element = fromNullable(
|
|
2380
|
-
* document.getElementById('app'),
|
|
2381
|
-
* () => 'ELEMENT_NOT_FOUND' as const
|
|
2382
|
-
* );
|
|
2383
|
-
*
|
|
2384
|
-
* // Convert optional property
|
|
2385
|
-
* const userId = fromNullable(
|
|
2386
|
-
* user.id,
|
|
2387
|
-
* () => 'USER_ID_MISSING' as const
|
|
2388
|
-
* );
|
|
2389
|
-
*
|
|
2390
|
-
* // Convert database query result
|
|
2391
|
-
* const record = fromNullable(
|
|
2392
|
-
* await db.find(id),
|
|
2393
|
-
* () => ({ type: 'NOT_FOUND' as const, id })
|
|
2394
|
-
* );
|
|
2395
|
-
* ```
|
|
2237
|
+
* Create a StreamEndedMarker.
|
|
2396
2238
|
*/
|
|
2397
|
-
declare function
|
|
2239
|
+
declare function streamEnded(finalPosition: number): StreamEndedMarker;
|
|
2398
2240
|
/**
|
|
2399
|
-
*
|
|
2400
|
-
*
|
|
2401
|
-
* @remarks When to use: Transform only the Ok value while leaving Err untouched.
|
|
2402
|
-
*
|
|
2403
|
-
* ## When to Use
|
|
2404
|
-
*
|
|
2405
|
-
* Use `map()` when:
|
|
2406
|
-
* - You need to transform a success value to another type
|
|
2407
|
-
* - You want to apply a pure function to the value
|
|
2408
|
-
* - You're building a pipeline of transformations
|
|
2409
|
-
* - The transformation cannot fail (use `andThen` if it can fail)
|
|
2410
|
-
*
|
|
2411
|
-
* ## Why Use This
|
|
2412
|
-
*
|
|
2413
|
-
* - **Functional style**: Composable, chainable transformations
|
|
2414
|
-
* - **Error-preserving**: Errors pass through unchanged
|
|
2415
|
-
* - **Type-safe**: TypeScript tracks the transformation
|
|
2416
|
-
* - **No unwrapping**: Avoids manual `if (r.ok)` checks
|
|
2417
|
-
*
|
|
2418
|
-
* @param r - The Result to transform
|
|
2419
|
-
* @param fn - Pure function that transforms the success value (must not throw)
|
|
2420
|
-
* @returns A new Result with the transformed value, or the original error if `r` was an error
|
|
2421
|
-
*
|
|
2422
|
-
* @example
|
|
2423
|
-
* ```typescript
|
|
2424
|
-
* // Transform numeric value
|
|
2425
|
-
* const doubled = map(ok(21), n => n * 2);
|
|
2426
|
-
* // doubled: { ok: true, value: 42 }
|
|
2427
|
-
*
|
|
2428
|
-
* // Transform object property
|
|
2429
|
-
* const name = map(fetchUser(id), user => user.name);
|
|
2430
|
-
*
|
|
2431
|
-
* // Chain transformations
|
|
2432
|
-
* const formatted = map(
|
|
2433
|
-
* map(parseNumber(input), n => n * 2),
|
|
2434
|
-
* n => `Result: ${n}`
|
|
2435
|
-
* );
|
|
2436
|
-
* ```
|
|
2241
|
+
* Create a StreamBackpressureError.
|
|
2437
2242
|
*/
|
|
2438
|
-
declare function
|
|
2439
|
-
|
|
2440
|
-
declare function map<T, U, E, C>(r: Result<T, E, C>, fn: (value: T) => U): Result<U, E, C>;
|
|
2243
|
+
declare function streamBackpressureError(bufferedCount: number, highWaterMark: number): StreamBackpressureError;
|
|
2244
|
+
|
|
2441
2245
|
/**
|
|
2442
|
-
*
|
|
2443
|
-
*
|
|
2444
|
-
* @remarks When to use: Retype or normalize errors while leaving Ok values unchanged.
|
|
2246
|
+
* awaitly/persistence
|
|
2445
2247
|
*
|
|
2446
|
-
*
|
|
2447
|
-
*
|
|
2448
|
-
* Use `mapError()` when:
|
|
2449
|
-
* - You need to normalize or transform error types
|
|
2450
|
-
* - You want to convert errors to a different error type
|
|
2451
|
-
* - You're building error handling pipelines
|
|
2452
|
-
* - You need to format error messages or codes
|
|
2453
|
-
*
|
|
2454
|
-
* ## Why Use This
|
|
2455
|
-
*
|
|
2456
|
-
* - **Error normalization**: Convert errors to a common format
|
|
2457
|
-
* - **Type transformation**: Change error type while preserving value type
|
|
2458
|
-
* - **Composable**: Can be chained with other transformers
|
|
2459
|
-
* - **Success-preserving**: Success values pass through unchanged
|
|
2460
|
-
*
|
|
2461
|
-
* @param r - The Result to transform
|
|
2462
|
-
* @param fn - Function that transforms the error value (must not throw)
|
|
2463
|
-
* @returns A new Result with the original value, or the transformed error if `r` was an error
|
|
2464
|
-
*
|
|
2465
|
-
* @example
|
|
2466
|
-
* ```typescript
|
|
2467
|
-
* // Normalize error codes
|
|
2468
|
-
* const normalized = mapError(err('not_found'), e => e.toUpperCase());
|
|
2469
|
-
* // normalized: { ok: false, error: 'NOT_FOUND' }
|
|
2470
|
-
*
|
|
2471
|
-
* // Convert error types
|
|
2472
|
-
* const typed = mapError(
|
|
2473
|
-
* err('404'),
|
|
2474
|
-
* code => ({ type: 'HTTP_ERROR' as const, status: parseInt(code) })
|
|
2475
|
-
* );
|
|
2476
|
-
*
|
|
2477
|
-
* // Format error messages
|
|
2478
|
-
* const formatted = mapError(
|
|
2479
|
-
* err('PARSE_ERROR'),
|
|
2480
|
-
* code => `Failed to parse: ${code}`
|
|
2481
|
-
* );
|
|
2482
|
-
* ```
|
|
2248
|
+
* Simplified Persistence API for workflow snapshots.
|
|
2249
|
+
* Provides JSON-serializable snapshot format and store adapters.
|
|
2483
2250
|
*/
|
|
2484
|
-
|
|
2251
|
+
|
|
2485
2252
|
/**
|
|
2486
|
-
*
|
|
2487
|
-
*
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
*
|
|
2494
|
-
*
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2253
|
+
* Enforce JSON-safety at type level.
|
|
2254
|
+
* Only allows values that can be safely serialized with JSON.stringify.
|
|
2255
|
+
*/
|
|
2256
|
+
type JSONValue = null | boolean | number | string | JSONValue[] | {
|
|
2257
|
+
[k: string]: JSONValue;
|
|
2258
|
+
};
|
|
2259
|
+
/**
|
|
2260
|
+
* Canonical error wire format - handles both Error instances and thrown non-Errors.
|
|
2261
|
+
* This is the single source of truth for serialized errors in snapshots.
|
|
2262
|
+
*/
|
|
2263
|
+
type SerializedCause = {
|
|
2264
|
+
type: "error";
|
|
2265
|
+
name: string;
|
|
2266
|
+
message: string;
|
|
2267
|
+
stack?: string;
|
|
2268
|
+
cause?: SerializedCause;
|
|
2269
|
+
} | {
|
|
2270
|
+
type: "thrown";
|
|
2271
|
+
originalType?: string;
|
|
2272
|
+
value?: JSONValue;
|
|
2273
|
+
stringRepresentation: string;
|
|
2274
|
+
truncated?: true;
|
|
2275
|
+
};
|
|
2276
|
+
/**
|
|
2277
|
+
* Single source of truth for step outcome (no error/cause confusion).
|
|
2278
|
+
* Uses discriminated union with `ok` field.
|
|
2279
|
+
*/
|
|
2280
|
+
type StepResult = {
|
|
2281
|
+
ok: true;
|
|
2282
|
+
value: JSONValue;
|
|
2283
|
+
} | {
|
|
2284
|
+
ok: false;
|
|
2285
|
+
error: JSONValue;
|
|
2286
|
+
cause: SerializedCause;
|
|
2287
|
+
meta?: {
|
|
2288
|
+
origin: "result" | "throw";
|
|
2289
|
+
};
|
|
2290
|
+
};
|
|
2291
|
+
/**
|
|
2292
|
+
* JSON-serializable workflow snapshot.
|
|
2293
|
+
* Designed to be passed directly to JSON.stringify without special handling.
|
|
2510
2294
|
*
|
|
2511
2295
|
* @example
|
|
2512
2296
|
* ```typescript
|
|
2513
|
-
* //
|
|
2514
|
-
*
|
|
2515
|
-
* ok: (user) => `Hello ${user.name}`,
|
|
2516
|
-
* err: (error) => `Error: ${error}`,
|
|
2517
|
-
* });
|
|
2518
|
-
*
|
|
2519
|
-
* // Transform to API response
|
|
2520
|
-
* const response = match(operation(), {
|
|
2521
|
-
* ok: (data) => ({ status: 200, body: data }),
|
|
2522
|
-
* err: (error) => ({ status: 400, error: String(error) }),
|
|
2523
|
-
* });
|
|
2297
|
+
* // Persist
|
|
2298
|
+
* localStorage.setItem('wf-123', JSON.stringify(wf.getSnapshot()));
|
|
2524
2299
|
*
|
|
2525
|
-
* //
|
|
2526
|
-
* const
|
|
2527
|
-
*
|
|
2528
|
-
*
|
|
2529
|
-
* });
|
|
2300
|
+
* // Restore (safe pattern - storage can be empty/corrupt)
|
|
2301
|
+
* const raw = localStorage.getItem('wf-123');
|
|
2302
|
+
* const snapshot = raw ? JSON.parse(raw) : null;
|
|
2303
|
+
* createWorkflow(deps, { snapshot }); // null = fresh start
|
|
2530
2304
|
* ```
|
|
2531
2305
|
*/
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
*
|
|
2573
|
-
* andThen(operation2(value1), value2 =>
|
|
2574
|
-
* ok({ value1, value2 })
|
|
2575
|
-
* )
|
|
2576
|
-
* )
|
|
2577
|
-
* ```
|
|
2578
|
-
*
|
|
2579
|
-
* @param r - The first Result
|
|
2580
|
-
* @param fn - Function that takes the success value and returns a new Result (may fail)
|
|
2581
|
-
* @returns The Result from `fn` if `r` was successful, otherwise the original error
|
|
2582
|
-
*
|
|
2583
|
-
* @example
|
|
2584
|
-
* ```typescript
|
|
2585
|
-
* // Chain dependent operations
|
|
2586
|
-
* const userPosts = andThen(
|
|
2587
|
-
* fetchUser('1'),
|
|
2588
|
-
* user => fetchPosts(user.id)
|
|
2589
|
-
* );
|
|
2590
|
-
*
|
|
2591
|
-
* // Build complex pipelines
|
|
2592
|
-
* const result = andThen(parseInput(input), parsed =>
|
|
2593
|
-
* andThen(validate(parsed), validated =>
|
|
2594
|
-
* process(validated)
|
|
2595
|
-
* )
|
|
2596
|
-
* );
|
|
2597
|
-
*
|
|
2598
|
-
* // Chain with different error types
|
|
2599
|
-
* const data = andThen(
|
|
2600
|
-
* fetchUser(id), // Returns Result<User, 'FETCH_ERROR'>
|
|
2601
|
-
* user => fetchPosts(user.id) // Returns Result<Post[], 'NOT_FOUND'>
|
|
2602
|
-
* );
|
|
2603
|
-
* // data.error: 'FETCH_ERROR' | 'NOT_FOUND'
|
|
2604
|
-
* ```
|
|
2306
|
+
interface WorkflowSnapshot {
|
|
2307
|
+
/** Snapshot format version (literal type - bump when shape changes) */
|
|
2308
|
+
formatVersion: 1;
|
|
2309
|
+
/** Workflow name (from createWorkflow first argument). */
|
|
2310
|
+
workflowName?: string;
|
|
2311
|
+
/** Step results keyed by step ID. Uses Object.create(null) internally. */
|
|
2312
|
+
steps: Record<string, StepResult>;
|
|
2313
|
+
/** Execution state metadata */
|
|
2314
|
+
execution: {
|
|
2315
|
+
status: "running" | "completed" | "failed";
|
|
2316
|
+
/** ISO timestamp (UTC toISOString()) */
|
|
2317
|
+
lastUpdated: string;
|
|
2318
|
+
/** ISO timestamp if finished */
|
|
2319
|
+
completedAt?: string;
|
|
2320
|
+
/**
|
|
2321
|
+
* For paused/running workflows: the step key of the current step.
|
|
2322
|
+
* Aligns with Workflow Diagram DSL step state ids (see awaitly/workflow diagram-dsl)
|
|
2323
|
+
* so visualizers can highlight the current node.
|
|
2324
|
+
*/
|
|
2325
|
+
currentStepId?: string;
|
|
2326
|
+
};
|
|
2327
|
+
/** Optional metadata for workflow identification and replay */
|
|
2328
|
+
metadata?: {
|
|
2329
|
+
/** Detect wrong snapshot for wrong workflow */
|
|
2330
|
+
workflowId?: string;
|
|
2331
|
+
/** Optional: detect definition changes (user-supplied, advisory only) */
|
|
2332
|
+
definitionHash?: string;
|
|
2333
|
+
/** Original input for replay */
|
|
2334
|
+
input?: JSONValue;
|
|
2335
|
+
[key: string]: JSONValue | undefined;
|
|
2336
|
+
};
|
|
2337
|
+
/** Warnings for lossy serialization (keeps step results pure) */
|
|
2338
|
+
warnings?: Array<{
|
|
2339
|
+
type: "lossy_value";
|
|
2340
|
+
stepId: string;
|
|
2341
|
+
path: string;
|
|
2342
|
+
reason: "non-json" | "circular" | "encode-failed";
|
|
2343
|
+
}>;
|
|
2344
|
+
}
|
|
2345
|
+
/**
|
|
2346
|
+
* Warning entry for lossy value serialization.
|
|
2605
2347
|
*/
|
|
2606
|
-
|
|
2607
|
-
declare function andThen<T, F, C2>(r: Ok<T>, fn: (value: T) => Err<F, C2>): Err<F, C2>;
|
|
2608
|
-
declare function andThen<T, U, F, C2>(r: Ok<T>, fn: (value: T) => Result<U, F, C2>): Result<U, F, C2>;
|
|
2609
|
-
declare function andThen<T, U, E, F, C1, C2>(r: Err<E, C1>, fn: (value: T) => Result<U, F, C2>): Err<E, C1>;
|
|
2610
|
-
declare function andThen<T, U, E, F, C1, C2>(r: Result<T, E, C1>, fn: (value: T) => Result<U, F, C2>): Result<U, E | F, C1 | C2>;
|
|
2348
|
+
type SnapshotWarning = NonNullable<WorkflowSnapshot["warnings"]>[number];
|
|
2611
2349
|
/**
|
|
2612
|
-
*
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
*
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2350
|
+
* Error thrown when snapshot structure is invalid.
|
|
2351
|
+
*/
|
|
2352
|
+
declare class SnapshotFormatError extends Error {
|
|
2353
|
+
readonly errors: string[];
|
|
2354
|
+
constructor(message: string, errors?: string[]);
|
|
2355
|
+
}
|
|
2356
|
+
/**
|
|
2357
|
+
* Error thrown when snapshot doesn't match workflow (unknown steps, workflowId mismatch).
|
|
2358
|
+
*/
|
|
2359
|
+
declare class SnapshotMismatchError extends Error {
|
|
2360
|
+
readonly mismatchType: "unknown_steps" | "workflow_id" | "definition_hash";
|
|
2361
|
+
readonly details?: {
|
|
2362
|
+
unknownSteps?: string[];
|
|
2363
|
+
snapshotWorkflowId?: string;
|
|
2364
|
+
expectedWorkflowId?: string;
|
|
2365
|
+
snapshotHash?: string;
|
|
2366
|
+
expectedHash?: string;
|
|
2367
|
+
} | undefined;
|
|
2368
|
+
constructor(message: string, mismatchType: "unknown_steps" | "workflow_id" | "definition_hash", details?: {
|
|
2369
|
+
unknownSteps?: string[];
|
|
2370
|
+
snapshotWorkflowId?: string;
|
|
2371
|
+
expectedWorkflowId?: string;
|
|
2372
|
+
snapshotHash?: string;
|
|
2373
|
+
expectedHash?: string;
|
|
2374
|
+
} | undefined);
|
|
2375
|
+
}
|
|
2376
|
+
/**
|
|
2377
|
+
* Error thrown when decode fails during restore.
|
|
2378
|
+
*/
|
|
2379
|
+
declare class SnapshotDecodeError extends Error {
|
|
2380
|
+
readonly stepId: string;
|
|
2381
|
+
readonly originalError?: unknown | undefined;
|
|
2382
|
+
constructor(message: string, stepId: string, originalError?: unknown | undefined);
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* Light check to see if an object looks like a WorkflowSnapshot.
|
|
2386
|
+
* Cheap check for basic structure - use validateSnapshot() for full validation.
|
|
2634
2387
|
*
|
|
2635
2388
|
* @example
|
|
2636
2389
|
* ```typescript
|
|
2637
|
-
*
|
|
2638
|
-
*
|
|
2639
|
-
*
|
|
2640
|
-
*
|
|
2641
|
-
* // Debug in pipeline
|
|
2642
|
-
* const debugged = pipe(
|
|
2643
|
-
* fetchUser(id),
|
|
2644
|
-
* r => tap(r, user => console.log('Fetched:', user)),
|
|
2645
|
-
* r => map(r, user => user.name)
|
|
2646
|
-
* );
|
|
2647
|
-
*
|
|
2648
|
-
* // Mutate external state
|
|
2649
|
-
* const tracked = tap(result, data => {
|
|
2650
|
-
* analytics.track('operation_success', data);
|
|
2651
|
-
* });
|
|
2390
|
+
* const raw = JSON.parse(localStorage.getItem('wf-123') || 'null');
|
|
2391
|
+
* if (looksLikeWorkflowSnapshot(raw)) {
|
|
2392
|
+
* createWorkflow(deps, { snapshot: raw });
|
|
2393
|
+
* }
|
|
2652
2394
|
* ```
|
|
2653
2395
|
*/
|
|
2654
|
-
declare function
|
|
2396
|
+
declare function looksLikeWorkflowSnapshot(obj: unknown): obj is WorkflowSnapshot;
|
|
2655
2397
|
/**
|
|
2656
|
-
*
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
*
|
|
2661
|
-
*
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2398
|
+
* Type guard for WorkflowSnapshot. Same as looksLikeWorkflowSnapshot; use for consistent naming with isResumeState / isSerializedResumeState.
|
|
2399
|
+
*/
|
|
2400
|
+
declare const isWorkflowSnapshot: typeof looksLikeWorkflowSnapshot;
|
|
2401
|
+
/**
|
|
2402
|
+
* Full validation with detailed errors.
|
|
2403
|
+
* Returns either a validated snapshot or an array of validation errors.
|
|
2404
|
+
*/
|
|
2405
|
+
declare function validateSnapshot(obj: unknown): {
|
|
2406
|
+
valid: true;
|
|
2407
|
+
snapshot: WorkflowSnapshot;
|
|
2408
|
+
} | {
|
|
2409
|
+
valid: false;
|
|
2410
|
+
errors: string[];
|
|
2411
|
+
};
|
|
2412
|
+
/**
|
|
2413
|
+
* Throwing helper for cleaner code.
|
|
2414
|
+
* Validates a snapshot and throws SnapshotFormatError if invalid.
|
|
2669
2415
|
*
|
|
2670
|
-
*
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2416
|
+
* @throws {SnapshotFormatError} If snapshot is invalid
|
|
2417
|
+
*/
|
|
2418
|
+
declare function assertValidSnapshot(obj: unknown): WorkflowSnapshot;
|
|
2419
|
+
/**
|
|
2420
|
+
* Merge two snapshots (for incremental updates).
|
|
2421
|
+
* Delta steps overwrite base steps; execution from delta; metadata shallow merge.
|
|
2422
|
+
*/
|
|
2423
|
+
declare function mergeSnapshots(base: WorkflowSnapshot, delta: WorkflowSnapshot): WorkflowSnapshot;
|
|
2424
|
+
/**
|
|
2425
|
+
* Serialize an Error object to SerializedCause format.
|
|
2426
|
+
* Preserves Error.cause recursively.
|
|
2427
|
+
*/
|
|
2428
|
+
declare function serializeError(error: Error): SerializedCause;
|
|
2429
|
+
/**
|
|
2430
|
+
* Serialize a non-Error thrown value to SerializedCause format.
|
|
2431
|
+
*/
|
|
2432
|
+
declare function serializeThrown(value: unknown): SerializedCause;
|
|
2433
|
+
/**
|
|
2434
|
+
* Deserialize a SerializedCause back to its original form.
|
|
2435
|
+
*/
|
|
2436
|
+
declare function deserializeCauseNew(serialized: SerializedCause): unknown;
|
|
2437
|
+
/**
|
|
2438
|
+
* Simplified store interface for workflow snapshot persistence.
|
|
2439
|
+
* Works directly with WorkflowSnapshot objects.
|
|
2674
2440
|
*
|
|
2675
|
-
*
|
|
2676
|
-
*
|
|
2677
|
-
*
|
|
2441
|
+
* Adapters may implement an extended contract (see awaitly/workflow): save can accept
|
|
2442
|
+
* WorkflowSnapshot | ResumeState; load can return WorkflowSnapshot | ResumeState | null.
|
|
2443
|
+
* Use isWorkflowSnapshot / isSerializedResumeState and serializeResumeState / deserializeResumeState
|
|
2444
|
+
* when branching. For type-safe restore, use store.loadResumeState(id) or toResumeState(await store.load(id)).
|
|
2678
2445
|
*
|
|
2679
2446
|
* @example
|
|
2680
2447
|
* ```typescript
|
|
2681
|
-
*
|
|
2682
|
-
*
|
|
2683
|
-
* console.error('Error:', error, cause);
|
|
2684
|
-
* });
|
|
2448
|
+
* import { postgres } from 'awaitly-postgres';
|
|
2449
|
+
* import { createWorkflow } from 'awaitly/workflow';
|
|
2685
2450
|
*
|
|
2686
|
-
*
|
|
2687
|
-
* const
|
|
2688
|
-
*
|
|
2689
|
-
*
|
|
2451
|
+
* const store = postgres('postgresql://localhost/mydb');
|
|
2452
|
+
* const workflow = createWorkflow(deps);
|
|
2453
|
+
*
|
|
2454
|
+
* // Run and persist resume state
|
|
2455
|
+
* const { result, resumeState } = await workflow.runWithState(fn);
|
|
2456
|
+
* await store.save('wf-123', resumeState);
|
|
2690
2457
|
*
|
|
2691
|
-
* //
|
|
2692
|
-
* const
|
|
2693
|
-
*
|
|
2694
|
-
*
|
|
2695
|
-
* r => mapError(r, err => 'FORMATTED_ERROR')
|
|
2696
|
-
* );
|
|
2458
|
+
* // Restore
|
|
2459
|
+
* const loaded = await store.load('wf-123');
|
|
2460
|
+
* const resumeState = toResumeState(loaded);
|
|
2461
|
+
* if (resumeState) await workflow.run(fn, { resumeState });
|
|
2697
2462
|
* ```
|
|
2698
2463
|
*/
|
|
2699
|
-
|
|
2464
|
+
interface SnapshotStore {
|
|
2465
|
+
/** Save a workflow snapshot (upsert - insert or update). Adapters may also accept ResumeState. */
|
|
2466
|
+
save(id: string, snapshot: WorkflowSnapshot): Promise<void>;
|
|
2467
|
+
/** Load a workflow snapshot. Returns null if not found. Adapters may return ResumeState when stored as such. */
|
|
2468
|
+
load(id: string): Promise<WorkflowSnapshot | null>;
|
|
2469
|
+
/** Delete a workflow snapshot. */
|
|
2470
|
+
delete(id: string): Promise<void>;
|
|
2471
|
+
/** List workflow IDs with their last update time. */
|
|
2472
|
+
list(options?: {
|
|
2473
|
+
prefix?: string;
|
|
2474
|
+
limit?: number;
|
|
2475
|
+
}): Promise<Array<{
|
|
2476
|
+
id: string;
|
|
2477
|
+
updatedAt: string;
|
|
2478
|
+
}>>;
|
|
2479
|
+
/** Clean shutdown for tests/graceful exit. */
|
|
2480
|
+
close(): Promise<void>;
|
|
2481
|
+
}
|
|
2700
2482
|
/**
|
|
2701
|
-
*
|
|
2702
|
-
*
|
|
2703
|
-
* @remarks When to use: Transform Ok values with a function that might throw and capture the failure.
|
|
2704
|
-
*
|
|
2705
|
-
* ## When to Use
|
|
2706
|
-
*
|
|
2707
|
-
* Use `mapTry()` when:
|
|
2708
|
-
* - Your transform function might throw exceptions
|
|
2709
|
-
* - You want to convert transform errors to typed errors
|
|
2710
|
-
* - You're working with libraries that throw (e.g., JSON.parse, Date parsing)
|
|
2711
|
-
* - You need to handle both Result errors and transform exceptions
|
|
2712
|
-
*
|
|
2713
|
-
* ## Why Use This Instead of `map`
|
|
2714
|
-
*
|
|
2715
|
-
* - **Exception-safe**: Catches exceptions from the transform function
|
|
2716
|
-
* - **Error mapping**: Converts thrown exceptions to typed errors
|
|
2717
|
-
* - **Dual error handling**: Handles both Result errors and transform exceptions
|
|
2718
|
-
*
|
|
2719
|
-
* @param result - The Result to transform
|
|
2720
|
-
* @param transform - Function to transform the success value (may throw exceptions)
|
|
2721
|
-
* @param onError - Function to map thrown exceptions to a typed error
|
|
2722
|
-
* @returns A Result with:
|
|
2723
|
-
* - Transformed value if both Result and transform succeed
|
|
2724
|
-
* - Original error if Result was an error
|
|
2725
|
-
* - Transform error if transform threw an exception
|
|
2726
|
-
*
|
|
2727
|
-
* @example
|
|
2728
|
-
* ```typescript
|
|
2729
|
-
* // Safe JSON parsing
|
|
2730
|
-
* const parsed = mapTry(
|
|
2731
|
-
* ok('{"key": "value"}'),
|
|
2732
|
-
* JSON.parse,
|
|
2733
|
-
* () => 'PARSE_ERROR' as const
|
|
2734
|
-
* );
|
|
2735
|
-
*
|
|
2736
|
-
* // Safe date parsing
|
|
2737
|
-
* const date = mapTry(
|
|
2738
|
-
* ok('2024-01-01'),
|
|
2739
|
-
* str => new Date(str),
|
|
2740
|
-
* () => 'INVALID_DATE' as const
|
|
2741
|
-
* );
|
|
2742
|
-
*
|
|
2743
|
-
* // Transform with error details
|
|
2744
|
-
* const processed = mapTry(
|
|
2745
|
-
* result,
|
|
2746
|
-
* value => riskyTransform(value),
|
|
2747
|
-
* (cause) => ({ type: 'TRANSFORM_ERROR' as const, cause })
|
|
2748
|
-
* );
|
|
2749
|
-
* ```
|
|
2483
|
+
* Options for the in-memory cache adapter.
|
|
2750
2484
|
*/
|
|
2751
|
-
|
|
2485
|
+
interface MemoryCacheOptions {
|
|
2486
|
+
/**
|
|
2487
|
+
* Maximum number of entries to store.
|
|
2488
|
+
* Oldest entries are evicted when limit is reached.
|
|
2489
|
+
*/
|
|
2490
|
+
maxSize?: number;
|
|
2491
|
+
/**
|
|
2492
|
+
* Time-to-live in milliseconds.
|
|
2493
|
+
* Entries are automatically removed after this duration.
|
|
2494
|
+
*/
|
|
2495
|
+
ttl?: number;
|
|
2496
|
+
}
|
|
2752
2497
|
/**
|
|
2753
|
-
*
|
|
2754
|
-
*
|
|
2755
|
-
* @remarks When to use: Transform errors when the mapping might throw and you want that captured.
|
|
2498
|
+
* Create an in-memory StepCache with optional LRU eviction and TTL.
|
|
2756
2499
|
*
|
|
2757
|
-
*
|
|
2758
|
-
*
|
|
2759
|
-
* Use `mapErrorTry()` when:
|
|
2760
|
-
* - Your error transform function might throw exceptions
|
|
2761
|
-
* - You're doing complex error transformations (e.g., string formatting, object construction)
|
|
2762
|
-
* - You want to handle both Result errors and transform exceptions
|
|
2763
|
-
* - You need to safely normalize error types
|
|
2764
|
-
*
|
|
2765
|
-
* ## Why Use This Instead of `mapError`
|
|
2766
|
-
*
|
|
2767
|
-
* - **Exception-safe**: Catches exceptions from the error transform function
|
|
2768
|
-
* - **Error mapping**: Converts thrown exceptions to typed errors
|
|
2769
|
-
* - **Dual error handling**: Handles both Result errors and transform exceptions
|
|
2770
|
-
*
|
|
2771
|
-
* @param result - The Result to transform
|
|
2772
|
-
* @param transform - Function to transform the error value (may throw exceptions)
|
|
2773
|
-
* @param onError - Function to map thrown exceptions to a typed error
|
|
2774
|
-
* @returns A Result with:
|
|
2775
|
-
* - Original value if Result was successful
|
|
2776
|
-
* - Transformed error if both Result was error and transform succeeded
|
|
2777
|
-
* - Transform error if transform threw an exception
|
|
2500
|
+
* @param options - Cache options
|
|
2501
|
+
* @returns StepCache implementation
|
|
2778
2502
|
*
|
|
2779
2503
|
* @example
|
|
2780
2504
|
* ```typescript
|
|
2781
|
-
*
|
|
2782
|
-
* const
|
|
2783
|
-
* err('not_found'),
|
|
2784
|
-
* e => e.toUpperCase(), // Might throw if e is not a string
|
|
2785
|
-
* () => 'FORMAT_ERROR' as const
|
|
2786
|
-
* );
|
|
2787
|
-
*
|
|
2788
|
-
* // Complex error transformation
|
|
2789
|
-
* const normalized = mapErrorTry(
|
|
2790
|
-
* result,
|
|
2791
|
-
* error => ({ type: 'NORMALIZED', message: String(error) }),
|
|
2792
|
-
* () => 'TRANSFORM_ERROR' as const
|
|
2793
|
-
* );
|
|
2505
|
+
* const cache = createMemoryCache({ maxSize: 1000, ttl: 60000 });
|
|
2506
|
+
* const workflow = createWorkflow(deps, { cache });
|
|
2794
2507
|
* ```
|
|
2795
2508
|
*/
|
|
2796
|
-
declare function
|
|
2509
|
+
declare function createMemoryCache(options?: MemoryCacheOptions): StepCache;
|
|
2510
|
+
|
|
2511
|
+
/**
|
|
2512
|
+
* Workflow type definitions.
|
|
2513
|
+
* Pure types and interfaces; no runtime code.
|
|
2514
|
+
*/
|
|
2515
|
+
|
|
2797
2516
|
/**
|
|
2798
|
-
*
|
|
2517
|
+
* Interface for step result caching.
|
|
2518
|
+
* Implement this interface to provide custom caching strategies.
|
|
2519
|
+
* A simple Map<string, Result> works for in-memory caching.
|
|
2799
2520
|
*
|
|
2800
|
-
* ## When
|
|
2521
|
+
* ## When Cache is Populated
|
|
2801
2522
|
*
|
|
2802
|
-
*
|
|
2803
|
-
*
|
|
2804
|
-
* - You're normalizing Results to a common format
|
|
2805
|
-
* - You want symmetric transformation of both cases
|
|
2806
|
-
* - You're building adapters between different Result types
|
|
2523
|
+
* The cache `set()` method is called after each step completes (success or error)
|
|
2524
|
+
* when the step has a `key` option. Both calling patterns work identically:
|
|
2807
2525
|
*
|
|
2808
|
-
*
|
|
2526
|
+
* ```typescript
|
|
2527
|
+
* // Function-wrapped pattern - cache is populated
|
|
2528
|
+
* await step(() => fetchUser("1"), { key: "user:1" });
|
|
2809
2529
|
*
|
|
2810
|
-
*
|
|
2811
|
-
*
|
|
2812
|
-
*
|
|
2530
|
+
* // Direct AsyncResult pattern - cache is also populated
|
|
2531
|
+
* await step(fetchUser("1"), { key: "user:1" });
|
|
2532
|
+
* ```
|
|
2813
2533
|
*
|
|
2814
|
-
*
|
|
2815
|
-
*
|
|
2816
|
-
*
|
|
2817
|
-
*
|
|
2534
|
+
* Note: Cache stores Result<unknown, unknown, unknown> because different steps
|
|
2535
|
+
* have different value/error/cause types. The actual runtime values are preserved;
|
|
2536
|
+
* only the static types are widened. For error results, the cause value is encoded
|
|
2537
|
+
* in CachedErrorCause to preserve metadata for proper replay.
|
|
2818
2538
|
*
|
|
2819
2539
|
* @example
|
|
2820
|
-
*
|
|
2821
|
-
*
|
|
2822
|
-
*
|
|
2823
|
-
*
|
|
2824
|
-
*
|
|
2825
|
-
*
|
|
2826
|
-
* )
|
|
2827
|
-
*
|
|
2828
|
-
*
|
|
2829
|
-
*
|
|
2830
|
-
*
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2540
|
+
* // Simple in-memory cache
|
|
2541
|
+
* const cache = new Map<string, Result<unknown, unknown, unknown>>();
|
|
2542
|
+
*
|
|
2543
|
+
* // Or implement custom cache with TTL, LRU, etc.
|
|
2544
|
+
* const cache: StepCache = {
|
|
2545
|
+
* get: (key) => myCache.get(key),
|
|
2546
|
+
* set: (key, result) => myCache.set(key, result, { ttl: 60000 }),
|
|
2547
|
+
* has: (key) => myCache.has(key),
|
|
2548
|
+
* delete: (key) => myCache.delete(key),
|
|
2549
|
+
* clear: () => myCache.clear(),
|
|
2550
|
+
* };
|
|
2551
|
+
*/
|
|
2552
|
+
interface StepCache {
|
|
2553
|
+
get(key: string): Result<unknown, unknown, unknown> | undefined;
|
|
2554
|
+
set(key: string, result: Result<unknown, unknown, unknown>, options?: {
|
|
2555
|
+
ttl?: number;
|
|
2556
|
+
}): void;
|
|
2557
|
+
has(key: string): boolean;
|
|
2558
|
+
delete(key: string): boolean;
|
|
2559
|
+
clear(): void;
|
|
2560
|
+
}
|
|
2561
|
+
/**
|
|
2562
|
+
* Entry for a saved step result with optional metadata.
|
|
2563
|
+
* The meta field preserves origin information for proper replay.
|
|
2842
2564
|
*/
|
|
2843
|
-
|
|
2565
|
+
interface ResumeStateEntry {
|
|
2566
|
+
result: Result<unknown, unknown, unknown>;
|
|
2567
|
+
/** Optional metadata for error origin (from step_complete event) */
|
|
2568
|
+
meta?: StepFailureMeta;
|
|
2569
|
+
}
|
|
2844
2570
|
/**
|
|
2845
|
-
*
|
|
2846
|
-
*
|
|
2847
|
-
*
|
|
2848
|
-
* @remarks When to use: Recover from Err by returning a fallback Result or retyping the error.
|
|
2571
|
+
* Resume state for workflow replay.
|
|
2572
|
+
* Pre-populate step results to skip execution on resume.
|
|
2849
2573
|
*
|
|
2850
|
-
*
|
|
2574
|
+
* Note: When saving to persistent storage, you may need custom serialization
|
|
2575
|
+
* for complex cause types. JSON.stringify works for simple values, but Error
|
|
2576
|
+
* objects and other non-plain types require special handling.
|
|
2851
2577
|
*
|
|
2852
|
-
*
|
|
2853
|
-
*
|
|
2854
|
-
*
|
|
2855
|
-
*
|
|
2856
|
-
*
|
|
2857
|
-
*
|
|
2858
|
-
*
|
|
2859
|
-
*
|
|
2860
|
-
* - **Fallback chains**: Try alternative operations on failure
|
|
2861
|
-
* - **Error recovery**: Convert errors to success with fallback values
|
|
2862
|
-
* - **Composable**: Can chain multiple orElse calls for cascading fallbacks
|
|
2863
|
-
* - **Type-safe**: TypeScript tracks the error union through recovery
|
|
2864
|
-
*
|
|
2865
|
-
* @param r - The Result to potentially recover from
|
|
2866
|
-
* @param fn - Function that takes the error and returns a new Result (may succeed or fail)
|
|
2867
|
-
* @returns The original Result if successful, or the result of the recovery function
|
|
2578
|
+
* @example
|
|
2579
|
+
* // Collect from step_complete events using the helper
|
|
2580
|
+
* const collector = createResumeStateCollector();
|
|
2581
|
+
* const workflow = createWorkflow({ fetchUser }, {
|
|
2582
|
+
* onEvent: collector.handleEvent,
|
|
2583
|
+
* });
|
|
2584
|
+
* // Later: collector.getResumeState() returns ResumeState
|
|
2868
2585
|
*
|
|
2869
2586
|
* @example
|
|
2870
|
-
*
|
|
2871
|
-
*
|
|
2872
|
-
*
|
|
2873
|
-
*
|
|
2874
|
-
* error => error === 'NOT_FOUND' ? ok(defaultUser) : err(error)
|
|
2875
|
-
* );
|
|
2876
|
-
*
|
|
2877
|
-
* // Try cache, then database, then fail
|
|
2878
|
-
* const data = orElse(
|
|
2879
|
-
* orElse(
|
|
2880
|
-
* fetchFromCache(key),
|
|
2881
|
-
* () => fetchFromDatabase(key)
|
|
2882
|
-
* ),
|
|
2883
|
-
* () => err('DATA_UNAVAILABLE' as const)
|
|
2884
|
-
* );
|
|
2885
|
-
*
|
|
2886
|
-
* // Convert specific errors to success
|
|
2887
|
-
* const result = orElse(
|
|
2888
|
-
* riskyOperation(),
|
|
2889
|
-
* error => error.code === 'RETRY' ? ok(defaultValue) : err(error)
|
|
2890
|
-
* );
|
|
2891
|
-
* ```
|
|
2587
|
+
* // Resume with saved state
|
|
2588
|
+
* const workflow = createWorkflow({ fetchUser }, {
|
|
2589
|
+
* resumeState: { steps: savedSteps }
|
|
2590
|
+
* });
|
|
2892
2591
|
*/
|
|
2893
|
-
|
|
2592
|
+
interface ResumeState {
|
|
2593
|
+
/** Map of step keys to their cached results with optional metadata */
|
|
2594
|
+
steps: Map<string, ResumeStateEntry>;
|
|
2595
|
+
}
|
|
2894
2596
|
/**
|
|
2895
|
-
*
|
|
2896
|
-
*
|
|
2897
|
-
* @param r - The Result or AsyncResult to potentially recover from
|
|
2898
|
-
* @param fn - Async function that takes the error and returns a new Result
|
|
2899
|
-
* @returns Promise of the original Result if successful, or the result of the recovery function
|
|
2900
|
-
*
|
|
2901
|
-
* @example
|
|
2902
|
-
* ```typescript
|
|
2903
|
-
* // Try primary API, fall back to secondary
|
|
2904
|
-
* const data = await orElseAsync(
|
|
2905
|
-
* await fetchFromPrimaryApi(),
|
|
2906
|
-
* async (error) => {
|
|
2907
|
-
* if (error === 'UNAVAILABLE') {
|
|
2908
|
-
* return await fetchFromSecondaryApi();
|
|
2909
|
-
* }
|
|
2910
|
-
* return err(error);
|
|
2911
|
-
* }
|
|
2912
|
-
* );
|
|
2913
|
-
* ```
|
|
2597
|
+
* Constraint for Result-returning functions
|
|
2598
|
+
* Used by createWorkflow to ensure only valid functions are passed
|
|
2914
2599
|
*/
|
|
2915
|
-
|
|
2600
|
+
type AnyResultFn = (...args: any[]) => Result<any, any, any> | Promise<Result<any, any, any>>;
|
|
2916
2601
|
/**
|
|
2917
|
-
*
|
|
2918
|
-
*
|
|
2919
|
-
*
|
|
2920
|
-
* ## When to Use
|
|
2921
|
-
*
|
|
2922
|
-
* Use `recover()` when:
|
|
2923
|
-
* - You want to provide a fallback value on error
|
|
2924
|
-
* - Recovery cannot fail (unlike orElse which returns a Result)
|
|
2925
|
-
* - You're implementing default value patterns
|
|
2926
|
-
* - You want to guarantee a successful Result
|
|
2927
|
-
*
|
|
2928
|
-
* ## Why Use This Instead of `orElse`
|
|
2929
|
-
*
|
|
2930
|
-
* - **Simpler**: Recovery function returns plain value, not Result
|
|
2931
|
-
* - **Guaranteed success**: Always returns ok() after recovery
|
|
2932
|
-
* - **Clearer intent**: Shows recovery cannot fail
|
|
2933
|
-
*
|
|
2934
|
-
* @param r - The Result to potentially recover from
|
|
2935
|
-
* @param fn - Function that takes the error and returns a recovery value
|
|
2936
|
-
* @returns The original Result if successful, or ok(recoveryValue) if error
|
|
2937
|
-
*
|
|
2938
|
-
* @example
|
|
2939
|
-
* ```typescript
|
|
2940
|
-
* // Provide default user on NOT_FOUND
|
|
2941
|
-
* const user = recover(
|
|
2942
|
-
* fetchUser(id),
|
|
2943
|
-
* error => error === 'NOT_FOUND' ? defaultUser : guestUser
|
|
2944
|
-
* );
|
|
2945
|
-
*
|
|
2946
|
-
* // Convert all errors to default
|
|
2947
|
-
* const config = recover(
|
|
2948
|
-
* loadConfig(),
|
|
2949
|
-
* () => defaultConfig
|
|
2950
|
-
* );
|
|
2951
|
-
*
|
|
2952
|
-
* // Recover with error-based defaults
|
|
2953
|
-
* const value = recover(
|
|
2954
|
-
* parseNumber(input),
|
|
2955
|
-
* error => error === 'EMPTY' ? 0 : -1
|
|
2956
|
-
* );
|
|
2957
|
-
* ```
|
|
2602
|
+
* Extract union of error types from a deps object
|
|
2603
|
+
* Example: ErrorsOfDeps<{ fetchUser: typeof fetchUser, fetchPosts: typeof fetchPosts }>
|
|
2604
|
+
* yields: 'NOT_FOUND' | 'FETCH_ERROR'
|
|
2958
2605
|
*/
|
|
2959
|
-
|
|
2606
|
+
type ErrorsOfDeps<Deps extends Record<string, AnyResultFn>> = {
|
|
2607
|
+
[K in keyof Deps]: ErrorOf<Deps[K]>;
|
|
2608
|
+
}[keyof Deps];
|
|
2960
2609
|
/**
|
|
2961
|
-
*
|
|
2610
|
+
* Extract union of cause types from a deps object.
|
|
2611
|
+
* Example: CausesOfDeps<{ fetchUser: typeof fetchUser }> where fetchUser returns Result<User, "NOT_FOUND", Error>
|
|
2612
|
+
* yields: Error
|
|
2962
2613
|
*
|
|
2963
|
-
*
|
|
2964
|
-
*
|
|
2965
|
-
*
|
|
2966
|
-
*
|
|
2967
|
-
* @example
|
|
2968
|
-
* ```typescript
|
|
2969
|
-
* // Recover by fetching default from API
|
|
2970
|
-
* const user = await recoverAsync(
|
|
2971
|
-
* await fetchUser(id),
|
|
2972
|
-
* async (error) => await fetchDefaultUser()
|
|
2973
|
-
* );
|
|
2974
|
-
* ```
|
|
2614
|
+
* Note: This represents the domain cause types from declared functions.
|
|
2615
|
+
* However, workflow results may also have unknown causes from step.try failures
|
|
2616
|
+
* or uncaught exceptions, so the actual Result cause type is `unknown`.
|
|
2975
2617
|
*/
|
|
2976
|
-
|
|
2618
|
+
type CausesOfDeps<Deps extends Record<string, AnyResultFn>> = CauseOf<Deps[keyof Deps]>;
|
|
2977
2619
|
/**
|
|
2978
|
-
*
|
|
2620
|
+
* Execution-time options that can override creation-time options.
|
|
2621
|
+
* Pass these to `workflow.run(fn, execOptions)` for per-run configuration.
|
|
2979
2622
|
*
|
|
2980
|
-
*
|
|
2981
|
-
* the serialized form IS the Result. This function validates the structure and
|
|
2982
|
-
* provides type-safe narrowing.
|
|
2983
|
-
*
|
|
2984
|
-
* ## When to Use
|
|
2985
|
-
*
|
|
2986
|
-
* Use `hydrate()` when:
|
|
2987
|
-
* - Receiving Results over RPC/network
|
|
2988
|
-
* - Deserializing Results from storage
|
|
2989
|
-
* - Validating untrusted data as Results
|
|
2990
|
-
*
|
|
2991
|
-
* @param value - The unknown value to validate as a Result
|
|
2992
|
-
* @returns The value as a typed Result, or null if invalid
|
|
2623
|
+
* Rule: Use `workflow(...)` for normal runs. Use `workflow.run(...)` when you need per-run hooks/options.
|
|
2993
2624
|
*
|
|
2994
2625
|
* @example
|
|
2995
2626
|
* ```typescript
|
|
2996
|
-
*
|
|
2997
|
-
* const parsed = JSON.parse(jsonString);
|
|
2998
|
-
* const result = hydrate<User, ApiError>(parsed);
|
|
2999
|
-
* if (result) {
|
|
3000
|
-
* // result is Result<User, ApiError>
|
|
3001
|
-
* }
|
|
2627
|
+
* const workflow = createWorkflow(deps, { cache, onEvent: defaultHandler });
|
|
3002
2628
|
*
|
|
3003
|
-
* //
|
|
3004
|
-
*
|
|
3005
|
-
* const result = hydrate<Data, ServiceError>(rpcResponse);
|
|
3006
|
-
* ```
|
|
3007
|
-
*/
|
|
3008
|
-
declare function hydrate<T, E, C = unknown>(value: unknown): Result<T, E, C> | null;
|
|
3009
|
-
/**
|
|
3010
|
-
* Type guard to check if a value is a valid serialized Result.
|
|
2629
|
+
* // Normal run uses creation-time options
|
|
2630
|
+
* await workflow(async ({ step }) => { ... });
|
|
3011
2631
|
*
|
|
3012
|
-
*
|
|
3013
|
-
*
|
|
2632
|
+
* // Per-run options override creation-time options
|
|
2633
|
+
* await workflow.run(async ({ step }) => { ... }, { onEvent: viz.handleEvent });
|
|
3014
2634
|
*
|
|
3015
|
-
*
|
|
3016
|
-
*
|
|
3017
|
-
*
|
|
3018
|
-
* // data is Result<unknown, unknown, unknown>
|
|
3019
|
-
* if (data.ok) {
|
|
3020
|
-
* console.log(data.value);
|
|
3021
|
-
* }
|
|
3022
|
-
* }
|
|
2635
|
+
* // Pre-bind defaults with .with() (overridable by .run())
|
|
2636
|
+
* const visualized = workflow.with({ onEvent: viz.handleEvent });
|
|
2637
|
+
* await visualized(async ({ step }) => { ... });
|
|
3023
2638
|
* ```
|
|
3024
2639
|
*/
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
2640
|
+
type ExecutionOptions<E, U = UnexpectedError, C = void> = {
|
|
2641
|
+
/**
|
|
2642
|
+
* Event handler for workflow and step lifecycle events.
|
|
2643
|
+
* Overrides `onEvent` from creation-time options.
|
|
2644
|
+
*/
|
|
2645
|
+
onEvent?: (event: WorkflowEvent<E | U, C>, ctx: C) => void;
|
|
2646
|
+
/**
|
|
2647
|
+
* Error handler called when a step fails.
|
|
2648
|
+
* Overrides `onError` from creation-time options.
|
|
2649
|
+
*/
|
|
2650
|
+
onError?: (error: E | U, stepName?: string, ctx?: C) => void;
|
|
2651
|
+
/**
|
|
2652
|
+
* AbortSignal for workflow-level cancellation.
|
|
2653
|
+
* Overrides `signal` from creation-time options.
|
|
2654
|
+
*/
|
|
2655
|
+
signal?: AbortSignal;
|
|
2656
|
+
/**
|
|
2657
|
+
* Factory to create per-run context. Can be async.
|
|
2658
|
+
* Overrides `createContext` from creation-time options.
|
|
2659
|
+
*/
|
|
2660
|
+
createContext?: () => C | Promise<C>;
|
|
2661
|
+
/**
|
|
2662
|
+
* Resume state for workflow replay. Can be a factory function (sync or async).
|
|
2663
|
+
* Overrides `resumeState` from creation-time options.
|
|
2664
|
+
*/
|
|
2665
|
+
resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
|
|
2666
|
+
/**
|
|
2667
|
+
* Hook to check if workflow should run (concurrency control).
|
|
2668
|
+
* Overrides `shouldRun` from creation-time options.
|
|
2669
|
+
*/
|
|
2670
|
+
shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
|
|
2671
|
+
/**
|
|
2672
|
+
* Hook called before workflow execution starts.
|
|
2673
|
+
* Overrides `onBeforeStart` from creation-time options.
|
|
2674
|
+
*/
|
|
2675
|
+
onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
|
|
2676
|
+
/**
|
|
2677
|
+
* Hook called after each step completes (only for steps with a `key`).
|
|
2678
|
+
* Overrides `onAfterStep` from creation-time options.
|
|
2679
|
+
*/
|
|
2680
|
+
onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
|
|
2681
|
+
/**
|
|
2682
|
+
* Enable strict mode for this specific run (analyzer validation only).
|
|
2683
|
+
*/
|
|
2684
|
+
strict?: boolean;
|
|
2685
|
+
/**
|
|
2686
|
+
* Declared workflow graph for strict runtime validation.
|
|
2687
|
+
* Undeclared step/decision ids fail the run immediately.
|
|
2688
|
+
* Overrides `graph` from creation-time options.
|
|
2689
|
+
*/
|
|
2690
|
+
graph?: DeclaredGraph;
|
|
2691
|
+
/**
|
|
2692
|
+
* Enable development warnings for this run.
|
|
2693
|
+
* Only active when NODE_ENV !== 'production'.
|
|
2694
|
+
*/
|
|
2695
|
+
devWarnings?: boolean;
|
|
3028
2696
|
};
|
|
3029
|
-
type AllErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {
|
|
3030
|
-
[K in keyof T]: T[K] extends Ok<unknown> ? never : T[K] extends Err<infer E, unknown> ? E : T[K] extends Result<unknown, infer E, unknown> ? E : never;
|
|
3031
|
-
}[number];
|
|
3032
|
-
type AllCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {
|
|
3033
|
-
[K in keyof T]: T[K] extends Ok<unknown> ? never : T[K] extends Err<unknown, infer C> ? C : T[K] extends Result<unknown, unknown, infer C> ? C : never;
|
|
3034
|
-
}[number];
|
|
3035
|
-
type AllResult<T extends readonly Result<unknown, unknown, unknown>[]> = [
|
|
3036
|
-
AllErrors<T>
|
|
3037
|
-
] extends [never] ? Ok<AllValues<T>> : Result<AllValues<T>, AllErrors<T>, AllCauses<T>>;
|
|
3038
2697
|
/**
|
|
3039
|
-
*
|
|
3040
|
-
*
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
*
|
|
3054
|
-
*
|
|
3055
|
-
*
|
|
3056
|
-
* ## Important
|
|
3057
|
-
*
|
|
3058
|
-
* - **Short-circuits**: Returns first error immediately, doesn't wait for all Results
|
|
3059
|
-
* - **All must succeed**: If any Result fails, the entire operation fails
|
|
3060
|
-
* - **Use `allSettled`**: If you need to collect all errors (e.g., form validation)
|
|
3061
|
-
*
|
|
3062
|
-
* @param results - Array of Results to combine (all must succeed)
|
|
3063
|
-
* @returns A Result with an array of all success values, or the first error encountered
|
|
3064
|
-
*
|
|
3065
|
-
* @example
|
|
3066
|
-
* ```typescript
|
|
3067
|
-
* // Combine multiple successful Results
|
|
3068
|
-
* const combined = all([Awaitly.ok(1), Awaitly.ok(2), Awaitly.ok(3)]);
|
|
3069
|
-
* // combined: { ok: true, value: [1, 2, 3] }
|
|
3070
|
-
*
|
|
3071
|
-
* // Short-circuits on first error
|
|
3072
|
-
* const error = all([Awaitly.ok(1), Awaitly.err('ERROR'), Awaitly.ok(3)]);
|
|
3073
|
-
* // error: { ok: false, error: 'ERROR' }
|
|
3074
|
-
* // Note: Awaitly.ok(3) is never evaluated
|
|
3075
|
-
*
|
|
3076
|
-
* // Combine API responses
|
|
3077
|
-
* const data = all([
|
|
3078
|
-
* fetchUser(id),
|
|
3079
|
-
* fetchPosts(id),
|
|
3080
|
-
* fetchComments(id)
|
|
3081
|
-
* ]);
|
|
3082
|
-
* // data.value: [user, posts, comments] if all succeed
|
|
3083
|
-
* ```
|
|
2698
|
+
* Per-run configuration. Extends ExecutionOptions with dep overrides.
|
|
2699
|
+
* Pass to `workflow.run(fn, config)` or `workflow.run(name, fn, config)`.
|
|
2700
|
+
*/
|
|
2701
|
+
type RunConfig<E, U = UnexpectedError, C = void, Deps = unknown> = ExecutionOptions<E, U, C> & {
|
|
2702
|
+
/** Override creation-time deps (partial merge). */
|
|
2703
|
+
deps?: Partial<Deps>;
|
|
2704
|
+
/** Step result cache for this run. */
|
|
2705
|
+
cache?: StepCache;
|
|
2706
|
+
/** Restore workflow from a previously saved snapshot. */
|
|
2707
|
+
snapshot?: WorkflowSnapshot | null;
|
|
2708
|
+
/** Stream store for this run. */
|
|
2709
|
+
streamStore?: StreamStore;
|
|
2710
|
+
};
|
|
2711
|
+
/**
|
|
2712
|
+
* Workflow options. Error union is always closed: E | U.
|
|
2713
|
+
* When catchUnexpected is omitted, U defaults to UnexpectedError.
|
|
3084
2714
|
*/
|
|
3085
|
-
|
|
2715
|
+
type WorkflowOptions<E, U = UnexpectedError, C = void, Errs extends readonly string[] = readonly string[]> = {
|
|
2716
|
+
/** Standard Schema for input validation. Works with Zod, Valibot, ArkType, etc. */
|
|
2717
|
+
inputSchema?: StandardSchemaV1;
|
|
2718
|
+
/** Input data to validate against inputSchema and pass to workflow context. */
|
|
2719
|
+
input?: unknown;
|
|
2720
|
+
/** Short description for labels/tooltips (static analysis) */
|
|
2721
|
+
description?: string;
|
|
2722
|
+
/** Full markdown documentation (static analysis) */
|
|
2723
|
+
markdown?: string;
|
|
2724
|
+
/**
|
|
2725
|
+
* Map uncaught exceptions (and cancellation) to your error type U.
|
|
2726
|
+
* When omitted, U = UnexpectedError and the default mapper returns an UnexpectedError instance.
|
|
2727
|
+
*/
|
|
2728
|
+
catchUnexpected?: (cause: unknown) => U;
|
|
2729
|
+
/**
|
|
2730
|
+
* Declared errors for the workflow (strict validation).
|
|
2731
|
+
* When provided, the analyzer validates that computed errors match declared errors.
|
|
2732
|
+
*/
|
|
2733
|
+
errors?: Errs;
|
|
2734
|
+
onError?: (error: E | U, stepName?: string, ctx?: C) => void;
|
|
2735
|
+
/**
|
|
2736
|
+
* Unified event stream for workflow and step lifecycle.
|
|
2737
|
+
*
|
|
2738
|
+
* Context is automatically included in `event.context` when provided via `createContext`.
|
|
2739
|
+
* The separate `ctx` parameter is provided for convenience.
|
|
2740
|
+
*/
|
|
2741
|
+
onEvent?: (event: WorkflowEvent<E | U, C>, ctx: C) => void;
|
|
2742
|
+
/** Create per-run context for event correlation */
|
|
2743
|
+
createContext?: () => C;
|
|
2744
|
+
/** Step result cache - only steps with a `key` option are cached */
|
|
2745
|
+
cache?: StepCache;
|
|
2746
|
+
/** Pre-populate cache from saved state for workflow resume. Prefer `snapshot` option. */
|
|
2747
|
+
resumeState?: ResumeState | (() => ResumeState | Promise<ResumeState>);
|
|
2748
|
+
/**
|
|
2749
|
+
* Restore workflow from a previously saved snapshot.
|
|
2750
|
+
* Pass `null` for fresh start (e.g., when store.load() returns nothing).
|
|
2751
|
+
*/
|
|
2752
|
+
snapshot?: WorkflowSnapshot | null;
|
|
2753
|
+
/**
|
|
2754
|
+
* Custom serialization for encoding/decoding values during snapshot operations.
|
|
2755
|
+
*/
|
|
2756
|
+
serialization?: {
|
|
2757
|
+
encode?: (value: unknown) => JSONValue;
|
|
2758
|
+
decode?: (value: JSONValue) => unknown;
|
|
2759
|
+
};
|
|
2760
|
+
snapshotSerialization?: {
|
|
2761
|
+
strict?: boolean;
|
|
2762
|
+
};
|
|
2763
|
+
onUnknownSteps?: "warn" | "error" | "ignore";
|
|
2764
|
+
onDefinitionChange?: "warn" | "error" | "ignore";
|
|
2765
|
+
/**
|
|
2766
|
+
* External AbortSignal for workflow-level cancellation.
|
|
2767
|
+
* Cancellation is mapped through catchUnexpected (default: UnexpectedError with cause.thrown = WorkflowCancelledError).
|
|
2768
|
+
*/
|
|
2769
|
+
signal?: AbortSignal;
|
|
2770
|
+
onBeforeStart?: (workflowId: string, context: C) => boolean | Promise<boolean>;
|
|
2771
|
+
onAfterStep?: (stepKey: string, result: Result<unknown, unknown, unknown>, workflowId: string, context: C) => void | Promise<void>;
|
|
2772
|
+
shouldRun?: (workflowId: string, context: C) => boolean | Promise<boolean>;
|
|
2773
|
+
streamStore?: StreamStore;
|
|
2774
|
+
/**
|
|
2775
|
+
* Declared workflow graph for strict runtime validation.
|
|
2776
|
+
* When provided, any runtime step/decision id not present in the graph
|
|
2777
|
+
* fails the workflow immediately, guaranteeing the static diagram matches
|
|
2778
|
+
* what actually runs. Produce it with awaitly-analyze's renderWorkflowDSL,
|
|
2779
|
+
* or pass a plain list of ids.
|
|
2780
|
+
*/
|
|
2781
|
+
graph?: DeclaredGraph;
|
|
2782
|
+
/**
|
|
2783
|
+
* Enable development warnings.
|
|
2784
|
+
* Only active when NODE_ENV !== 'production'.
|
|
2785
|
+
*/
|
|
2786
|
+
devWarnings?: boolean;
|
|
2787
|
+
};
|
|
3086
2788
|
/**
|
|
3087
|
-
*
|
|
3088
|
-
*
|
|
3089
|
-
*
|
|
3090
|
-
*
|
|
3091
|
-
* Use `allAsync()` when:
|
|
3092
|
-
* - You have multiple async operations that all must succeed
|
|
3093
|
-
* - You want to run operations in parallel (better performance)
|
|
3094
|
-
* - You want to short-circuit on the first error (fail-fast)
|
|
3095
|
-
* - You need all values together from parallel operations
|
|
3096
|
-
*
|
|
3097
|
-
* ## Why Use This Instead of `all`
|
|
3098
|
-
*
|
|
3099
|
-
* - **Parallel execution**: All Promises start immediately (faster)
|
|
3100
|
-
* - **Async support**: Works with Promises and AsyncResults
|
|
3101
|
-
* - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`
|
|
3102
|
-
*
|
|
3103
|
-
* ## Important
|
|
3104
|
-
*
|
|
3105
|
-
* - **Short-circuits**: Returns first error immediately, cancels remaining operations
|
|
3106
|
-
* - **Parallel**: All operations start simultaneously (unlike sequential `andThen`)
|
|
3107
|
-
* - **Use `allSettledAsync`**: If you need to collect all errors
|
|
3108
|
-
*
|
|
3109
|
-
* @param results - Array of Results or Promises of Results to combine (all must succeed)
|
|
3110
|
-
* @returns A Promise resolving to a Result with an array of all success values, or the first error
|
|
3111
|
-
*
|
|
3112
|
-
* @example
|
|
3113
|
-
* ```typescript
|
|
3114
|
-
* // Parallel API calls
|
|
3115
|
-
* const combined = await allAsync([
|
|
3116
|
-
* fetchUser('1'),
|
|
3117
|
-
* fetchPosts('1'),
|
|
3118
|
-
* fetchComments('1')
|
|
3119
|
-
* ]);
|
|
3120
|
-
* // All three calls start simultaneously
|
|
3121
|
-
* // combined: { ok: true, value: [user, posts, comments] } if all succeed
|
|
3122
|
-
*
|
|
3123
|
-
* // Mix Results and Promises
|
|
3124
|
-
* const data = await allAsync([
|
|
3125
|
-
* ok(cachedUser), // Already resolved
|
|
3126
|
-
* fetchPosts(userId), // Promise
|
|
3127
|
-
* ]);
|
|
3128
|
-
* ```
|
|
2789
|
+
* Workflow context provided to callbacks, containing workflow metadata
|
|
2790
|
+
* and data store for step outputs.
|
|
2791
|
+
* This allows conditional helpers and other utilities to access workflowId, onEvent, and context.
|
|
3129
2792
|
*/
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
2793
|
+
type WorkflowContext<C = void, Input = Record<string, unknown>, Data = Record<string, unknown>> = {
|
|
2794
|
+
/**
|
|
2795
|
+
* Unique ID for this workflow run.
|
|
2796
|
+
*/
|
|
2797
|
+
workflowId: string;
|
|
2798
|
+
/**
|
|
2799
|
+
* Event emitter function for workflow events.
|
|
2800
|
+
* Can be used with conditional helpers to emit step_skipped events.
|
|
2801
|
+
*/
|
|
2802
|
+
onEvent?: (event: WorkflowEvent<unknown, C>) => void;
|
|
2803
|
+
/**
|
|
2804
|
+
* Per-run context created by createContext (or undefined if not provided).
|
|
2805
|
+
* Automatically included in all workflow events.
|
|
2806
|
+
*/
|
|
2807
|
+
context?: C;
|
|
2808
|
+
/**
|
|
2809
|
+
* Workflow-level AbortSignal (if provided in workflow options).
|
|
2810
|
+
* Use this to check cancellation or pass to operations that support AbortSignal.
|
|
2811
|
+
*
|
|
2812
|
+
* @example
|
|
2813
|
+
* ```typescript
|
|
2814
|
+
* const result = await workflow(async ({ step, deps, ctx }) => {
|
|
2815
|
+
* // Pass signal to fetch
|
|
2816
|
+
* const response = await fetch(url, { signal: ctx.signal });
|
|
2817
|
+
* // Or check manually
|
|
2818
|
+
* if (ctx.signal?.aborted) return early();
|
|
2819
|
+
* });
|
|
2820
|
+
* ```
|
|
2821
|
+
*/
|
|
2822
|
+
signal?: AbortSignal;
|
|
2823
|
+
/**
|
|
2824
|
+
* Input data passed to the workflow.
|
|
2825
|
+
* Access via `ctx.input.key` for static analysis tracking.
|
|
2826
|
+
*
|
|
2827
|
+
* @example
|
|
2828
|
+
* ```typescript
|
|
2829
|
+
* await step('getCart', () => getCart(ctx.input.cartId), {
|
|
2830
|
+
* errors: ['CART_NOT_FOUND'],
|
|
2831
|
+
* });
|
|
2832
|
+
* ```
|
|
2833
|
+
*/
|
|
2834
|
+
input: Input;
|
|
2835
|
+
/**
|
|
2836
|
+
* Get a value from the workflow data store by key.
|
|
2837
|
+
* Preferred over `ctx.get()` for static analysis as it's easier to trace.
|
|
2838
|
+
*
|
|
2839
|
+
* @param key - The key to retrieve
|
|
2840
|
+
* @returns The value at that key
|
|
2841
|
+
*
|
|
2842
|
+
* @example
|
|
2843
|
+
* ```typescript
|
|
2844
|
+
* // Use ctx.ref() inside step callbacks for tracked dependencies
|
|
2845
|
+
* await step('charge', () => chargeCard(ctx.ref('cart').total), {
|
|
2846
|
+
* errors: ['CARD_DECLINED'],
|
|
2847
|
+
* });
|
|
2848
|
+
* ```
|
|
2849
|
+
*/
|
|
2850
|
+
ref: <K extends keyof Data>(key: K) => Data[K];
|
|
2851
|
+
/**
|
|
2852
|
+
* Set a value in the workflow data store.
|
|
2853
|
+
* Prefer using `out` option on steps instead for better static analysis.
|
|
2854
|
+
*
|
|
2855
|
+
* @param key - The key to set
|
|
2856
|
+
* @param value - The value to store
|
|
2857
|
+
*
|
|
2858
|
+
* @example
|
|
2859
|
+
* ```typescript
|
|
2860
|
+
* // Prefer out option:
|
|
2861
|
+
* await step('getCart', () => getCart(id), { out: 'cart' });
|
|
2862
|
+
*
|
|
2863
|
+
* // Escape hatch (less analyzable):
|
|
2864
|
+
* const cart = await step('getCart', () => getCart(id));
|
|
2865
|
+
* ctx.set('cart', cart);
|
|
2866
|
+
* ```
|
|
2867
|
+
*/
|
|
2868
|
+
set: <K extends string>(key: K, value: unknown) => void;
|
|
2869
|
+
/**
|
|
2870
|
+
* Get a value from the workflow data store.
|
|
2871
|
+
* Prefer `ctx.ref()` for better static analysis.
|
|
2872
|
+
*
|
|
2873
|
+
* @param key - The key to retrieve
|
|
2874
|
+
* @returns The value at that key (or undefined)
|
|
2875
|
+
*/
|
|
2876
|
+
get: <K extends keyof Data>(key: K) => Data[K] | undefined;
|
|
3140
2877
|
};
|
|
3141
|
-
type AllSettledResult<T extends readonly Result<unknown, unknown, unknown>[]> = [
|
|
3142
|
-
AllErrors<T>
|
|
3143
|
-
] extends [never] ? Ok<AllValues<T>> : Result<AllValues<T>, SettledError<AllErrors<T>, AllCauses<T>>[]>;
|
|
3144
2878
|
/**
|
|
3145
|
-
*
|
|
3146
|
-
*
|
|
3147
|
-
*
|
|
3148
|
-
*
|
|
3149
|
-
* Use `allSettled()` when:
|
|
3150
|
-
* - You need to see ALL errors, not just the first one
|
|
3151
|
-
* - You're doing form validation (show all field errors)
|
|
3152
|
-
* - You want to collect partial results (some succeed, some fail)
|
|
3153
|
-
* - You need to process all Results regardless of failures
|
|
3154
|
-
*
|
|
3155
|
-
* ## Why Use This Instead of `all`
|
|
3156
|
-
*
|
|
3157
|
-
* - **Collects all errors**: Returns array of all errors, not just first
|
|
3158
|
-
* - **No short-circuit**: Evaluates all Results even if some fail
|
|
3159
|
-
* - **Partial success**: Can see which operations succeeded and which failed
|
|
3160
|
-
* - **Better UX**: Show users all validation errors at once
|
|
3161
|
-
*
|
|
3162
|
-
* ## Important
|
|
3163
|
-
*
|
|
3164
|
-
* - **No short-circuit**: All Results are evaluated (slower if many fail early)
|
|
3165
|
-
* - **Error array**: Returns array of `{ error, cause }` objects, not single error
|
|
3166
|
-
* - **Use `all`**: If you want fail-fast behavior (better performance)
|
|
3167
|
-
*
|
|
3168
|
-
* @param results - Array of Results to combine (all are evaluated)
|
|
3169
|
-
* @returns A Result with:
|
|
3170
|
-
* - Array of all success values if all succeed
|
|
3171
|
-
* - Array of `{ error, cause }` objects if any fail
|
|
3172
|
-
*
|
|
3173
|
-
* @example
|
|
3174
|
-
* ```typescript
|
|
3175
|
-
* // Form validation - show all errors
|
|
3176
|
-
* const validated = allSettled([
|
|
3177
|
-
* validateEmail(email),
|
|
3178
|
-
* validatePassword(password),
|
|
3179
|
-
* validateAge(age),
|
|
3180
|
-
* ]);
|
|
3181
|
-
* // If email and password fail:
|
|
3182
|
-
* // { ok: false, error: [
|
|
3183
|
-
* // { error: 'INVALID_EMAIL' },
|
|
3184
|
-
* // { error: 'WEAK_PASSWORD' }
|
|
3185
|
-
* // ]}
|
|
3186
|
-
*
|
|
3187
|
-
* // Collect partial results
|
|
3188
|
-
* const results = allSettled([
|
|
3189
|
-
* fetchUser('1'), // succeeds
|
|
3190
|
-
* fetchUser('2'), // fails
|
|
3191
|
-
* fetchUser('3'), // succeeds
|
|
3192
|
-
* ]);
|
|
3193
|
-
* // Can see which succeeded and which failed
|
|
3194
|
-
* ```
|
|
2879
|
+
* Bound steps for a workflow's deps: each dep key becomes a step function
|
|
2880
|
+
* with the dep's arguments that unwraps ok / early-exits on err — same as
|
|
2881
|
+
* the deps-first run(deps, fn) form. `never` deps (no deps) yield no steps.
|
|
3195
2882
|
*/
|
|
3196
|
-
|
|
2883
|
+
type WorkflowSteps<Deps> = [Deps] extends [
|
|
2884
|
+
Record<string, (...args: never[]) => unknown>
|
|
2885
|
+
] ? BoundSteps<Deps> : Record<string, never>;
|
|
2886
|
+
/** Workflow function type (no args). E is the full step error union (deps errors + any ExtraE from step.workflow/withFallback). */
|
|
2887
|
+
type WorkflowFn<T, E, Deps, C = void> = (context: {
|
|
2888
|
+
step: RunStep<E>;
|
|
2889
|
+
steps: WorkflowSteps<Deps>;
|
|
2890
|
+
deps: Deps;
|
|
2891
|
+
ctx: WorkflowContext<C>;
|
|
2892
|
+
}) => T | Promise<T>;
|
|
3197
2893
|
/**
|
|
3198
|
-
*
|
|
3199
|
-
*
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
*
|
|
3207
|
-
*
|
|
3208
|
-
*
|
|
3209
|
-
*
|
|
3210
|
-
* - **Simple separation**: One call splits successes and errors
|
|
3211
|
-
* - **Type-safe**: TypeScript knows `values` is `T[]` and `errors` is `E[]`
|
|
3212
|
-
* - **No unwrapping**: Doesn't require manual `if (r.ok)` checks
|
|
3213
|
-
* - **Preserves order**: Maintains original array order in both arrays
|
|
3214
|
-
*
|
|
3215
|
-
* ## Common Pattern
|
|
3216
|
-
*
|
|
3217
|
-
* Often used after `Promise.all()` with Results:
|
|
3218
|
-
* ```typescript
|
|
3219
|
-
* const results = await Promise.all(ids.map(id => fetchUser(id)));
|
|
3220
|
-
* const { values: users, errors } = partition(results);
|
|
3221
|
-
* // Process successful users, handle errors separately
|
|
3222
|
-
* ```
|
|
2894
|
+
* Return type of runWithState: result plus resume state for persistence.
|
|
2895
|
+
* resumeState is always present, even when the run fails or returns an error Result.
|
|
2896
|
+
*/
|
|
2897
|
+
type RunWithStateResult<T, E, U> = {
|
|
2898
|
+
result: Result<T, E | U, unknown>;
|
|
2899
|
+
resumeState: ResumeState;
|
|
2900
|
+
};
|
|
2901
|
+
/**
|
|
2902
|
+
* Workflow return type. Error union is always closed: E | ExtraE | U (default U = UnexpectedError).
|
|
2903
|
+
* ExtraE is inferred from the callback when using step.workflow or step.withFallback with errors not in deps.
|
|
2904
|
+
* Methods: .run() (4 overloads) and .runWithState() (4 overloads) for run-and-persist flows.
|
|
3223
2905
|
*
|
|
3224
|
-
*
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
2906
|
+
* Cause type is `unknown` because step.try/catchUnexpected receive thrown values.
|
|
2907
|
+
*/
|
|
2908
|
+
interface Workflow<E, U = UnexpectedError, Deps = unknown, C = void> {
|
|
2909
|
+
/**
|
|
2910
|
+
* Pre-bind dependency overrides and return another `Workflow`.
|
|
2911
|
+
* Chain `.withDeps()` and call `.run()` / `.runWithState()` as normal.
|
|
2912
|
+
* Precedence: createWorkflow deps < withDeps deps < run config deps.
|
|
2913
|
+
*/
|
|
2914
|
+
withDeps(overrides: Partial<Deps>): Workflow<E, U, Deps, C>;
|
|
2915
|
+
/**
|
|
2916
|
+
* Execute workflow (anonymous run).
|
|
2917
|
+
* ExtraE is inferred from the callback (e.g. from step.workflow / step.withFallback); result is Result<T, E | ExtraE | U>.
|
|
2918
|
+
* T is inferred from the callback return type. For nested workflows (calling another workflow.run() inside the callback),
|
|
2919
|
+
* inference can sometimes fall back to `any`; adding an explicit return type to the callback (e.g.
|
|
2920
|
+
* `async (ctx): Promise<{ user: User; enriched: Enriched }> => { ... }`) gives the compiler a target and preserves types.
|
|
2921
|
+
*/
|
|
2922
|
+
run<T, ExtraE = never>(fn: WorkflowFn<T, E | ExtraE, Deps, C>): AsyncResult<T, E | ExtraE | U, unknown>;
|
|
2923
|
+
/**
|
|
2924
|
+
* Execute workflow with config overrides.
|
|
2925
|
+
*/
|
|
2926
|
+
run<T, ExtraE = never>(fn: WorkflowFn<T, E | ExtraE, Deps, C>, config: RunConfig<E, U, C, Deps>): AsyncResult<T, E | ExtraE | U, unknown>;
|
|
2927
|
+
/**
|
|
2928
|
+
* Execute named workflow run (for logging, tracing, resume).
|
|
2929
|
+
*/
|
|
2930
|
+
run<T, ExtraE = never>(name: string, fn: WorkflowFn<T, E | ExtraE, Deps, C>): AsyncResult<T, E | ExtraE | U, unknown>;
|
|
2931
|
+
/**
|
|
2932
|
+
* Execute named workflow run with config overrides.
|
|
2933
|
+
*/
|
|
2934
|
+
run<T, ExtraE = never>(name: string, fn: WorkflowFn<T, E | ExtraE, Deps, C>, config: RunConfig<E, U, C, Deps>): AsyncResult<T, E | ExtraE | U, unknown>;
|
|
2935
|
+
/**
|
|
2936
|
+
* Execute workflow and return result plus resume state for persistence.
|
|
2937
|
+
* resumeState is always present (even on failure) so callers can persist partial state.
|
|
2938
|
+
* Same overloads as run(); does not throw — follows the same "never throw, always Result" contract as run().
|
|
2939
|
+
*
|
|
2940
|
+
* @example
|
|
2941
|
+
* const { result, resumeState } = await workflow.runWithState(fn);
|
|
2942
|
+
* await store.save(id, resumeState);
|
|
2943
|
+
*/
|
|
2944
|
+
runWithState<T, ExtraE = never>(fn: WorkflowFn<T, E | ExtraE, Deps, C>): Promise<RunWithStateResult<T, E | ExtraE, U>>;
|
|
2945
|
+
/**
|
|
2946
|
+
* Execute workflow with config overrides and return result plus resume state.
|
|
2947
|
+
*/
|
|
2948
|
+
runWithState<T, ExtraE = never>(fn: WorkflowFn<T, E | ExtraE, Deps, C>, config: RunConfig<E, U, C, Deps>): Promise<RunWithStateResult<T, E | ExtraE, U>>;
|
|
2949
|
+
/**
|
|
2950
|
+
* Execute named workflow run and return result plus resume state.
|
|
2951
|
+
*/
|
|
2952
|
+
runWithState<T, ExtraE = never>(name: string, fn: WorkflowFn<T, E | ExtraE, Deps, C>): Promise<RunWithStateResult<T, E | ExtraE, U>>;
|
|
2953
|
+
/**
|
|
2954
|
+
* Execute named workflow run with config overrides and return result plus resume state.
|
|
2955
|
+
*/
|
|
2956
|
+
runWithState<T, ExtraE = never>(name: string, fn: WorkflowFn<T, E | ExtraE, Deps, C>, config: RunConfig<E, U, C, Deps>): Promise<RunWithStateResult<T, E | ExtraE, U>>;
|
|
2957
|
+
}
|
|
2958
|
+
/**
|
|
2959
|
+
* Error returned when a workflow is cancelled via AbortSignal.
|
|
3228
2960
|
*
|
|
3229
2961
|
* @example
|
|
3230
2962
|
* ```typescript
|
|
3231
|
-
*
|
|
3232
|
-
* const
|
|
3233
|
-
* const { values, errors } = partition(results);
|
|
3234
|
-
* // values: [1, 3]
|
|
3235
|
-
* // errors: ['ERROR_1', 'ERROR_2']
|
|
3236
|
-
*
|
|
3237
|
-
* // Process batch operations
|
|
3238
|
-
* const userResults = await Promise.all(userIds.map(id => fetchUser(id)));
|
|
3239
|
-
* const { values: users, errors: fetchErrors } = partition(userResults);
|
|
2963
|
+
* const controller = new AbortController();
|
|
2964
|
+
* const workflow = createWorkflow(deps, { signal: controller.signal });
|
|
3240
2965
|
*
|
|
3241
|
-
* //
|
|
3242
|
-
*
|
|
2966
|
+
* // Later:
|
|
2967
|
+
* controller.abort('User navigated away');
|
|
3243
2968
|
*
|
|
3244
|
-
*
|
|
3245
|
-
*
|
|
2969
|
+
* const result = await workflowPromise;
|
|
2970
|
+
* if (!result.ok && isWorkflowCancelled(result.error)) {
|
|
2971
|
+
* console.log('Cancelled:', result.error.reason);
|
|
2972
|
+
* }
|
|
3246
2973
|
* ```
|
|
3247
2974
|
*/
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
2975
|
+
type WorkflowCancelledError = {
|
|
2976
|
+
type: "WORKFLOW_CANCELLED";
|
|
2977
|
+
/** Reason from AbortSignal.reason (if provided) */
|
|
2978
|
+
reason?: string;
|
|
2979
|
+
/** Last successfully completed keyed step (for resume purposes) */
|
|
2980
|
+
lastStepKey?: string;
|
|
3251
2981
|
};
|
|
3252
|
-
type AnyValue<T extends readonly Result<unknown, unknown, unknown>[]> = T[number] extends Result<infer U, unknown, unknown> ? U : never;
|
|
3253
|
-
type AnyErrors<T extends readonly Result<unknown, unknown, unknown>[]> = {
|
|
3254
|
-
-readonly [K in keyof T]: T[K] extends Result<unknown, infer E, unknown> ? E : never;
|
|
3255
|
-
}[number];
|
|
3256
|
-
type AnyCauses<T extends readonly Result<unknown, unknown, unknown>[]> = {
|
|
3257
|
-
-readonly [K in keyof T]: T[K] extends Result<unknown, unknown, infer C> ? C : never;
|
|
3258
|
-
}[number];
|
|
3259
2982
|
/**
|
|
3260
|
-
*
|
|
3261
|
-
*
|
|
3262
|
-
* ## When to Use
|
|
3263
|
-
*
|
|
3264
|
-
* Use `any()` when:
|
|
3265
|
-
* - You have multiple fallback options and need the first that succeeds
|
|
3266
|
-
* - You're trying multiple strategies (e.g., cache → DB → API)
|
|
3267
|
-
* - You want fail-fast success (stops on first success)
|
|
3268
|
-
* - You have redundant data sources and any one will do
|
|
3269
|
-
*
|
|
3270
|
-
* ## Why Use This
|
|
3271
|
-
*
|
|
3272
|
-
* - **Succeeds fast**: Returns immediately on first success (better performance)
|
|
3273
|
-
* - **Fallback pattern**: Perfect for trying multiple options
|
|
3274
|
-
* - **Short-circuits**: Stops evaluating after first success
|
|
3275
|
-
* - **Type-safe**: TypeScript infers the success type
|
|
3276
|
-
*
|
|
3277
|
-
* ## Important
|
|
3278
|
-
*
|
|
3279
|
-
* - **First success wins**: Returns first successful Result, ignores rest
|
|
3280
|
-
* - **All errors**: If all fail, returns first error (not all errors)
|
|
3281
|
-
* - **Empty array**: Returns `EmptyInputError` if array is empty
|
|
3282
|
-
* - **Use `all`**: If you need ALL to succeed
|
|
3283
|
-
*
|
|
3284
|
-
* @param results - Array of Results to check (evaluated in order)
|
|
3285
|
-
* @returns The first successful Result, or first error if all fail, or `EmptyInputError` if empty
|
|
2983
|
+
* Standard error type for steps awaiting human approval.
|
|
2984
|
+
* Use this as the error type for approval-gated steps.
|
|
3286
2985
|
*
|
|
3287
2986
|
* @example
|
|
3288
|
-
*
|
|
3289
|
-
*
|
|
3290
|
-
*
|
|
3291
|
-
*
|
|
3292
|
-
*
|
|
3293
|
-
*
|
|
3294
|
-
*
|
|
3295
|
-
* // Returns first that succeeds
|
|
3296
|
-
*
|
|
3297
|
-
* // Try multiple formats
|
|
3298
|
-
* const parsed = any([
|
|
3299
|
-
* parseJSON(input),
|
|
3300
|
-
* parseXML(input),
|
|
3301
|
-
* parseYAML(input)
|
|
3302
|
-
* ]);
|
|
3303
|
-
*
|
|
3304
|
-
* // All errors case
|
|
3305
|
-
* const allErrors = any([err('A'), err('B'), err('C')]);
|
|
3306
|
-
* // allErrors: { ok: false, error: 'A' } (first error)
|
|
3307
|
-
* ```
|
|
2987
|
+
* const requireApproval = async (userId: string): AsyncResult<Approval, PendingApproval> => {
|
|
2988
|
+
* const status = await checkApprovalStatus(userId);
|
|
2989
|
+
* if (status === 'pending') {
|
|
2990
|
+
* return err({ type: 'PENDING_APPROVAL', stepKey: `approval:${userId}` });
|
|
2991
|
+
* }
|
|
2992
|
+
* return ok(status.approval);
|
|
2993
|
+
* };
|
|
3308
2994
|
*/
|
|
3309
|
-
|
|
3310
|
-
type
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
2995
|
+
type PendingApproval = {
|
|
2996
|
+
type: "PENDING_APPROVAL";
|
|
2997
|
+
/** Step key for correlation when resuming */
|
|
2998
|
+
stepKey: string;
|
|
2999
|
+
/** Optional reason for the pending state */
|
|
3000
|
+
reason?: string;
|
|
3001
|
+
/** Optional metadata for the approval request */
|
|
3002
|
+
metadata?: Record<string, unknown>;
|
|
3003
|
+
};
|
|
3317
3004
|
/**
|
|
3318
|
-
*
|
|
3319
|
-
*
|
|
3320
|
-
*
|
|
3321
|
-
*
|
|
3322
|
-
* Use `anyAsync()` when:
|
|
3323
|
-
* - You have multiple async fallback options and need the first that succeeds
|
|
3324
|
-
* - You're trying multiple async strategies in parallel (cache → DB → API)
|
|
3325
|
-
* - You want fail-fast success from parallel operations
|
|
3326
|
-
* - You have redundant async data sources and any one will do
|
|
3327
|
-
*
|
|
3328
|
-
* ## Why Use This Instead of `any`
|
|
3329
|
-
*
|
|
3330
|
-
* - **Parallel execution**: All Promises start immediately (faster)
|
|
3331
|
-
* - **Async support**: Works with Promises and AsyncResults
|
|
3332
|
-
* - **Promise rejection handling**: Converts Promise rejections to `PromiseRejectedError`
|
|
3333
|
-
*
|
|
3334
|
-
* ## Important
|
|
3335
|
-
*
|
|
3336
|
-
* - **First success wins**: Returns first successful Result (from any Promise)
|
|
3337
|
-
* - **Parallel**: All operations run simultaneously
|
|
3338
|
-
* - **All errors**: If all fail, returns first error encountered
|
|
3339
|
-
*
|
|
3340
|
-
* @param results - Array of Results or Promises of Results to check (all start in parallel)
|
|
3341
|
-
* @returns A Promise resolving to the first successful Result, or first error if all fail
|
|
3342
|
-
*
|
|
3343
|
-
* @example
|
|
3344
|
-
* ```typescript
|
|
3345
|
-
* // Try multiple async fallbacks in parallel
|
|
3346
|
-
* const data = await anyAsync([
|
|
3347
|
-
* fetchFromCache(id), // Fastest wins
|
|
3348
|
-
* fetchFromDB(id),
|
|
3349
|
-
* fetchFromAPI(id)
|
|
3350
|
-
* ]);
|
|
3351
|
-
*
|
|
3352
|
-
* // Try multiple API endpoints
|
|
3353
|
-
* const response = await anyAsync([
|
|
3354
|
-
* fetch('/api/v1/data'),
|
|
3355
|
-
* fetch('/api/v2/data'),
|
|
3356
|
-
* fetch('/backup-api/data')
|
|
3357
|
-
* ]);
|
|
3358
|
-
* ```
|
|
3005
|
+
* Standard error type for steps awaiting an HTTP callback (webhook).
|
|
3006
|
+
* Use with injectHook() to resume when the app receives the callback.
|
|
3007
|
+
* stepKey is always "hook:" + hookId for resume state.
|
|
3359
3008
|
*/
|
|
3360
|
-
|
|
3361
|
-
type
|
|
3362
|
-
|
|
3009
|
+
type PendingHook = {
|
|
3010
|
+
type: "PENDING_HOOK";
|
|
3011
|
+
hookId: string;
|
|
3012
|
+
/** Step key used in resume state; always "hook:" + hookId */
|
|
3013
|
+
stepKey: string;
|
|
3014
|
+
metadata?: Record<string, unknown>;
|
|
3363
3015
|
};
|
|
3364
|
-
type AllAsyncErrors<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
|
|
3365
|
-
[K in keyof T]: Awaited<T[K]> extends Result<unknown, infer E, unknown> ? E : never;
|
|
3366
|
-
}[number];
|
|
3367
|
-
type AllAsyncCauses<T extends readonly MaybeAsyncResult<unknown, unknown, unknown>[]> = {
|
|
3368
|
-
[K in keyof T]: Awaited<T[K]> extends Result<unknown, unknown, infer C> ? C : never;
|
|
3369
|
-
}[number];
|
|
3370
3016
|
/**
|
|
3371
|
-
*
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
*
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
*
|
|
3403
|
-
* @returns A Promise resolving to a Result with:
|
|
3404
|
-
* - `ok(values[])` - Array of all success values if ALL succeed
|
|
3405
|
-
* - `err(errors[])` - Array of `SettledError` objects if ANY fail
|
|
3406
|
-
*
|
|
3407
|
-
* @example
|
|
3408
|
-
* ```typescript
|
|
3409
|
-
* // Async form validation - see all errors at once
|
|
3410
|
-
* const validated = await allSettledAsync([
|
|
3411
|
-
* validateEmailAsync(email),
|
|
3412
|
-
* validatePasswordAsync(password),
|
|
3413
|
-
* checkUsernameAvailableAsync(username),
|
|
3414
|
-
* ]);
|
|
3415
|
-
*
|
|
3416
|
-
* if (!validated.ok) {
|
|
3417
|
-
* // validated.error is array of all validation failures
|
|
3418
|
-
* console.log('Errors:', validated.error.map(e => e.error));
|
|
3419
|
-
* }
|
|
3420
|
-
*
|
|
3421
|
-
* // Parallel API calls with error collection
|
|
3422
|
-
* const results = await allSettledAsync([
|
|
3423
|
-
* fetchUser('1'),
|
|
3424
|
-
* fetchUser('2'),
|
|
3425
|
-
* fetchUser('3'),
|
|
3426
|
-
* ]);
|
|
3427
|
-
* ```
|
|
3017
|
+
* Error returned when approval is rejected.
|
|
3018
|
+
*/
|
|
3019
|
+
type ApprovalRejected = {
|
|
3020
|
+
type: "APPROVAL_REJECTED";
|
|
3021
|
+
/** Step key for correlation */
|
|
3022
|
+
stepKey: string;
|
|
3023
|
+
/** Reason the approval was rejected */
|
|
3024
|
+
reason: string;
|
|
3025
|
+
};
|
|
3026
|
+
/**
|
|
3027
|
+
* Options for creating an approval-gated step.
|
|
3028
|
+
*/
|
|
3029
|
+
interface ApprovalStepOptions<T> {
|
|
3030
|
+
/** Stable key for this approval step (used for resume) */
|
|
3031
|
+
key: string;
|
|
3032
|
+
/** Function to check current approval status from external source */
|
|
3033
|
+
checkApproval: () => Promise<{
|
|
3034
|
+
status: "pending";
|
|
3035
|
+
} | {
|
|
3036
|
+
status: "approved";
|
|
3037
|
+
value: T;
|
|
3038
|
+
} | {
|
|
3039
|
+
status: "rejected";
|
|
3040
|
+
reason: string;
|
|
3041
|
+
}>;
|
|
3042
|
+
/** Optional reason shown when pending */
|
|
3043
|
+
pendingReason?: string;
|
|
3044
|
+
/** Optional metadata for the approval request */
|
|
3045
|
+
metadata?: Record<string, unknown>;
|
|
3046
|
+
}
|
|
3047
|
+
/**
|
|
3048
|
+
* Options for creating a gated (pre-approval) step.
|
|
3428
3049
|
*/
|
|
3429
|
-
|
|
3050
|
+
interface GatedStepOptions<TArgs, T> {
|
|
3051
|
+
/** Stable key for this gated step (used for approval tracking) */
|
|
3052
|
+
key: string;
|
|
3053
|
+
/**
|
|
3054
|
+
* Condition to check if approval is required.
|
|
3055
|
+
* If returns true, execution pauses for approval.
|
|
3056
|
+
* If returns false, operation executes immediately.
|
|
3057
|
+
*/
|
|
3058
|
+
requiresApproval: boolean | ((args: TArgs) => boolean | Promise<boolean>);
|
|
3059
|
+
/**
|
|
3060
|
+
* Human-readable description of what this operation does.
|
|
3061
|
+
* Shown in the approval UI so humans understand what they're approving.
|
|
3062
|
+
*/
|
|
3063
|
+
description: string | ((args: TArgs) => string);
|
|
3064
|
+
/**
|
|
3065
|
+
* Check if approval has been granted externally.
|
|
3066
|
+
* If not provided, the step always returns PendingApproval when gated.
|
|
3067
|
+
*/
|
|
3068
|
+
checkApproval?: () => Promise<{
|
|
3069
|
+
status: "pending";
|
|
3070
|
+
} | {
|
|
3071
|
+
status: "approved";
|
|
3072
|
+
value?: T;
|
|
3073
|
+
} | {
|
|
3074
|
+
status: "rejected";
|
|
3075
|
+
reason: string;
|
|
3076
|
+
}>;
|
|
3077
|
+
/**
|
|
3078
|
+
* Optional metadata to include in the approval request.
|
|
3079
|
+
* The args are automatically included as `pendingArgs`.
|
|
3080
|
+
*/
|
|
3081
|
+
metadata?: Record<string, unknown>;
|
|
3082
|
+
}
|
|
3430
3083
|
|
|
3431
|
-
export {
|
|
3084
|
+
export { STREAM_ENDED as $, type AsyncResult as A, type BackoffStrategy as B, type WorkflowSnapshot as C, type DepValueOfReturn as D, EARLY_EXIT_SYMBOL as E, type ApprovalStepOptions as F, type GatedStepOptions as G, type Workflow as H, type WorkflowOptions as I, type SnapshotStore as J, type ResumeStateEntry as K, type StreamStore as L, type StreamReader as M, type CausesOfDeps as N, type Ok as O, type PendingApproval as P, type ExecutionOptions as Q, type Result as R, type StepOptions as S, type TimeoutOptions as T, type JSONValue as U, type MemoryCacheOptions as V, type WorkflowEvent as W, type RunConfig as X, type RunWithStateResult as Y, STREAM_BACKPRESSURE_ERROR as Z, STREAM_CLOSE_ERROR as _, type RetryOptions as a, STREAM_READ_ERROR as a0, STREAM_STORE_ERROR as a1, STREAM_WRITE_ERROR as a2, type SerializedCause as a3, SnapshotDecodeError as a4, SnapshotFormatError as a5, SnapshotMismatchError as a6, type SnapshotWarning as a7, type StepCache as a8, type StepErrorDiagnostics as a9, isWorkflowSnapshot as aA, looksLikeWorkflowSnapshot as aB, mergeSnapshots as aC, serializeError as aD, serializeThrown as aE, streamBackpressureError as aF, streamCloseError as aG, streamEnded as aH, streamReadError as aI, streamStoreError as aJ, streamWriteError as aK, validateSnapshot as aL, type StepMetadata as aa, type StreamBackpressureError as ab, type StreamCloseError as ac, type StreamEndedMarker as ad, type StreamError as ae, type StreamForEachOptions as af, type StreamForEachResult as ag, type StreamItem as ah, type StreamMetadata as ai, type StreamOptions as aj, type StreamReadError as ak, type StreamReadOptions as al, type StreamStoreError as am, type StreamWriteError as an, type StreamWriter as ao, type Unsubscribe as ap, type WorkflowFn as aq, type WorkflowSteps as ar, assertValidSnapshot as as, createMemoryCache as at, deserializeCauseNew as au, isStreamBackpressureError as av, isStreamEnded as aw, isStreamReadError as ax, isStreamStoreError as ay, isStreamWriteError as az, type BoundSteps as b, type EarlyExit as c, type RunOptions as d, type RunOptionsWithCatch as e, type RunOptionsWithoutCatch as f, type RunStep as g, STEP_TIMEOUT_MARKER as h, type ScopeType as i, type StepFailureMeta as j, type StepTimeoutError as k, type StepTimeoutMarkerMeta as l, createEarlyExit as m, getStepTimeoutMeta as n, isEarlyExit as o, isStepTimeoutError as p, type AnyResultFn as q, run as r, type ErrorsOfDeps as s, type WorkflowContext as t, type Err as u, type ApprovalRejected as v, type PendingHook as w, type ResumeState as x, type WorkflowCancelledError as y, type StepResult as z };
|